Skip to content

Commit 5240200

Browse files
(test) O3-3601 : E2E tests for User onboarding (#7)
--------- Co-authored-by: Jayasanka Weerasinghe <[email protected]>
1 parent 711ed30 commit 5240200

File tree

9 files changed

+1657
-1497
lines changed

9 files changed

+1657
-1497
lines changed

e2e/specs/onboarding-test.spec.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { test } from '@playwright/test';
2+
import { HomePage } from '../pages';
3+
import { expect } from '@playwright/test';
4+
5+
test('Basic Walkthrough', async ({ page }) => {
6+
const homePage = new HomePage(page);
7+
8+
await test.step('When I visit the home page', async () => {
9+
await homePage.goto();
10+
});
11+
12+
await test.step('And I click on the help menu button', async () => {
13+
await page.locator('[id="single-spa-application\\:\\@openmrs\\/esm-help-menu-app-page-0"]').getByRole('button').click();
14+
});
15+
16+
await test.step('And I click on the tutorials button', async () => {
17+
await page.getByText(/tutorials/i).click();
18+
});
19+
20+
await test.step('Then I should see the tutorial modal', async () => {
21+
await expect(page.getByRole('heading', { name: 'Tutorials' })).toBeVisible();
22+
await expect(
23+
page.getByText(/find walkthroughs and video tutorials on some of the core features of openMRS./i),
24+
).toBeVisible();
25+
});
26+
27+
await test.step('And I click on the Basic Tutorial walkthrough', async () => {
28+
await page
29+
.locator('li')
30+
.filter({ hasText: 'Basic Tutorial' })
31+
.locator('button', { hasText: 'Walkthrough' })
32+
.click();
33+
});
34+
35+
await test.step('Then I should see the first Joyride tooltip', async () => {
36+
await expect(
37+
page.getByText(
38+
'Welcome to OpenMRS! This is the main dashboard where you can navigate to various features of the system.',
39+
),
40+
).toBeVisible();
41+
});
42+
43+
await test.step('And I click the next button', async () => {
44+
await page.getByLabel('Next', { exact: true }).click();
45+
});
46+
47+
await test.step('Then I should see the search icon Joyride tooltip', async () => {
48+
await expect(
49+
page.getByText('This is the search icon. Use it to find patients in the system quickly.'),
50+
).toBeVisible();
51+
});
52+
await test.step('And I click the next button', async () => {
53+
await page.getByLabel('Next', { exact: true }).click();
54+
});
55+
56+
await test.step('Then I should see the add patient icon Joyride tooltip', async () => {
57+
await expect(
58+
page.getByText('This is the add patient icon. Click here to register a new patient into the system.'),
59+
).toBeVisible();
60+
});
61+
await test.step('And I click the next button', async () => {
62+
await page.getByLabel('Next', { exact: true }).click();
63+
});
64+
65+
await test.step('Then I should see the user icon Joyride tooltip', async () => {
66+
await expect(
67+
page.getByText('The user icon. Click here to change your user preferences and settings.'),
68+
).toBeVisible();
69+
});
70+
await test.step('And I click the next button', async () => {
71+
await page.getByLabel('Next', { exact: true }).click();
72+
});
73+
74+
await test.step('Then I should see the active visits Joyride tooltip', async () => {
75+
await expect(
76+
page.getByText('This table displays active visits. Here you can see all the ongoing patient visits.'),
77+
).toBeVisible();
78+
});
79+
80+
await test.step('And I click the next button', async () => {
81+
await page.getByLabel('Next', { exact: true }).click();
82+
});
83+
84+
await test.step('And I should see the appointments table Joyride tooltip', async () => {
85+
await expect(
86+
page.getByText('This table shows appointments. View and manage patient appointments from this section.'),
87+
).toBeVisible();
88+
});
89+
90+
await test.step('And I click the finish button', async () => {
91+
await page.getByLabel('Last').click();
92+
});
93+
});

e2e/specs/sample-test.spec.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

e2e/support/github/run-e2e-docker-env.sh

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,36 @@
11
#!/usr/bin/env bash -eu
2-
32
# get the dir containing the script
43
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
54
# create a temporary working directory
65
working_dir=$(mktemp -d "${TMPDIR:-/tmp/}openmrs-e2e-frontends.XXXXXXXXXX")
7-
# get a list of all the apps in this workspace
8-
apps=$(yarn workspaces list --json | jq -r 'if ((.location == ".") or (.location | test("form-engine-app")) or (.location | test("-app") | not)) then halt else .name end')
9-
# this array will hold all of the packed app names
10-
app_names=()
6+
# get the app name
7+
app_name=$(jq -r '.name' "$script_dir/../../../package.json")
118

12-
echo "Creating packed archives of apps..."
13-
# for each app
14-
for app in $apps
15-
do
16-
# @openmrs/esm-whatever -> _openmrs_esm_whatever
17-
app_name=$(echo "$app" | tr '[:punct:]' '_');
18-
# add to our array
19-
app_names+=("$app_name.tgz");
20-
# run yarn pack for our app and add it to the working directory
21-
yarn workspace "$app" pack -o "$working_dir/$app_name.tgz" >/dev/null;
22-
done;
23-
echo "Created packed app archives"
9+
echo "Creating packed archive of the app..."
10+
# @openmrs/esm-whatever -> _openmrs_esm_whatever
11+
packed_app_name=$(echo "$app_name" | tr '[:punct:]' '_');
12+
# run yarn pack for our app and add it to the working directory
13+
yarn pack -o "$working_dir/$packed_app_name.tgz" >/dev/null;
14+
echo "Created packed app archives"
2415

2516
echo "Creating dynamic spa-assemble-config.json..."
2617
# dynamically assemble our list of frontend modules, prepending the login app and
2718
# primary navigation apps; apps will all be in the /app directory of the Docker
2819
# container
2920
jq -n \
30-
--arg apps "$apps" \
31-
--arg app_names "$(echo ${app_names[@]})" \
32-
'{"@openmrs/esm-primary-navigation-app": "next", "@openmrs/esm-home-app": "next"} + (
33-
($apps | split("\n")) as $apps | ($app_names | split(" ") | map("/app/" + .)) as $app_files
34-
| [$apps, $app_files]
35-
| transpose
36-
| map({"key": .[0], "value": .[1]})
37-
| from_entries
38-
)' | jq '{"frontendModules": .}' > "$working_dir/spa-assemble-config.json"
21+
--arg app_name "$app_name" \
22+
--arg app_file "/app/$packed_app_name.tgz" \
23+
'{
24+
"@openmrs/esm-primary-navigation-app": "next",
25+
"@openmrs/esm-home-app": "next",
26+
"@openmrs/esm-help-menu-app": "next",
27+
"@openmrs/esm-patient-search-app": "next",
28+
"@openmrs/esm-patient-registration-app": "next",
29+
"@openmrs/esm-active-visits-app": "next",
30+
"@openmrs/esm-appointments-app": "next"
31+
} + {
32+
($app_name): $app_file
33+
}' | jq '{"frontendModules": .}' > "$working_dir/spa-assemble-config.json"
3934
echo "Created dynamic spa-assemble-config.json"
4035

