feather-testing-core 0.3.0 → 0.4.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/README.md +133 -4
- package/dist/errors.d.ts +8 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +12 -0
- package/dist/eslint-plugin/index.d.ts +18 -0
- package/dist/eslint-plugin/index.d.ts.map +1 -0
- package/dist/eslint-plugin/index.js +37 -0
- package/dist/eslint-plugin/rules/no-conditional-skip.d.ts +4 -0
- package/dist/eslint-plugin/rules/no-conditional-skip.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-conditional-skip.js +56 -0
- package/dist/eslint-plugin/rules/no-swallowed-cleanup-catch.d.ts +4 -0
- package/dist/eslint-plugin/rules/no-swallowed-cleanup-catch.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-swallowed-cleanup-catch.js +63 -0
- package/dist/eslint-plugin/rules/no-wait-for-timeout.d.ts +4 -0
- package/dist/eslint-plugin/rules/no-wait-for-timeout.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-wait-for-timeout.js +69 -0
- package/dist/eslint-plugin/rules/no-weak-assertions.d.ts +4 -0
- package/dist/eslint-plugin/rules/no-weak-assertions.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-weak-assertions.js +73 -0
- package/dist/eslint-plugin/rules/warn-serial-mode.d.ts +4 -0
- package/dist/eslint-plugin/rules/warn-serial-mode.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/warn-serial-mode.js +59 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/playwright/driver.d.ts +16 -3
- package/dist/playwright/driver.d.ts.map +1 -1
- package/dist/playwright/driver.js +49 -2
- package/dist/playwright/index.d.ts +4 -4
- package/dist/playwright/index.d.ts.map +1 -1
- package/dist/playwright/index.js +1 -1
- package/dist/rtl/driver.d.ts +28 -4
- package/dist/rtl/driver.d.ts.map +1 -1
- package/dist/rtl/driver.js +78 -2
- package/dist/rtl/index.d.ts +5 -4
- package/dist/rtl/index.d.ts.map +1 -1
- package/dist/rtl/index.js +2 -2
- package/dist/session.d.ts +36 -4
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +67 -1
- package/dist/types.d.ts +35 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -2
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
function memberPath(node) {
|
|
2
|
+
if (node.type === "Identifier")
|
|
3
|
+
return node.name;
|
|
4
|
+
if (node.type === "MemberExpression" &&
|
|
5
|
+
!node.computed &&
|
|
6
|
+
node.property.type === "Identifier") {
|
|
7
|
+
const prefix = memberPath(node.object);
|
|
8
|
+
return prefix === null ? null : `${prefix}.${node.property.name}`;
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const rule = {
|
|
13
|
+
meta: {
|
|
14
|
+
type: "suggestion",
|
|
15
|
+
docs: {
|
|
16
|
+
description: "Flag serial mode, which makes each test depend on the ones before it",
|
|
17
|
+
recommended: true,
|
|
18
|
+
},
|
|
19
|
+
schema: [],
|
|
20
|
+
messages: {
|
|
21
|
+
serial: "Serial mode couples these tests: one failure cascades into the rest, " +
|
|
22
|
+
"so the report stops naming the real cause and a flake becomes a wall " +
|
|
23
|
+
"of red. Make them independent — share setup, not state — or keep " +
|
|
24
|
+
"serial with an eslint-disable-next-line comment saying why it is " +
|
|
25
|
+
"required.",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
create(context) {
|
|
29
|
+
return {
|
|
30
|
+
CallExpression(node) {
|
|
31
|
+
const path = memberPath(node.callee);
|
|
32
|
+
if (path === null)
|
|
33
|
+
return;
|
|
34
|
+
const segments = path.split(".");
|
|
35
|
+
const isSerialRunner = segments.includes("serial") &&
|
|
36
|
+
["test", "it", "describe", "suite"].includes(segments[0] ?? "");
|
|
37
|
+
if (isSerialRunner) {
|
|
38
|
+
context.report({ node, messageId: "serial" });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// test.describe.configure({ mode: "serial" })
|
|
42
|
+
if (!path.endsWith(".configure"))
|
|
43
|
+
return;
|
|
44
|
+
const [options] = node.arguments;
|
|
45
|
+
if (!options || options.type !== "ObjectExpression")
|
|
46
|
+
return;
|
|
47
|
+
const declaresSerial = options.properties.some((property) => property.type === "Property" &&
|
|
48
|
+
!property.computed &&
|
|
49
|
+
property.key.type === "Identifier" &&
|
|
50
|
+
property.key.name === "mode" &&
|
|
51
|
+
property.value.type === "Literal" &&
|
|
52
|
+
property.value.value === "serial");
|
|
53
|
+
if (declaresSerial)
|
|
54
|
+
context.report({ node, messageId: "serial" });
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
export default rule;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { Session } from "./session.js";
|
|
2
|
-
export { StepError } from "./errors.js";
|
|
3
|
-
export type { AssertHasOptions, AssertPathOptions, QueuedStep, TestDriver, } from "./types.js";
|
|
2
|
+
export { StepError, BrowserOnlyVerbError } from "./errors.js";
|
|
3
|
+
export type { AssertHasOptions, AssertPathOptions, DownloadOptions, QueuedStep, TestDriver, UntilOptions, UntilPredicate, } from "./types.js";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9D,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,UAAU,EACV,YAAY,EACZ,cAAc,GACf,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Session } from "./session.js";
|
|
2
|
-
export { StepError } from "./errors.js";
|
|
2
|
+
export { StepError, BrowserOnlyVerbError } from "./errors.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type Page, type Locator } from "@playwright/test";
|
|
2
|
-
import type { AssertHasOptions, AssertPathOptions, TestDriver } from "../types.js";
|
|
2
|
+
import type { AssertHasOptions, AssertPathOptions, DownloadOptions, TestDriver, UntilOptions, UntilPredicate } from "../types.js";
|
|
3
3
|
/** Context handed to custom step() callbacks in the Playwright adapter. */
|
|
4
4
|
export interface PlaywrightStepContext {
|
|
5
5
|
page: Page;
|
|
6
6
|
/** Current scope: the page, or the container locator inside within(). */
|
|
7
7
|
scope: Page | Locator;
|
|
8
8
|
}
|
|
9
|
-
export declare class PlaywrightDriver implements TestDriver<PlaywrightStepContext> {
|
|
9
|
+
export declare class PlaywrightDriver implements TestDriver<PlaywrightStepContext, Page> {
|
|
10
10
|
private page;
|
|
11
11
|
private scope;
|
|
12
12
|
private lastFormLocator;
|
|
@@ -24,7 +24,11 @@ export declare class PlaywrightDriver implements TestDriver<PlaywrightStepContex
|
|
|
24
24
|
uncheck(label: string): Promise<void>;
|
|
25
25
|
choose(label: string): Promise<void>;
|
|
26
26
|
submit(): Promise<void>;
|
|
27
|
+
attachFile(label: string, path: string): Promise<void>;
|
|
28
|
+
/** @deprecated Older name for {@link PlaywrightDriver.attachFile}. */
|
|
27
29
|
upload(label: string, path: string): Promise<void>;
|
|
30
|
+
pressKey(key: string): Promise<void>;
|
|
31
|
+
hover(text: string): Promise<void>;
|
|
28
32
|
dropFile(selector: string, path: string): Promise<void>;
|
|
29
33
|
assertHas(selector: string, opts?: AssertHasOptions): Promise<void>;
|
|
30
34
|
refuteHas(selector: string, opts?: AssertHasOptions): Promise<void>;
|
|
@@ -37,8 +41,17 @@ export declare class PlaywrightDriver implements TestDriver<PlaywrightStepContex
|
|
|
37
41
|
assertOptions(label: string, optionLabels: string[]): Promise<void>;
|
|
38
42
|
assertPath(path: string, opts?: AssertPathOptions): Promise<void>;
|
|
39
43
|
refutePath(path: string): Promise<void>;
|
|
44
|
+
assertDownload(expected: string | RegExp, trigger: () => Promise<void>, opts?: DownloadOptions): Promise<void>;
|
|
45
|
+
until(description: string, predicate: UntilPredicate<PlaywrightStepContext>, opts?: UntilOptions): Promise<void>;
|
|
40
46
|
step(fn: (context: PlaywrightStepContext) => Promise<unknown>): Promise<void>;
|
|
41
|
-
|
|
47
|
+
/**
|
|
48
|
+
* raw() hands over the page itself, not the within() scope: it exists for
|
|
49
|
+
* the cases the DSL does not model, where re-scoping is the caller's job.
|
|
50
|
+
*/
|
|
51
|
+
raw(fn: (page: Page) => unknown | Promise<unknown>): Promise<void>;
|
|
52
|
+
/** The adapter context handed to step(), until(), and friends. */
|
|
53
|
+
protected context(): PlaywrightStepContext;
|
|
54
|
+
within(selector: string): Promise<TestDriver<PlaywrightStepContext, Page>>;
|
|
42
55
|
debug(): Promise<void>;
|
|
43
56
|
wrapStep(name: string, fn: () => Promise<void>): Promise<void>;
|
|
44
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/playwright/driver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,OAAO,EAAgB,MAAM,kBAAkB,CAAC;AACzE,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/playwright/driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -99,11 +99,21 @@ export class PlaywrightDriver {
|
|
|
99
99
|
.press("Enter");
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
-
async
|
|
102
|
+
async attachFile(label, path) {
|
|
103
103
|
const input = this.labelled(label);
|
|
104
104
|
await input.setInputFiles(path);
|
|
105
105
|
this.lastFormLocator = this.scope.locator("form", { has: input });
|
|
106
106
|
}
|
|
107
|
+
/** @deprecated Older name for {@link PlaywrightDriver.attachFile}. */
|
|
108
|
+
async upload(label, path) {
|
|
109
|
+
await this.attachFile(label, path);
|
|
110
|
+
}
|
|
111
|
+
async pressKey(key) {
|
|
112
|
+
await this.page.keyboard.press(key);
|
|
113
|
+
}
|
|
114
|
+
async hover(text) {
|
|
115
|
+
await this.scope.getByText(text, EXACT).hover();
|
|
116
|
+
}
|
|
107
117
|
async dropFile(selector, path) {
|
|
108
118
|
const content = await readFile(path);
|
|
109
119
|
const name = basename(path);
|
|
@@ -183,8 +193,45 @@ export class PlaywrightDriver {
|
|
|
183
193
|
})
|
|
184
194
|
.not.toBe(path);
|
|
185
195
|
}
|
|
196
|
+
async assertDownload(expected, trigger, opts) {
|
|
197
|
+
// The wait has to be armed before the click that starts the download,
|
|
198
|
+
// which is why the trigger arrives as a callback rather than as an
|
|
199
|
+
// earlier step in the chain.
|
|
200
|
+
const [download] = await Promise.all([
|
|
201
|
+
this.page.waitForEvent("download", { timeout: opts?.timeout }),
|
|
202
|
+
trigger(),
|
|
203
|
+
]);
|
|
204
|
+
const filename = download.suggestedFilename();
|
|
205
|
+
const matched = typeof expected === "string"
|
|
206
|
+
? filename === expected
|
|
207
|
+
: expected.test(filename);
|
|
208
|
+
if (!matched) {
|
|
209
|
+
throw new Error(`assertDownload(${typeof expected === "string" ? `'${expected}'` : String(expected)}): ` +
|
|
210
|
+
`the browser offered a download named '${filename}' instead.`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
async until(description, predicate, opts) {
|
|
214
|
+
await expect
|
|
215
|
+
.poll(async () => Boolean(await predicate(this.context())), {
|
|
216
|
+
message: `until: ${description}`,
|
|
217
|
+
timeout: opts?.timeout,
|
|
218
|
+
intervals: opts?.interval === undefined ? undefined : [opts.interval],
|
|
219
|
+
})
|
|
220
|
+
.toBe(true);
|
|
221
|
+
}
|
|
186
222
|
async step(fn) {
|
|
187
|
-
await fn(
|
|
223
|
+
await fn(this.context());
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* raw() hands over the page itself, not the within() scope: it exists for
|
|
227
|
+
* the cases the DSL does not model, where re-scoping is the caller's job.
|
|
228
|
+
*/
|
|
229
|
+
async raw(fn) {
|
|
230
|
+
await fn(this.page);
|
|
231
|
+
}
|
|
232
|
+
/** The adapter context handed to step(), until(), and friends. */
|
|
233
|
+
context() {
|
|
234
|
+
return { page: this.page, scope: this.scope };
|
|
188
235
|
}
|
|
189
236
|
async within(selector) {
|
|
190
237
|
const scopedLocator = this.scope.locator(selector);
|
|
@@ -2,12 +2,12 @@ import { type Page } from "@playwright/test";
|
|
|
2
2
|
import { Session } from "../session.js";
|
|
3
3
|
import { type PlaywrightStepContext } from "./driver.js";
|
|
4
4
|
export { Session } from "../session.js";
|
|
5
|
-
export { StepError } from "../errors.js";
|
|
5
|
+
export { StepError, BrowserOnlyVerbError } from "../errors.js";
|
|
6
6
|
export { PlaywrightDriver, type PlaywrightStepContext } from "./driver.js";
|
|
7
|
-
export type { AssertHasOptions, AssertPathOptions, TestDriver, } from "../types.js";
|
|
8
|
-
export declare function createSession(page: Page): Session<PlaywrightStepContext>;
|
|
7
|
+
export type { AssertHasOptions, AssertPathOptions, DownloadOptions, TestDriver, UntilOptions, UntilPredicate, } from "../types.js";
|
|
8
|
+
export declare function createSession(page: Page): Session<PlaywrightStepContext, Page>;
|
|
9
9
|
export declare const test: import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions & {
|
|
10
|
-
session: Session<PlaywrightStepContext>;
|
|
10
|
+
session: Session<PlaywrightStepContext, Page>;
|
|
11
11
|
}, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions>;
|
|
12
12
|
export { expect } from "@playwright/test";
|
|
13
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/playwright/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/playwright/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC3E,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,YAAY,EACZ,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,wBAAgB,aAAa,CAC3B,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAEtC;AAED,eAAO,MAAM,IAAI;aACN,OAAO,CAAC,qBAAqB,EAAE,IAAI,CAAC;sGAK7C,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/playwright/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { test as base } from "@playwright/test";
|
|
|
2
2
|
import { Session } from "../session.js";
|
|
3
3
|
import { PlaywrightDriver } from "./driver.js";
|
|
4
4
|
export { Session } from "../session.js";
|
|
5
|
-
export { StepError } from "../errors.js";
|
|
5
|
+
export { StepError, BrowserOnlyVerbError } from "../errors.js";
|
|
6
6
|
export { PlaywrightDriver } from "./driver.js";
|
|
7
7
|
export function createSession(page) {
|
|
8
8
|
return new Session(new PlaywrightDriver(page));
|
package/dist/rtl/driver.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { screen, within as rtlWithin } from "@testing-library/react";
|
|
2
2
|
import { type UserEvent } from "@testing-library/user-event";
|
|
3
|
-
import type { AssertHasOptions, TestDriver } from "../types.js";
|
|
3
|
+
import type { AssertHasOptions, DownloadOptions, TestDriver, UntilOptions, UntilPredicate } from "../types.js";
|
|
4
|
+
/** The scoped query object raw() callbacks receive in the RTL adapter. */
|
|
5
|
+
export type RTLQueries = ReturnType<typeof rtlWithin>;
|
|
4
6
|
/** Context handed to custom step() callbacks in the RTL adapter. */
|
|
5
7
|
export interface RTLStepContext {
|
|
6
8
|
user: UserEvent;
|
|
@@ -19,7 +21,7 @@ export interface RTLStepContext {
|
|
|
19
21
|
* driver to markup whose labels are wrapper siblings rather than `htmlFor`
|
|
20
22
|
* targets.
|
|
21
23
|
*/
|
|
22
|
-
export declare class RTLDriver implements TestDriver<RTLStepContext> {
|
|
24
|
+
export declare class RTLDriver implements TestDriver<RTLStepContext, RTLQueries> {
|
|
23
25
|
protected user: UserEvent;
|
|
24
26
|
/** The element every query and selector in this driver resolves against. */
|
|
25
27
|
protected root: HTMLElement;
|
|
@@ -39,7 +41,7 @@ export declare class RTLDriver implements TestDriver<RTLStepContext> {
|
|
|
39
41
|
*/
|
|
40
42
|
protected findField(label: string): Promise<HTMLElement>;
|
|
41
43
|
/** Subclasses override this so within() yields a driver of their own type. */
|
|
42
|
-
protected scoped(element: HTMLElement): TestDriver<RTLStepContext>;
|
|
44
|
+
protected scoped(element: HTMLElement): TestDriver<RTLStepContext, RTLQueries>;
|
|
43
45
|
visit(): Promise<void>;
|
|
44
46
|
click(text: string): Promise<void>;
|
|
45
47
|
clickLink(text: string): Promise<void>;
|
|
@@ -50,7 +52,16 @@ export declare class RTLDriver implements TestDriver<RTLStepContext> {
|
|
|
50
52
|
uncheck(label: string): Promise<void>;
|
|
51
53
|
choose(label: string): Promise<void>;
|
|
52
54
|
submit(): Promise<void>;
|
|
55
|
+
attachFile(label: string, path: string): Promise<void>;
|
|
56
|
+
/** @deprecated Older name for {@link RTLDriver.attachFile}. */
|
|
53
57
|
upload(label: string, path: string): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Keys are named the Playwright way ('Enter', 'Control+A') and translated
|
|
60
|
+
* to user-event's keyboard syntax, so one spec reads the same on both
|
|
61
|
+
* adapters.
|
|
62
|
+
*/
|
|
63
|
+
pressKey(key: string): Promise<void>;
|
|
64
|
+
hover(text: string): Promise<void>;
|
|
54
65
|
dropFile(selector: string, path: string): Promise<void>;
|
|
55
66
|
assertHas(_selector: string, _opts?: AssertHasOptions): Promise<void>;
|
|
56
67
|
refuteHas(_selector: string, _opts?: AssertHasOptions): Promise<void>;
|
|
@@ -63,8 +74,21 @@ export declare class RTLDriver implements TestDriver<RTLStepContext> {
|
|
|
63
74
|
assertOptions(label: string, optionLabels: string[]): Promise<void>;
|
|
64
75
|
assertPath(): Promise<void>;
|
|
65
76
|
refutePath(): Promise<void>;
|
|
77
|
+
assertDownload(_expected: string | RegExp, _trigger: () => Promise<void>, _opts?: DownloadOptions): Promise<void>;
|
|
78
|
+
until(description: string, predicate: UntilPredicate<RTLStepContext>, opts?: UntilOptions): Promise<void>;
|
|
66
79
|
step(fn: (context: RTLStepContext) => Promise<unknown>): Promise<void>;
|
|
67
|
-
within(
|
|
80
|
+
/** raw() hands over the scoped query object — `within(root)`, i.e. screen
|
|
81
|
+
* when the driver is unscoped. */
|
|
82
|
+
raw(fn: (queries: RTLQueries) => unknown | Promise<unknown>): Promise<void>;
|
|
83
|
+
/** The adapter context handed to step(), until(), and friends. */
|
|
84
|
+
protected context(): RTLStepContext;
|
|
85
|
+
within(selector: string): Promise<TestDriver<RTLStepContext, RTLQueries>>;
|
|
68
86
|
debug(): Promise<void>;
|
|
69
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* 'Enter' -> '{Enter}', 'a' -> 'a', 'Control+A' -> '{Control>}A{/Control}'.
|
|
90
|
+
* Printable characters are typed literally with user-event's own `{` and `[`
|
|
91
|
+
* escapes applied, so a key name never turns into a descriptor by accident.
|
|
92
|
+
*/
|
|
93
|
+
export declare function toKeyboardSyntax(key: string): string;
|
|
70
94
|
//# sourceMappingURL=driver.d.ts.map
|
package/dist/rtl/driver.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/rtl/driver.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EAEN,MAAM,IAAI,SAAS,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/rtl/driver.ts"],"names":[],"mappings":"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"}
|
package/dist/rtl/driver.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fireEvent, screen, waitFor, within as rtlWithin, } from "@testing-library/react";
|
|
2
2
|
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { BrowserOnlyVerbError } from "../errors.js";
|
|
3
4
|
/**
|
|
4
5
|
* RTL adapter implementing the subset of TestDriver that applies in JSDOM.
|
|
5
6
|
* Navigation methods (visit, assertPath, refutePath) are not supported.
|
|
@@ -116,7 +117,7 @@ export class RTLDriver {
|
|
|
116
117
|
this.lastFormElement.requestSubmit();
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
|
-
async
|
|
120
|
+
async attachFile(label, path) {
|
|
120
121
|
const input = await this.findField(label);
|
|
121
122
|
// JSDOM has no filesystem access; synthesize a File from the basename.
|
|
122
123
|
const name = path.split(/[\\/]/).pop() ?? path;
|
|
@@ -124,6 +125,22 @@ export class RTLDriver {
|
|
|
124
125
|
await this.user.upload(input, file);
|
|
125
126
|
this.lastFormElement = input.closest("form");
|
|
126
127
|
}
|
|
128
|
+
/** @deprecated Older name for {@link RTLDriver.attachFile}. */
|
|
129
|
+
async upload(label, path) {
|
|
130
|
+
await this.attachFile(label, path);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Keys are named the Playwright way ('Enter', 'Control+A') and translated
|
|
134
|
+
* to user-event's keyboard syntax, so one spec reads the same on both
|
|
135
|
+
* adapters.
|
|
136
|
+
*/
|
|
137
|
+
async pressKey(key) {
|
|
138
|
+
await this.user.keyboard(toKeyboardSyntax(key));
|
|
139
|
+
}
|
|
140
|
+
async hover(text) {
|
|
141
|
+
const element = await this.container.findByText(text, undefined, this.waitOpts());
|
|
142
|
+
await this.user.hover(element);
|
|
143
|
+
}
|
|
127
144
|
async dropFile(selector, path) {
|
|
128
145
|
const target = this.rootElement().querySelector(selector);
|
|
129
146
|
if (!target) {
|
|
@@ -207,8 +224,32 @@ export class RTLDriver {
|
|
|
207
224
|
async refutePath() {
|
|
208
225
|
throw new Error("refutePath() is not available in the RTL adapter (no real URL in JSDOM).");
|
|
209
226
|
}
|
|
227
|
+
async assertDownload(_expected, _trigger, _opts) {
|
|
228
|
+
throw new BrowserOnlyVerbError("assertDownload()", "Assert the request the download would make, or move this case to a " +
|
|
229
|
+
"Playwright spec where a real browser can accept the file.");
|
|
230
|
+
}
|
|
231
|
+
async until(description, predicate, opts) {
|
|
232
|
+
await waitFor(async () => {
|
|
233
|
+
if (!(await predicate(this.context()))) {
|
|
234
|
+
throw new Error(`until: ${description} — condition was still not met.`);
|
|
235
|
+
}
|
|
236
|
+
}, {
|
|
237
|
+
...this.waitOpts(),
|
|
238
|
+
...(opts?.timeout === undefined ? {} : { timeout: opts.timeout }),
|
|
239
|
+
...(opts?.interval === undefined ? {} : { interval: opts.interval }),
|
|
240
|
+
});
|
|
241
|
+
}
|
|
210
242
|
async step(fn) {
|
|
211
|
-
await fn(
|
|
243
|
+
await fn(this.context());
|
|
244
|
+
}
|
|
245
|
+
/** raw() hands over the scoped query object — `within(root)`, i.e. screen
|
|
246
|
+
* when the driver is unscoped. */
|
|
247
|
+
async raw(fn) {
|
|
248
|
+
await fn(this.container);
|
|
249
|
+
}
|
|
250
|
+
/** The adapter context handed to step(), until(), and friends. */
|
|
251
|
+
context() {
|
|
252
|
+
return { user: this.user, container: this.container };
|
|
212
253
|
}
|
|
213
254
|
async within(selector) {
|
|
214
255
|
const element = this.rootElement().querySelector(selector);
|
|
@@ -220,3 +261,38 @@ export class RTLDriver {
|
|
|
220
261
|
screen.debug(this.rootElement());
|
|
221
262
|
}
|
|
222
263
|
}
|
|
264
|
+
/** Playwright key names -> user-event keyboard syntax. */
|
|
265
|
+
const KEY_ALIASES = {
|
|
266
|
+
Ctrl: "Control",
|
|
267
|
+
Cmd: "Meta",
|
|
268
|
+
Command: "Meta",
|
|
269
|
+
Space: " ",
|
|
270
|
+
};
|
|
271
|
+
const MODIFIERS = new Set(["Control", "Shift", "Alt", "Meta"]);
|
|
272
|
+
/**
|
|
273
|
+
* 'Enter' -> '{Enter}', 'a' -> 'a', 'Control+A' -> '{Control>}A{/Control}'.
|
|
274
|
+
* Printable characters are typed literally with user-event's own `{` and `[`
|
|
275
|
+
* escapes applied, so a key name never turns into a descriptor by accident.
|
|
276
|
+
*/
|
|
277
|
+
export function toKeyboardSyntax(key) {
|
|
278
|
+
const parts = key.split("+").map((p) => KEY_ALIASES[p] ?? p);
|
|
279
|
+
const target = parts.pop();
|
|
280
|
+
if (target === undefined || target === "") {
|
|
281
|
+
throw new Error(`pressKey('${key}'): no key to press.`);
|
|
282
|
+
}
|
|
283
|
+
const held = parts.filter((p) => MODIFIERS.has(p));
|
|
284
|
+
if (held.length !== parts.length) {
|
|
285
|
+
throw new Error(`pressKey('${key}'): '${parts.find((p) => !MODIFIERS.has(p))}' is not a ` +
|
|
286
|
+
"modifier. Use Control, Shift, Alt, or Meta.");
|
|
287
|
+
}
|
|
288
|
+
const pressed = target.length === 1
|
|
289
|
+
? target.replace(/[{[]/g, (c) => c + c)
|
|
290
|
+
: `{${target}}`;
|
|
291
|
+
return (held.map((m) => `{${m}>}`).join("") +
|
|
292
|
+
pressed +
|
|
293
|
+
held
|
|
294
|
+
.slice()
|
|
295
|
+
.reverse()
|
|
296
|
+
.map((m) => `{/${m}}`)
|
|
297
|
+
.join(""));
|
|
298
|
+
}
|
package/dist/rtl/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Session } from "../session.js";
|
|
2
|
-
import { type RTLStepContext } from "./driver.js";
|
|
2
|
+
import { type RTLQueries, type RTLStepContext } from "./driver.js";
|
|
3
3
|
export { Session } from "../session.js";
|
|
4
|
-
export { StepError } from "../errors.js";
|
|
5
|
-
export { RTLDriver, type RTLStepContext } from "./driver.js";
|
|
6
|
-
export
|
|
4
|
+
export { StepError, BrowserOnlyVerbError } from "../errors.js";
|
|
5
|
+
export { RTLDriver, type RTLQueries, type RTLStepContext, } from "./driver.js";
|
|
6
|
+
export type { AssertHasOptions, DownloadOptions, TestDriver, UntilOptions, UntilPredicate, } from "../types.js";
|
|
7
|
+
export declare function createSession(): Session<RTLStepContext, RTLQueries>;
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/rtl/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rtl/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rtl/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAa,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,SAAS,EACT,KAAK,UAAU,EACf,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,YAAY,EACZ,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,wBAAgB,aAAa,IAAI,OAAO,CAAC,cAAc,EAAE,UAAU,CAAC,CAEnE"}
|
package/dist/rtl/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Session } from "../session.js";
|
|
2
2
|
import { RTLDriver } from "./driver.js";
|
|
3
3
|
export { Session } from "../session.js";
|
|
4
|
-
export { StepError } from "../errors.js";
|
|
5
|
-
export { RTLDriver } from "./driver.js";
|
|
4
|
+
export { StepError, BrowserOnlyVerbError } from "../errors.js";
|
|
5
|
+
export { RTLDriver, } from "./driver.js";
|
|
6
6
|
export function createSession() {
|
|
7
7
|
return new Session(new RTLDriver());
|
|
8
8
|
}
|
package/dist/session.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { AssertHasOptions, AssertPathOptions, TestDriver } from "./types.js";
|
|
2
|
-
export declare class Session<TContext = unknown> implements PromiseLike<void> {
|
|
1
|
+
import type { AssertHasOptions, AssertPathOptions, DownloadOptions, TestDriver, UntilOptions, UntilPredicate } from "./types.js";
|
|
2
|
+
export declare class Session<TContext = unknown, TNative = unknown> implements PromiseLike<void> {
|
|
3
3
|
private driver;
|
|
4
4
|
private steps;
|
|
5
5
|
private executedSteps;
|
|
6
6
|
private stepIndex;
|
|
7
|
-
constructor(driver: TestDriver<TContext>);
|
|
7
|
+
constructor(driver: TestDriver<TContext, TNative>);
|
|
8
8
|
then<TResult1 = void, TResult2 = never>(onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
9
9
|
private executeSteps;
|
|
10
10
|
private enqueue;
|
|
@@ -18,8 +18,15 @@ export declare class Session<TContext = unknown> implements PromiseLike<void> {
|
|
|
18
18
|
uncheck(label: string): this;
|
|
19
19
|
choose(label: string): this;
|
|
20
20
|
submit(): this;
|
|
21
|
+
/** Set a file input, found by its label, to the file at `path`. */
|
|
22
|
+
attachFile(label: string, path: string): this;
|
|
23
|
+
/** @deprecated Older name for {@link Session.attachFile}. */
|
|
21
24
|
upload(label: string, path: string): this;
|
|
22
25
|
dropFile(selector: string, path: string): this;
|
|
26
|
+
/** Press a key on the focused element, e.g. 'Enter' or 'Control+A'. */
|
|
27
|
+
pressKey(key: string): this;
|
|
28
|
+
/** Hover the element with this text. */
|
|
29
|
+
hover(text: string): this;
|
|
23
30
|
assertText(text: string): this;
|
|
24
31
|
refuteText(text: string): this;
|
|
25
32
|
assertValue(label: string, value: string): this;
|
|
@@ -31,6 +38,24 @@ export declare class Session<TContext = unknown> implements PromiseLike<void> {
|
|
|
31
38
|
refuteHas(selector: string, opts?: AssertHasOptions): this;
|
|
32
39
|
assertPath(path: string, opts?: AssertPathOptions): this;
|
|
33
40
|
refutePath(path: string): this;
|
|
41
|
+
/**
|
|
42
|
+
* Assert that running `trigger` makes the browser offer a download whose
|
|
43
|
+
* suggested filename matches `expected`. The trigger is a callback because
|
|
44
|
+
* the wait has to be armed before the click that starts the download.
|
|
45
|
+
*
|
|
46
|
+
* Browser-only: the RTL adapter throws a BrowserOnlyVerbError.
|
|
47
|
+
*/
|
|
48
|
+
assertDownload(expected: string | RegExp, trigger: (scoped: Session<TContext, TNative>) => Session<TContext, TNative> | PromiseLike<unknown>, opts?: DownloadOptions): this;
|
|
49
|
+
/**
|
|
50
|
+
* Wait for a condition instead of sleeping. `description` is mandatory: it
|
|
51
|
+
* is what the chain trace prints, so a timeout reads
|
|
52
|
+
* `[FAILED] until: the export finishes` rather than naming a mechanism.
|
|
53
|
+
*
|
|
54
|
+
* The predicate receives the adapter's context ({ page, scope } for
|
|
55
|
+
* Playwright, { user, container } for RTL) and may be sync or async; it
|
|
56
|
+
* is polled until it returns something truthy or the budget is spent.
|
|
57
|
+
*/
|
|
58
|
+
until(description: string, predicate: UntilPredicate<TContext>, opts?: UntilOptions): this;
|
|
34
59
|
/**
|
|
35
60
|
* Queue a named custom step. `fn` receives the adapter's context
|
|
36
61
|
* ({ page, scope } for Playwright, { user, container } for RTL), so a
|
|
@@ -38,12 +63,19 @@ export declare class Session<TContext = unknown> implements PromiseLike<void> {
|
|
|
38
63
|
* StepError output like any built-in step.
|
|
39
64
|
*/
|
|
40
65
|
step(name: string, fn: (context: TContext) => Promise<unknown>): this;
|
|
66
|
+
/**
|
|
67
|
+
* Drop to the driver itself — Playwright's `page`, RTL's scoped queries —
|
|
68
|
+
* without leaving the chain. `label` is mandatory and registers as a named
|
|
69
|
+
* step, so an escape hatch still names intent in the trace instead of
|
|
70
|
+
* ending it: `[FAILED] raw('drag the card to Done')`.
|
|
71
|
+
*/
|
|
72
|
+
raw(label: string, fn: (native: TNative) => unknown | Promise<unknown>): this;
|
|
41
73
|
/**
|
|
42
74
|
* `fn` must either return the scoped session — so its queued steps run — or
|
|
43
75
|
* a promise it already awaited. Returning anything else would silently drop
|
|
44
76
|
* the scoped chain, which is why the callback's return type is not `unknown`.
|
|
45
77
|
*/
|
|
46
|
-
within(selector: string, fn: (scoped: Session<TContext>) => Session<TContext> | PromiseLike<unknown>): this;
|
|
78
|
+
within(selector: string, fn: (scoped: Session<TContext, TNative>) => Session<TContext, TNative> | PromiseLike<unknown>): this;
|
|
47
79
|
debug(): this;
|
|
48
80
|
}
|
|
49
81
|
//# sourceMappingURL=session.d.ts.map
|
package/dist/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EAEf,UAAU,EACV,YAAY,EACZ,cAAc,EACf,MAAM,YAAY,CAAC;AAsBpB,qBAAa,OAAO,CAAC,QAAQ,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,CACxD,YAAW,WAAW,CAAC,IAAI,CAAC;IAMhB,OAAO,CAAC,MAAM;IAJ1B,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,SAAS,CAAK;gBAEF,MAAM,EAAE,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC;IAEzD,IAAI,CAAC,QAAQ,GAAG,IAAI,EAAE,QAAQ,GAAG,KAAK,EACpC,WAAW,CAAC,EACR,CAAC,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GACnD,IAAI,EACR,UAAU,CAAC,EACP,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GACvD,IAAI,GACP,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAIjB,YAAY;IAuB1B,OAAO,CAAC,OAAO;IAOf,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMzB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIzB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM7B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM/B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAM1C,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAMjD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI1B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM5B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM3B,MAAM,IAAI,IAAI;IAId,mEAAmE;IACnE,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAM7C,6DAA6D;IAC7D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAQzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAM9C,uEAAuE;IACvE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI3B,wCAAwC;IACxC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMzB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM9B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM9B,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAM/C,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMlC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMlC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAOxD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI;IAO1D,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAO1D,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAO1D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAMxD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM9B;;;;;;OAMG;IACH,cAAc,CACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,EACzB,OAAO,EAAE,CACP,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAC/B,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,EACtD,IAAI,CAAC,EAAE,eAAe,GACrB,IAAI;IAcP;;;;;;;;OAQG;IACH,KAAK,CACH,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,cAAc,CAAC,QAAQ,CAAC,EACnC,IAAI,CAAC,EAAE,YAAY,GAClB,IAAI;IASP;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI;IAIrE;;;;;OAKG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI;IAO7E;;;;OAIG;IACH,MAAM,CACJ,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,CACF,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAC/B,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,GACrD,IAAI;IAUP,KAAK,IAAI,IAAI;CAGd"}
|