Skip to content

Commit 33e26ed

Browse files
authored
test: add e2e tests for 1st step of create colony flow
2 parents 9ead315 + 298f240 commit 33e26ed

File tree

18 files changed

+535
-25
lines changed

18 files changed

+535
-25
lines changed

.eslintrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ module.exports = {
4646
jest: true,
4747
},
4848
},
49+
{
50+
files: ['playwright/**/*.ts'],
51+
extends: 'plugin:playwright/recommended',
52+
rules: {
53+
'no-await-in-loop': 'off',
54+
},
55+
},
4956
],
5057
rules: {
5158
// Using the typescript-eslint version for these

package-lock.json

Lines changed: 56 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
"docker:compose:all": "docker compose --file docker/colony-cdapp-dev-env-orchestration-all.yaml",
2020
"dev": "npm run watch-amplify & npm run generate-notifications-dev-key && npm run docker:build:core && npm run docker:compose:core up -- --force-recreate -V",
2121
"dev:all": "npm run generate-notifications-dev-key && npm run docker:build:all && npm run docker:compose:all up -- --force-recreate -V",
22-
"lint": "eslint src --fix --ext ts,tsx --report-unused-disable-directives",
23-
"lint:ci": "eslint src --ext ts,tsx --report-unused-disable-directives",
22+
"lint": "eslint src playwright --fix --ext ts,tsx --report-unused-disable-directives",
23+
"lint:ci": "eslint src playwright --ext ts,tsx --report-unused-disable-directives",
2424
"stylelint:ci": "stylelint --allow-empty-input \"src/**/*.css\"",
2525
"typecheck": "tsc --noEmit",
2626
"frontend": "ulimit -n 2048 && vite",
@@ -39,9 +39,9 @@
3939
"postinstall": "if [ -z \"$SKIP_HOOKS\" ]; then ./scripts/lambda-functions-dependencies.sh && scripts/generate-amplify-local-config.sh; fi",
4040
"watch-amplify": "node scripts/watchAmplifyFiles",
4141
"forward-time": "node scripts/forward-time",
42-
"playwright:install": "npx playwright install --with-deps",
43-
"playwright:run": "playwright test",
44-
"playwright:watch": "playwright test --ui",
42+
"e2e:install": "npx playwright install --with-deps",
43+
"e2e": "playwright test --project=chromium",
44+
"e2e:ui": "playwright test --ui",
4545
"generate-notifications-dev-key": "node scripts/generate-local-notifications-key"
4646
},
4747
"repository": {
@@ -100,6 +100,7 @@
100100
"compare-versions": "^6.1.0",
101101
"cross-fetch": "^4.0.0",
102102
"crypto-browserify": "^3.12.0",
103+
"dotenv": "^16.4.5",
103104
"enzyme": "^3.11.0",
104105
"enzyme-to-json": "^3.3.4",
105106
"eslint": "^8.57.0",
@@ -111,6 +112,7 @@
111112
"eslint-plugin-jest": "^27.6.3",
112113
"eslint-plugin-jsdoc": "^48.0.2",
113114
"eslint-plugin-jsx-a11y": "^6.6.1",
115+
"eslint-plugin-playwright": "^1.7.0",
114116
"eslint-plugin-react": "^7.31.7",
115117
"eslint-plugin-react-hooks": "^4.6.0",
116118
"eslint-plugin-react-refresh": "^0.4.5",

playwright.config.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { defineConfig, devices } from '@playwright/test';
2+
import dotenv from 'dotenv';
3+
import path from 'path';
4+
5+
dotenv.config({ path: path.resolve(__dirname, '.env') });
26

37
/**
48
* See https://playwright.dev/docs/test-configuration.
59
*/
610
export default defineConfig({
711
testDir: './playwright/e2e',
8-
/* Run tests in files in parallel */
9-
fullyParallel: true,
1012
/* Fail the build on CI if you accidentally left test.only in the source code. */
1113
forbidOnly: !!process.env.CI,
1214
/* Retry on CI only */
@@ -21,9 +23,10 @@ export default defineConfig({
2123
baseURL: 'http://localhost:9091',
2224

2325
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
24-
trace: 'on-first-retry',
26+
trace: 'retain-on-failure',
2527
},
26-
28+
// Needed for running tests against the app in development mode
29+
timeout: !process.env.CI ? 90000 : undefined,
2730
/* Configure projects for major browsers */
2831
projects: [
2932
{

playwright/README.MD

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,18 @@ For more details on Playwright, you can visit the [Playwright documentation](htt
88
To install the necessary dependencies for Playwright, run the following command:
99

1010
```bash
11-
npm run playwright:install
11+
npm run e2e:install
12+
```
13+
14+
Setup and start your local dev environment following the root readme.md file instrutions (all BE services should be up and running).
15+
16+
```bash
17+
npm run dev
18+
```
19+
Seed the test data
20+
21+
```bash
22+
node scripts/create-data.js
1223
```
1324

1425
## Running the Tests
@@ -18,15 +29,15 @@ To execute the Playwright tests, use one of the following commands:
1829
Run all tests:
1930

2031
```bash
21-
npm run playwright:run
32+
npm run e2e
2233
```
2334

2435
This will run all Playwright tests in the headless mode.
2536

2637
Run tests in watch mode:
2738

2839
```bash
29-
npm run playwright:watch
40+
npm run e2e:ui
3041
```
3142

3243
This will launch Playwright's UI for running tests interactively, allowing you to watch and debug them in real time.
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
import {
4+
acceptCookieConsentBanner,
5+
fillInputByLabelWithDelay,
6+
} from '../utils/common.ts';
7+
import {
8+
generateRandomString,
9+
selectWalletAndUserProfile,
10+
} from '../utils/create-colony.ts';
11+
import { generateCreateColonyUrl } from '../utils/graphqlHelpers.ts';
12+
13+
test.describe('Create Colony flow', () => {
14+
const colonyName = 'testcolonyname';
15+
16+
test.beforeEach(async ({ page }) => {
17+
const colonyUrl = await generateCreateColonyUrl();
18+
19+
await page.goto(colonyUrl);
20+
21+
await selectWalletAndUserProfile(page);
22+
23+
await acceptCookieConsentBanner(page);
24+
});
25+
test.describe('Details step', () => {
26+
test('Should render Details step correctly', async ({ page }) => {
27+
// Heading of the step and form is shown
28+
await Promise.all([
29+
expect(
30+
page
31+
.getByTestId('onboarding-heading')
32+
.filter({ hasText: /Welcome/i }),
33+
).toBeVisible(),
34+
expect(
35+
page
36+
.getByTestId('onboarding-subheading')
37+
.filter({ hasText: /Lets set up your Colony/i }),
38+
).toBeVisible(),
39+
expect(page.getByLabel(/colony name/i)).toBeVisible(),
40+
expect(page.getByLabel(/custom colony URL/i)).toBeVisible(),
41+
expect(page.getByRole('button', { name: /continue/i })).toBeVisible(),
42+
]);
43+
// Sidebar navigation and its components are visible
44+
const sidebarNav = page.getByRole('navigation');
45+
46+
await Promise.all([
47+
expect(sidebarNav.getByText(/create your new colony/i)).toBeVisible(),
48+
expect(sidebarNav.getByText('Create', { exact: true })).toBeVisible(),
49+
expect(sidebarNav.getByText('Details')).toBeVisible(),
50+
expect(sidebarNav.getByText('Native Token')).toBeVisible(),
51+
expect(sidebarNav.getByText('Confirmation')).toBeVisible(),
52+
expect(sidebarNav.getByText('Complete')).toBeVisible(),
53+
expect(
54+
sidebarNav.getByRole('button', { name: 'Help & Feedback' }),
55+
).toBeVisible(),
56+
]);
57+
});
58+
59+
test('Should accept a valid Colony Name and Custom URL and navigate to the next step', async ({
60+
page,
61+
}) => {
62+
// continue button is disabled initially
63+
await expect(
64+
page.getByRole('button', { name: /continue/i }),
65+
).toBeDisabled();
66+
67+
// Fill in colony name and custom URL
68+
await fillInputByLabelWithDelay({
69+
page,
70+
label: /colony name/i,
71+
value: colonyName,
72+
});
73+
74+
await fillInputByLabelWithDelay({
75+
page,
76+
label: /custom colony URL/i,
77+
value: generateRandomString(),
78+
});
79+
80+
// Check if URL is available
81+
await expect(page.getByText(/URL available/i)).toBeVisible();
82+
83+
// Click continue and verify navigation to the next step
84+
await page.getByRole('button', { name: /continue/i }).click();
85+
await expect(
86+
page.getByRole('heading', { name: /creating a new native token/i }),
87+
).toBeVisible();
88+
});
89+
90+
test('Should show an error message when the Colony URL is already taken', async ({
91+
page,
92+
}) => {
93+
// Mock the response for the 'CheckColonyNameExists' query
94+
page.route('**/graphql', (route, request) => {
95+
const postData = request.postDataJSON();
96+
97+
if (postData.operationName === 'CheckColonyNameExists') {
98+
route.fulfill({
99+
status: 200,
100+
contentType: 'application/json',
101+
body: JSON.stringify({
102+
data: {
103+
getColonyByName: {
104+
items: ['someColonyId'],
105+
__typename: 'ModelColonyConnection',
106+
},
107+
},
108+
}),
109+
});
110+
} else {
111+
route.continue();
112+
}
113+
});
114+
115+
await fillInputByLabelWithDelay({
116+
page,
117+
label: /custom colony URL/i,
118+
value: 'takenurl',
119+
});
120+
121+
await expect(
122+
page.getByText(/This colony URL is already taken/i),
123+
).toBeVisible();
124+
});
125+
126+
test('Should reject invalid colony name', async ({ page }) => {
127+
// More than 20 characters
128+
await fillInputByLabelWithDelay({
129+
page,
130+
label: /colony name/i,
131+
value: 'A'.repeat(21),
132+
});
133+
134+
await expect(page.getByTestId('form-error')).toBeVisible();
135+
});
136+
137+
test("Should reject invalid custom colony URL's", async ({ page }) => {
138+
await test.step('Invalid value', async () => {
139+
await fillInputByLabelWithDelay({
140+
page,
141+
label: /custom colony URL/i,
142+
value: 'invalid name',
143+
});
144+
145+
await expect(page.getByTestId('form-error')).toBeVisible();
146+
});
147+
148+
await test.step('Contains invalid character', async () => {
149+
await page.getByLabel(/custom colony URL/i).clear();
150+
151+
await fillInputByLabelWithDelay({
152+
page,
153+
label: /custom colony URL/i,
154+
value: '/invalid',
155+
});
156+
157+
await expect(page.getByTestId('form-error')).toBeVisible();
158+
});
159+
160+
await test.step('More than 20 characters', async () => {
161+
await page.getByLabel(/custom colony URL/i).clear();
162+
163+
await fillInputByLabelWithDelay({
164+
page,
165+
label: /custom colony URL/i,
166+
value: 'a'.repeat(21),
167+
});
168+
169+
await expect(page.getByTestId('form-error')).toBeVisible();
170+
});
171+
172+
await test.step('Reserved keyword', async () => {
173+
await page.getByLabel(/custom colony URL/i).clear();
174+
175+
await fillInputByLabelWithDelay({
176+
page,
177+
label: /custom colony URL/i,
178+
value: 'account',
179+
});
180+
181+
await expect(page.getByTestId('form-error')).toBeVisible();
182+
});
183+
});
184+
});
185+
});

0 commit comments

Comments
 (0)