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

Improve visual testing #91

Merged
merged 2 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ COPY package-lock.json .
COPY tests tests
COPY playwright.config.js .

COPY app.js .
COPY public public
COPY routers routers
COPY templates templates
COPY utils utils
COPY .env .env

RUN npm install
RUN npx playwright install
RUN npx playwright install-deps
Expand Down
8 changes: 7 additions & 1 deletion playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default defineConfig({
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
reporter: process.env.CI ? 'html' : 'line',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
Expand All @@ -30,6 +30,12 @@ export default defineConfig({
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
expect: {
toHaveScreenshot: {
// An acceptable amount of pixels that could be different, unset by default.
maxDiffPixelRatio: 0.05,
},
},

/* Configure projects for major browsers */
projects: [
Expand Down
4 changes: 2 additions & 2 deletions public/login/santaLogin.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ <h5 class="modal-title">Forgot your password?</h5>
<form id="santa-email-form" class="margin-top">
<div class="modal-body">
<div class="form-group">
<label for="santa-email">Enter your email address:</label>
<label for="forgot-email">Enter your email address:</label>
<input
type="email"
class="form-control"
id="santa-email"
id="forgot-email"
required
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion public/login/santaLogin.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ $(async function () {
$('#santa-email-form').on('submit', function () {
$.post(
'api/email',
{ email: $('#santa-email').val() },
{ email: $('#forgot-email').val() },
function (result) {
$('#forgot-password-dialog').modal('hide');
showAlert(result);
Expand Down
12 changes: 7 additions & 5 deletions routers/session-router.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ sessionRouter.post('/api/email', async (req, res) => {
const data = fs.readFileSync('./templates/forgot-password-email.html');
emailText = data
.toString()
.replace(/{{name}}/, user.name)
.replace(/{{email}}/, user.email)
.replace(/{{password}}/, user.password);
} else {
const data = fs.readFileSync('./templates/unknown-user-email.html');
Expand All @@ -98,11 +98,13 @@ sessionRouter.post('/api/email', async (req, res) => {

const emailStatus = await sendEmail(emailTemplate);

if (emailStatus.success) {
res.send({ success: `Email successfully sent to ${emailTemplate.to}` });
} else {
res.send({ error: `Error sending email: ${emailStatus.error}` });
if (emailStatus.success !== true) {
return res.send({ error: `Error sending email: ${emailStatus.error}` });
}
return res.send({
success: `Email successfully sent to ${emailTemplate.to}`,
emailUrl: emailStatus.emailUrl,
});
});

passport.use(
Expand Down
6 changes: 4 additions & 2 deletions templates/forgot-password-email.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@
</tr>
<tr>
<th class="paddings">Email:</th>
<td class="paddings">{{name}}</td>
<td class="paddings"><span id="email-placeholder">{{email}}</span></td>
</tr>
<tr>
<th class="paddings">Password:</th>
<td class="paddings">{{password}}</td>
<td class="paddings">
<span id="password-placeholder">{{password}}</span>
</td>
</tr>
<tr>
<td colspan="2" class="paddings" style="text-align: center">
Expand Down
16 changes: 11 additions & 5 deletions tests/chat.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ test.describe('chat tests', () => {
let groupData;
let page;

test.beforeAll('setup', async ({ browser })=> {
test.beforeAll('setup', async ({ browser }) => {
page = await browser.newPage();
groupData = await createNewGroup(page.request);
})
});

test('user can send a message', async ({ page }) => {
await login(
Expand Down Expand Up @@ -53,8 +53,14 @@ test.describe('chat tests', () => {
);
await page.goto('/chat');

await expect(page.locator('[data-name="chatTo"]')).toContainText(groupData.users.user2.name);
await expect(page.locator('[data-name="chatMessage"]')).toHaveText(message.message);
await expect(page.locator('[data-name="chatFrom"]')).toHaveText('From: Anonymous');
await expect(page.locator('[data-name="chatTo"]')).toContainText(
groupData.users.user2.name
);
await expect(page.locator('[data-name="chatMessage"]')).toHaveText(
message.message
);
await expect(page.locator('[data-name="chatFrom"]')).toHaveText(
'From: Anonymous'
);
});
});
41 changes: 33 additions & 8 deletions tests/email.spec.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
// @ts-check
import { test, expect } from '@playwright/test';
import { faker } from '@faker-js/faker';
import { login, registerUser } from './helpers/login.js';
import { forgotPassword, login, registerUser } from './helpers/login.js';
import { inviteUserToGroup, updateGroup } from './helpers/admin.js';
import { createDraftedGroup, createNewGroup } from './helpers/setup.js';
import { sendMessage } from './helpers/chat.js';

test.describe('email tests', () => {

test.describe('admin tests', () => {
test('user should receive an email when forgot password is triggered', async ({
page,
}) => {
const user = {
email: faker.internet.email(),
password: faker.internet.password(),
};
await registerUser(page.request, user);
const response = await forgotPassword(page.request, user.email);
const responseJson = await response.json();
await expect(responseJson).toHaveProperty('emailUrl');
await page.goto(responseJson.emailUrl);

await expect(page).toHaveScreenshot('forgot-password-email.png', {
mask: [
page.locator('.mp_address_group').nth(1),
page.locator('.datestring'),
// Message-ID
page.locator('#message-header div').nth(4).locator('span'),
page.frameLocator('[style]').locator('#email-placeholder'),
page.frameLocator('[style]').locator('#password-placeholder'),
],
fullPage: true,
});
});

test('new user receives an email when invited to the group', async ({
page,
Expand Down Expand Up @@ -44,7 +68,6 @@ test.describe('email tests', () => {
await page.goto(bodyWithUrl.emailUrl);

await expect(page).toHaveScreenshot('invite-email.png', {
maxDiffPixelRatio: 0.05,
mask: [
page.locator('.mp_address_group').nth(1),
page.locator('.datestring'),
Expand All @@ -53,6 +76,7 @@ test.describe('email tests', () => {
page.frameLocator('[style]').locator('#group-placeholder'),
page.frameLocator('[style]').locator('#password-placeholder'),
],
fullPage: true,
});
});

Expand Down Expand Up @@ -88,7 +112,6 @@ test.describe('email tests', () => {
await page.goto(bodyWithUrl.emailUrl);

await expect(page).toHaveScreenshot('invite-email.png', {
maxDiffPixelRatio: 0.05,
mask: [
page.locator('.mp_address_group').nth(1),
page.locator('.datestring'),
Expand All @@ -97,12 +120,12 @@ test.describe('email tests', () => {
page.frameLocator('[style]').locator('#group-placeholder'),
page.frameLocator('[style]').locator('#password-placeholder'),
],
fullPage: true,
});
});
})
});

test.describe('chat tests', () => {

test('user should receive a chat email', async ({ page }) => {
const groupData = await createDraftedGroup(page.request);
const updatedGroupData = {
Expand Down Expand Up @@ -131,7 +154,9 @@ test.describe('email tests', () => {
await expect(page.locator('#message-header')).toContainText(
'<[email protected]>'
);
await expect(page.locator('#message-header')).toContainText(message.email);
await expect(page.locator('#message-header')).toContainText(
message.email
);
await expect(
page.frameLocator('#message iframe').locator('body')
).toContainText(message.message);
Expand All @@ -152,5 +177,5 @@ test.describe('email tests', () => {
const messageData = await sendMessage(page.request, message);
await expect(messageData).not.toHaveProperty('emailUrl');
});
})
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/email.spec.js-snapshots/invite-email-chromium-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/email.spec.js-snapshots/invite-email-chromium-win32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions tests/generateSnapshots.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#docker build -t playwright_image .
docker run --name playwright playwright_image
docker cp playwright:tests/email.spec.js-snapshots tests
docker rm playwright
read -p "Press enter to continue"
6 changes: 6 additions & 0 deletions tests/helpers/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ export function login(request, email, password) {
data: { username: email, password },
});
}

export function forgotPassword(request, email) {
return request.post('session/api/email', {
data: { email },
});
}
26 changes: 25 additions & 1 deletion tests/session.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,36 @@ test.describe('session tests', () => {

await page.goto('/');
await page.getByLabel('Santa email').fill(user.email);
await page.getByLabel('Santa password').fill(user.password);
await page.getByLabel('Santa password').fill(faker.internet.password());

await page.getByRole('button', { name: 'Login' }).click();
await expect(page.locator('#footerAlert')).toHaveText(
'Email or password wrong'
);

await page.getByLabel('Santa password').fill(user.password);
await page.getByRole('button', { name: 'Login' }).click();
await expect(page.locator('#footerAlert')).toHaveText('No active group');

await expect(page).toHaveTitle(/Secret Santa/);
await expect(page.locator('#unavailableImage')).toBeVisible();
});

test('user can request password', async ({ request, page }) => {
const user = {
email: faker.internet.email(),
password: faker.internet.password(),
};
await registerUser(request, user);

await page.goto('/');

await page.getByText('Forgot password').click();
await page.getByLabel('Enter your email address').fill(user.email);
await page.getByRole('button', { name: 'Email' }).click();

await expect(page.locator('#footerAlert')).toHaveText(
`Email successfully sent to ${user.email}`
);
});
});
Loading