Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(test) O3-3601 : E2E tests for User onboarding #7

Merged
merged 12 commits into from
Aug 5, 2024
Merged
60 changes: 60 additions & 0 deletions e2e/specs/onboarding-test.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { test } from '@playwright/test';
import { HomePage } from '../pages';
import { expect } from '@playwright/test';

test('Basic Walkthrough', async ({ page }) => {
const homePage = new HomePage(page);

await test.step('When I visit the home page', async () => {
await homePage.goto();
});

await test.step('And I click on the help menu button', async () => {
await page.locator('[id="single-spa-application\\:\\@openmrs\\/esm-help-menu-app-page-0"]').getByRole('button').click();
});

await test.step('And I click on the tutorials button', async () => {
await page.getByText(/tutorials/i).click();
});

await test.step('Then I should see the tutorial modal', async () => {
await expect(page.getByRole('heading', { name: 'Tutorials' })).toBeVisible();
await expect(
page.getByText(/find walkthroughs and video tutorials on some of the core features of openMRS./i),
).toBeVisible();
});

await test.step('And I click on the Basic Tutorial walkthrough', async () => {
await page.getByText('Walkthrough').nth(1).click();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't guarantee the order of the list. The order may change when we add new tutorials. So, we need to think of a better selector.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jayasanka-sack I didn't figure out how we can select those walkthoroughs.
An approach that came to my mind is having a selector in the tutorial modal #L49 and searching for the Heading and corresponding walkthrough. WDYT?

Copy link
Member

@jayasanka-sack jayasanka-sack Aug 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, I've noticed a few adjustments needed for the tutorial to follow best practices:

  • Change the list to an unordered list. This will be beneficial for both testing and accessibility.
  • Currently, the walkthrough button is a div. It should be a button. (A ghost button would be the option.)

Here is how your code should look (there won't be any visual changes):

<ul>
   {tutorials.map -> tutorial}
      <li>
          <h3>{title}</h3>
          <p>{description}</p>
          <Button kind="ghost">Button</Button>
      </li>
   {/tutorials}
</ul>

Once you've done that, you can select the button with this:

const tutorialTitle = "Basic ..."
await page.locator('li', { hasText: 'my item' }).locator('button').click();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a small visual change in the alignment of buttons. is this fine?

walkthrough-btn.mov

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. Btw, can we get the close button fixed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. Btw, can we get the close button fixed?

This is due to the upgrade in carbon dependencies in this PR

This would be the fix #215, I'll talk with dennis regarding merge of that PR in todays coffee call.

});

await test.step('Then I should see the first Joyride tooltip', async () => {
await expect(page.locator('div').filter({ hasText: 'Welcome to OpenMRS!' }).nth(1)).toBeVisible();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await expect(page.locator('div').filter({ hasText: 'Welcome to OpenMRS!' }).nth(1)).toBeVisible();
await expect(page.getByText('Welcome to OpenMRS!')).toBeVisible();

await page.getByLabel('Next', { exact: true }).click();
jayasanka-sack marked this conversation as resolved.
Show resolved Hide resolved
});

await test.step('And I should see the search icon Joyride tooltip', async () => {
await expect(page.locator('div').filter({ hasText: 'This is the search icon.' }).nth(1)).toBeVisible();
await page.getByLabel('Next', { exact: true }).click();
});

await test.step('Then I should see the add patient icon Joyride tooltip', async () => {
await expect(page.locator('div').filter({ hasText: 'This is the add patient' }).nth(1)).toBeVisible();
await page.getByLabel('Next', { exact: true }).click();
});

await test.step('And I should see the user icon Joyride tooltip', async () => {
await expect(page.locator('div').filter({ hasText: 'The user icon' }).nth(1)).toBeVisible();
await page.getByLabel('Next', { exact: true }).click();
});

await test.step('Then I should see the active visits Joyride tooltip', async () => {
await expect(page.locator('div').filter({ hasText: 'This table displays active visits' }).nth(1)).toBeVisible();
await page.getByLabel('Next', { exact: true }).click();
});

await test.step('And I should see the appointments table Joyride tooltip', async () => {
await expect(page.locator('div').filter({ hasText: 'This table shows appointments' }).nth(1)).toBeVisible();
await page.getByLabel('Last').click();
});
});
11 changes: 0 additions & 11 deletions e2e/specs/sample-test.spec.ts

This file was deleted.

47 changes: 21 additions & 26 deletions e2e/support/github/run-e2e-docker-env.sh
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
#!/usr/bin/env bash -eu

# get the dir containing the script
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# create a temporary working directory
working_dir=$(mktemp -d "${TMPDIR:-/tmp/}openmrs-e2e-frontends.XXXXXXXXXX")
# get a list of all the apps in this workspace
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')
# this array will hold all of the packed app names
app_names=()
# get the app name
app_name=$(jq -r '.name' "$script_dir/../../../package.json")

echo "Creating packed archives of apps..."
# for each app
for app in $apps
do
# @openmrs/esm-whatever -> _openmrs_esm_whatever
app_name=$(echo "$app" | tr '[:punct:]' '_');
# add to our array
app_names+=("$app_name.tgz");
# run yarn pack for our app and add it to the working directory
yarn workspace "$app" pack -o "$working_dir/$app_name.tgz" >/dev/null;
done;
echo "Created packed app archives"
echo "Creating packed archive of the app..."
# @openmrs/esm-whatever -> _openmrs_esm_whatever
packed_app_name=$(echo "$app_name" | tr '[:punct:]' '_');
# run yarn pack for our app and add it to the working directory
yarn pack -o "$working_dir/$packed_app_name.tgz" >/dev/null;
echo "Created packed app archives"

echo "Creating dynamic spa-assemble-config.json..."
# dynamically assemble our list of frontend modules, prepending the login app and
# primary navigation apps; apps will all be in the /app directory of the Docker
# container
jq -n \
--arg apps "$apps" \
--arg app_names "$(echo ${app_names[@]})" \
'{"@openmrs/esm-primary-navigation-app": "next", "@openmrs/esm-home-app": "next"} + (
($apps | split("\n")) as $apps | ($app_names | split(" ") | map("/app/" + .)) as $app_files
| [$apps, $app_files]
| transpose
| map({"key": .[0], "value": .[1]})
| from_entries
)' | jq '{"frontendModules": .}' > "$working_dir/spa-assemble-config.json"
--arg app_name "$app_name" \
--arg app_file "/app/$packed_app_name.tgz" \
'{
"@openmrs/esm-primary-navigation-app": "next",
"@openmrs/esm-home-app": "next",
"@openmrs/esm-help-menu-app": "next",
"@openmrs/esm-patient-search-app": "next",
"@openmrs/esm-patient-registration-app": "next",
"@openmrs/esm-active-visits-app": "next",
"@openmrs/esm-appointments-app": "next"
} + {
($app_name): $app_file
}' | jq '{"frontendModules": .}' > "$working_dir/spa-assemble-config.json"
echo "Created dynamic spa-assemble-config.json"

echo "Copying Docker configuration..."
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"devDependencies": {
"@openmrs/esm-framework": "next",
"@openmrs/esm-styleguide": "next",
"@playwright/test": "^1.42.1",
"@playwright/test": "1.44.0",
"@swc/cli": "^0.3.12",
"@swc/core": "^1.3.68",
"@swc/jest": "^0.2.36",
Expand Down
9 changes: 8 additions & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,19 @@ const config: PlaywrightTestConfig = {
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: 0,
reporter: process.env.CI ? [['junit', { outputFile: 'results.xml' }], ['html']] : [['html']],
outputDir: "../test-results/results",
reporter: process.env.CI
? [
["junit", { outputFile: "results.xml" }],
["html"],
]
: [["html", { outputFolder: "./../test-results/report" }]],
globalSetup: require.resolve('./e2e/core/global-setup'),
use: {
baseURL: `${process.env.E2E_BASE_URL}/spa/`,
storageState: 'e2e/storageState.json',
video: 'retain-on-failure',
Piumal1999 marked this conversation as resolved.
Show resolved Hide resolved
trace: 'retain-on-failure',
},
projects: [
{
Expand Down
14 changes: 6 additions & 8 deletions src/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@ export const configSchema = {
_default: [
{
title: 'Basic Tutorial',
description:
'Learn how to efficiently search for patients, register new patients, access user settings, and view ongoing visits and appointments.',
steps: [
{
target: '[aria-label="OpenMRS"]',
content:
'Welcome to OpenMRS! This is the main dashboard where you can navigate to various features of the system.',
},
description: 'Learn how to efficiently search for patients, register new patients, access user settings, and view ongoing visits and appointments.',
steps: [{
target: '[aria-label="OpenMRS"]',
content: 'Welcome to OpenMRS! This is the main dashboard where you can navigate to various features of the system.',
disableBeacon: true
},
{
target: '[name="SearchPatientIcon"]',
content: 'This is the search icon. Use it to find patients in the system quickly.',
Expand Down
Loading
Loading