@appsemble/e2e 0.34.21 → 0.35.3-test.0

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.
Files changed (54) hide show
  1. package/README.md +3 -3
  2. package/fixtures/expect/training/index.js +4 -1
  3. package/fixtures/test/app/index.d.ts +24 -2
  4. package/fixtures/test/app/index.js +40 -1
  5. package/fixtures/test/app-collection/index.d.ts +14 -7
  6. package/fixtures/test/app-collection/index.js +46 -32
  7. package/fixtures/test/index.d.ts +1 -1
  8. package/fixtures/test/index.js +2 -1
  9. package/fixtures/test/live-app/index.d.ts +4 -2
  10. package/fixtures/test/live-app/index.js +11 -5
  11. package/fixtures/test/organization/index.d.ts +26 -0
  12. package/fixtures/test/organization/index.js +35 -0
  13. package/fixtures/test/studio/index.d.ts +32 -0
  14. package/fixtures/test/studio/index.js +26 -1
  15. package/fixtures/test/test-utils/index.d.ts +5 -1
  16. package/fixtures/test/test-utils/index.js +15 -1
  17. package/package.json +4 -4
  18. package/playwright.config.js +21 -1
  19. package/tests/demo-apps/empty.spec.js +26 -0
  20. package/tests/{template-apps → demo-apps}/holidays.spec.js +13 -1
  21. package/tests/{template-apps → demo-apps}/notes.spec.js +12 -3
  22. package/tests/{template-apps → demo-apps}/person.spec.js +15 -1
  23. package/tests/static-ui/apps.spec.js +37 -0
  24. package/tests/static-ui/blocks.spec.js +35 -0
  25. package/tests/static-ui/individual-app.spec.js +69 -0
  26. package/tests/static-ui/organizations.spec.js +41 -0
  27. package/tests/static-ui/training.spec.js +39 -0
  28. package/tests/studio/app-collections/app-collections.spec.js +127 -103
  29. package/tests/studio/individual-app.spec.d.ts +1 -0
  30. package/tests/studio/individual-app.spec.js +51 -0
  31. package/tests/studio/organizations.spec.js +31 -24
  32. package/tests/studio/payments/subscription-flow.spec.d.ts +1 -0
  33. package/tests/studio/payments/subscription-flow.spec.js +68 -0
  34. package/tests/studio/trainings.spec.d.ts +1 -0
  35. package/tests/studio/trainings.spec.js +105 -0
  36. package/tests/studio/apps/app.spec.js +0 -79
  37. package/tests/studio/apps.spec.js +0 -30
  38. package/tests/studio/blocks.spec.js +0 -20
  39. package/tests/studio/trainings/constants.d.ts +0 -4
  40. package/tests/studio/trainings/constants.js +0 -5
  41. package/tests/studio/trainings/logged-in.spec.js +0 -93
  42. package/tests/studio/trainings/logged-out.spec.js +0 -42
  43. package/tests/template-apps/empty.spec.js +0 -14
  44. /package/tests/{template-apps → demo-apps}/empty.spec.d.ts +0 -0
  45. /package/tests/{template-apps → demo-apps}/holidays.spec.d.ts +0 -0
  46. /package/tests/{template-apps → demo-apps}/notes.spec.d.ts +0 -0
  47. /package/tests/{template-apps → demo-apps}/person.spec.d.ts +0 -0
  48. /package/tests/{studio → static-ui}/apps.spec.d.ts +0 -0
  49. /package/tests/{studio → static-ui}/blocks.spec.d.ts +0 -0
  50. /package/tests/{studio → static-ui}/docs.spec.d.ts +0 -0
  51. /package/tests/{studio → static-ui}/docs.spec.js +0 -0
  52. /package/tests/{studio/apps/app.spec.d.ts → static-ui/individual-app.spec.d.ts} +0 -0
  53. /package/tests/{studio/trainings/logged-in.spec.d.ts → static-ui/organizations.spec.d.ts} +0 -0
  54. /package/tests/{studio/trainings/logged-out.spec.d.ts → static-ui/training.spec.d.ts} +0 -0
@@ -1,33 +1,40 @@
1
1
  import { expect, test } from '../../index.js';
