🚀(app-impress) create the e2e app impress
Create the e2e app impress, it will be used to test the app impress.
This commit is contained in:
9
src/frontend/apps/e2e/.eslintrc.js
Normal file
9
src/frontend/apps/e2e/.eslintrc.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: ["impress/playwright"],
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ["./tsconfig.json"],
|
||||||
|
},
|
||||||
|
ignorePatterns: ["node_modules"],
|
||||||
|
};
|
||||||
5
src/frontend/apps/e2e/.gitignore
vendored
Normal file
5
src/frontend/apps/e2e/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# e2e
|
||||||
|
test-results/
|
||||||
|
report/
|
||||||
|
blob-report/
|
||||||
|
playwright/.cache/
|
||||||
29
src/frontend/apps/e2e/__tests__/app-desk/404.spec.ts
Normal file
29
src/frontend/apps/e2e/__tests__/app-desk/404.spec.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
await page.goto('unknown-page404');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('404', () => {
|
||||||
|
test('Checks all the elements are visible', async ({ page }) => {
|
||||||
|
await expect(page.getByLabel('Image 404')).toBeVisible();
|
||||||
|
await expect(page.getByText('Ouch')).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByText(
|
||||||
|
'It seems that the page you are looking for does not exist or cannot be displayed correctly.',
|
||||||
|
),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(page.getByText('Back to home page')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checks go back to home page redirects to home page', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await page.getByText('Back to home page').click();
|
||||||
|
await expect(page).toHaveURL('/');
|
||||||
|
});
|
||||||
|
});
|
||||||
89
src/frontend/apps/e2e/__tests__/app-desk/common.ts
Normal file
89
src/frontend/apps/e2e/__tests__/app-desk/common.ts
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import { Page, expect } from '@playwright/test';
|
||||||
|
|
||||||
|
export const keyCloakSignIn = async (page: Page, browserName: string) => {
|
||||||
|
const title = await page.locator('h1').first().textContent({
|
||||||
|
timeout: 5000,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (title?.includes('Sign in to your account')) {
|
||||||
|
await page
|
||||||
|
.getByRole('textbox', { name: 'username' })
|
||||||
|
.fill(`user-e2e-${browserName}`);
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('textbox', { name: 'password' })
|
||||||
|
.fill(`password-e2e-${browserName}`);
|
||||||
|
|
||||||
|
await page.click('input[type="submit"]', { force: true });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const randomName = (name: string, browserName: string, length: number) =>
|
||||||
|
Array.from({ length }, (_el, index) => {
|
||||||
|
return `${browserName}-${Math.floor(Math.random() * 10000)}-${index}-${name}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createTeam = async (
|
||||||
|
page: Page,
|
||||||
|
teamName: string,
|
||||||
|
browserName: string,
|
||||||
|
length: number,
|
||||||
|
) => {
|
||||||
|
const panel = page.getByLabel('Teams panel').first();
|
||||||
|
const buttonCreate = page.getByRole('button', { name: 'Create the team' });
|
||||||
|
|
||||||
|
const randomTeams = randomName(teamName, browserName, length);
|
||||||
|
|
||||||
|
for (let i = 0; i < randomTeams.length; i++) {
|
||||||
|
await panel.getByRole('button', { name: 'Add a team' }).click();
|
||||||
|
await page.getByText('Team name').fill(randomTeams[i]);
|
||||||
|
await expect(buttonCreate).toBeEnabled();
|
||||||
|
await buttonCreate.click();
|
||||||
|
await expect(
|
||||||
|
panel.locator('li').nth(0).getByText(randomTeams[i]),
|
||||||
|
).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomTeams;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addNewMember = async (
|
||||||
|
page: Page,
|
||||||
|
index: number,
|
||||||
|
role: 'Admin' | 'Owner' | 'Member',
|
||||||
|
fillText: string = 'test',
|
||||||
|
) => {
|
||||||
|
const responsePromiseSearchUser = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes(`/users/?q=${fillText}`) &&
|
||||||
|
response.status() === 200,
|
||||||
|
);
|
||||||
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
const inputSearch = page.getByLabel(/Find a member to add to the team/);
|
||||||
|
|
||||||
|
// Select a new user
|
||||||
|
await inputSearch.fill(fillText);
|
||||||
|
|
||||||
|
// Intercept response
|
||||||
|
const responseSearchUser = await responsePromiseSearchUser;
|
||||||
|
const users = (await responseSearchUser.json()).results as {
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
|
||||||
|
// Choose user
|
||||||
|
await page.getByRole('option', { name: users[index].name }).click();
|
||||||
|
|
||||||
|
// Choose a role
|
||||||
|
await page.getByRole('radio', { name: role }).click();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
|
||||||
|
await expect(table.getByText(users[index].name)).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByText(`Member ${users[index].name} added to the team`),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
return users[index].name;
|
||||||
|
};
|
||||||
43
src/frontend/apps/e2e/__tests__/app-desk/header.spec.ts
Normal file
43
src/frontend/apps/e2e/__tests__/app-desk/header.spec.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Header', () => {
|
||||||
|
test('checks all the elements are visible', async ({ page }) => {
|
||||||
|
const header = page.locator('header').first();
|
||||||
|
|
||||||
|
await expect(header.getByAltText('Marianne Logo')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
header.getByAltText('Freedom Equality Fraternity Logo'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(header.getByAltText('Impress Logo')).toBeVisible();
|
||||||
|
await expect(header.locator('h2').getByText('Impress')).toHaveCSS(
|
||||||
|
'color',
|
||||||
|
'rgb(0, 0, 145)',
|
||||||
|
);
|
||||||
|
await expect(header.locator('h2').getByText('Impress')).toHaveCSS(
|
||||||
|
'font-family',
|
||||||
|
/Marianne/i,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
header.getByText('Les applications de La Suite numérique'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(header.getByAltText('Language Icon')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(header.getByText('John Doe')).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
header.getByRole('img', {
|
||||||
|
name: 'profile picture',
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
29
src/frontend/apps/e2e/__tests__/app-desk/language.spec.ts
Normal file
29
src/frontend/apps/e2e/__tests__/app-desk/language.spec.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Language', () => {
|
||||||
|
test('checks the language picker', async ({ page }) => {
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', {
|
||||||
|
name: 'Create a new team',
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
const header = page.locator('header').first();
|
||||||
|
await header.getByRole('combobox').getByText('EN').click();
|
||||||
|
await header.getByRole('option', { name: 'FR' }).click();
|
||||||
|
await expect(header.getByRole('combobox').getByText('FR')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', {
|
||||||
|
name: 'Créer un nouveau groupe',
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
218
src/frontend/apps/e2e/__tests__/app-desk/member-create.spec.ts
Normal file
218
src/frontend/apps/e2e/__tests__/app-desk/member-create.spec.ts
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { createTeam, keyCloakSignIn, randomName } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Members Create', () => {
|
||||||
|
test('it opens the modals to add a member to the team', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'member-open-modal', browserName, 1);
|
||||||
|
|
||||||
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
|
||||||
|
await expect(page.getByText('Add a member')).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByLabel(/Find a member to add to the team/),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByRole('button', { name: 'Validate' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('button', { name: 'Cancel' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it selects 2 users and 1 invitation', async ({ page, browserName }) => {
|
||||||
|
const responsePromise = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/users/?q=test') && response.status() === 200,
|
||||||
|
);
|
||||||
|
await createTeam(page, 'member-modal-search-user', browserName, 1);
|
||||||
|
|
||||||
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
|
||||||
|
await expect(page.getByRole('radio', { name: 'Owner' })).toBeHidden();
|
||||||
|
|
||||||
|
const inputSearch = page.getByLabel(/Find a member to add to the team/);
|
||||||
|
|
||||||
|
// Select user 1
|
||||||
|
await inputSearch.fill('test');
|
||||||
|
|
||||||
|
const response = await responsePromise;
|
||||||
|
const users = (await response.json()).results as {
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
|
||||||
|
await page.getByRole('option', { name: users[0].name }).click();
|
||||||
|
|
||||||
|
// Select user 2
|
||||||
|
await inputSearch.fill('test1');
|
||||||
|
await page.getByRole('option', { name: users[1].name }).click();
|
||||||
|
|
||||||
|
// Select email
|
||||||
|
const email = randomName('test@test.fr', browserName, 1)[0];
|
||||||
|
await inputSearch.fill(email);
|
||||||
|
await page.getByRole('option', { name: email }).click();
|
||||||
|
|
||||||
|
// Check user 1 tag
|
||||||
|
await expect(
|
||||||
|
page.getByText(`${users[0].name}`, { exact: true }),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(page.getByLabel(`Remove ${users[0].name}`)).toBeVisible();
|
||||||
|
|
||||||
|
// Check user 2 tag
|
||||||
|
await expect(
|
||||||
|
page.getByText(`${users[1].name}`, { exact: true }),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(page.getByLabel(`Remove ${users[1].name}`)).toBeVisible();
|
||||||
|
|
||||||
|
// Check invitation tag
|
||||||
|
await expect(page.getByText(email, { exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByLabel(`Remove ${email}`)).toBeVisible();
|
||||||
|
|
||||||
|
// Check roles are displayed
|
||||||
|
await expect(page.getByText(/Choose a role/)).toBeVisible();
|
||||||
|
await expect(page.getByRole('radio', { name: 'Member' })).toBeChecked();
|
||||||
|
await expect(page.getByRole('radio', { name: 'Owner' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('radio', { name: 'Admin' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it sends a new invitation and adds a new member', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
const responsePromiseSearchUser = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/users/?q=test') && response.status() === 200,
|
||||||
|
);
|
||||||
|
|
||||||
|
await createTeam(page, 'member-invitation', browserName, 1);
|
||||||
|
|
||||||
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
|
||||||
|
// Select a new email
|
||||||
|
const inputSearch = page.getByLabel(/Find a member to add to the team/);
|
||||||
|
|
||||||
|
const email = randomName('test@test.fr', browserName, 1)[0];
|
||||||
|
await inputSearch.fill(email);
|
||||||
|
await page.getByRole('option', { name: email }).click();
|
||||||
|
|
||||||
|
// Select a new user
|
||||||
|
await inputSearch.fill('test');
|
||||||
|
const responseSearchUser = await responsePromiseSearchUser;
|
||||||
|
const users = (await responseSearchUser.json()).results as {
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
await page.getByRole('option', { name: users[0].name }).click();
|
||||||
|
|
||||||
|
// Choose a role
|
||||||
|
await page.getByRole('radio', { name: 'Admin' }).click();
|
||||||
|
|
||||||
|
const responsePromiseCreateInvitation = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/invitations/') && response.status() === 201,
|
||||||
|
);
|
||||||
|
const responsePromiseAddMember = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/accesses/') && response.status() === 201,
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
|
||||||
|
// Check invitation sent
|
||||||
|
await expect(page.getByText(`Invitation sent to ${email}`)).toBeVisible();
|
||||||
|
const responseCreateInvitation = await responsePromiseCreateInvitation;
|
||||||
|
expect(responseCreateInvitation.ok()).toBeTruthy();
|
||||||
|
|
||||||
|
// Check member added
|
||||||
|
await expect(
|
||||||
|
page.getByText(`Member ${users[0].name} added to the team`),
|
||||||
|
).toBeVisible();
|
||||||
|
const responseAddMember = await responsePromiseAddMember;
|
||||||
|
expect(responseAddMember.ok()).toBeTruthy();
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
await expect(table.getByText(users[0].name)).toBeVisible();
|
||||||
|
await expect(table.getByText('Admin')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it try to add twice the same user', async ({ page, browserName }) => {
|
||||||
|
const responsePromiseSearchUser = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/users/?q=test') && response.status() === 200,
|
||||||
|
);
|
||||||
|
|
||||||
|
await createTeam(page, 'member-twice', browserName, 1);
|
||||||
|
|
||||||
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
|
||||||
|
const inputSearch = page.getByLabel(/Find a member to add to the team/);
|
||||||
|
await inputSearch.fill('test');
|
||||||
|
const responseSearchUser = await responsePromiseSearchUser;
|
||||||
|
const users = (await responseSearchUser.json()).results as {
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
await page.getByRole('option', { name: users[0].name }).click();
|
||||||
|
|
||||||
|
// Choose a role
|
||||||
|
await page.getByRole('radio', { name: 'Owner' }).click();
|
||||||
|
|
||||||
|
const responsePromiseAddMember = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/accesses/') && response.status() === 201,
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText(`Member ${users[0].name} added to the team`),
|
||||||
|
).toBeVisible();
|
||||||
|
const responseAddMember = await responsePromiseAddMember;
|
||||||
|
expect(responseAddMember.ok()).toBeTruthy();
|
||||||
|
|
||||||
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
|
||||||
|
await inputSearch.fill('test');
|
||||||
|
await expect(
|
||||||
|
page.getByRole('option', { name: users[0].name }),
|
||||||
|
).toBeHidden();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it try to add twice the same invitation', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'invitation-twice', browserName, 1);
|
||||||
|
|
||||||
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
|
||||||
|
const inputSearch = page.getByLabel(/Find a member to add to the team/);
|
||||||
|
|
||||||
|
const email = randomName('test@test.fr', browserName, 1)[0];
|
||||||
|
await inputSearch.fill(email);
|
||||||
|
await page.getByRole('option', { name: email }).click();
|
||||||
|
|
||||||
|
// Choose a role
|
||||||
|
await page.getByRole('radio', { name: 'Owner' }).click();
|
||||||
|
|
||||||
|
const responsePromiseCreateInvitation = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/invitations/') && response.status() === 201,
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
|
||||||
|
// Check invitation sent
|
||||||
|
await expect(page.getByText(`Invitation sent to ${email}`)).toBeVisible();
|
||||||
|
const responseCreateInvitation = await responsePromiseCreateInvitation;
|
||||||
|
expect(responseCreateInvitation.ok()).toBeTruthy();
|
||||||
|
|
||||||
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
|
||||||
|
await inputSearch.fill(email);
|
||||||
|
await expect(page.getByRole('option', { name: email })).toBeHidden();
|
||||||
|
});
|
||||||
|
});
|
||||||
170
src/frontend/apps/e2e/__tests__/app-desk/member-delete.spec.ts
Normal file
170
src/frontend/apps/e2e/__tests__/app-desk/member-delete.spec.ts
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { addNewMember, createTeam, keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Members Delete', () => {
|
||||||
|
test('it cannot delete himself when it is the last owner', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'member-delete-1', browserName, 1);
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
|
||||||
|
const cells = table.getByRole('row').nth(1).getByRole('cell');
|
||||||
|
await expect(cells.nth(1)).toHaveText(
|
||||||
|
new RegExp(`E2E ${browserName}`, 'i'),
|
||||||
|
);
|
||||||
|
await cells.nth(4).getByLabel('Member options').click();
|
||||||
|
await page.getByLabel('Open the modal to delete this member').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText(
|
||||||
|
'You are the last owner, you cannot be removed from your team.',
|
||||||
|
),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(page.getByRole('button', { name: 'Validate' })).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it deletes himself when it is not the last owner', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'member-delete-2', browserName, 1);
|
||||||
|
|
||||||
|
await addNewMember(page, 0, 'Owner');
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
|
||||||
|
// find row where regexp match the name
|
||||||
|
const cells = table
|
||||||
|
.getByRole('row')
|
||||||
|
.filter({ hasText: new RegExp(`E2E ${browserName}`, 'i') })
|
||||||
|
.getByRole('cell');
|
||||||
|
await cells.nth(4).getByLabel('Member options').click();
|
||||||
|
await page.getByLabel('Open the modal to delete this member').click();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
await expect(
|
||||||
|
page.getByText(`The member has been removed from the team`),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: `Create a new team` }),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it cannot delete owner member', async ({ page, browserName }) => {
|
||||||
|
await createTeam(page, 'member-delete-3', browserName, 1);
|
||||||
|
|
||||||
|
const username = await addNewMember(page, 0, 'Owner');
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
|
||||||
|
// find row where regexp match the name
|
||||||
|
const cells = table
|
||||||
|
.getByRole('row')
|
||||||
|
.filter({ hasText: username })
|
||||||
|
.getByRole('cell');
|
||||||
|
await cells.nth(4).getByLabel('Member options').click();
|
||||||
|
await page.getByLabel('Open the modal to delete this member').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText(`You cannot remove other owner.`),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(page.getByRole('button', { name: 'Validate' })).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it deletes admin member', async ({ page, browserName }) => {
|
||||||
|
await createTeam(page, 'member-delete-4', browserName, 1);
|
||||||
|
|
||||||
|
const username = await addNewMember(page, 0, 'Admin');
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
|
||||||
|
// find row where regexp match the name
|
||||||
|
const cells = table
|
||||||
|
.getByRole('row')
|
||||||
|
.filter({ hasText: username })
|
||||||
|
.getByRole('cell');
|
||||||
|
await cells.nth(4).getByLabel('Member options').click();
|
||||||
|
await page.getByLabel('Open the modal to delete this member').click();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
await expect(
|
||||||
|
page.getByText(`The member has been removed from the team`),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(table.getByText(username)).toBeHidden();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it cannot delete owner member when admin', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'member-delete-5', browserName, 1);
|
||||||
|
|
||||||
|
const username = await addNewMember(page, 0, 'Owner');
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
|
||||||
|
// find row where regexp match the name
|
||||||
|
const myCells = table
|
||||||
|
.getByRole('row')
|
||||||
|
.filter({ hasText: new RegExp(`E2E ${browserName}`, 'i') })
|
||||||
|
.getByRole('cell');
|
||||||
|
await myCells.nth(4).getByLabel('Member options').click();
|
||||||
|
|
||||||
|
// Change role to Admin
|
||||||
|
await page.getByText('Update the role').click();
|
||||||
|
const radioGroup = page.getByLabel('Radio buttons to update the roles');
|
||||||
|
await radioGroup.getByRole('radio', { name: 'Admin' }).click();
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
|
||||||
|
const cells = table
|
||||||
|
.getByRole('row')
|
||||||
|
.filter({ hasText: username })
|
||||||
|
.getByRole('cell');
|
||||||
|
await expect(cells.getByLabel('Member options')).toBeHidden();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it deletes admin member when admin', async ({ page, browserName }) => {
|
||||||
|
await createTeam(page, 'member-delete-6', browserName, 1);
|
||||||
|
|
||||||
|
// To not be the only owner
|
||||||
|
await addNewMember(page, 0, 'Owner');
|
||||||
|
|
||||||
|
const username = await addNewMember(page, 1, 'Admin', 'something');
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
|
||||||
|
// find row where regexp match the name
|
||||||
|
const myCells = table
|
||||||
|
.getByRole('row')
|
||||||
|
.filter({ hasText: new RegExp(`E2E ${browserName}`, 'i') })
|
||||||
|
.getByRole('cell');
|
||||||
|
await myCells.nth(4).getByLabel('Member options').click();
|
||||||
|
|
||||||
|
// Change role to Admin
|
||||||
|
await page.getByText('Update the role').click();
|
||||||
|
const radioGroup = page.getByLabel('Radio buttons to update the roles');
|
||||||
|
await radioGroup.getByRole('radio', { name: 'Admin' }).click();
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
|
||||||
|
const cells = table
|
||||||
|
.getByRole('row')
|
||||||
|
.filter({ hasText: username })
|
||||||
|
.getByRole('cell');
|
||||||
|
await cells.nth(4).getByLabel('Member options').click();
|
||||||
|
await page.getByLabel('Open the modal to delete this member').click();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
await expect(
|
||||||
|
page.getByText(`The member has been removed from the team`),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(table.getByText(username)).toBeHidden();
|
||||||
|
});
|
||||||
|
});
|
||||||
65
src/frontend/apps/e2e/__tests__/app-desk/member-grid.spec.ts
Normal file
65
src/frontend/apps/e2e/__tests__/app-desk/member-grid.spec.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { createTeam, keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Member Grid', () => {
|
||||||
|
test('checks the owner member is displayed correctly', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'team-owner', browserName, 1);
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
|
||||||
|
const thead = table.locator('thead');
|
||||||
|
await expect(thead.getByText(/Names/i)).toBeVisible();
|
||||||
|
await expect(thead.getByText(/Emails/i)).toBeVisible();
|
||||||
|
await expect(thead.getByText(/Roles/i)).toBeVisible();
|
||||||
|
|
||||||
|
const cells = table.getByRole('row').nth(1).getByRole('cell');
|
||||||
|
await expect(cells.nth(0).getByLabel('Member icon')).toBeVisible();
|
||||||
|
await expect(cells.nth(1)).toHaveText(
|
||||||
|
new RegExp(`E2E ${browserName}`, 'i'),
|
||||||
|
);
|
||||||
|
await expect(cells.nth(2)).toHaveText(`user@${browserName}.e2e`);
|
||||||
|
await expect(cells.nth(3)).toHaveText(/Owner/i);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('try to update the owner role but cannot because it is the last owner', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'team-owner-role', browserName, 1);
|
||||||
|
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
|
||||||
|
const cells = table.getByRole('row').nth(1).getByRole('cell');
|
||||||
|
await expect(cells.nth(1)).toHaveText(
|
||||||
|
new RegExp(`E2E ${browserName}`, 'i'),
|
||||||
|
);
|
||||||
|
await cells.nth(4).getByLabel('Member options').click();
|
||||||
|
await page.getByText('Update the role').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('You are the last owner, you cannot change your role.'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
const radioGroup = page.getByLabel('Radio buttons to update the roles');
|
||||||
|
|
||||||
|
const radios = await radioGroup.getByRole('radio').all();
|
||||||
|
for (const radio of radios) {
|
||||||
|
await expect(radio).toBeDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', {
|
||||||
|
name: 'Validate',
|
||||||
|
}),
|
||||||
|
).toBeDisabled();
|
||||||
|
});
|
||||||
|
});
|
||||||
81
src/frontend/apps/e2e/__tests__/app-desk/menu.spec.ts
Normal file
81
src/frontend/apps/e2e/__tests__/app-desk/menu.spec.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Menu', () => {
|
||||||
|
const menuItems = [
|
||||||
|
{ name: 'Search', isDefault: true },
|
||||||
|
{ name: 'Favorite', isDefault: false },
|
||||||
|
{ name: 'Recent', isDefault: false },
|
||||||
|
{ name: 'Contacts', isDefault: false },
|
||||||
|
{ name: 'Groups', isDefault: false },
|
||||||
|
];
|
||||||
|
for (const { name, isDefault } of menuItems) {
|
||||||
|
test(`checks that ${name} menu item is displaying correctly`, async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const menu = page.locator('menu').first();
|
||||||
|
|
||||||
|
const buttonMenu = menu.getByLabel(`${name} button`);
|
||||||
|
await expect(buttonMenu).toBeVisible();
|
||||||
|
await buttonMenu.hover();
|
||||||
|
await expect(menu.getByLabel('tooltip')).toHaveText(name);
|
||||||
|
|
||||||
|
// Checks the tooltip is with inactive color
|
||||||
|
await expect(menu.getByLabel('tooltip')).toHaveCSS(
|
||||||
|
'background-color',
|
||||||
|
isDefault ? 'rgb(255, 255, 255)' : 'rgb(22, 22, 22)',
|
||||||
|
);
|
||||||
|
|
||||||
|
await buttonMenu.click();
|
||||||
|
|
||||||
|
// Checks the tooltip has active color
|
||||||
|
await buttonMenu.hover();
|
||||||
|
await expect(menu.getByLabel('tooltip')).toHaveCSS(
|
||||||
|
'background-color',
|
||||||
|
'rgb(255, 255, 255)',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`checks that ${name} menu item is routing correctly`, async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', {
|
||||||
|
name: 'Create a new team',
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
const menu = page.locator('menu').first();
|
||||||
|
|
||||||
|
const buttonMenu = menu.getByLabel(`${name} button`);
|
||||||
|
await buttonMenu.click();
|
||||||
|
|
||||||
|
/* eslint-disable playwright/no-conditional-expect */
|
||||||
|
/* eslint-disable playwright/no-conditional-in-test */
|
||||||
|
if (isDefault) {
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', {
|
||||||
|
name: 'Create a new team',
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
} else {
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', {
|
||||||
|
name: 'Create a new team',
|
||||||
|
}),
|
||||||
|
).toBeHidden();
|
||||||
|
|
||||||
|
const reg = new RegExp(name.toLowerCase());
|
||||||
|
await expect(page).toHaveURL(reg);
|
||||||
|
}
|
||||||
|
/* eslint-enable playwright/no-conditional-expect */
|
||||||
|
/* eslint-enable playwright/no-conditional-in-test */
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
62
src/frontend/apps/e2e/__tests__/app-desk/team.spec.ts
Normal file
62
src/frontend/apps/e2e/__tests__/app-desk/team.spec.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { createTeam, keyCloakSignIn, randomName } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Team', () => {
|
||||||
|
test('checks all the top box elements are visible', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
const teamName = (
|
||||||
|
await createTeam(page, 'team-top-box', browserName, 1)
|
||||||
|
).shift();
|
||||||
|
|
||||||
|
await expect(page.getByLabel('icon group')).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByRole('heading', {
|
||||||
|
name: `Members of “${teamName}“`,
|
||||||
|
level: 3,
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByText(`Add people to the “${teamName}“ group.`),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByText(`1 member`)).toBeVisible();
|
||||||
|
|
||||||
|
const today = new Date(Date.now());
|
||||||
|
const todayFormated = today.toLocaleDateString('en', {
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
});
|
||||||
|
await expect(page.getByText(`Created at ${todayFormated}`)).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByText(`Last update at ${todayFormated}`),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it updates the team name', async ({ page, browserName }) => {
|
||||||
|
await createTeam(page, 'team-update-name', browserName, 1);
|
||||||
|
|
||||||
|
await page.getByLabel(`Open the team options`).click();
|
||||||
|
await page.getByRole('button', { name: `Update the team` }).click();
|
||||||
|
|
||||||
|
const teamName = randomName('new-team-update-name', browserName, 1)[0];
|
||||||
|
await page.getByText('New name...', { exact: true }).fill(teamName);
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('button', { name: 'Validate the modification' })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(page.getByText('The team has been updated.')).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByText(`Add people to the “${teamName}“ group.`),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
127
src/frontend/apps/e2e/__tests__/app-desk/teams-create.spec.ts
Normal file
127
src/frontend/apps/e2e/__tests__/app-desk/teams-create.spec.ts
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Teams Create', () => {
|
||||||
|
test('checks all the create team elements are visible', async ({ page }) => {
|
||||||
|
const buttonCreateHomepage = page.getByRole('button', {
|
||||||
|
name: 'Create a new team',
|
||||||
|
});
|
||||||
|
await buttonCreateHomepage.click();
|
||||||
|
await expect(buttonCreateHomepage).toBeHidden();
|
||||||
|
|
||||||
|
const card = page.getByLabel('Create new team card').first();
|
||||||
|
|
||||||
|
await expect(card.getByLabel('Team name')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(card.getByLabel('icon group')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
card.getByRole('heading', {
|
||||||
|
name: 'Name the team',
|
||||||
|
level: 3,
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
card.getByRole('button', {
|
||||||
|
name: 'Create the team',
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
card.getByRole('button', {
|
||||||
|
name: 'Cancel',
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checks the cancel button interaction', async ({ page }) => {
|
||||||
|
const buttonCreateHomepage = page.getByRole('button', {
|
||||||
|
name: 'Create a new team',
|
||||||
|
});
|
||||||
|
await buttonCreateHomepage.click();
|
||||||
|
await expect(buttonCreateHomepage).toBeHidden();
|
||||||
|
|
||||||
|
const card = page.getByLabel('Create new team card').first();
|
||||||
|
|
||||||
|
await card
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Cancel',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(buttonCreateHomepage).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checks the routing on new team created', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
const panel = page.getByLabel('Teams panel').first();
|
||||||
|
|
||||||
|
await panel.getByRole('button', { name: 'Add a team' }).click();
|
||||||
|
|
||||||
|
const teamName = `My routing team ${browserName}-${Math.floor(Math.random() * 1000)}`;
|
||||||
|
await page.getByText('Team name').fill(teamName);
|
||||||
|
await page.getByRole('button', { name: 'Create the team' }).click();
|
||||||
|
|
||||||
|
const elTeam = page.getByText(`Members of “${teamName}“`);
|
||||||
|
await expect(elTeam).toBeVisible();
|
||||||
|
|
||||||
|
await panel.getByRole('button', { name: 'Add a team' }).click();
|
||||||
|
await expect(elTeam).toBeHidden();
|
||||||
|
|
||||||
|
await panel.locator('li').getByText(teamName).click();
|
||||||
|
await expect(elTeam).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checks alias teams url with homepage', async ({ page }) => {
|
||||||
|
await expect(page).toHaveURL('/');
|
||||||
|
|
||||||
|
const buttonCreateHomepage = page.getByRole('button', {
|
||||||
|
name: 'Create a new team',
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(buttonCreateHomepage).toBeVisible();
|
||||||
|
|
||||||
|
await page.goto('/teams');
|
||||||
|
await expect(buttonCreateHomepage).toBeVisible();
|
||||||
|
await expect(page).toHaveURL(/\/teams$/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checks error when duplicate team', async ({ page, browserName }) => {
|
||||||
|
const panel = page.getByLabel('Teams panel').first();
|
||||||
|
|
||||||
|
await panel.getByRole('button', { name: 'Add a team' }).click();
|
||||||
|
|
||||||
|
const teamName = `My duplicate team ${browserName}-${Math.floor(Math.random() * 1000)}`;
|
||||||
|
await page.getByText('Team name').fill(teamName);
|
||||||
|
await page.getByRole('button', { name: 'Create the team' }).click();
|
||||||
|
|
||||||
|
await panel.getByRole('button', { name: 'Add a team' }).click();
|
||||||
|
|
||||||
|
await page.getByText('Team name').fill(teamName);
|
||||||
|
await page.getByRole('button', { name: 'Create the team' }).click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('Team with this Slug already exists.'),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checks 404 on teams/[id] page', async ({ page }) => {
|
||||||
|
await page.goto('/teams/some-unknown-team');
|
||||||
|
await expect(
|
||||||
|
page.getByText(
|
||||||
|
'It seems that the page you are looking for does not exist or cannot be displayed correctly.',
|
||||||
|
),
|
||||||
|
).toBeVisible({
|
||||||
|
timeout: 15000,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { addNewMember, createTeam, keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Teams Delete', () => {
|
||||||
|
test('it deletes the team when we are owner', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'team-update-name-1', browserName, 1);
|
||||||
|
|
||||||
|
await page.getByLabel(`Open the team options`).click();
|
||||||
|
await page.getByRole('button', { name: `Delete the team` }).click();
|
||||||
|
await page.getByRole('button', { name: `Confirm deletion` }).click();
|
||||||
|
await expect(page.getByText(`The team has been removed.`)).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: `Create a new team` }),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it cannot delete the team when we are admin', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'team-update-name-2', browserName, 1);
|
||||||
|
|
||||||
|
await addNewMember(page, 0, 'Owner');
|
||||||
|
|
||||||
|
// Change role to Admin
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
const myCells = table
|
||||||
|
.getByRole('row')
|
||||||
|
.filter({ hasText: new RegExp(`E2E ${browserName}`, 'i') })
|
||||||
|
.getByRole('cell');
|
||||||
|
await myCells.nth(4).getByLabel('Member options').click();
|
||||||
|
|
||||||
|
await page.getByText('Update the role').click();
|
||||||
|
const radioGroup = page.getByLabel('Radio buttons to update the roles');
|
||||||
|
await radioGroup.getByRole('radio', { name: 'Admin' }).click();
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
|
||||||
|
// Delete the team button should be hidden
|
||||||
|
await page.getByLabel(`Open the team options`).click();
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: `Delete the team` }),
|
||||||
|
).toBeHidden();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it cannot delete the team when we are member', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await createTeam(page, 'team-update-name-3', browserName, 1);
|
||||||
|
|
||||||
|
await addNewMember(page, 0, 'Owner');
|
||||||
|
|
||||||
|
// Change role to Admin
|
||||||
|
const table = page.getByLabel('List members card').getByRole('table');
|
||||||
|
const myCells = table
|
||||||
|
.getByRole('row')
|
||||||
|
.filter({ hasText: new RegExp(`E2E ${browserName}`, 'i') })
|
||||||
|
.getByRole('cell');
|
||||||
|
await myCells.nth(4).getByLabel('Member options').click();
|
||||||
|
|
||||||
|
await page.getByText('Update the role').click();
|
||||||
|
const radioGroup = page.getByLabel('Radio buttons to update the roles');
|
||||||
|
await radioGroup.getByRole('radio', { name: 'Member' }).click();
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
|
||||||
|
// Option button should be hidden
|
||||||
|
await expect(page.getByLabel(`Open the team options`)).toBeHidden();
|
||||||
|
});
|
||||||
|
});
|
||||||
97
src/frontend/apps/e2e/__tests__/app-desk/teams-panel.spec.ts
Normal file
97
src/frontend/apps/e2e/__tests__/app-desk/teams-panel.spec.ts
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { waitForElementCount } from '../helpers';
|
||||||
|
|
||||||
|
import { createTeam, keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, browserName }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Teams Panel', () => {
|
||||||
|
test('checks all the elements are visible', async ({ page }) => {
|
||||||
|
const panel = page.getByLabel('Teams panel').first();
|
||||||
|
|
||||||
|
await expect(panel.getByText('Recents')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
panel.getByRole('button', {
|
||||||
|
name: 'Sort the teams',
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
panel.getByRole('button', {
|
||||||
|
name: 'Add a team',
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checks the sort button', async ({ page }) => {
|
||||||
|
const responsePromiseSortDesc = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/teams/?page=1&ordering=-created_at') &&
|
||||||
|
response.status() === 200,
|
||||||
|
);
|
||||||
|
|
||||||
|
const responsePromiseSortAsc = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/teams/?page=1&ordering=created_at') &&
|
||||||
|
response.status() === 200,
|
||||||
|
);
|
||||||
|
|
||||||
|
const panel = page.getByLabel('Teams panel').first();
|
||||||
|
|
||||||
|
await panel
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Sort the teams by creation date ascendent',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const responseSortAsc = await responsePromiseSortAsc;
|
||||||
|
expect(responseSortAsc.ok()).toBeTruthy();
|
||||||
|
|
||||||
|
await panel
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Sort the teams by creation date descendent',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const responseSortDesc = await responsePromiseSortDesc;
|
||||||
|
expect(responseSortDesc.ok()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checks the infinite scroll', async ({ page, browserName }) => {
|
||||||
|
test.setTimeout(90000);
|
||||||
|
const panel = page.getByLabel('Teams panel').first();
|
||||||
|
|
||||||
|
const randomTeams = await createTeam(
|
||||||
|
page,
|
||||||
|
'team-infinite',
|
||||||
|
browserName,
|
||||||
|
40,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(panel.locator('li')).toHaveCount(20);
|
||||||
|
await panel.getByText(randomTeams[24]).click();
|
||||||
|
|
||||||
|
await waitForElementCount(panel.locator('li'), 21, 10000);
|
||||||
|
expect(await panel.locator('li').count()).toBeGreaterThan(20);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checks the hover and selected state', async ({ page, browserName }) => {
|
||||||
|
const panel = page.getByLabel('Teams panel').first();
|
||||||
|
await createTeam(page, 'team-hover', browserName, 2);
|
||||||
|
|
||||||
|
const selectedTeam = panel.locator('li').nth(0);
|
||||||
|
await expect(selectedTeam).toHaveCSS(
|
||||||
|
'background-color',
|
||||||
|
'rgb(202, 202, 251)',
|
||||||
|
);
|
||||||
|
|
||||||
|
const hoverTeam = panel.locator('li').nth(1);
|
||||||
|
await hoverTeam.hover();
|
||||||
|
await expect(hoverTeam).toHaveCSS('background-color', 'rgb(227, 227, 253)');
|
||||||
|
});
|
||||||
|
});
|
||||||
21
src/frontend/apps/e2e/__tests__/helpers.ts
Normal file
21
src/frontend/apps/e2e/__tests__/helpers.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Locator } from '@playwright/test';
|
||||||
|
|
||||||
|
export async function waitForElementCount(
|
||||||
|
locator: Locator,
|
||||||
|
count: number,
|
||||||
|
timeout: number,
|
||||||
|
) {
|
||||||
|
let elapsedTime = 0;
|
||||||
|
const interval = 200; // Check every 200 ms
|
||||||
|
while (elapsedTime < timeout) {
|
||||||
|
const currentCount = await locator.count();
|
||||||
|
if (currentCount >= count) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
await locator.page().waitForTimeout(interval); // Wait for the interval before checking again
|
||||||
|
elapsedTime += interval;
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
`Timeout after ${timeout}ms waiting for element count to be at least ${count}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
17
src/frontend/apps/e2e/package.json
Normal file
17
src/frontend/apps/e2e/package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "app-e2e",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint . --ext .ts",
|
||||||
|
"install": "playwright install --with-deps",
|
||||||
|
"test": "playwright test",
|
||||||
|
"test:ui": "yarn test --ui"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@playwright/test": "1.42.1",
|
||||||
|
"@types/node": "*",
|
||||||
|
"eslint-config-impress": "*",
|
||||||
|
"typescript": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/frontend/apps/e2e/playwright.config.ts
Normal file
54
src/frontend/apps/e2e/playwright.config.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test';
|
||||||
|
|
||||||
|
const PORT = process.env.PORT || 3000;
|
||||||
|
|
||||||
|
const baseURL = `http://localhost:${PORT}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
// Timeout per test
|
||||||
|
timeout: 30 * 1000,
|
||||||
|
testDir: './__tests__',
|
||||||
|
outputDir: './test-results',
|
||||||
|
|
||||||
|
/* Run tests in files in parallel */
|
||||||
|
fullyParallel: true,
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 3 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: [['html', { outputFolder: './report' }]],
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
baseURL: baseURL,
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
|
||||||
|
webServer: {
|
||||||
|
command: `cd ../.. && yarn app:${
|
||||||
|
process.env.CI ? 'start -p ' : 'dev --port '
|
||||||
|
} ${PORT}`,
|
||||||
|
url: baseURL,
|
||||||
|
timeout: 120 * 1000,
|
||||||
|
reuseExistingServer: !process.env.CI,
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Configure projects for major browsers */
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'], locale: 'en-US' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'webkit',
|
||||||
|
use: { ...devices['Desktop Safari'], locale: 'en-US' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
19
src/frontend/apps/e2e/tsconfig.json
Normal file
19
src/frontend/apps/e2e/tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
},
|
||||||
|
"include": ["**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user