Skip to content

Commit e2d3966

Browse files
authored
HMS-5813: QE: migrate Template CRUD test (#495)
* Add template delete helper * HMS-5813: migrate Template CRUD test * Change to centirepos no number in URL * Add createCustomRepo helper * Use github repo path
1 parent 31fe664 commit e2d3966

8 files changed

+194
-15
lines changed

_playwright-tests/UI/CustomRepoCRUD.spec.ts

+4-9
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,12 @@ import { test, expect } from '@playwright/test';
22
import { navigateToRepositories } from './helpers/navHelpers';
33
import { deleteAllRepos } from './helpers/deleteRepositories';
44
import { closePopupsIfExist, getRowByNameOrUrl } from './helpers/helpers';
5+
import { randomName, randomUrl } from './helpers/repoHelpers';
56

6-
export const repoNamePrefix = 'Repo-CRUD';
7-
export const randomName = () => (Math.random() + 1).toString(36).substring(2, 6);
8-
export const repoName = `${repoNamePrefix}-${randomName()}`;
9-
export const rank = () => Math.floor(Math.random() * 10 + 1).toString();
10-
export const randomNum = () =>
11-
Math.floor(Math.random() * 10 + 1)
12-
.toString()
13-
.padStart(2, '0');
7+
const repoNamePrefix = 'Repo-CRUD';
8+
const repoName = `${repoNamePrefix}-${randomName()}`;
149

15-
export const url = `https://stephenw.fedorapeople.org/multirepos/${rank()}/repo${randomNum()}/`;
10+
const url = randomUrl();
1611

1712
test.describe('Custom Repositories CRUD', () => {
1813
test('Add, Read, update, delete a repo', async ({ page }) => {

_playwright-tests/UI/CustomRepoPagination.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ test.describe('Custom repositories pagination', () => {
1212
await deleteAllRepos(page, `&search=${repoNamePrefix}`);
1313
});
1414
await test.step('Populate the custom repo table', async () => {
15-
await bulkCreateRepos(page, 12);
15+
await bulkCreateRepos(page, 12, repoNamePrefix);
1616
await navigateToRepositories(page);
1717
await closePopupsIfExist(page);
1818
await page.getByPlaceholder(/^Filter by name.*$/).fill(repoNamePrefix);
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { test, expect } from '@playwright/test';
2+
import { navigateToRepositories, navigateToTemplates } from './helpers/navHelpers';
3+
import { closePopupsIfExist, getRowByNameOrUrl } from './helpers/helpers';
4+
import { deleteAllTemplates } from './helpers/deleteTemplates';
5+
import { deleteAllRepos } from './helpers/deleteRepositories';
6+
import { createCustomRepo } from './helpers/createRepositories';
7+
8+
import { randomName } from './helpers/repoHelpers';
9+
10+
const templateNamePrefix = 'template_CRUD';
11+
const repoNamePrefix = 'custom_repo-template';
12+
13+
const repoName = `${repoNamePrefix}-${randomName()}`;
14+
const templateName = `${templateNamePrefix}-${randomName()}`;
15+
16+
const smallRHRepo = 'Red Hat CodeReady Linux Builder for RHEL 9 ARM 64 (RPMs)';
17+
18+
test.describe('Templates CRUD', () => {
19+
test('Add, Read, update, delete a template', async ({ page }) => {
20+
await test.step('Delete any templates and template test repos that exist', async () => {
21+
await deleteAllRepos(page, `&search=${repoNamePrefix}`);
22+
await deleteAllTemplates(page, `&search=${templateNamePrefix}`);
23+
await navigateToRepositories(page);
24+
await closePopupsIfExist(page);
25+
});
26+
await test.step('Create a repository', async () => {
27+
await createCustomRepo(page, repoName);
28+
const row = await getRowByNameOrUrl(page, repoName);
29+
await expect(row.getByText('Valid')).toBeVisible();
30+
});
31+
await test.step('Navigate to templates, ensure the Add content template button can be clicked', async () => {
32+
await navigateToTemplates(page);
33+
await expect(page.getByRole('button', { name: 'Add content template' })).toBeVisible();
34+
});
35+
await test.step('Create a template', async () => {
36+
await page.getByRole('button', { name: 'Add content template' }).click();
37+
await page.getByRole('button', { name: 'Select architecture' }).click();
38+
await page.getByRole('option', { name: 'aarch64' }).click();
39+
await page.getByRole('button', { name: 'Select version' }).click();
40+
await page.getByRole('option', { name: 'el9' }).click();
41+
await page.getByRole('button', { name: 'Next', exact: true }).click();
42+
const modalPage = page.getByTestId('add_template_modal');
43+
const rowRHELRepo = await getRowByNameOrUrl(modalPage, smallRHRepo);
44+
await rowRHELRepo.getByLabel('Select row 0', { exact: true }).click();
45+
await page.getByRole('button', { name: 'Next', exact: true }).click();
46+
await modalPage.getByRole('textbox', { name: 'Filter by name/url' }).fill(repoName);
47+
const rowRepo = await getRowByNameOrUrl(modalPage, repoName);
48+
await rowRepo.getByLabel('Select row 0', { exact: true }).click();
49+
await page.getByRole('button', { name: 'Next', exact: true }).click();
50+
await page.getByText('Use latest content', { exact: true }).click();
51+
await page.getByRole('button', { name: 'Next', exact: true }).click();
52+
await page.getByText('add template modal', { exact: true });
53+
await page.getByPlaceholder('Enter name').fill(`${templateName}`);
54+
await page.getByPlaceholder('Description').fill('Template test');
55+
await page.getByRole('button', { name: 'Next', exact: true }).click();
56+
await page.getByRole('button', { name: 'Create other options' }).click();
57+
await page.getByText('Create template only', { exact: true }).click();
58+
});
59+
await test.step('Read and update values in the template', async () => {
60+
const rowTemplate = await getRowByNameOrUrl(page, templateName);
61+
await rowTemplate.getByRole('button', { name: templateName }).click();
62+
await expect(page.getByLabel('Breadcrumb').first()).toHaveText('RHELContentTemplates');
63+
await expect(page.getByRole('heading', { level: 1 })).toHaveText(templateName);
64+
await expect(page.getByText('Description:Template test')).toBeVisible();
65+
await page.getByRole('button', { name: 'Actions' }).click();
66+
await page.getByRole('menuitem', { name: 'Edit' }).click();
67+
await expect(
68+
page.getByRole('heading', { name: 'Define template content', exact: true }),
69+
).toBeVisible();
70+
await page.getByRole('button', { name: 'Next', exact: true }).click();
71+
await expect(
72+
page.getByRole('heading', { name: 'Additional Red Hat repositories', exact: true }),
73+
).toBeVisible();
74+
await page.getByRole('button', { name: 'Next', exact: true }).click();
75+
await expect(
76+
page.getByRole('heading', { name: 'Custom repositories', exact: true }),
77+
).toBeVisible();
78+
await expect(page.getByText(`${repoName}`)).toBeVisible();
79+
await page.getByRole('button', { name: 'Next', exact: true }).click();
80+
await expect(page.getByRole('heading', { name: 'Set up date', exact: true })).toBeVisible();
81+
await page.getByRole('button', { name: 'Next', exact: true }).click();
82+
await expect(page.getByText('Enter template details')).toBeVisible();
83+
await expect(page.getByPlaceholder('Enter name')).toHaveValue(`${templateName}`);
84+
await expect(page.getByPlaceholder('Description')).toHaveValue('Template test');
85+
await page.getByPlaceholder('Enter name').fill(`${templateName}-edited`);
86+
await page.getByPlaceholder('Description').fill('Template test edited');
87+
await page.getByRole('button', { name: 'Next', exact: true }).click();
88+
await page.getByRole('button', { name: 'Confirm changes', exact: true }).click();
89+
});
90+
await test.step('Delete the template', async () => {
91+
const rowTemplate = await getRowByNameOrUrl(page, `${templateName}-edited`);
92+
await expect(rowTemplate.getByText('Valid')).toBeVisible({ timeout: 60000 });
93+
await rowTemplate.getByLabel('Kebab toggle').click();
94+
await rowTemplate.getByRole('menuitem', { name: 'Delete' }).click();
95+
await expect(page.getByText('Remove template?')).toBeVisible();
96+
await page.getByRole('button', { name: 'Remove' }).click();
97+
await expect(rowTemplate.getByText('Valid')).not.toBeVisible();
98+
await deleteAllTemplates(page, `&search=${templateNamePrefix}`);
99+
});
100+
});
101+
});

_playwright-tests/UI/helpers/createRepositories.ts

+45-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { expect, type Page } from '@playwright/test';
2+
import { randomUrl } from './repoHelpers';
23

3-
export const bulkCreateRepos = async ({ request }: Page, repoCount: number) => {
4+
export const bulkCreateRepos = async (
5+
{ request }: Page,
6+
repoCount: number,
7+
repoNamePrefix: string,
8+
) => {
49
const list: Record<string, string | boolean | number>[] = [];
510
for (let count = 1; count <= repoCount; count++) {
6-
const rank = () => Math.floor(Math.random() * 100 + 1).toString();
711
const repoNum = `${count.toString().padStart(2, '0')}`;
812
const randomURL = () =>
9-
`https://stephenw.fedorapeople.org/multirepos/${rank()}/repo${repoNum}/`;
13+
`https://content-services.github.io/fixtures/yum/centirepos/repo${repoNum}/`;
1014
list.push({
11-
name: `custom_repo-pagination-${repoNum}`,
15+
name: `${repoNamePrefix}-${repoNum}`,
1216
url: randomURL(),
1317
snapshot: false,
1418
});
@@ -21,3 +25,40 @@ export const bulkCreateRepos = async ({ request }: Page, repoCount: number) => {
2125
// Ensure the request was successful
2226
expect(response.status()).toBe(201);
2327
};
28+
29+
export const createCustomRepo = async ({ request }: Page, repoName: string) => {
30+
const repoData = {
31+
distribution_arch: 'aarch64',
32+
distribution_versions: ['8', '9'],
33+
name: repoName,
34+
origin: 'external',
35+
snapshot: true,
36+
url: randomUrl(), // Ensure randomUrl() returns a valid string
37+
};
38+
39+
try {
40+
const response = await request.post('/api/content-sources/v1/repositories/', {
41+
data: repoData, // Will be automatically stringified by Playwright
42+
headers: { 'Content-Type': 'application/json' }, // Optional if data is an object
43+
});
44+
45+
// Check if response is successful
46+
if (!response.ok()) {
47+
throw new Error(`Request failed with status ${response.status()}`);
48+
}
49+
50+
// Parse response body
51+
const data = await response.json();
52+
53+
// Extract and return UUID (assuming it's in data.uuid)
54+
const uuid = data?.uuid;
55+
if (!uuid) {
56+
throw new Error('UUID not found in response');
57+
}
58+
59+
return uuid;
60+
} catch (error) {
61+
console.error('Error creating custom repo:', error);
62+
throw error;
63+
}
64+
};

_playwright-tests/UI/helpers/deleteRepositories.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const deleteAllRepos = async ({ request }: Page, filter?: string) => {
3030
expect(result.status()).toBe(204);
3131
} catch (error) {
3232
console.error('Failed to delete repositories:', error);
33-
throw error; // Optionally re-throw the error if you need to fail the test
33+
throw error;
3434
}
3535
}
3636
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { expect, type Page } from '@playwright/test';
2+
3+
export const deleteAllTemplates = async ({ request }: Page, filter?: string) => {
4+
const response = await request.get(`/api/content-sources/v1/templates/?${filter}`);
5+
6+
// Ensure the request was successful
7+
expect(response.status()).toBe(200);
8+
9+
// Parse the response body
10+
const body = await response.json();
11+
12+
// Check that the response body contains an array of data
13+
expect(Array.isArray(body.data)).toBeTruthy();
14+
15+
// Extract UUIDs from the response data
16+
const uuidList = body.data.map((data: { uuid: string }) => data.uuid) as string[];
17+
18+
// If there are UUIDs to delete, make the delete request
19+
if (uuidList.length > 0)
20+
for (const value of uuidList) {
21+
try {
22+
const result = await request.delete(`/api/content-sources/v1/templates/${value}`);
23+
24+
// Ensure the deletion was successful
25+
expect(result.status()).toBe(204);
26+
} catch (error) {
27+
console.error('Failed to delete template:', error);
28+
throw error;
29+
}
30+
}
31+
};

_playwright-tests/UI/helpers/helpers.ts

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import customParseFormat from 'dayjs/plugin/customParseFormat';
44

55
export const snapshotTimestampFormat = 'DD MMM YYYY - HH:mm:ss';
66

7+
export const randomName = () => (Math.random() + 1).toString(36).substring(2, 6);
8+
79
export const closePopupsIfExist = async (page: Page) => {
810
const locatorsToCheck = [
911
page.locator('.pf-v5-c-alert.notification-item button'), // This closes all toast pop-ups
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const randomName = () => (Math.random() + 1).toString(36).substring(2, 6);
2+
3+
export const randomNum = () =>
4+
Math.floor(Math.random() * 100 + 1)
5+
.toString()
6+
.padStart(2, '0');
7+
8+
export const randomUrl = () =>
9+
`https://content-services.github.io/fixtures/yum/centirepos/repo${randomNum()}/`;

0 commit comments

Comments
 (0)