@appsemble/e2e 0.36.10-test.2 → 0.36.10-test.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#  Appsemble End 2 End Tests
|
|
2
2
|
|
|
3
3
|
> Run end 2 end tests on an Appsemble environment and provide Appsemble fixtures
|
|
4
4
|
|
|
5
|
-
[](https://gitlab.com/appsemble/appsemble/-/releases/0.36.10-test.4)
|
|
6
6
|
[](https://prettier.io)
|
|
7
7
|
|
|
8
8
|
## Table of Contents
|
|
@@ -102,5 +102,5 @@ When writing end-to-end tests, have a look at the
|
|
|
102
102
|
|
|
103
103
|
## License
|
|
104
104
|
|
|
105
|
-
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.36.10-test.
|
|
105
|
+
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.36.10-test.4/LICENSE.md) ©
|
|
106
106
|
[Appsemble](https://appsemble.com)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsemble/e2e",
|
|
3
|
-
"version": "0.36.10-test.
|
|
3
|
+
"version": "0.36.10-test.4",
|
|
4
4
|
"description": "End-to-end tests used for testing Appsemble apps in an existing environment.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"app",
|
|
@@ -37,10 +37,13 @@
|
|
|
37
37
|
"codegen": "playwright codegen",
|
|
38
38
|
"test": "vitest"
|
|
39
39
|
},
|
|
40
|
+
"dependenciesComments": {
|
|
41
|
+
"@playwright/test": "Pinned exact and kept in sync with the mcr.microsoft.com/playwright:v<version>-noble tag of the `e2e node` job in .gitlab-ci.yml; Renovate bumps both together (see renovate.json)."
|
|
42
|
+
},
|
|
40
43
|
"dependencies": {
|
|
41
|
-
"@appsemble/lang-sdk": "0.36.10-test.
|
|
42
|
-
"@appsemble/node-utils": "0.36.10-test.
|
|
43
|
-
"@appsemble/types": "0.36.10-test.
|
|
44
|
+
"@appsemble/lang-sdk": "0.36.10-test.4",
|
|
45
|
+
"@appsemble/node-utils": "0.36.10-test.4",
|
|
46
|
+
"@appsemble/types": "0.36.10-test.4",
|
|
44
47
|
"@playwright/test": "1.58.2",
|
|
45
48
|
"strip-indent": "^4.0.0"
|
|
46
49
|
},
|
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
import { createUser, deleteUser } from '@appsemble/node-utils';
|
|
2
2
|
import { test as setup } from '@playwright/test';
|
|
3
|
+
async function ensureAppsembleOrganization(baseURL) {
|
|
4
|
+
const organizationResponse = await fetch(`${baseURL}/api/organizations/appsemble`);
|
|
5
|
+
if (organizationResponse.status === 200) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
if (organizationResponse.status !== 404) {
|
|
9
|
+
throw new Error(`Unexpected status ${organizationResponse.status} while fetching the appsemble organization`);
|
|
10
|
+
}
|
|
11
|
+
const email = 'worker-0@appsemble.com';
|
|
12
|
+
const password = 'worker-0';
|
|
13
|
+
const loginResponse = await fetch(`${baseURL}/api/auth/email/login`, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
headers: {
|
|
16
|
+
authorization: `Basic ${Buffer.from(`${email}:${password}`).toString('base64')}`,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
if (loginResponse.status !== 200) {
|
|
20
|
+
throw new Error(`Unexpected status ${loginResponse.status} while logging in to create the appsemble organization`);
|
|
21
|
+
}
|
|
22
|
+
const { access_token: accessToken } = (await loginResponse.json());
|
|
23
|
+
const formData = new FormData();
|
|
24
|
+
formData.set('id', 'appsemble');
|
|
25
|
+
formData.set('name', 'Appsemble');
|
|
26
|
+
formData.set('description', '');
|
|
27
|
+
formData.set('email', '');
|
|
28
|
+
formData.set('website', 'http');
|
|
29
|
+
const createResponse = await fetch(`${baseURL}/api/organizations`, {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: {
|
|
32
|
+
authorization: `Bearer ${accessToken}`,
|
|
33
|
+
},
|
|
34
|
+
body: formData,
|
|
35
|
+
});
|
|
36
|
+
if (createResponse.status !== 201 && createResponse.status !== 409) {
|
|
37
|
+
throw new Error(`Unexpected status ${createResponse.status} while creating the appsemble organization: ${await createResponse.text()}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
3
40
|
setup('create accounts for workers', async ({}, testInfo) => {
|
|
4
41
|
for (let i = 0; i < testInfo.config.workers; i += 1) {
|
|
5
42
|
const id = `worker-${i}`;
|
|
@@ -8,5 +45,9 @@ setup('create accounts for workers', async ({}, testInfo) => {
|
|
|
8
45
|
await deleteUser(email);
|
|
9
46
|
await createUser(id, email, password);
|
|
10
47
|
}
|
|
48
|
+
if (!testInfo.project.use.baseURL) {
|
|
49
|
+
throw new Error('Missing Playwright baseURL');
|
|
50
|
+
}
|
|
51
|
+
await ensureAppsembleOrganization(String(testInfo.project.use.baseURL));
|
|
11
52
|
});
|
|
12
53
|
//# sourceMappingURL=create-accounts.setup.js.map
|
|
@@ -24,10 +24,27 @@ test.describe('Person', () => {
|
|
|
24
24
|
const lastName = `Last name ${date}`;
|
|
25
25
|
const email = `Email${date}@example.com`;
|
|
26
26
|
const description = `Description ${date}`;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
await
|
|
27
|
+
// The form block resets field values while it finishes initializing (the
|
|
28
|
+
// file field briefly holds the form in a loading state), dropping values
|
|
29
|
+
// typed too early. Re-fill until every field keeps its value.
|
|
30
|
+
await expect(async () => {
|
|
31
|
+
await page.getByPlaceholder('First name').fill(firstName);
|
|
32
|
+
await page.getByPlaceholder('Last name').fill(lastName);
|
|
33
|
+
await page.getByPlaceholder('Email').fill(email);
|
|
34
|
+
await page.getByPlaceholder('Description').fill(description);
|
|
35
|
+
await expect(page.getByPlaceholder('First name')).toHaveValue(firstName, {
|
|
36
|
+
timeout: 1000,
|
|
37
|
+
});
|
|
38
|
+
await expect(page.getByPlaceholder('Last name')).toHaveValue(lastName, {
|
|
39
|
+
timeout: 1000,
|
|
40
|
+
});
|
|
41
|
+
await expect(page.getByPlaceholder('Email')).toHaveValue(email, {
|
|
42
|
+
timeout: 1000,
|
|
43
|
+
});
|
|
44
|
+
await expect(page.getByPlaceholder('Description')).toHaveValue(description, {
|
|
45
|
+
timeout: 1000,
|
|
46
|
+
});
|
|
47
|
+
}).toPass({ timeout: 10000 });
|
|
31
48
|
await page.click('button[type="submit"]');
|
|
32
49
|
await page.click(`td:has-text("${firstName}")`);
|
|
33
50
|
await expect(page.getByText(firstName)).toBeVisible();
|
|
@@ -33,7 +33,6 @@ test.describe('Individual app', () => {
|
|
|
33
33
|
test('should not prompt when user has saved their changes', async ({ clickAppSideMenuItem, page, }) => {
|
|
34
34
|
await clickAppSideMenuItem('Editor');
|
|
35
35
|
page.on('dialog', (alert) => {
|
|
36
|
-
// If a dialog comes up at all, the test should fail
|
|
37
36
|
expect(alert).toBeNull();
|
|
38
37
|
});
|
|
39
38
|
await expect(page.getByRole('button', { name: 'Publish' })).toBeDisabled();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { expect, authenticatedTest as test } from '../../index.js';
|
|
2
|
+
let membersAppId;
|
|
3
|
+
let membersAppPath;
|
|
4
|
+
test.describe('Studio member roles', () => {
|
|
5
|
+
test.beforeAll(async ({ createApp, createOrganization, randomTestId }) => {
|
|
6
|
+
const organizationId = (await createOrganization({ id: randomTestId() })).id;
|
|
7
|
+
const app = await createApp(organizationId, `
|
|
8
|
+
name: Member Roles App
|
|
9
|
+
defaultPage: Test Page
|
|
10
|
+
security:
|
|
11
|
+
default:
|
|
12
|
+
role: User
|
|
13
|
+
policy: everyone
|
|
14
|
+
roles:
|
|
15
|
+
User: {}
|
|
16
|
+
Admin: {}
|
|
17
|
+
Auditor: {}
|
|
18
|
+
pages:
|
|
19
|
+
- name: Test Page
|
|
20
|
+
blocks:
|
|
21
|
+
- type: data-loader
|
|
22
|
+
version: 0.34.15
|
|
23
|
+
`);
|
|
24
|
+
membersAppId = app.id;
|
|
25
|
+
membersAppPath = app.path;
|
|
26
|
+
});
|
|
27
|
+
test.afterAll(async ({ deleteApp }) => {
|
|
28
|
+
if (membersAppId != null) {
|
|
29
|
+
await deleteApp(membersAppId);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
test('should update multiple member roles in Studio', async ({ page, randomTestId, request }) => {
|
|
33
|
+
const email = `${randomTestId()}@example.com`;
|
|
34
|
+
const registration = new FormData();
|
|
35
|
+
registration.append('email', email);
|
|
36
|
+
registration.append('password', 'password');
|
|
37
|
+
registration.append('timezone', 'Europe/Amsterdam');
|
|
38
|
+
const registerResponse = await request.post(`/api/apps/${membersAppId}/auth/email/register`, {
|
|
39
|
+
multipart: registration,
|
|
40
|
+
});
|
|
41
|
+
expect(registerResponse.status()).toBe(201);
|
|
42
|
+
await page.goto(`/en/apps/${membersAppId}/${membersAppPath}/members`);
|
|
43
|
+
const rolesSelect = page.getByTestId(`app-member-roles-${email}`);
|
|
44
|
+
await rolesSelect.selectOption(['Admin', 'Auditor']);
|
|
45
|
+
await expect(page.getByText(`Successfully changed roles of ${email} to Admin, Auditor.`)).toBeVisible();
|
|
46
|
+
await page.reload();
|
|
47
|
+
await expect
|
|
48
|
+
.poll(() => page
|
|
49
|
+
.getByTestId(`app-member-roles-${email}`)
|
|
50
|
+
.evaluate((element) => Array.from(element.selectedOptions, ({ value }) => value)))
|
|
51
|
+
.toEqual(['Admin', 'Auditor']);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=member-roles.spec.js.map
|