@aerokit/sdk 14.68.0 → 14.70.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.
- package/package.json +1 -1
- package/test/flows/multilingual.js +53 -6
- package/test/form.js +6 -2
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { expect, test } from '../fixtures.js';
|
|
2
2
|
import { listCrumb } from './list.js';
|
|
3
3
|
|
|
4
|
+
const LANGUAGE_KEY = 'codbex.harmonia.language';
|
|
5
|
+
// A reload in another language is three round trips on a cold instance - the page, the list's
|
|
6
|
+
// data GET and the translation overlay behind it - so the 5 s default flaked on slower runners.
|
|
7
|
+
const OVERLAY_TIMEOUT = 15_000;
|
|
8
|
+
|
|
4
9
|
// The read-time translation overlay: switch the shared language key (what the Region &
|
|
5
10
|
// Language setting writes), reload, and a known seed row shows its translated name.
|
|
6
11
|
// Needs a concrete sample in the manifest: { language, base, translated }.
|
|
@@ -11,11 +16,53 @@ export function multilingualFlow(manifest, entity) {
|
|
|
11
16
|
test(`${entity.name}: ${sample.language} translation overlays on read`, async ({ page }) => {
|
|
12
17
|
await page.goto(manifest.standaloneShell + entity.route);
|
|
13
18
|
await expect(listCrumb(page, entity)).toBeVisible();
|
|
14
|
-
|
|
15
|
-
await page.
|
|
16
|
-
await
|
|
17
|
-
await page
|
|
18
|
-
await page.reload();
|
|
19
|
-
await expect(page.locator('tbody tr', { hasText: sample.base }).first()).toBeVisible();
|
|
19
|
+
const translatedRead = await reloadIn(page, manifest, entity, sample.language);
|
|
20
|
+
await expectRowShowing(page, sample.translated, translatedRead);
|
|
21
|
+
const baseRead = await reloadIn(page, manifest, entity, 'en');
|
|
22
|
+
await expectRowShowing(page, sample.base, baseRead);
|
|
20
23
|
});
|
|
21
24
|
}
|
|
25
|
+
|
|
26
|
+
// Set the language key and reload, waiting for the list's own data GET (the paged getAll on the
|
|
27
|
+
// entity's controller) so the assertion starts once the rows are on their way, and answering what
|
|
28
|
+
// that read asked for and got back - which is what tells a slow render from a missing translation.
|
|
29
|
+
// The wait is registered only once the reload has committed: registered before it, it also matched
|
|
30
|
+
// a list GET still in flight from the document the reload replaced, whose body is gone (#7584). The
|
|
31
|
+
// new document issues its own GET only after its scripts have loaded, so it cannot slip past.
|
|
32
|
+
async function reloadIn(page, manifest, entity, language) {
|
|
33
|
+
await page.evaluate(([key, lang]) => localStorage.setItem(key, lang), [LANGUAGE_KEY, language]);
|
|
34
|
+
const controllerPath = manifest.restBase + entity.api;
|
|
35
|
+
await page.reload({ waitUntil: 'commit' });
|
|
36
|
+
const response = await page.waitForResponse(
|
|
37
|
+
(candidate) => candidate.request().method() === 'GET' && new URL(candidate.url()).pathname === controllerPath,
|
|
38
|
+
{ timeout: OVERLAY_TIMEOUT },
|
|
39
|
+
);
|
|
40
|
+
return {
|
|
41
|
+
language,
|
|
42
|
+
acceptLanguage: await response.request().headerValue('accept-language'),
|
|
43
|
+
status: response.status(),
|
|
44
|
+
// Only the diagnostic reads the body, so a body the browser no longer holds must not fail the flow.
|
|
45
|
+
body: await response.text().catch(() => null),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function expectRowShowing(page, text, read) {
|
|
50
|
+
const rows = page.locator('tbody tr');
|
|
51
|
+
try {
|
|
52
|
+
await expect(rows.filter({ hasText: text }).first()).toBeVisible({ timeout: OVERLAY_TIMEOUT });
|
|
53
|
+
} catch (error) {
|
|
54
|
+
const firstRow = (await rows.allInnerTexts())[0]?.replace(/\s+/g, ' ').trim();
|
|
55
|
+
throw new Error(
|
|
56
|
+
`no list row shows '${text}' after reloading in '${read.language}': the list GET sent Accept-Language ` +
|
|
57
|
+
`${read.acceptLanguage ?? '(none)'} and answered ${read.status}, ` +
|
|
58
|
+
`${describeBody(read.body, text)}; the table's first row reads ` +
|
|
59
|
+
`${firstRow ? `'${firstRow}'` : '(no rows)'}`,
|
|
60
|
+
{ cause: error },
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function describeBody(body, text) {
|
|
66
|
+
if (body === null) return 'its body unavailable';
|
|
67
|
+
return `${body.includes(text) ? 'WITH' : 'WITHOUT'} '${text}' in its body`;
|
|
68
|
+
}
|
package/test/form.js
CHANGED
|
@@ -122,9 +122,13 @@ export async function fillForm(page, manifest, entity, record, relationSamples,
|
|
|
122
122
|
if (record[field.name] === undefined) continue;
|
|
123
123
|
await fillField(page, field, record[field.name], opts);
|
|
124
124
|
}
|
|
125
|
+
// a readOnly relation renders as a disabled combobox (an update-time calculated action, a
|
|
126
|
+
// platform-owned FK) - the server sets it, so there is nothing to pick (dirigible #7554); the
|
|
127
|
+
// REST flows still post its sample, which the calculated action overwrites or checks
|
|
128
|
+
const pickable = relationSamples.filter((s) => !s.relation.readOnly);
|
|
125
129
|
// cascade order: a dependsOn trigger must be picked BEFORE its dependent, so the narrowed
|
|
126
130
|
// option list is the one the dependent's sample was chosen from
|
|
127
|
-
const triggers =
|
|
128
|
-
const dependents =
|
|
131
|
+
const triggers = pickable.filter((s) => !s.relation.dependsOn);
|
|
132
|
+
const dependents = pickable.filter((s) => s.relation.dependsOn);
|
|
129
133
|
for (const sample of [...triggers, ...dependents]) await pickDropdown(page, sample.relation, sample.label);
|
|
130
134
|
}
|