Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automated form list tests #79

Merged
merged 10 commits into from
Jan 18, 2024
4 changes: 2 additions & 2 deletions web/frontend/src/layout/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const MobileMenu = ({ authCtx, handleLogout, fctx, t }) => (
<XIcon className="h-6 w-6" aria-hidden="true" />
</Popover.Button>
</div>
<div>
<div data-testid="mobileMenuLogo">
<img className="h-10 w-auto" src={logo} alt="Workflow" />
</div>
</div>
Expand Down Expand Up @@ -177,7 +177,7 @@ const RightSideNavBar = ({ authCtx, handleLogout, handleChangeId, fctx, t }) =>

const LeftSideNavBar = ({ authCtx, t }) => (
<div className="flex-1 flex items-center justify-center md:justify-start">
<div className="flex-shrink-0 flex items-center">
<div data-testid="leftSideNavBarLogo" className="flex-shrink-0 flex items-center">
<NavLink to={ROUTE_HOME}>
<img className="hidden lg:block h-10 w-auto" src={logo} alt="Workflow" />
</NavLink>
Expand Down
2 changes: 1 addition & 1 deletion web/frontend/src/pages/form/components/QuickAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type QuickActionProps = {

const QuickAction: FC<QuickActionProps> = ({ status, formID }) => {
return (
<div>
<div data-testid="quickAction">
{status === Status.Open && <VoteButton status={status} formID={formID} />}
{status === Status.ResultAvailable && <ResultButton status={status} formID={formID} />}
</div>
Expand Down
93 changes: 91 additions & 2 deletions web/frontend/tests/formIndex.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { expect, test } from '@playwright/test';
import { default as i18n } from 'i18next';
import { assertHasFooter, assertHasNavBar, initI18n, setUp } from './shared';
import { mockEvoting, mockPersonalInfo } from './mocks';
import { assertHasFooter, assertHasNavBar, initI18n, logIn, setUp, translate } from './shared';
import { SCIPER_ADMIN, SCIPER_USER, mockEvoting, mockPersonalInfo } from './mocks';
import Forms from './json/formList.json';
import User from './json/personal_info/789012.json';
import Admin from './json/personal_info/123456.json';

initI18n();

async function goForward(page: page) {
await page.getByRole('button', { name: i18n.t('next') }).click();
}

test.beforeEach(async ({ page }) => {
// mock empty list per default
await mockEvoting(page);
Expand Down Expand Up @@ -66,3 +73,85 @@ test('Assert pagination works correctly for non-empty list', async ({ page }) =>
await expect(previous).toBeDisabled();
await expect(next).toBeEnabled();
});

test('Assert no forms are displayed for empty list', async ({ page }) => {
// 1 header row
await expect
.poll(async () => {
const rows = await page.getByRole('table').getByRole('row');
return rows.all();
})
.toHaveLength(1);
});

async function assertQuickAction(row: locator, form: object, sciper?: string) {
const user = sciper === SCIPER_USER ? User : (sciper === SCIPER_ADMIN ? Admin : undefined); // eslint-disable-line
const quickAction = row.getByTestId('quickAction');
switch (form.Status) {
case 1:
// only authenticated user w/ right to vote sees 'vote' button
if (
user !== undefined &&
form.FormID in user.authorization &&
user.authorization[form.FormID].includes('vote')
) {
await expect(quickAction).toHaveText(i18n.t('vote'));
await expect(await quickAction.getByRole('link')).toHaveAttribute(
'href',
`/ballot/show/${form.FormID}`
);
await expect(quickAction).toBeVisible();
} else {
await expect(quickAction).toBeHidden();
}
break;
case 5:
// any user can see the results of a past election
await expect(quickAction).toHaveText(i18n.t('seeResult'));
await expect(await quickAction.getByRole('link')).toHaveAttribute(
'href',
`/forms/${form.FormID}/result`
);
break;
default:
await expect(quickAction).toBeHidden();
}
}

test('Assert forms are displayed correctly for unauthenticated user', async ({ page }) => {
await mockEvoting(page, false);
await page.reload();
const table = await page.getByRole('table');
for (let form of Forms.Forms.slice(0, -1)) {
let name = translate(form.Title);
let row = await table.getByRole('row', { name: name });
await expect(row).toBeVisible();
// row entry leads to form view
let link = await row.getByRole('link', { name: name });
await expect(link).toBeVisible();
await expect(link).toHaveAttribute('href', `/forms/${form.FormID}`);
await assertQuickAction(row, form);
}
await goForward(page);
let row = await table.getByRole('row', { name: translate(Forms.Forms.at(-1).Title) });
await expect(row).toBeVisible();
await assertQuickAction(row, Forms.Forms.at(-1));
});

test('Assert quick actions are displayed correctly for authenticated users', async ({ page }) => {
for (let sciper of [SCIPER_USER, SCIPER_ADMIN]) {
await logIn(page, sciper);
await mockEvoting(page, false);
await page.reload();
const table = await page.getByRole('table');
for (let form of Forms.Forms.slice(0, -1)) {
let row = await table.getByRole('row', { name: translate(form.Title) });
await assertQuickAction(row, form, sciper);
}
await goForward(page);
await assertQuickAction(
await table.getByRole('row', { name: translate(Forms.Forms.at(-1).Title) }),
Forms.Forms.at(-1)
);
}
});
4 changes: 2 additions & 2 deletions web/frontend/tests/json/formList.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
"Fr": "",
"De": ""
},
"Status": 0,
"Pubkey": ""
"Status": 1,
"Pubkey": "348f56a444e1b75214a9c675587222099007ce739a04651667c054d9be626e07"
},
{
"FormID": "1269a8507dc316a9ec983ede527705078bfef2b151a49f7ffae6e903ef1bb38f",
Expand Down
25 changes: 24 additions & 1 deletion web/frontend/tests/json/personal_info/123456.json
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
{"sciper":123456,"lastName":"123456","firstName":"sciper-#","isLoggedIn":true,"authorization":{"roles":["add","list","remove"],"proxies":["post","put","delete"],"election":["create"]}}
{
"sciper": 123456,
"lastName": "123456",
"firstName": "sciper-#",
"isLoggedIn": true,
"authorization": {
"roles": [
"add",
"list",
"remove"
],
"proxies": [
"post",
"put",
"delete"
],
"election": [
"create"
],
"fdf8bfb702e8883e330a2b303b24212b6fc16df5a53a097998b77ba74632dc72": ["own"],
"ed26713245824d44ee46ec90507ef521962f2313706934cdfe76ff1823738109": ["vote"],
"9f50ad723805a6419ba1a9f83dd0aa582f3e13b94f14727cd0c8c01744e0dba2": ["vote", "own"]
}
}
11 changes: 10 additions & 1 deletion web/frontend/tests/json/personal_info/789012.json
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
{"sciper":789012,"lastName":"789012","firstName":"sciper-#","isLoggedIn":true,"authorization":{}}
{
"sciper": 789012,
"lastName": "789012",
"firstName": "sciper-#",
"isLoggedIn": true,
"authorization": {
"fdf8bfb702e8883e330a2b303b24212b6fc16df5a53a097998b77ba74632dc72": ["vote"],
"ed26713245824d44ee46ec90507ef521962f2313706934cdfe76ff1823738109": ["vote"]
}
}
5 changes: 2 additions & 3 deletions web/frontend/tests/navbar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ test('Assert cookie is set', async ({ page }) => {
});

test('Assert D-Voting logo is present', async ({ page }) => {
const logo = await page.getByAltText(i18n.t('Workflow'));
const logo = await page.getByTestId('leftSideNavBarLogo');
await expect(logo).toBeVisible();
await logo.click();
await expect(page).toHaveURL('/');
await expect(await logo.getByRole('link')).toHaveAttribute('href', '/');
});

test('Assert link to form table is present', async ({ page }) => {
Expand Down
13 changes: 13 additions & 0 deletions web/frontend/tests/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,16 @@ export async function assertHasNavBar(page: page) {
export async function assertHasFooter(page: page) {
await expect(page.getByTestId('footer')).toBeVisible();
}

export function translate(internationalizable: object) {
switch (i18n.language) {
case 'en':
return internationalizable.En;
case 'fr':
return internationalizable.Fr || internationalizable.En;
case 'de':
return internationalizable.De || internationalizable.En;
default:
return internationalizable.En;
}
}
Loading