2
+ let organizationId;
2
3
  test.describe('Organizations', () => {
3
- test.beforeEach(async ({ page }) => {
4
- await page.goto('/en/organizations');
4
+ test.beforeAll(async ({ createOrganization, randomTestId }) => {
5
+ organizationId = randomTestId();
6
+ await createOrganization({ id: organizationId });
5
7
  });
6
- test('should render a list of organizations', async ({ page }) => {
7
- await expect(page.getByRole('link', { name: 'Appsemble appsemble', exact: true })).toBeVisible();
8
+ test.afterAll(async ({ deleteOrganization }) => {
9
+ await deleteOrganization(organizationId);
8
10
  });
9
- test('should link to organization details', async ({ page }) => {
10
- await page.getByRole('link', { name: 'Appsemble appsemble', exact: true }).click();
11
- await expect(page.getByText('The open source low-code app building platform')).toBeVisible();
12
- await expect(page.getByRole('heading', { name: 'Apps', exact: true })).toBeVisible();
13
- await expect(page.getByRole('heading', { name: 'Blocks', exact: true })).toBeVisible();
14
- await expect(page.getByText('Unlittered')).toBeVisible();
15
- await expect(page.getByText('action-button')).toBeVisible();
11
+ test.beforeEach(async ({ page }) => {
12
+ await page.goto(`/en/organizations/${organizationId}`);
16
13
  });
17
- test('should cancel the deletion of invite', async ({ page }) => {
18
- await page.goto('/en/organizations/appsemble/members');
19
- await page.click('button.button');
20
- await page.fill('input[name="email"]', 'e2e@appsemble.com');
21
- await page.click('button[type="submit"]');
22
- await page.click('button[title="Delete invite"]');
23
- await page.click('button[type="button"]:has-text("Cancel")');
24
- await expect(page.getByRole('paragraph', { name: 'Add new members' })).toBeHidden();
14
+ test('should cancel the deletion of invite', async ({ page, randomTestId }) => {
15
+ const email = `${randomTestId()}@appsemble.com`;
16
+ await page.getByRole('link', { name: ' Members' }).click();
17
+ await page.getByRole('button', { name: 'Add members' }).click();
18
+ await page.getByRole('textbox', { name: 'Email' }).fill(email);
19
+ await page.locator('form').getByRole('button', { name: 'Add members' }).click();
20
+ const memberRow = page.getByRole('row', { name: email });
21
+ await expect(memberRow).toBeVisible();
22
+ await memberRow.getByRole('button', { name: '' }).click();
23
+ await page.getByRole('button', { name: 'Cancel' }).click();
24
+ await expect(memberRow).toBeVisible();
25
25
  });
26
- test('should delete invite', async ({ page }) => {
27
- await page.goto('/en/organizations/appsemble/members');
28
- await page.click('button[title="Delete invite"]');
29
- await page.click('button[type="button"]:has-text("Delete invite")');
30
- await expect(page.locator('table tr:has-text("e2e@appsemble.com")')).toBeHidden();
26
+ test('should delete invite', async ({ page, randomTestId }) => {
27
+ const email = `${randomTestId()}@appsemble.com`;
28
+ await page.getByRole('link', { name: ' Members' }).click();
29
+ await page.getByRole('button', { name: 'Add members' }).click();
30
+ await page.getByRole('textbox', { name: 'Email' }).fill(email);
31
+ await page.locator('form').getByRole('button', { name: 'Add members' }).click();
32
+ const memberRow = page.getByRole('row', { name: email });
33
+ await expect(memberRow).toBeVisible();
34
+ await memberRow.getByRole('button', { name: '' }).click();
35
+ await page.getByRole('button', { name: 'Delete invite' }).click();
36
+ await expect(page.getByText('The invite has been deleted')).toBeVisible();
37
+ await expect(memberRow).toBeHidden();
31
38
  });
32
39
  });
33
40
  //# sourceMappingURL=organizations.spec.js.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,68 @@
1
+ import { expect, test } from '../../../fixtures/index.js';
2
+ const organization = 'Appsemble';
3
+ const email = 'test+test_mode@test.com';
4
+ const streetName = 'street one';
5
+ const houseNumber = '12a';
6
+ const city = 'Eindhoven';
7
+ const zipCode = '1234DF';
8
+ const country = 'NL';
9
+ test.describe('Payments', () => {
10
+ const { CI } = process.env;
11
+ test('should cancel a subscription', async ({ page }) => {
12
+ await page.goto(`/en/organizations/${organization.toLowerCase()}/subscriptions`);
13
+ await page
14
+ .locator('.card:has-text("STANDARD")')
15
+ .getByRole('button', { name: 'Cancel' })
16
+ .click();
17
+ await page.getByLabel('Cancellation reason(Optional)').fill('Not happy.');
18
+ await expect(page.getByRole('button', { name: 'Cancel subscription' })).toBeVisible();
19
+ // eslint-disable-next-line playwright/no-conditional-in-test
20
+ if (!CI) {
21
+ await page.getByRole('button', { name: 'Cancel subscription' }).click();
22
+ await expect(page.getByText('Extend')).toBeVisible();
23
+ await expect(page.getByText('Expires on')).toBeVisible();
24
+ }
25
+ });
26
+ (CI ? test.skip : test)('should confirm correct redirect by extension', async ({ page }) => {
27
+ await page.goto(`/en/organizations/${organization.toLowerCase()}/subscriptions`);
28
+ await page.locator('.card:has-text("STANDARD")').getByRole('link', { name: 'Extend' }).click();
29
+ await expect(page).toHaveTitle('Activate · Appsemble', { timeout: 10000 });
30
+ });
31
+ test('should purchase a subscription', async ({ page }) => {
32
+ await page.goto(`/en/organizations/${organization.toLowerCase()}/subscriptions`);
33
+ await page.locator('.card:has-text("EXTENSIVE")').getByRole('link', { name: 'Switch' }).click();
34
+ await expect(page.getByText('Select type of')).toBeVisible();
35
+ await expect(page.getByText('Total subscription priceActive subscription discountCoupon discountTotal price')).toBeVisible();
36
+ await page.getByRole('button', { name: 'Checkout ' }).click();
37
+ await page.getByLabel('Email').fill(email);
38
+ await page.getByLabel('Street name').fill(streetName);
39
+ await page.getByLabel('House number').fill(houseNumber);
40
+ await page.getByLabel('City').fill(city);
41
+ await page.getByLabel('Zip code').fill(zipCode);
42
+ await page.getByLabel('Country').selectOption(country);
43
+ await page.getByLabel('Name', { exact: true }).fill(organization);
44
+ await page.getByRole('button').getByText('Continue').click();
45
+ await expect(page.getByText('Total subscription priceActive subscription discountCoupon discountVAT 21%Total price')).toBeVisible();
46
+ // eslint-disable-next-line playwright/no-conditional-in-test
47
+ if (!CI) {
48
+ await page.getByRole('button', { name: 'Summary ' }).click();
49
+ await expect(page).toHaveTitle('Appsemble b.v.', { timeout: 10000 });
50
+ await page.getByTestId('sepa_debit-accordion-item').click();
51
+ await page.locator('[placeholder="\\NL00 AAAA 0000 0000 00"]').click();
52
+ await page.locator('[placeholder="\\NL00 AAAA 0000 0000 00"]').fill('NL39RABO0300065264');
53
+ await page.getByLabel('Name on account').fill(organization);
54
+ await page.getByPlaceholder('Address line 1').fill(streetName);
55
+ await page.getByPlaceholder('Postal code').fill(zipCode);
56
+ await page.getByPlaceholder('City').fill(city);
57
+ await page.getByTestId('hosted-payment-submit-button').click();
58
+ await expect(page.getByText('Purchase successful')).toBeVisible({ timeout: 30000 });
59
+ await expect(page.getByText('New expiration date')).toBeVisible({ timeout: 60000 });
60
+ await expect(page.getByText('Subscription plan')).toBeVisible();
61
+ await expect(page.getByText('Renewal period')).toBeVisible();
62
+ await expect(page.getByText('extensive')).toBeVisible();
63
+ await expect(page.getByText('month')).toBeVisible();
64
+ await page.getByRole('link', { name: 'Finish' }).click();
65
+ }
66
+ });
67
+ });
68
+ //# sourceMappingURL=subscription-flow.spec.js.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,105 @@
1
+ import { expect, test } from '../../index.js';
2
+ test.describe('Training', () => {
3
+ test.beforeEach(async ({ page, resetTrainingProgress }) => {
4
+ await resetTrainingProgress();
5
+ await page.goto('/en/trainings');
6
+ });
7
+ // We only have 1 account, so tests can influence each other
8
+ test.describe.configure({ mode: 'serial' });
9
+ test("should show 'Training' in breadcrumbs", async ({ page }) => {
10
+ await expect(page.getByLabel('Breadcrumbs').getByRole('listitem').filter({ hasText: 'Training' })).toBeVisible();
11
+ });
12
+ test('should update training and chapter status once training is completed', async ({ page }) => {
13
+ await page.getByTestId('rf__node-what-is-appsemble').getByRole('link').click();
14
+ await page.getByRole('button', { name: 'Click to complete' }).click();
15
+ await page.getByRole('button', { name: 'Back to tree' }).click();
16
+ await expect(page.getByTestId('rf__node-introduction')).toHaveChapterStatus('in progress');
17
+ await expect(page.getByTestId('rf__node-what-is-appsemble')).toHaveChapterStatus('completed');
18
+ });
19
+ test('should show the first chapter unlocked and the second one blocked', async ({ page }) => {
20
+ const nodeStatus = [
21
+ { name: 'rf__node-introduction', status: 'available' },
22
+ { name: 'rf__node-what-is-appsemble', status: 'available' },
23
+ { name: 'rf__node-get-familiar-with-the-studio', status: 'available' },
24
+ { name: 'rf__node-how-to-create-an-app', status: 'blocked' },
25
+ { name: 'rf__node-app-structure', status: 'blocked' },
26
+ { name: 'rf__node-what-is-a-page', status: 'blocked' },
27
+ { name: 'rf__node-what-is-a-block', status: 'blocked' },
28
+ { name: 'rf__node-simple-app', status: 'blocked' },
29
+ ];
30
+ for (const { name, status } of nodeStatus) {
31
+ await expect(page.getByTestId(name)).toHaveChapterStatus(status);
32
+ }
33
+ });
34
+ test('should unlock next chapter once blocking chapter is completed', async ({ page }) => {
35
+ await page.getByTestId('rf__node-what-is-appsemble').getByRole('link').click();
36
+ await page.getByRole('button', { name: 'Click to complete' }).click();
37
+ await page.getByRole('button', { name: 'To "Get familiar with the studio"' }).click();
38
+ await page.getByRole('button', { name: 'Click to complete' }).click();
39
+ await page.getByRole('button', { name: 'Back to tree' }).click();
40
+ const nodeStatus = [
41
+ { name: 'rf__node-introduction', status: 'completed' },
42
+ { name: 'rf__node-what-is-appsemble', status: 'completed' },
43
+ { name: 'rf__node-get-familiar-with-the-studio', status: 'completed' },
44
+ { name: 'rf__node-how-to-create-an-app', status: 'available' },
45
+ { name: 'rf__node-app-structure', status: 'available' },
46
+ { name: 'rf__node-what-is-a-page', status: 'available' },
47
+ { name: 'rf__node-what-is-a-block', status: 'available' },
48
+ { name: 'rf__node-simple-app', status: 'available' },
49
+ ];
50
+ for (const { name, status } of nodeStatus) {
51
+ await expect(page.getByTestId(name)).toHaveChapterStatus(status);
52
+ }
53
+ });
54
+ test('should unlock all blocked chapters once blocker is completed', async ({ completeTraining, page, }) => {
55
+ await expect(page.getByTestId('rf__node-data-transformation')).toHaveChapterStatus('blocked');
56
+ await expect(page.getByTestId('rf__node-styling-apps')).toHaveChapterStatus('blocked');
57
+ const prerequisiteTrainings = [
58
+ 'what-is-appsemble',
59
+ 'get-familiar-with-the-studio',
60
+ 'app-structure',
61
+ 'what-is-a-page',
62
+ 'what-is-a-block',
63
+ 'simple-app',
64
+ 'events',
65
+ 'actions',
66
+ 'what-is-a-resource',
67
+ 'storing-resource-entry',
68
+ 'fetching-resources',
69
+ ];
70
+ for (const trainingId of prerequisiteTrainings) {
71
+ await completeTraining(trainingId);
72
+ }
73
+ await page.reload();
74
+ await expect(page.getByTestId('rf__node-data-transformation')).toHaveChapterStatus('available');
75
+ await expect(page.getByTestId('rf__node-styling-apps')).toHaveChapterStatus('available');
76
+ });
77
+ test('should unlock chapter that is blocked by multiple chapters when they are all completed', async ({ completeTraining, page, }) => {
78
+ await expect(page.getByTestId('rf__node-basic-app')).toHaveChapterStatus('blocked');
79
+ const prerequisiteTrainings = [
80
+ 'what-is-appsemble',
81
+ 'get-familiar-with-the-studio',
82
+ 'app-structure',
83
+ 'what-is-a-page',
84
+ 'what-is-a-block',
85
+ 'simple-app',
86
+ 'events',
87
+ 'actions',
88
+ 'what-is-a-resource',
89
+ 'storing-resource-entry',
90
+ 'fetching-resources',
91
+ 'what-are-remappers',
92
+ 'remapper-chaining',
93
+ 'remapper-history',
94
+ 'styling-options',
95
+ 'bulma-theming',
96
+ 'custom-css',
97
+ ];
98
+ for (const trainingId of prerequisiteTrainings) {
99
+ await completeTraining(trainingId);
100
+ }
101
+ await page.reload();
102
+ await expect(page.getByTestId('rf__node-basic-app')).toHaveChapterStatus('available');
103
+ });
104
+ });
105
+ //# sourceMappingURL=trainings.spec.js.map
@@ -1,79 +0,0 @@
1
- import { expect, test } from '../../../index.js';
2
- async function clickSideMenuItem(page, title) {
3
- await page.getByTestId('studio-app-side-menu').getByRole('link', { name: title }).click();
4
- }
5
- test.describe('/apps/:appId', () => {
6
- test.beforeEach(async ({ page }) => {
7
- await page.goto('/en/apps');
8
- await page.getByRole('link', { name: 'Person Appsemble' }).first().click();
9
- await expect(page.getByTestId('studio-app-side-menu-name')).toHaveText('Person');
10
- });
11
- test('should prompt when user has unsaved changes', async ({ page }) => {
12
- await clickSideMenuItem(page, 'Editor');
13
- page.on('dialog', (alert) => {
14
- expect(alert.type()).toBe('confirm');
15
- expect(alert.message()).toBe('You have unsaved changes. Do you wish to continue?');
16
- alert.dismiss();
17
- });
18
- await expect(page.getByRole('button', { name: 'Publish' })).toBeDisabled();
19
- await page.getByRole('code').getByText('Person', { exact: true }).dblclick();
20
- await page.getByRole('code').getByText('Person', { exact: true }).press('Backspace');
21
- await page.getByRole('code').getByText('name:').first().press('t+e+s+t');
22
- await expect(page.getByRole('button', { name: 'Publish' })).toBeEnabled();
23
- await page.getByRole('link', { name: 'Details' }).click();
24
- await expect(page.getByText('Clone App')).toBeHidden();
25
- });
26
- test('should not prompt when user has saved their changes', async ({ page }) => {
27
- await clickSideMenuItem(page, 'Editor');
28
- await page.route('/api/apps/*', (route) => {
29
- route.fulfill({ path: 'mock-data/person-app-definition.json' });
30
- });
31
- page.on('dialog', (alert) => {
32
- // If a dialog comes up at all, the test should fail
33
- expect(alert).toBeNull();
34
- });
35
- await expect(page.getByRole('button', { name: 'Publish' })).toBeDisabled();
36
- await page.getByRole('code').getByText('Person', { exact: true }).dblclick();
37
- await page.getByRole('code').getByText('Person', { exact: true }).press('Backspace');
38
- await page.getByRole('code').getByText('name:').first().press('P+e+r+s+o+n');
39
- await page.getByRole('button', { name: 'Publish' }).click();
40
- await expect(page.getByText('Successfully updated app definition')).toBeVisible();
41
- await page.getByRole('link', { name: 'Details' }).click();
42
- await expect(page.getByText('Clone App')).toBeVisible();
43
- });
44
- test('should link to the asset viewer', async ({ page }) => {
45
- await clickSideMenuItem(page, 'Assets');
46
- await expect(page.getByText('Upload new asset')).toBeVisible();
47
- });
48
- test('should link to resources', async ({ page }) => {
49
- await clickSideMenuItem(page, 'Resources');
50
- await expect(page.getByText('This app has the following resources')).toBeVisible();
51
- });
52
- test('should link to a specific resource', async ({ page }) => {
53
- await clickSideMenuItem(page, 'Resources');
54
- await page.click('li :has-text("person")');
55
- await expect(page.getByText('Resource: person')).toBeVisible();
56
- });
57
- test('should link to the translator tool', async ({ page }) => {
58
- await clickSideMenuItem(page, 'Translations');
59
- await expect(page.getByText('Selected language')).toBeVisible();
60
- });
61
- test('should link to the notification sender', async ({ page }) => {
62
- await clickSideMenuItem(page, 'Notifications');
63
- await expect(page.getByText('Push notifications are currently not enabled in this app.')).toBeVisible();
64
- });
65
- test('should link to the snapshots page', async ({ page }) => {
66
- await clickSideMenuItem(page, 'Snapshots');
67
- await expect(page.getByRole('heading', { name: 'Snapshots' })).toBeVisible();
68
- await expect(page.getByRole('listitem').filter({ has: page.getByRole('heading', { name: 'Appsemble' }) })).toBeVisible();
69
- });
70
- test('should link to the app settings', async ({ page }) => {
71
- await clickSideMenuItem(page, 'Settings');
72
- await expect(page.getByRole('heading', { name: 'App lock' })).toBeVisible();
73
- });
74
- test('should link to the app secrets', async ({ page }) => {
75
- await clickSideMenuItem(page, 'Secrets');
76
- await expect(page.getByRole('heading', { name: 'Appsemble Login' })).toBeVisible();
77
- });
78
- });
79
- //# sourceMappingURL=app.spec.js.map
@@ -1,30 +0,0 @@
1
- import { expect, test } from '../../index.js';
2
- test.describe('Apps', () => {
3
- test.beforeEach(async ({ page }) => {
4
- await page.goto('/en/apps');
5
- });
6
- test('should show the page header', async ({ page }) => {
7
- await expect(page.locator('text=All Apps')).toBeVisible();
8
- });
9
- test('should display “My Apps” when logged in', async ({ page }) => {
10
- await expect(page.getByText('My Apps')).toBeVisible();
11
- });
12
- test('should render default apps', async ({ page }) => {
13
- const defaultApps = [
14
- { name: 'Empty App' },
15
- { name: 'Holidays' },
16
- { name: 'Notes' },
17
- { name: 'Person' },
18
- { name: 'Survey' },
19
- { name: 'Unlittered' },
20
- ];
21
- for (const { name } of defaultApps) {
22
- await expect(page.getByText(name).first()).toBeVisible();
23
- }
24
- });
25
- test('should link to app details', async ({ page }) => {
26
- await page.click('text=Empty App');
27
- await expect(page.getByText('Empty App is a bare-bones app with two pages and buttons switching between them.')).toBeVisible();
28
- });
29
- });
30
- //# sourceMappingURL=apps.spec.js.map
@@ -1,20 +0,0 @@
1
- import { expect, test } from '../../index.js';
2
- test.describe('Blocks', () => {
3
- test.beforeEach(async ({ page }) => {
4
- await page.goto('/en/blocks');
5
- });
6
- test('should render a list of blocks', async ({ page }) => {
7
- const dataLoader = page.locator('[title="@appsemble/data-loader"]');
8
- await expect(dataLoader).toContainText('data-loader');
9
- await expect(dataLoader).toContainText('@appsemble');
10
- await expect(dataLoader).toContainText('A block that fetches data and emits it using the events API.');
11
- });
12
- test('should link to block details', async ({ page }) => {
13
- const dataLoader = page.locator('[title="@appsemble/data-loader"]');
14
- await dataLoader.locator('text=View details').click();
15
- await expect(page.getByRole('heading', { name: 'Parameters', exact: true })).toBeVisible();
16
- await expect(page.getByRole('heading', { name: 'Actions', exact: true })).toBeVisible();
17
- await expect(page.getByRole('heading', { name: 'Events', exact: true })).toBeVisible();
18
- });
19
- });
20
- //# sourceMappingURL=blocks.spec.js.map
@@ -1,4 +0,0 @@
1
- export declare const availableColor = "rgb(255, 255, 255)";
2
- export declare const inProgressColor = "rgb(255, 127, 39)";
3
- export declare const completedColor = "rgb(34, 177, 76)";
4
- export declare const blockedColor = "rgb(211, 211, 211)";
@@ -1,5 +0,0 @@
1
- export const availableColor = 'rgb(255, 255, 255)';
2
- export const inProgressColor = 'rgb(255, 127, 39)';
3
- export const completedColor = 'rgb(34, 177, 76)';
4
- export const blockedColor = 'rgb(211, 211, 211)';
5
- //# sourceMappingURL=constants.js.map
@@ -1,93 +0,0 @@
1
- import { expect, test } from '../../../index.js';
2
- test.beforeEach(async ({ page, resetTrainingProgress }) => {
3
- await resetTrainingProgress();
4
- await page.goto('/en/trainings');
5
- });
6
- // We only have 1 account, so tests can influence each other
7
- test.describe.configure({ mode: 'serial' });
8
- test('should show the first chapter unlocked and the second one blocked', async ({ page }) => {
9
- const nodeStatus = [
10
- { name: 'rf__node-introduction', status: 'available' },
11
- { name: 'rf__node-what-is-appsemble', status: 'available' },
12
- { name: 'rf__node-get-familiar-with-the-studio', status: 'available' },
13
- { name: 'rf__node-how-to-create-an-app', status: 'blocked' },
14
- { name: 'rf__node-app-structure', status: 'blocked' },
15
- { name: 'rf__node-what-is-a-page', status: 'blocked' },
16
- { name: 'rf__node-what-is-a-block', status: 'blocked' },
17
- { name: 'rf__node-simple-app', status: 'blocked' },
18
- ];
19
- for (const { name, status } of nodeStatus) {
20
- await expect(page.getByTestId(name)).toHaveChapterStatus(status);
21
- }
22
- });
23
- test('should unlock next chapter once blocking chapter is completed', async ({ page }) => {
24
- await page.getByTestId('rf__node-what-is-appsemble').getByRole('link').click();
25
- await page.getByRole('button', { name: 'Click to complete' }).click();
26
- await page.getByRole('button', { name: 'To "Get familiar with the studio"' }).click();
27
- await page.getByRole('button', { name: 'Click to complete' }).click();
28
- await page.getByRole('button', { name: 'Back to tree' }).click();
29
- const nodeStatus = [
30
- { name: 'rf__node-introduction', status: 'completed' },
31
- { name: 'rf__node-what-is-appsemble', status: 'completed' },
32
- { name: 'rf__node-get-familiar-with-the-studio', status: 'completed' },
33
- { name: 'rf__node-how-to-create-an-app', status: 'available' },
34
- { name: 'rf__node-app-structure', status: 'available' },
35
- { name: 'rf__node-what-is-a-page', status: 'available' },
36
- { name: 'rf__node-what-is-a-block', status: 'available' },
37
- { name: 'rf__node-simple-app', status: 'available' },
38
- ];
39
- for (const { name, status } of nodeStatus) {
40
- await expect(page.getByTestId(name)).toHaveChapterStatus(status);
41
- }
42
- });
43
- test('should unlock all blocked chapters once blocker is completed', async ({ completeTraining, page, }) => {
44
- await expect(page.getByTestId('rf__node-data-transformation')).toHaveChapterStatus('blocked');
45
- await expect(page.getByTestId('rf__node-styling-apps')).toHaveChapterStatus('blocked');
46
- const prerequisiteTrainings = [
47
- 'what-is-appsemble',
48
- 'get-familiar-with-the-studio',
49
- 'app-structure',
50
- 'what-is-a-page',
51
- 'what-is-a-block',
52
- 'simple-app',
53
- 'events',
54
- 'actions',
55
- 'what-is-a-resource',
56
- 'storing-resource-entry',
57
- 'fetching-resources',
58
- ];
59
- for (const trainingId of prerequisiteTrainings) {
60
- await completeTraining(trainingId);
61
- }
62
- await page.reload();
63
- await expect(page.getByTestId('rf__node-data-transformation')).toHaveChapterStatus('available');
64
- await expect(page.getByTestId('rf__node-styling-apps')).toHaveChapterStatus('available');
65
- });
66
- test('should unlock chapter that is blocked by multiple chapters when they are all completed', async ({ completeTraining, page, }) => {
67
- await expect(page.getByTestId('rf__node-basic-app')).toHaveChapterStatus('blocked');
68
- const prerequisiteTrainings = [
69
- 'what-is-appsemble',
70
- 'get-familiar-with-the-studio',
71
- 'app-structure',
72
- 'what-is-a-page',
73
- 'what-is-a-block',
74
- 'simple-app',
75
- 'events',
76
- 'actions',
77
- 'what-is-a-resource',
78
- 'storing-resource-entry',
79
- 'fetching-resources',
80
- 'what-are-remappers',
81
- 'remapper-chaining',
82
- 'remapper-history',
83
- 'styling-options',
84
- 'bulma-theming',
85
- 'custom-css',
86
- ];
87
- for (const trainingId of prerequisiteTrainings) {
88
- await completeTraining(trainingId);
89
- }
90
- await page.reload();
91
- await expect(page.getByTestId('rf__node-basic-app')).toHaveChapterStatus('available');
92
- });
93
- //# sourceMappingURL=logged-in.spec.js.map
@@ -1,42 +0,0 @@
1
- import { availableColor } from './constants.js';
2
- import { expect, test } from '../../../fixtures/index.js';
3
- test.beforeEach(async ({ page }) => {
4
- await page.goto('/en/trainings');
5
- await expect(page.getByLabel('Breadcrumbs').getByRole('listitem').filter({ hasText: 'Training' })).toBeVisible();
6
- });
7
- test.use({ storageState: { cookies: [], origins: [] } });
8
- test('should render first chapter in training tree', async ({ page }) => {
9
- await expect(page.getByTestId('rf__node-introduction')).toBeVisible();
10
- });
11
- test('should show banner if user is not logged in', async ({ page }) => {
12
- await expect(page.getByText('Warning: You are currently not logged in. While logged out you can access all trainings, but progress will not be saved')).toBeVisible();
13
- });
14
- test('should have all trainings unlocked if user is not logged in', async ({ page }) => {
15
- // Wait for initialization since locator.all() does not wait for elements to be visible
16
- await page.getByTestId('rf__node-introduction').waitFor({ state: 'visible' });
17
- const statusCircles = await page.getByTestId('status-circle').all();
18
- expect(statusCircles.length).toBeGreaterThan(0);
19
- for (const statusCircle of statusCircles) {
20
- await expect(statusCircle).toHaveCSS('background-color', availableColor);
21
- }
22
- const blockedNodeTitles = await page.getByTestId('node-title-blocked').all();
23
- expect(blockedNodeTitles.length).toBe(0);
24
- });
25
- test('should navigate to training once the link is clicked', async ({ page }) => {
26
- await page.getByTestId('rf__node-what-is-appsemble').getByRole('link').click();
27
- await expect(page.getByRole('heading', { name: 'Appsemble Introduction ' })).toBeVisible();
28
- });
29
- test('should update training and chapter status once training is completed', async ({ page }) => {
30
- await page.getByTestId('rf__node-what-is-appsemble').getByRole('link').click();
31
- await page.getByRole('button', { name: 'Click to complete' }).click();
32
- await page.getByRole('button', { name: 'Back to tree' }).click();
33
- await expect(page.getByTestId('rf__node-introduction')).toHaveChapterStatus('in progress');
34
- await expect(page.getByTestId('rf__node-what-is-appsemble')).toHaveChapterStatus('completed');
35
- });
36
- test('should allow user to click through chapter trainings', async ({ page }) => {
37
- await page.getByTestId('rf__node-what-is-appsemble').getByRole('link').click();
38
- await page.getByRole('button', { name: 'Click to complete' }).click();
39
- await page.getByRole('button', { name: 'To "Get familiar with the studio"' }).click();
40
- await expect(page.getByRole('heading', { name: 'Get familiar with the studio' })).toBeVisible();
41
- });
42
- //# sourceMappingURL=logged-out.spec.js.map
@@ -1,14 +0,0 @@
1
- import { expect, test } from '../../index.js';
2
- test.describe('Empty', () => {
3
- test.beforeEach(async ({ page, visitApp }) => {
4
- await visitApp('empty');
5
- await page.waitForURL('**/example-page-a');
6
- });
7
- test('should navigate to the second page and back', async ({ page }) => {
8
- await page.click('a.button');
9
- await expect(page.getByRole('heading', { name: 'Example Page B' })).toBeVisible();
10
- await page.click('a.button');
11
- await expect(page.getByRole('heading', { name: 'Example Page A' })).toBeVisible();
12
- });
13
- });
14
- //# sourceMappingURL=empty.spec.js.map
File without changes
File without changes
File without changes
File without changes