test: add accept invitation invalid token tests

This commit is contained in:
Jakub P.
2024-07-16 12:08:50 +02:00
parent b7b3a3025b
commit 2f1f537e00
17 changed files with 143 additions and 12 deletions

View File

@@ -0,0 +1,5 @@
POSTGRES_DB=automatisch
POSTGRES_USER=automatisch_user
POSTGRES_PASSWORD=automatisch_password
POSTGRES_PORT=5432
POSTGRES_HOST=localhost

View File

@@ -1,3 +1,4 @@
const { expect } = require('@playwright/test');
const { BasePage } = require('./base-page'); const { BasePage } = require('./base-page');
export class AcceptInvitation extends BasePage { export class AcceptInvitation extends BasePage {
@@ -14,6 +15,7 @@ export class AcceptInvitation extends BasePage {
this.passwordConfirmationTextField = this.page.getByTestId('confirm-password-text-field'); this.passwordConfirmationTextField = this.page.getByTestId('confirm-password-text-field');
this.submitButton = this.page.getByTestId('submit-button'); this.submitButton = this.page.getByTestId('submit-button');
this.pageTitle = this.page.getByTestId('accept-invitation-form-title'); this.pageTitle = this.page.getByTestId('accept-invitation-form-title');
this.formErrorMessage = this.page.getByTestId('accept-invitation-form-error');
} }
async open(token) { async open(token) {
@@ -28,4 +30,17 @@ export class AcceptInvitation extends BasePage {
await this.submitButton.click(); await this.submitButton.click();
} }
async fillPasswordField(password) {
await this.passwordTextField.fill(password);
await this.passwordConfirmationTextField.fill(password);
}
async excpectSubmitButtonToBeDisabled() {
await expect(this.submitButton).toBeDisabled();
}
async expectAlertToBeVisible() {
await expect(this.formErrorMessage).toBeVisible();
}
} }

View File

@@ -1,4 +1,3 @@
const path = require('node:path');
const { ApplicationsModal } = require('./applications-modal'); const { ApplicationsModal } = require('./applications-modal');
const { AuthenticatedPage } = require('./authenticated-page'); const { AuthenticatedPage } = require('./authenticated-page');

View File

@@ -5,6 +5,7 @@ const { ExecutionsPage } = require('./executions-page');
const { FlowEditorPage } = require('./flow-editor-page'); const { FlowEditorPage } = require('./flow-editor-page');
const { UserInterfacePage } = require('./user-interface-page'); const { UserInterfacePage } = require('./user-interface-page');
const { LoginPage } = require('./login-page'); const { LoginPage } = require('./login-page');
const { AcceptInvitation } = require('./accept-invitation-page');
const { adminFixtures } = require('./admin'); const { adminFixtures } = require('./admin');
exports.test = test.extend({ exports.test = test.extend({
@@ -46,6 +47,11 @@ exports.publicTest = test.extend({
await use(loginPage); await use(loginPage);
}, },
acceptInvitationPage: async ({ page }, use) => {
const acceptInvitationPage = new AcceptInvitation(page);
await use(acceptInvitationPage);
}
}); });
expect.extend({ expect.extend({

View File

@@ -0,0 +1,11 @@
const { Client } = require('pg');
const client = new Client({
host: process.env.POSTGRES_HOST,
user: process.env.POSTGRES_USERNAME,
port: process.env.POSTGRES_PORT,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DATABASE
});
exports.client = client;

View File

@@ -32,7 +32,9 @@
"eslint": "^8.13.0", "eslint": "^8.13.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"luxon": "^3.4.4",
"micro": "^10.0.1", "micro": "^10.0.1",
"pg": "^8.12.0",
"prettier": "^2.5.1" "prettier": "^2.5.1"
} }
} }

View File

