Skip to content

Commit 9e6df75

Browse files
authored
Merge pull request #120 from c4dt/playwright
Add remaining ballots tests
2 parents 1a32df8 + a0abffd commit 9e6df75

File tree

2 files changed

+92
-2
lines changed

2 files changed

+92
-2
lines changed

web/frontend/tests/ballot.spec.ts

+76-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@ import { expect, test } from '@playwright/test';
22
import { default as i18n } from 'i18next';
33
import { assertHasFooter, assertHasNavBar, initI18n, logIn, setUp } from './shared';
44
import { FORMID } from './mocks/shared';
5-
import { SCIPER_ADMIN, SCIPER_OTHER_USER, SCIPER_USER, mockPersonalInfo } from './mocks/api';
5+
import {
6+
SCIPER_ADMIN,
7+
SCIPER_OTHER_USER,
8+
SCIPER_USER,
9+
mockFormsVote,
10+
mockPersonalInfo,
11+
} from './mocks/api';
612
import { mockFormsFormID } from './mocks/evoting';
13+
import Form from './json/evoting/forms/open.json';
714

815
initI18n();
916

@@ -43,7 +50,74 @@ test('Assert ballot form is correctly handled for anonymous users, non-voter use
4350
await page.goto(`/ballot/show/${FORMID}`, { waitUntil: 'networkidle' });
4451
await expect(page).toHaveURL(`/ballot/show/${FORMID}`);
4552
await expect(castVoteButton).toBeVisible();
46-
await expect(page.getByText(i18n.t('vote'))).toBeVisible();
53+
await expect(page.getByText(i18n.t('vote'), { exact: true })).toBeVisible();
4754
await expect(page.getByText(i18n.t('voteExplanation'))).toBeVisible();
4855
});
4956
});
57+
58+
test('Assert ballot is displayed properly', async ({ page }) => {
59+
const content = await page.getByTestId('content');
60+
// TODO integrate localisation
61+
i18n.changeLanguage('en'); // force 'en' for this test
62+
await expect(content.locator('xpath=./div/div[3]/h3')).toContainText(Form.Configuration.Title.En);
63+
const scaffold = Form.Configuration.Scaffold.at(0);
64+
await expect(content.locator('xpath=./div/div[3]/div/div/h3')).toContainText(scaffold.Title.En);
65+
const select = scaffold.Selects.at(0);
66+
await expect(
67+
content.locator('xpath=./div/div[3]/div/div/div/div/div/div[1]/div/h3')
68+
).toContainText(select.Title.En);
69+
await expect(
70+
page.getByText(i18n.t('selectBetween', { minSelect: select.MinN, maxSelect: select.MaxN }))
71+
).toBeVisible();
72+
for (const choice of select.Choices.map((x) => JSON.parse(x))) {
73+
await expect(page.getByRole('checkbox', { name: choice.en })).toBeVisible();
74+
}
75+
i18n.changeLanguage(); // unset language for the other tests
76+
});
77+
78+
test('Assert minimum/maximum number of choices are handled correctly', async ({ page }) => {
79+
const castVoteButton = await page.getByRole('button', { name: i18n.t('castVote') });
80+
const select = Form.Configuration.Scaffold.at(0).Selects.at(0);
81+
await test.step(
82+
`Assert minimum number of choices (${select.MinN}) are handled correctly`,
83+
async () => {
84+
await castVoteButton.click();
85+
await expect(
86+
page.getByText(
87+
i18n.t('minSelectError', { min: select.MinN, singularPlural: i18n.t('singularAnswer') })
88+
)
89+
).toBeVisible();
90+
}
91+
);
92+
await test.step(
93+
`Assert maximum number of choices (${select.MaxN}) are handled correctly`,
94+
async () => {
95+
for (const choice of select.Choices.map((x) => JSON.parse(x))) {
96+
await page.getByRole('checkbox', { name: choice.en }).setChecked(true);
97+
}
98+
await castVoteButton.click();
99+
await expect(page.getByText(i18n.t('maxSelectError', { max: select.MaxN }))).toBeVisible();
100+
}
101+
);
102+
});
103+
104+
test('Assert that correct number of choices are accepted', async ({ page, baseURL }) => {
105+
await mockFormsVote(page);
106+
page.waitForRequest(async (request) => {
107+
const body = await request.postDataJSON();
108+
return (
109+
request.url() === `${baseURL}/api/evoting/forms/${FORMID}/vote` &&
110+
request.method() === 'POST' &&
111+
body.UserID === null &&
112+
body.Ballot.length === 1 &&
113+
body.Ballot.at(0).K.length === 32 &&
114+
body.Ballot.at(0).C.length === 32
115+
);
116+
});
117+
await page
118+
.getByRole('checkbox', {
119+
name: JSON.parse(Form.Configuration.Scaffold.at(0).Selects.at(0).Choices.at(0)).en,
120+
})
121+
.setChecked(true);
122+
await page.getByRole('button', { name: i18n.t('castVote') }).click();
123+
});

web/frontend/tests/mocks/api.ts

+16
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ export async function mockForms(page: page) {
3838
});
3939
}
4040

41+
export async function mockFormsVote(page: page) {
42+
await page.route(`/api/evoting/forms/${FORMID}/vote`, async (route) => {
43+
if (route.request().method() === 'POST') {
44+
await route.fulfill({
45+
status: 200,
46+
contentType: 'application/json',
47+
body: {
48+
Status: 0,
49+
Token:
50+
'eyJTdGF0dXMiOjAsIlRyYW5zYWN0aW9uSUQiOiJQQWluaEVjNVNzM2JiVWkxbldNWU55dWdPVkFpdVZ3YklZcGpKTFJ1SUdnPSIsIkxhc3RCbG9ja0lkeCI6NSwiVGltZSI6MTcwODAxNDgyMSwiSGFzaCI6ImtVT3g3Ykw0eC9IYXdwanppTityTVFIL3Fmb1pnRHBFUFc3S2tzRWl1TTA9IiwiU2lnbmF0dXJlIjoiZXlKT1lXMWxJam9pUWt4VExVTlZVbFpGTFVKT01qVTJJaXdpUkdGMFlTSTZJbU00UjFwUVYyWjZTRlpqT1dGV1dWaGhTbEUwWVhKT1UyRTRVbXB2VEVOSGIyZFBlbWRpVDFKSlYxVnVSbkE0ZFdaemQyMWlVVXA2ZWpScWJHNVFRa3QzUzJwWmVEaDJkVmgzZUhCWE5FeE1hVFZWUkRsUlBUMGlmUT09In0=',
51+
},
52+
});
53+
}
54+
});
55+
}
56+
4157
// /api/config
4258

4359
export async function mockProxy(page: page) {

0 commit comments

Comments
 (0)