4136
echo "Copying Docker configuration..."

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"devDependencies": {
5656
"@openmrs/esm-framework": "next",
5757
"@openmrs/esm-styleguide": "next",
58-
"@playwright/test": "^1.42.1",
58+
"@playwright/test": "1.44.0",
5959
"@swc/cli": "^0.3.12",
6060
"@swc/core": "^1.3.68",
6161
"@swc/jest": "^0.2.36",

playwright.config.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,19 @@ const config: PlaywrightTestConfig = {
1212
fullyParallel: true,
1313
forbidOnly: !!process.env.CI,
1414
retries: 0,
15-
reporter: process.env.CI ? [['junit', { outputFile: 'results.xml' }], ['html']] : [['html']],
15+
outputDir: "../test-results/results",
16+
reporter: process.env.CI
17+
? [
18+
["junit", { outputFile: "results.xml" }],
19+
["html"],
20+
]
21+
: [["html", { outputFolder: "./../test-results/report" }]],
1622
globalSetup: require.resolve('./e2e/core/global-setup'),
1723
use: {
1824
baseURL: `${process.env.E2E_BASE_URL}/spa/`,
1925
storageState: 'e2e/storageState.json',
20-
video: 'retain-on-failure',
26+
video: 'on',
27+
trace: 'retain-on-failure',
2128
},
2229
projects: [
2330
{

src/config-schema.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ export const configSchema = {
1212
_default: [
1313
{
1414
title: 'Basic Tutorial',
15-
description:
16-
'Learn how to efficiently search for patients, register new patients, access user settings, and view ongoing visits and appointments.',
17-
steps: [
18-
{
19-
target: '[aria-label="OpenMRS"]',
20-
content:
21-
'Welcome to OpenMRS! This is the main dashboard where you can navigate to various features of the system.',
22-
},
15+
description: 'Learn how to efficiently search for patients, register new patients, access user settings, and view ongoing visits and appointments.',
16+
steps: [{
17+
target: '[aria-label="OpenMRS"]',
18+
content: 'Welcome to OpenMRS! This is the main dashboard where you can navigate to various features of the system.',
19+
disableBeacon: true
20+
},
2321
{
2422
target: '[name="SearchPatientIcon"]',
2523
content: 'This is the search icon. Use it to find patients in the system quickly.',

src/tutorial/modal.component.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
33
import { useConfig, useAppContext, navigate } from '@openmrs/esm-framework';
44
import styles from './styles.scss';
55
import { type TutorialContext } from '../types';
6-
import { ModalHeader, ModalBody } from '@carbon/react';
6+
import { ModalHeader, ModalBody, Button } from '@carbon/react';
77

88
const TutorialModal = ({ open, onClose }) => {
99
const { t } = useTranslation();
@@ -45,15 +45,17 @@ const TutorialModal = ({ open, onClose }) => {
4545
</p>
4646
</ModalHeader>
4747
<ModalBody className={styles.tutorialModal}>
48-
{tutorials.map((tutorial, index) => (
49-
<div className={styles.tutorialItem} key={index}>
50-
<h3 className={styles.tutorialTitle}>{tutorial.title}</h3>
51-
<p className={styles.tutorialDescription}>{tutorial.description}</p>
52-
<div className={styles.walkthrough} onClick={() => handleWalkthroughClick(index)}>
53-
{t('walkthrough', 'Walkthrough')}
54-
</div>
55-
</div>
56-
))}
48+
<ul>
49+
{tutorials.map((tutorial, index) => (
50+
<li className={styles.tutorialItem} key={index}>
51+
<h3 className={styles.tutorialTitle}>{tutorial.title}</h3>
52+
<p className={styles.tutorialDescription}>{tutorial.description}</p>
53+
<Button kind="ghost" onClick={() => handleWalkthroughClick(index)}>
54+
{t('walkthrough', 'Walkthrough')}
55+
</Button>
56+
</li>
57+
))}
58+
</ul>
5759
</ModalBody>
5860
</React.Fragment>
5961
);

src/tutorial/styles.scss

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,5 @@
2626
@include type.type-style('body-compact-01');
2727
}
2828

29-
.walkthrough {
30-
margin-bottom: spacing.$spacing-03;
31-
margin-top: spacing.$spacing-03;
32-
color: $color-blue-60-2;
33-
@include type.type-style('body-compact-02');
34-
}
3529
}
3630
}

0 commit comments

Comments
 (0)