@@ -1,4 +1,3 @@
// @ts-check
const { defineConfig, devices } = require('@playwright/test'); const { defineConfig, devices } = require('@playwright/test');
/** /**

View File

@@ -1,4 +1,3 @@
// @ts-check
const { test, expect } = require('../../fixtures/index'); const { test, expect } = require('../../fixtures/index');
test.describe('Apps page', () => { test.describe('Apps page', () => {

View File

@@ -1,5 +1,4 @@
// @ts-check const { publicTest, expect } = require('../../fixtures/index');
const { publicTest, test, expect } = require('../../fixtures/index');
publicTest.describe('Login page', () => { publicTest.describe('Login page', () => {
publicTest('shows login form', async ({ loginPage }) => { publicTest('shows login form', async ({ loginPage }) => {

View File

@@ -1,8 +1,7 @@
// @ts-check
const { test, expect } = require('../../fixtures/index'); const { test, expect } = require('../../fixtures/index');
test.describe('Connections page', () => { test.describe('Connections page', () => {
test.beforeEach(async ({ page, connectionsPage }) => { test.beforeEach(async ({ page }) => {
await page.getByTestId('apps-page-drawer-link').click(); await page.getByTestId('apps-page-drawer-link').click();
await page.goto('/app/ntfy/connections'); await page.goto('/app/ntfy/connections');
}); });

View File

@@ -1,4 +1,3 @@
// @ts-check
const { test, expect } = require('../../fixtures/index'); const { test, expect } = require('../../fixtures/index');
// no execution data exists in an empty account // no execution data exists in an empty account

View File

@@ -1,8 +1,7 @@
// @ts-check
const { test, expect } = require('../../fixtures/index'); const { test, expect } = require('../../fixtures/index');
test.describe('Executions page', () => { test.describe('Executions page', () => {
test.beforeEach(async ({ page, executionsPage }) => { test.beforeEach(async ({ page }) => {
await page.getByTestId('executions-page-drawer-link').click(); await page.getByTestId('executions-page-drawer-link').click();
}); });

View File

@@ -1,4 +1,3 @@
// @ts-check
const { test, expect } = require('../../fixtures/index'); const { test, expect } = require('../../fixtures/index');
test('Ensure creating a new flow works', async ({ page }) => { test('Ensure creating a new flow works', async ({ page }) => {

View File

@@ -1,4 +1,3 @@
// @ts-check
const { test, expect } = require('../../fixtures/index'); const { test, expect } = require('../../fixtures/index');
test.describe('User interface page', () => { test.describe('User interface page', () => {

View File

@@ -0,0 +1,62 @@
const { AdminCreateUserPage } = require('../../fixtures/admin/create-user-page');
const { publicTest, expect } = require('../../fixtures/index');
const { client } = require('../../fixtures/postgres-client-config');
const { DateTime } = require('luxon');
publicTest.describe('Accept invitation page', () => {
publicTest.beforeAll(async () => {
await client.connect();
});
publicTest.afterAll(async () => {
await client.end();
});
publicTest('should not be able to set the password if token is empty', async ({ acceptInvitationPage }) => {
await acceptInvitationPage.open('');
await acceptInvitationPage.excpectSubmitButtonToBeDisabled();
await acceptInvitationPage.fillPasswordField('something');
await acceptInvitationPage.excpectSubmitButtonToBeDisabled();
});
publicTest('should not be able to set the password if token is expired', async ({ acceptInvitationPage, page }) => {
const expiredTokenDate = DateTime.now().minus({days: 3}).toISO();
const expiredToken = (Math.random() + 1).toString(36).substring(2);
const adminCreateUserPage = new AdminCreateUserPage(page);
adminCreateUserPage.seed(Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER));
const user = adminCreateUserPage.generateUser();
const queryRole = {
text: 'SELECT * FROM roles WHERE name = $1',
values: ['Admin']
};
try {
const queryRoleIdResult = await client.query(queryRole);
expect(queryRoleIdResult.rowCount).toEqual(1);
const insertUser = {
text: 'INSERT INTO users (email, full_name, role_id, status, invitation_token, invitation_token_sent_at) VALUES ($1, $2, $3, $4, $5, $6)',
values: [user.email, user.fullName, queryRoleIdResult.rows[0].id, 'invited', expiredToken, expiredTokenDate],
};
const insertUserResult = await client.query(insertUser);
expect(insertUserResult.rowCount).toBe(1);
expect(insertUserResult.command).toBe('INSERT');
} catch (err) {
console.error(err.message);
throw err;
}
await acceptInvitationPage.open(expiredToken);
await acceptInvitationPage.acceptInvitation('something');
await acceptInvitationPage.expectAlertToBeVisible();
});
publicTest('should not be able to set the password if token is not in db', async ({ acceptInvitationPage }) => {
await acceptInvitationPage.open('abc');
await acceptInvitationPage.acceptInvitation('something');
await acceptInvitationPage.expectAlertToBeVisible();
});
});

View File

@@ -111,6 +111,7 @@ export default function ResetPasswordForm() {
{acceptInvitation.isError && ( {acceptInvitation.isError && (
<Alert <Alert
data-test='accept-invitation-form-error'
severity="error" severity="error"
sx={{ mt: 1, fontWeight: 500 }} sx={{ mt: 1, fontWeight: 500 }}
> >

View File

@@ -11349,6 +11349,11 @@ luxon@^3.0.1:
resolved "https://registry.npmjs.org/luxon/-/luxon-3.0.4.tgz" resolved "https://registry.npmjs.org/luxon/-/luxon-3.0.4.tgz"
integrity sha512-aV48rGUwP/Vydn8HT+5cdr26YYQiUZ42NM6ToMoaGKwYfWbfLeRkEu1wXWMHBZT6+KyLfcbbtVcoQFCbbPjKlw== integrity sha512-aV48rGUwP/Vydn8HT+5cdr26YYQiUZ42NM6ToMoaGKwYfWbfLeRkEu1wXWMHBZT6+KyLfcbbtVcoQFCbbPjKlw==
luxon@^3.4.4:
version "3.4.4"
resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.4.tgz#cf20dc27dc532ba41a169c43fdcc0063601577af"
integrity sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==
lz-string@^1.4.4: lz-string@^1.4.4:
version "1.4.4" version "1.4.4"
resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz" resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz"
@@ -12926,11 +12931,21 @@ performance-now@^2.1.0:
resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
pg-cloudflare@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98"
integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==
pg-connection-string@2.5.0, pg-connection-string@^2.5.0: pg-connection-string@2.5.0, pg-connection-string@^2.5.0:
version "2.5.0" version "2.5.0"
resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz" resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz"
integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ== integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==
pg-connection-string@^2.6.4:
version "2.6.4"
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.4.tgz#f543862adfa49fa4e14bc8a8892d2a84d754246d"
integrity sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==
pg-int8@1.0.1: pg-int8@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz" resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz"
@@ -12941,11 +12956,21 @@ pg-pool@^3.4.1:
resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz" resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz"
integrity sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ== integrity sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ==
pg-pool@^3.6.2:
version "3.6.2"
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.2.tgz#3a592370b8ae3f02a7c8130d245bc02fa2c5f3f2"
integrity sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==
pg-protocol@^1.5.0: pg-protocol@^1.5.0:
version "1.5.0" version "1.5.0"
resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz" resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz"
integrity sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ== integrity sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==
pg-protocol@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.1.tgz#21333e6d83b01faaebfe7a33a7ad6bfd9ed38cb3"
integrity sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==
pg-types@^2.1.0: pg-types@^2.1.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz" resolved "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz"
@@ -12957,6 +12982,19 @@ pg-types@^2.1.0:
postgres-date "~1.0.4" postgres-date "~1.0.4"
postgres-interval "^1.1.0" postgres-interval "^1.1.0"
pg@^8.12.0:
version "8.12.0"
resolved "https://registry.yarnpkg.com/pg/-/pg-8.12.0.tgz#9341724db571022490b657908f65aee8db91df79"
integrity sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==
dependencies:
pg-connection-string "^2.6.4"
pg-pool "^3.6.2"
pg-protocol "^1.6.1"
pg-types "^2.1.0"
pgpass "1.x"
optionalDependencies:
pg-cloudflare "^1.1.1"
pg@^8.7.1: pg@^8.7.1:
version "8.7.1" version "8.7.1"
resolved "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz" resolved "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz"