Skip to content

Commit bda4b50

Browse files
committed
test(web): add e2e tests for examples from guide
Build-bot: skip build:web Test-bot: skip
1 parent 58a565b commit bda4b50

8 files changed

Lines changed: 353 additions & 15 deletions

File tree

web/build.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,21 @@ build_tests_action() {
114114

115115
cp "${KEYMAN_ROOT}/web/src/test/auto/dom/cases/attachment/textStoreForElement.tests.html" \
116116
"${KEYMAN_ROOT}/web/build/test/dom/cases/attachment/"
117+
118+
# Copy and update guide examples - for local, PR, and test builds we
119+
# replace the CDN URL with the local build path, so that we can test
120+
# against the current build
121+
mkdir -p "${KEYMAN_ROOT}/web/build/docs/engine/guide"
122+
cp -r "${KEYMAN_ROOT}/web/docs/engine/guide/examples" \
123+
"${KEYMAN_ROOT}/web/build/docs/engine/guide/"
124+
125+
# shellcheck disable=SC2310
126+
if ! builder_is_ci_release_build; then
127+
for f in "${KEYMAN_ROOT}/web/build/docs/engine/guide/examples"/*.html; do
128+
sed "s|https://s\.keyman\.com/kmw/engine/[0-9]*\.[0-9]*\.[0-9]*/|/build/publish/${config}/|g" \
129+
"${f}" > "${f}.tmp" && mv "${f}.tmp" "${f}"
130+
done
131+
fi
117132
}
118133

119134
coverage_action() {

web/docs/engine/guide/examples/__auto-control.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
<body>
2020
<h1>Automatic Mode Example</h1>
2121
<form action='.' method='post'>
22-
<p><input type='text' id='multilingual' name='multilingual' size="40" /></p>
23-
<p><textarea cols='40' rows='5'></textarea></p>
22+
<p><input type='text' id='multilingual' name='multilingual' size="40" data-testid='multilingual'/></p>
23+
<p><textarea cols='40' rows='5' data-testid='textarea'></textarea></p>
2424
</form>
2525

2626
<a href="automatic-control">Back to Document</a>

web/docs/engine/guide/examples/__full-manual-control.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@
2424
}
2525
document.f.multilingual.focus();
2626

27-
keyman.setActiveKeyboard('', '');
27+
await keyman.setActiveKeyboard('', '');
2828
});
2929

30-
function KWControlChange() {
30+
async function KWControlChange() {
3131
var name = KWControl.value.substr(0, KWControl.value.indexOf("$$"));
3232
var languageCode = KWControl.value.substr(KWControl.value.indexOf("$$") + 2);
33-
keyman.setActiveKeyboard(name, languageCode);
33+
await keyman.setActiveKeyboard(name, languageCode);
3434
document.f.multilingual.focus();
3535
}
3636

@@ -40,7 +40,7 @@
4040
<h1>Manual Control - Custom Interface</h1>
4141
<form name='f' action='.' method='post'>
4242

43-
<p>Keyboard: <select id='KWControl' onchange='KWControlChange()'><option value=''>English</option></select></p>
43+
<p><label for='KWControl'>Keyboard:</label> <select id='KWControl' onchange='KWControlChange()'><option value=''>English</option></select></p>
4444

4545
<p><input type='text' id='multilingual' name='multilingual' size="40" placeholder="id='multilingual'"/></p>
4646
</form>

web/docs/engine/guide/examples/__manual-control.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
languages: { id: 'lo', name: 'Lao' },
1212
filename: "./js/laokeys.js"
1313
});
14-
keyman.setActiveKeyboard('laokeys');
14+
await keyman.setActiveKeyboard('laokeys');
1515
keyman.osk.hide();
1616
});
1717

@@ -30,8 +30,8 @@ <h1>Manual Mode Example</h1>
3030

3131
<p><img style="border: solid 1px black; padding: 2px 2px 3px 2px" src='js/kmicon.png' alt='KeymanWeb' onclick='KWControlClick()' id='KWControl' /></p>
3232

33-
<p><input type='text' id='multilingual' name='multilingual' size="40" /></p>
34-
<p><textarea cols='40' rows='5'></textarea></p>
33+
<p><input type='text' id='multilingual' name='multilingual' size="40" data-testid='multilingual'/></p>
34+
<p><textarea cols='40' rows='5' data-testid='textarea'></textarea></p>
3535

3636
<a href="manual-control">Back to Document</a>
3737
</form>

web/docs/engine/guide/examples/full-manual-control.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ Include the following script in the HEAD of your page:
2828
}
2929
document.f.multilingual.focus();
3030

