test: add coverage for new features

This commit is contained in:
Nicolas Meienberger 2023-06-07 22:12:49 +02:00 committed by Nicolas Meienberger
parent 25ad967ccb
commit 70b6c20b29
10 changed files with 81 additions and 12 deletions

View file

@ -104,7 +104,7 @@ jobs:
cd runtipi
echo 'Checking out branch ${{ github.head_ref }}'
git checkout ${{ github.head_ref }}
sudo ./scripts/start-e2e.sh latest
sudo ./scripts/start-e2e.sh e2e
echo 'App deployed'
host: ${{ steps.get-droplet-ip.outputs.droplet_ip }}
user: root

View file

@ -30,8 +30,8 @@ test('user can install and uninstall app', async ({ page, context }) => {
await expect(page.getByText('Running')).toBeVisible({ timeout: 60000 });
await expect(page.getByText('App installed successfully')).toBeVisible();
await page.getByTestId('app-details').getByRole('button', { name: 'Open' }).click();
const [newPage] = await Promise.all([context.waitForEvent('page'), await page.getByRole('menuitem', { name: 'localhost:8000' }).click()]);
await page.getByTestId('app-details').getByRole('button', { name: 'Open' }).press('ArrowDown');
const [newPage] = await Promise.all([context.waitForEvent('page'), await page.getByRole('menuitem', { name: `${process.env.SERVER_IP}:8000` }).click()]);
await newPage.waitForLoadState();
await expect(newPage.getByText('Hello World')).toBeVisible();

View file

@ -114,9 +114,11 @@ function generateTLSCert() {
if ! openssl req -x509 -newkey rsa:4096 -keyout traefik/tls/key.pem -out traefik/tls/cert.pem -days 365 -subj "/O=runtipi.io/OU=IT/CN=*.${domain}/emailAddress=webmaster@${domain}" -addext "subjectAltName = DNS:*.${domain},DNS:${domain}" -nodes; then
echo "Failed to generate TLS certificate"
fi
else
echo "TLS certificate generated"
# Create a file to indicate that the certificate has been generated for this domain
touch "traefik/tls/$domain.txt"
fi
}

View file

@ -103,7 +103,7 @@ env_variables_json=$(cat <<EOF
"local_domain": "tipi.lan",
"repo_id": "$("${ROOT_FOLDER}"/scripts/git.sh get_hash "${apps_repository}")",
"apps_repository": "${apps_repository}",
"domain": "tipi.lan",
"domain": "example.com",
"storage_path": "${ROOT_FOLDER}",
"demo_mode": false,
}

View file

@ -253,7 +253,8 @@
"submit": "Save",
"user-settings-title": "User settings",
"language": "Language",
"help-translate": "Help translate Tipi"
"help-translate": "Help translate Tipi",
"download-certificate": "Download certificate"
},
"security": {
"tab-title": "Security",

View file

@ -29,7 +29,7 @@ export const handlers = [
getTRPCMock({
path: ['system', 'getSettings'],
type: 'query',
response: { internalIp: 'localhost', dnsIp: '1.1.1.1', appsRepoUrl: 'https://test.com/test', domain: 'tipi.localhost' },
response: { internalIp: 'localhost', dnsIp: '1.1.1.1', appsRepoUrl: 'https://test.com/test', domain: 'tipi.localhost', localDomain: 'tipi.lan' },
}),
getTRPCMock({
path: ['system', 'updateSettings'],

View file

@ -124,6 +124,54 @@ describe('Test: AppDetailsContainer', () => {
});
spy.mockRestore();
});
it('should open with domain when domain is clicked', async () => {
// Arrange
const app = createAppEntity({ overrides: { domain: 'test.com', exposed: true } });
const spy = jest.spyOn(window, 'open').mockImplementation(() => null);
render(<AppDetailsContainer app={app} />);
// Act
const openButton = screen.getByRole('button', { name: 'Open' });
userEvent.type(openButton, '{arrowdown}');
await waitFor(() => {
expect(screen.getByText(/test.com/)).toBeInTheDocument();
});
const openButtonItem = screen.getByText(/test.com/);
userEvent.click(openButtonItem);
// Assert
await waitFor(() => {
expect(spy).toHaveBeenCalledWith(`https://test.com`, '_blank', 'noreferrer');
});
spy.mockRestore();
});
it('should open with local domain when local domain is clicked', async () => {
// Arrange
const app = createAppEntity({});
const spy = jest.spyOn(window, 'open').mockImplementation(() => null);
render(<AppDetailsContainer app={app} />);
// Act
const openButton = screen.getByRole('button', { name: 'Open' });
userEvent.type(openButton, '{arrowdown}');
await waitFor(() => {
expect(screen.getByText(/.tipi.lan/)).toBeInTheDocument();
});
const openButtonItem = screen.getByText(/.tipi.lan/);
userEvent.click(openButtonItem);
// Assert
await waitFor(() => {
expect(spy).toHaveBeenCalledWith(`https://${app.id}.tipi.lan`, '_blank', 'noreferrer');
});
spy.mockRestore();
});
});
describe('Test: Install app', () => {

View file

@ -39,6 +39,7 @@ describe('Test: SettingsForm', () => {
internalIp: 'invalid internal ip',
appsRepoUrl: 'invalid url',
storagePath: 'invalid path',
localDomain: 'invalid local domain',
};
render(<SettingsForm onSubmit={jest.fn()} submitErrors={submitErrors} />);
@ -50,6 +51,7 @@ describe('Test: SettingsForm', () => {
expect(screen.getByText(submitErrors.internalIp)).toBeInTheDocument();
expect(screen.getByText(submitErrors.appsRepoUrl)).toBeInTheDocument();
expect(screen.getByText(submitErrors.storagePath)).toBeInTheDocument();
expect(screen.getByText(submitErrors.localDomain)).toBeInTheDocument();
});
it('should correctly validate the form', async () => {
@ -60,19 +62,21 @@ describe('Test: SettingsForm', () => {
const domainInput = screen.getByRole('textbox', { name: 'domain' });
const internalIpInput = screen.getByRole('textbox', { name: 'internalIp' });
const appsRepoUrlInput = screen.getByRole('textbox', { name: 'appsRepoUrl' });
const localDomainInput = screen.getByRole('textbox', { name: 'localDomain' });
// act
fireEvent.change(dnsIpInput, { target: { value: 'invalid ip' } });
fireEvent.change(domainInput, { target: { value: 'invalid domain' } });
fireEvent.change(internalIpInput, { target: { value: 'invalid internal ip' } });
fireEvent.change(appsRepoUrlInput, { target: { value: 'invalid url' } });
fireEvent.change(localDomainInput, { target: { value: 'invalid local domain' } });
fireEvent.click(submitButton);
// assert
await waitFor(() => {
expect(screen.getAllByText('Invalid IP address')).toHaveLength(2);
});
expect(screen.getByText('Invalid domain')).toBeInTheDocument();
expect(screen.getAllByText('Invalid domain')).toHaveLength(2);
expect(screen.getByText('Invalid URL')).toBeInTheDocument();
});
@ -90,4 +94,19 @@ describe('Test: SettingsForm', () => {
expect(onSubmit).toHaveBeenCalledTimes(1);
});
});
it('should download the certificate when the download button is clicked', async () => {
// arrange
const spy = jest.spyOn(window, 'open').mockImplementation();
render(<SettingsForm onSubmit={jest.fn} />);
const downloadButton = screen.getByRole('button', { name: 'Download certificate' });
// act
fireEvent.click(downloadButton);
// assert
await waitFor(() => {
expect(spy).toHaveBeenCalledTimes(1);
});
});
});

View file

@ -183,9 +183,8 @@ export const SettingsForm = (props: IProps) => {
error={errors.localDomain?.message}
placeholder="tipi.lan"
/>
<Button className="mt-2" onClick={downloadCertificate}>
Download certificate
{t('download-certificate')}
</Button>
</div>
<Button loading={loading} type="submit" className="btn-success">

View file

@ -65,7 +65,7 @@ nextApp.prepare().then(async () => {
EventDispatcher.clear();
// Run database migrations
if (getConfig().NODE_ENV === 'development') {
if (getConfig().NODE_ENV !== 'development') {
await runPostgresMigrations();
}
setConfig('status', 'RUNNING');