31-
keyman.setActiveKeyboard('', '');
31+
await keyman.setActiveKeyboard('', '');
3232
});
3333

3434
/* KWControlChange: Called when user selects an item in the KWControl SELECT */
35-
function KWControlChange() {
35+
async function KWControlChange() {
3636
/* Select the keyboard in KeymanWeb */
3737
var name = KWControl.value.substr(0, KWControl.value.indexOf("$$"));
38-
var languageCode = KWControl.value.substr(KWControl.value.indexOf("$$"+2));
39-
keyman.setActiveKeyboard(name, languageCode);
38+
var languageCode = KWControl.value.substr(KWControl.value.indexOf("$$") + 2);
39+
await keyman.setActiveKeyboard(name, languageCode);
4040
/* Focus onto the multilingual field in the form */
4141
document.f.multilingual.focus();
4242
}

web/docs/engine/guide/examples/manual-control.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
title: Manual Mode Example
33
---
44

5-
In this example, the web page designer specifies when KeymanWeb's on-screen keyboard may be displayed on non-mobile devices. They have also specified that the LaoKeys keyboard should be activated by default. This example continues to use the KeymanWeb default interface. Please click [this link](__manual-control.html) to open the test page.
5+
In this example, the web page designer specifies when KeymanWeb's on-screen keyboard may be
6+
displayed on non-mobile devices. They have also specified that the LaoKeys keyboard should be
7+
activated by default. This example continues to use the KeymanWeb default interface. Please click
8+
[this link](__manual-control.html) to open the test page.
69

710
## Code Walkthrough
811

@@ -17,7 +20,7 @@ Include the following script in the HEAD of your page:
1720
languages:{id:'lo',name:'Lao'},
1821
filename: "./js/laokeys.js"
1922
});
20-
keyman.setActiveKeyboard('laokeys');
23+
await keyman.setActiveKeyboard('laokeys');
2124
keyman.osk.hide();
2225
});
2326

web/src/test/auto/e2e/e2eUtils.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Keyman is copyright (C) SIL Global. MIT License.
3+
*/
4+
5+
import { type Locator, type Page } from "@playwright/test";
6+
7+
/**
8+
* Expands the keyboard selection menu and returns the text content of the
9+
* currently selected keyboard.
10+
*/
11+
export async function getSelectedKeyboardMenuText(page: Page): Promise<string | undefined> {
12+
const watchDog = page.waitForFunction(() => !!document.getElementById('KeymanWeb_KbdList'));
13+
await page.getByRole('img', { name: 'Use Web Keyboard' }).click();
14+
await watchDog;
15+
return page.evaluate(() => {
16+
const selectedKbd = document.querySelector('#kmwico .selected');
17+
return selectedKbd?.textContent;
18+
});
19+
};
20+
21+
/**
22+
* Expands the keyboard selection menu and returns the menu items as an array
23+
*/
24+
export async function getAllKeyboardMenuText(page: Page): Promise<(string|undefined)[]> {
25+
const watchDog = page.waitForFunction(() => !!document.getElementById('KeymanWeb_KbdList'));
26+
await page.getByRole('img', { name: 'Use Web Keyboard' }).hover();
27+
await watchDog;
28+
return page.evaluate(() => {
29+
const menuItems = [];
30+
const menuDiv = document.querySelector('#kmwico');
31+
const kbdList = menuDiv?.lastElementChild;
32+
for (let i = 0; i < (kbdList ? kbdList.children.length : 0); i++) {
33+
const item = kbdList?.children[i];
34+
menuItems.push(item?.textContent);
35+
}
36+
return menuItems;
37+
});
38+
}
39+
40+
/**
41+
* Loads the specified URL and waits for the page load event.
42+
*/
43+
export async function loadPage(page: Page, url: string): Promise<Page> {
44+
const loadPromise = page.waitForEvent('load');
45+
await page.goto(url);
46+
return loadPromise;
47+
}
48+
49+
/**
50+
* Clicks the specified field and waits for the OSK to be shown, returning a
51+
* locator for the OSK title bar.
52+
*/
53+
export async function clickFieldAndWaitForOSK(page: Page, fieldLocator: Locator): Promise<Locator> {
54+
const keyboardchangePromise = page.evaluate(async () => {
55+
return new Promise((resolve) => {
56+
keyman.addEventListener('keyboardchange', function (kbd) {
57+
resolve(kbd);
58+
});
59+
});
60+
});
61+
await fieldLocator.click();
62+
await keyboardchangePromise;
63+
return page.locator('#keymanweb_title_bar');
64+
}

0 commit comments

Comments
 (0)