@atomic-testing/playwright 0.78.0 → 0.79.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/dist/{index.js → index.cjs} +51 -88
- package/dist/index.cjs.map +1 -0
- package/dist/{index.d.ts → index.d.cts} +1 -1
- package/dist/index.mjs +15 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -5
- package/dist/index.js.map +0 -1
|
@@ -1,28 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
const __atomic_testing_core = __toESM(require("@atomic-testing/core"));
|
|
25
|
-
const __playwright_test = __toESM(require("@playwright/test"));
|
|
1
|
+
let _atomic_testing_core = require("@atomic-testing/core");
|
|
2
|
+
let _playwright_test = require("@playwright/test");
|
|
26
3
|
|
|
27
4
|
//#region src/PlaywrightInteractor.ts
|
|
28
5
|
/**
|
|
@@ -42,7 +19,7 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
42
19
|
* @param values - Values to select.
|
|
43
20
|
*/
|
|
44
21
|
async selectOptionValue(locator, values) {
|
|
45
|
-
const cssLocator = await
|
|
22
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
46
23
|
await this.page.locator(cssLocator).selectOption(values);
|
|
47
24
|
}
|
|
48
25
|
/**
|
|
@@ -52,7 +29,7 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
52
29
|
* @returns The current value of the input or `undefined` if not present.
|
|
53
30
|
*/
|
|
54
31
|
async getInputValue(locator) {
|
|
55
|
-
const cssLocator = await
|
|
32
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
56
33
|
return this.page.locator(cssLocator).inputValue();
|
|
57
34
|
}
|
|
58
35
|
/**
|
|
@@ -62,9 +39,9 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
62
39
|
* @returns Array of selected option values or `undefined` when no option is selected.
|
|
63
40
|
*/
|
|
64
41
|
async getSelectValues(locator) {
|
|
65
|
-
const optionLocator = (0,
|
|
66
|
-
const selectedOptionLocator =
|
|
67
|
-
const cssLocator = await
|
|
42
|
+
const optionLocator = (0, _atomic_testing_core.byCssSelector)("option:checked");
|
|
43
|
+
const selectedOptionLocator = _atomic_testing_core.locatorUtil.append(locator, optionLocator);
|
|
44
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(selectedOptionLocator, this);
|
|
68
45
|
const allOptions = await this.page.locator(cssLocator).all();
|
|
69
46
|
const values = [];
|
|
70
47
|
for (const option of allOptions) {
|
|
@@ -74,9 +51,9 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
74
51
|
return values;
|
|
75
52
|
}
|
|
76
53
|
async getSelectLabels(locator) {
|
|
77
|
-
const optionLocator = (0,
|
|
78
|
-
const selectedOptionLocator =
|
|
79
|
-
const cssLocator = await
|
|
54
|
+
const optionLocator = (0, _atomic_testing_core.byCssSelector)("option:checked");
|
|
55
|
+
const selectedOptionLocator = _atomic_testing_core.locatorUtil.append(locator, optionLocator);
|
|
56
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(selectedOptionLocator, this);
|
|
80
57
|
const allOptions = await this.page.locator(cssLocator).all();
|
|
81
58
|
const labels = [];
|
|
82
59
|
for (const option of allOptions) {
|
|
@@ -86,29 +63,27 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
86
63
|
return labels;
|
|
87
64
|
}
|
|
88
65
|
async getStyleValue(locator, propertyName) {
|
|
89
|
-
const cssLocator = await
|
|
90
|
-
|
|
91
|
-
const value = await elLocator.evaluate((element, prop) => {
|
|
66
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
67
|
+
return await this.page.locator(cssLocator).evaluate((element, prop) => {
|
|
92
68
|
return window.getComputedStyle(element).getPropertyValue(prop);
|
|
93
69
|
}, propertyName);
|
|
94
|
-
return value;
|
|
95
70
|
}
|
|
96
71
|
async enterText(locator, text, option) {
|
|
97
|
-
const cssLocator = await
|
|
72
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
98
73
|
if (!option?.append) await this.page.locator(cssLocator).clear();
|
|
99
74
|
const type = await this.getAttribute(locator, "type") ?? "";
|
|
100
|
-
if (
|
|
101
|
-
const result =
|
|
75
|
+
if (_atomic_testing_core.dateUtil.isHtmlDateInputType(type)) {
|
|
76
|
+
const result = _atomic_testing_core.dateUtil.validateHtmlDateInput(type, text);
|
|
102
77
|
if (!result.valid) throw new Error(`Invalid date format for type: ${type}, expected format: ${result.format}, example: ${result.example}`);
|
|
103
78
|
}
|
|
104
79
|
await this.page.locator(cssLocator).fill(text);
|
|
105
80
|
}
|
|
106
81
|
async click(locator, option) {
|
|
107
|
-
const cssLocator = await
|
|
82
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
108
83
|
await this.page.locator(cssLocator).click({ position: option?.position });
|
|
109
84
|
}
|
|
110
85
|
async hover(locator, option) {
|
|
111
|
-
const cssLocator = await
|
|
86
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
112
87
|
await this.page.locator(cssLocator).hover({ position: option?.position });
|
|
113
88
|
}
|
|
114
89
|
async mouseMove(locator, option) {
|
|
@@ -140,64 +115,56 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
140
115
|
return this.mouseOut(locator);
|
|
141
116
|
}
|
|
142
117
|
async focus(locator, _option) {
|
|
143
|
-
const cssLocator = await
|
|
118
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
144
119
|
return this.page.focus(cssLocator);
|
|
145
120
|
}
|
|
146
121
|
wait(ms) {
|
|
147
|
-
return
|
|
122
|
+
return _atomic_testing_core.timingUtil.wait(ms);
|
|
148
123
|
}
|
|
149
|
-
async waitUntilComponentState(locator, option =
|
|
150
|
-
return
|
|
124
|
+
async waitUntilComponentState(locator, option = _atomic_testing_core.defaultWaitForOption) {
|
|
125
|
+
return _atomic_testing_core.interactorUtil.interactorWaitUtil(locator, this, option);
|
|
151
126
|
}
|
|
152
127
|
waitUntil(option) {
|
|
153
|
-
return
|
|
128
|
+
return _atomic_testing_core.timingUtil.waitUntil(option);
|
|
154
129
|
}
|
|
155
130
|
async getAttribute(locator, name, isMultiple) {
|
|
156
|
-
const cssLocator = await
|
|
131
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
157
132
|
const elLocator = this.page.locator(cssLocator);
|
|
158
133
|
if (isMultiple) {
|
|
159
134
|
const locators = await elLocator.all();
|
|
160
135
|
const values = [];
|
|
161
136
|
for (const locator$1 of locators) {
|
|
162
|
-
const value
|
|
163
|
-
if (value
|
|
137
|
+
const value = await locator$1.getAttribute(name);
|
|
138
|
+
if (value != null) values.push(value);
|
|
164
139
|
}
|
|
165
140
|
return values;
|
|
166
141
|
}
|
|
167
|
-
|
|
168
|
-
return value ?? void 0;
|
|
142
|
+
return await elLocator.getAttribute(name) ?? void 0;
|
|
169
143
|
}
|
|
170
144
|
async getText(locator) {
|
|
171
|
-
const cssLocator = await
|
|
172
|
-
|
|
173
|
-
return text ?? void 0;
|
|
145
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
146
|
+
return await this.page.locator(cssLocator).textContent() ?? void 0;
|
|
174
147
|
}
|
|
175
148
|
async exists(locator) {
|
|
176
|
-
const cssLocator = await
|
|
177
|
-
|
|
178
|
-
return count > 0;
|
|
149
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
150
|
+
return await this.page.locator(cssLocator).count() > 0;
|
|
179
151
|
}
|
|
180
152
|
async isChecked(locator) {
|
|
181
|
-
const cssLocator = await
|
|
182
|
-
|
|
183
|
-
return checked;
|
|
153
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
154
|
+
return await this.page.locator(cssLocator).isChecked();
|
|
184
155
|
}
|
|
185
156
|
async isDisabled(locator) {
|
|
186
|
-
const cssLocator = await
|
|
187
|
-
|
|
188
|
-
return isDisabled;
|
|
157
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
158
|
+
return await this.page.locator(cssLocator).isDisabled();
|
|
189
159
|
}
|
|
190
160
|
async isReadonly(locator) {
|
|
191
|
-
|
|
192
|
-
return readonly != null;
|
|
161
|
+
return await this.getAttribute(locator, "readonly") != null;
|
|
193
162
|
}
|
|
194
163
|
async isVisible(locator) {
|
|
195
|
-
|
|
196
|
-
if (!exists) return false;
|
|
164
|
+
if (!await this.exists(locator)) return false;
|
|
197
165
|
async function checkCssVisibility(prop, invisibleValue, interactor) {
|
|
198
166
|
try {
|
|
199
|
-
|
|
200
|
-
return value !== invisibleValue;
|
|
167
|
+
return await interactor.getStyleValue(locator, prop) !== invisibleValue;
|
|
201
168
|
} catch (e) {
|
|
202
169
|
if (await interactor.exists(locator) === false) return false;
|
|
203
170
|
throw e;
|
|
@@ -211,15 +178,13 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
211
178
|
async hasCssClass(locator, className) {
|
|
212
179
|
const classNames = await this.getAttribute(locator, "class");
|
|
213
180
|
if (classNames == null) return false;
|
|
214
|
-
|
|
215
|
-
return names.includes(className);
|
|
181
|
+
return classNames.split(/\s+/).includes(className);
|
|
216
182
|
}
|
|
217
183
|
async hasAttribute(locator, name) {
|
|
218
|
-
|
|
219
|
-
return attrValue != null;
|
|
184
|
+
return await this.getAttribute(locator, name) != null;
|
|
220
185
|
}
|
|
221
186
|
async innerHTML(locator) {
|
|
222
|
-
const cssLocator = await
|
|
187
|
+
const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
|
|
223
188
|
return this.page.locator(cssLocator).innerHTML();
|
|
224
189
|
}
|
|
225
190
|
clone() {
|
|
@@ -238,15 +203,13 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
238
203
|
* @returns A configured {@link TestEngine} ready for use.
|
|
239
204
|
*/
|
|
240
205
|
function createTestEngine(page, partDefinitions) {
|
|
241
|
-
|
|
242
|
-
return engine;
|
|
206
|
+
return new _atomic_testing_core.TestEngine([], new PlaywrightInteractor(page), { parts: partDefinitions });
|
|
243
207
|
}
|
|
244
208
|
|
|
245
209
|
//#endregion
|
|
246
210
|
//#region src/testRunnerAdapter.ts
|
|
247
211
|
async function goto(url, fixture) {
|
|
248
|
-
|
|
249
|
-
await page.goto(url);
|
|
212
|
+
await fixture.page.goto(url);
|
|
250
213
|
}
|
|
251
214
|
/**
|
|
252
215
|
* Create a {@link TestEngine} bound to the Playwright page in the given fixture.
|
|
@@ -259,14 +222,14 @@ function playwrightGetTestEngine(scenePart, fixture) {
|
|
|
259
222
|
return createTestEngine(page, scenePart);
|
|
260
223
|
}
|
|
261
224
|
const playWrightTestFrameworkMapper = {
|
|
262
|
-
assertEqual: (a, b) => (0,
|
|
263
|
-
describe:
|
|
264
|
-
beforeEach:
|
|
265
|
-
afterEach:
|
|
266
|
-
beforeAll:
|
|
267
|
-
afterAll:
|
|
268
|
-
test:
|
|
269
|
-
it:
|
|
225
|
+
assertEqual: (a, b) => (0, _playwright_test.expect)(a).toEqual(b),
|
|
226
|
+
describe: _playwright_test.test.describe,
|
|
227
|
+
beforeEach: _playwright_test.test.beforeEach,
|
|
228
|
+
afterEach: _playwright_test.test.afterEach,
|
|
229
|
+
beforeAll: _playwright_test.test.beforeAll,
|
|
230
|
+
afterAll: _playwright_test.test.afterAll,
|
|
231
|
+
test: _playwright_test.test,
|
|
232
|
+
it: _playwright_test.test
|
|
270
233
|
};
|
|
271
234
|
/**
|
|
272
235
|
* Get a typed interface for running end-to-end tests with Playwright.
|
|
@@ -285,4 +248,4 @@ exports.getTestRunnerInterface = getTestRunnerInterface;
|
|
|
285
248
|
exports.goto = goto;
|
|
286
249
|
exports.playWrightTestFrameworkMapper = playWrightTestFrameworkMapper;
|
|
287
250
|
exports.playwrightGetTestEngine = playwrightGetTestEngine;
|
|
288
|
-
//# sourceMappingURL=index.
|
|
251
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["page: Page","locatorUtil","optionLocator: PartLocator","values: string[]","labels: string[]","dateUtil","timingUtil","defaultWaitForOption","interactorUtil","locator","TestEngine","playWrightTestFrameworkMapper: TestFrameworkMapper","test"],"sources":["../src/PlaywrightInteractor.ts","../src/createTestEngine.ts","../src/testRunnerAdapter.ts"],"sourcesContent":["import {\n byCssSelector,\n ClickOption,\n CssProperty,\n dateUtil,\n defaultWaitForOption,\n EnterTextOption,\n FocusOption,\n HoverOption,\n Interactor,\n interactorUtil,\n locatorUtil,\n MouseEnterOption,\n MouseLeaveOption,\n MouseOutOption,\n MouseDownOption,\n MouseMoveOption,\n MouseUpOption,\n Optional,\n PartLocator,\n timingUtil,\n WaitForOption,\n WaitUntilOption,\n} from '@atomic-testing/core';\nimport { Page } from '@playwright/test';\n\n/**\n * Implementation of the {@link Interactor} interface using Playwright.\n */\nexport class PlaywrightInteractor implements Interactor {\n /**\n * @param page - Playwright page instance used to drive the browser.\n */\n constructor(public readonly page: Page) {}\n\n /**\n * Select the given option values on a `<select>` element.\n *\n * @param locator - Locator to the `<select>` element.\n * @param values - Values to select.\n */\n async selectOptionValue(locator: PartLocator, values: string[]): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).selectOption(values);\n }\n\n /**\n * Get the value of an `<input>` element.\n *\n * @param locator - Locator pointing to the input element.\n * @returns The current value of the input or `undefined` if not present.\n */\n async getInputValue(locator: PartLocator): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.locator(cssLocator).inputValue();\n }\n\n /**\n * Retrieve the values of selected options within a `<select>` element.\n *\n * @param locator - Locator to the `<select>` element.\n * @returns Array of selected option values or `undefined` when no option is selected.\n */\n async getSelectValues(locator: PartLocator): Promise<Optional<readonly string[]>> {\n const optionLocator: PartLocator = byCssSelector('option:checked');\n const selectedOptionLocator = locatorUtil.append(locator, optionLocator);\n const cssLocator = await locatorUtil.toCssSelector(selectedOptionLocator, this);\n const allOptions = await this.page.locator(cssLocator).all();\n const values: string[] = [];\n for (const option of allOptions) {\n const value = await option.getAttribute('value');\n if (value != null) {\n values.push(value);\n }\n }\n return values;\n }\n\n async getSelectLabels(locator: PartLocator): Promise<Optional<readonly string[]>> {\n const optionLocator: PartLocator = byCssSelector('option:checked');\n const selectedOptionLocator = locatorUtil.append(locator, optionLocator);\n const cssLocator = await locatorUtil.toCssSelector(selectedOptionLocator, this);\n const allOptions = await this.page.locator(cssLocator).all();\n const labels: string[] = [];\n for (const option of allOptions) {\n const label = await option.textContent();\n if (label != null) {\n labels.push(label);\n }\n }\n return labels;\n }\n\n async getStyleValue(locator: PartLocator, propertyName: CssProperty): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const elLocator = this.page.locator(cssLocator);\n const value = await elLocator.evaluate((element, prop) => {\n return window.getComputedStyle(element).getPropertyValue(prop as string);\n }, propertyName);\n return value;\n }\n\n async enterText(locator: PartLocator, text: string, option?: Optional<Partial<EnterTextOption>>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n if (!option?.append) {\n await this.page.locator(cssLocator).clear();\n }\n\n // If it is a date, time or datetime-local input, validate the date format\n const type = (await this.getAttribute(locator, 'type')) ?? '';\n if (dateUtil.isHtmlDateInputType(type)) {\n const result = dateUtil.validateHtmlDateInput(type, text);\n if (!result.valid) {\n throw new Error(\n `Invalid date format for type: ${type}, expected format: ${result.format}, example: ${result.example}`\n );\n }\n }\n await this.page.locator(cssLocator).fill(text);\n }\n\n async click(locator: PartLocator, option?: Partial<ClickOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).click({ position: option?.position });\n }\n\n async hover(locator: PartLocator, option?: Partial<HoverOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).hover({ position: option?.position });\n }\n\n async mouseMove(locator: PartLocator, option?: Partial<MouseMoveOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.move(0, 0);\n }\n\n async mouseDown(locator: PartLocator, option?: Partial<MouseDownOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.down();\n }\n\n async mouseUp(locator: PartLocator, option?: Partial<MouseUpOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.up();\n }\n\n async mouseOver(locator: PartLocator, option?: Partial<HoverOption>): Promise<void> {\n return this.hover(locator, option);\n }\n\n async mouseOut(locator: PartLocator, _option?: Partial<MouseOutOption>): Promise<void> {\n await this.hover(locator, {\n position: {\n x: 0,\n y: 0,\n },\n });\n await this.page.mouse.move(-10, -10);\n }\n\n async mouseEnter(locator: PartLocator, _option?: Partial<MouseEnterOption>): Promise<void> {\n return this.hover(locator);\n }\n\n async mouseLeave(locator: PartLocator, _option?: Partial<MouseLeaveOption>): Promise<void> {\n return this.mouseOut(locator);\n }\n\n async focus(locator: PartLocator, _option: Partial<FocusOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.focus(cssLocator);\n }\n\n //#region wait conditions\n wait(ms: number): Promise<void> {\n return timingUtil.wait(ms);\n }\n\n async waitUntilComponentState(\n locator: PartLocator,\n option: Partial<Readonly<WaitForOption>> = defaultWaitForOption\n ): Promise<void> {\n return interactorUtil.interactorWaitUtil(locator, this, option);\n }\n\n waitUntil<T>(option: WaitUntilOption<T>): Promise<T> {\n return timingUtil.waitUntil(option);\n }\n //#endregion\n\n async getAttribute(locator: PartLocator, name: string, isMultiple: true): Promise<readonly string[]>;\n async getAttribute(locator: PartLocator, name: string, isMultiple: false): Promise<Optional<string>>;\n async getAttribute(locator: PartLocator, name: string): Promise<Optional<string>>;\n async getAttribute(\n locator: PartLocator,\n name: string,\n isMultiple?: boolean\n ): Promise<Optional<string> | readonly string[]> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const elLocator = this.page.locator(cssLocator);\n if (isMultiple) {\n const locators = await elLocator.all();\n const values: string[] = [];\n for (const locator of locators) {\n const value = await locator.getAttribute(name);\n if (value != null) {\n values.push(value);\n }\n }\n return values;\n }\n const value = await elLocator.getAttribute(name);\n return value ?? undefined;\n }\n\n async getText(locator: PartLocator): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const text = await this.page.locator(cssLocator).textContent();\n return text ?? undefined;\n }\n\n async exists(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const count = await this.page.locator(cssLocator).count();\n return count > 0;\n }\n\n async isChecked(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const checked = await this.page.locator(cssLocator).isChecked();\n return checked;\n }\n\n async isDisabled(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const isDisabled = await this.page.locator(cssLocator).isDisabled();\n return isDisabled;\n }\n\n async isReadonly(locator: PartLocator): Promise<boolean> {\n const readonly = await this.getAttribute(locator, 'readonly');\n return readonly != null;\n }\n\n async isVisible(locator: PartLocator): Promise<boolean> {\n const exists = await this.exists(locator);\n if (!exists) {\n return false;\n }\n\n async function checkCssVisibility(\n prop: CssProperty,\n invisibleValue: string,\n interactor: PlaywrightInteractor\n ): Promise<boolean> {\n try {\n const value = await interactor.getStyleValue(locator, prop);\n return value !== invisibleValue;\n } catch (e) {\n // Element may disappear or detached while being checked because of animation\n // when it happens, an error is thrown. In this case, if indeed the element\n // is not visible, we return false. Otherwise, we re-throw the error.\n if ((await interactor.exists(locator)) === false) {\n return false;\n }\n throw e;\n }\n }\n\n if ((await checkCssVisibility('opacity', '0', this)) === false) {\n return false;\n }\n\n if ((await checkCssVisibility('visibility', 'hidden', this)) === false) {\n return false;\n }\n\n if ((await checkCssVisibility('display', 'none', this)) === false) {\n return false;\n }\n\n return true;\n }\n\n async hasCssClass(locator: PartLocator, className: string): Promise<boolean> {\n const classNames = await this.getAttribute(locator, 'class');\n if (classNames == null) {\n return false;\n }\n\n const names = classNames.split(/\\s+/);\n return names.includes(className);\n }\n\n async hasAttribute(locator: PartLocator, name: string): Promise<boolean> {\n const attrValue = await this.getAttribute(locator, name);\n return attrValue != null;\n }\n\n //#region\n async innerHTML(locator: PartLocator): Promise<string> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.locator(cssLocator).innerHTML();\n }\n //#endregion\n\n clone(): Interactor {\n return new PlaywrightInteractor(this.page);\n }\n}\n","import { ScenePart, TestEngine } from '@atomic-testing/core';\nimport { Page } from '@playwright/test';\n\nimport { PlaywrightInteractor } from './PlaywrightInteractor';\n\n/**\n * Create a {@link TestEngine} instance backed by Playwright.\n *\n * @param page - Playwright page used for interaction.\n * @param partDefinitions - Scene part definitions describing the scene\n * structure for the engine.\n * @returns A configured {@link TestEngine} ready for use.\n */\nexport function createTestEngine<T extends ScenePart>(page: Page, partDefinitions: T): TestEngine<T> {\n const engine = new TestEngine([], new PlaywrightInteractor(page), {\n parts: partDefinitions,\n });\n\n return engine;\n}\n","import { ScenePart, TestEngine } from '@atomic-testing/core';\nimport {\n E2eTestInterface,\n E2eTestRunEnvironmentFixture,\n TestFrameworkMapper,\n} from '@atomic-testing/internal-test-runner';\nimport { expect, Page, test } from '@playwright/test';\n\nimport { createTestEngine } from './createTestEngine';\n\n/**\n * Navigate the current Playwright page to the provided URL.\n *\n * @param url - Destination URL to load.\n * @param fixture - Optional test fixture supplying the Playwright page.\n */\nexport async function goto(url: string): Promise<void>;\nexport async function goto(url: string, fixture: E2eTestRunEnvironmentFixture): Promise<void>;\nexport async function goto(url: string, fixture?: E2eTestRunEnvironmentFixture): Promise<void> {\n const page = fixture!.page as Page;\n await page.goto(url);\n}\n\n/**\n * Create a {@link TestEngine} bound to the Playwright page in the given fixture.\n *\n * @param scenePart - Scene definition to drive.\n * @param fixture - Fixture providing the Playwright page.\n */\nexport function playwrightGetTestEngine<T extends ScenePart>(\n scenePart: T,\n fixture: E2eTestRunEnvironmentFixture\n): TestEngine<T> {\n const page = fixture.page as Page;\n return createTestEngine(page, scenePart);\n}\n\nexport const playWrightTestFrameworkMapper: TestFrameworkMapper = {\n assertEqual: (a, b) => expect(a).toEqual(b),\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n describe: test.describe,\n\n beforeEach: test.beforeEach,\n afterEach: test.afterEach,\n beforeAll: test.beforeAll,\n afterAll: test.afterAll,\n\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n test: test,\n\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n it: test,\n};\n\n/**\n * Get a typed interface for running end-to-end tests with Playwright.\n */\nexport function getTestRunnerInterface<T extends ScenePart>(): E2eTestInterface<T> {\n return {\n getTestEngine: playwrightGetTestEngine,\n goto,\n };\n}\n"],"mappings":"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"}
|
|
@@ -99,4 +99,4 @@ declare const playWrightTestFrameworkMapper: TestFrameworkMapper;
|
|
|
99
99
|
declare function getTestRunnerInterface<T extends ScenePart>(): E2eTestInterface<T>;
|
|
100
100
|
//#endregion
|
|
101
101
|
export { PlaywrightInteractor, createTestEngine, getTestRunnerInterface, goto, playWrightTestFrameworkMapper, playwrightGetTestEngine };
|
|
102
|
-
//# sourceMappingURL=index.d.
|
|
102
|
+
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.mjs
CHANGED
|
@@ -64,11 +64,9 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
64
64
|
}
|
|
65
65
|
async getStyleValue(locator, propertyName) {
|
|
66
66
|
const cssLocator = await locatorUtil.toCssSelector(locator, this);
|
|
67
|
-
|
|
68
|
-
const value = await elLocator.evaluate((element, prop) => {
|
|
67
|
+
return await this.page.locator(cssLocator).evaluate((element, prop) => {
|
|
69
68
|
return window.getComputedStyle(element).getPropertyValue(prop);
|
|
70
69
|
}, propertyName);
|
|
71
|
-
return value;
|
|
72
70
|
}
|
|
73
71
|
async enterText(locator, text, option) {
|
|
74
72
|
const cssLocator = await locatorUtil.toCssSelector(locator, this);
|
|
@@ -136,45 +134,37 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
136
134
|
const locators = await elLocator.all();
|
|
137
135
|
const values = [];
|
|
138
136
|
for (const locator$1 of locators) {
|
|
139
|
-
const value
|
|
140
|
-
if (value
|
|
137
|
+
const value = await locator$1.getAttribute(name);
|
|
138
|
+
if (value != null) values.push(value);
|
|
141
139
|
}
|
|
142
140
|
return values;
|
|
143
141
|
}
|
|
144
|
-
|
|
145
|
-
return value ?? void 0;
|
|
142
|
+
return await elLocator.getAttribute(name) ?? void 0;
|
|
146
143
|
}
|
|
147
144
|
async getText(locator) {
|
|
148
145
|
const cssLocator = await locatorUtil.toCssSelector(locator, this);
|
|
149
|
-
|
|
150
|
-
return text ?? void 0;
|
|
146
|
+
return await this.page.locator(cssLocator).textContent() ?? void 0;
|
|
151
147
|
}
|
|
152
148
|
async exists(locator) {
|
|
153
149
|
const cssLocator = await locatorUtil.toCssSelector(locator, this);
|
|
154
|
-
|
|
155
|
-
return count > 0;
|
|
150
|
+
return await this.page.locator(cssLocator).count() > 0;
|
|
156
151
|
}
|
|
157
152
|
async isChecked(locator) {
|
|
158
153
|
const cssLocator = await locatorUtil.toCssSelector(locator, this);
|
|
159
|
-
|
|
160
|
-
return checked;
|
|
154
|
+
return await this.page.locator(cssLocator).isChecked();
|
|
161
155
|
}
|
|
162
156
|
async isDisabled(locator) {
|
|
163
157
|
const cssLocator = await locatorUtil.toCssSelector(locator, this);
|
|
164
|
-
|
|
165
|
-
return isDisabled;
|
|
158
|
+
return await this.page.locator(cssLocator).isDisabled();
|
|
166
159
|
}
|
|
167
160
|
async isReadonly(locator) {
|
|
168
|
-
|
|
169
|
-
return readonly != null;
|
|
161
|
+
return await this.getAttribute(locator, "readonly") != null;
|
|
170
162
|
}
|
|
171
163
|
async isVisible(locator) {
|
|
172
|
-
|
|
173
|
-
if (!exists) return false;
|
|
164
|
+
if (!await this.exists(locator)) return false;
|
|
174
165
|
async function checkCssVisibility(prop, invisibleValue, interactor) {
|
|
175
166
|
try {
|
|
176
|
-
|
|
177
|
-
return value !== invisibleValue;
|
|
167
|
+
return await interactor.getStyleValue(locator, prop) !== invisibleValue;
|
|
178
168
|
} catch (e) {
|
|
179
169
|
if (await interactor.exists(locator) === false) return false;
|
|
180
170
|
throw e;
|
|
@@ -188,12 +178,10 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
188
178
|
async hasCssClass(locator, className) {
|
|
189
179
|
const classNames = await this.getAttribute(locator, "class");
|
|
190
180
|
if (classNames == null) return false;
|
|
191
|
-
|
|
192
|
-
return names.includes(className);
|
|
181
|
+
return classNames.split(/\s+/).includes(className);
|
|
193
182
|
}
|
|
194
183
|
async hasAttribute(locator, name) {
|
|
195
|
-
|
|
196
|
-
return attrValue != null;
|
|
184
|
+
return await this.getAttribute(locator, name) != null;
|
|
197
185
|
}
|
|
198
186
|
async innerHTML(locator) {
|
|
199
187
|
const cssLocator = await locatorUtil.toCssSelector(locator, this);
|
|
@@ -215,15 +203,13 @@ var PlaywrightInteractor = class PlaywrightInteractor {
|
|
|
215
203
|
* @returns A configured {@link TestEngine} ready for use.
|
|
216
204
|
*/
|
|
217
205
|
function createTestEngine(page, partDefinitions) {
|
|
218
|
-
|
|
219
|
-
return engine;
|
|
206
|
+
return new TestEngine([], new PlaywrightInteractor(page), { parts: partDefinitions });
|
|
220
207
|
}
|
|
221
208
|
|
|
222
209
|
//#endregion
|
|
223
210
|
//#region src/testRunnerAdapter.ts
|
|
224
211
|
async function goto(url, fixture) {
|
|
225
|
-
|
|
226
|
-
await page.goto(url);
|
|
212
|
+
await fixture.page.goto(url);
|
|
227
213
|
}
|
|
228
214
|
/**
|
|
229
215
|
* Create a {@link TestEngine} bound to the Playwright page in the given fixture.
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["page: Page","locator: PartLocator","values: string[]","optionLocator: PartLocator","labels: string[]","propertyName: CssProperty","text: string","option?: Optional<Partial<EnterTextOption>>","option?: Partial<ClickOption>","option?: Partial<HoverOption>","option?: Partial<MouseMoveOption>","option?: Partial<MouseDownOption>","option?: Partial<MouseUpOption>","_option?: Partial<MouseOutOption>","_option?: Partial<MouseEnterOption>","_option?: Partial<MouseLeaveOption>","_option: Partial<FocusOption>","ms: number","option: Partial<Readonly<WaitForOption>>","option: WaitUntilOption<T>","name: string","isMultiple?: boolean","locator","value","prop: CssProperty","invisibleValue: string","interactor: PlaywrightInteractor","className: string","page: Page","partDefinitions: T","url: string","fixture?: E2eTestRunEnvironmentFixture","scenePart: T","fixture: E2eTestRunEnvironmentFixture","playWrightTestFrameworkMapper: TestFrameworkMapper"],"sources":["../src/PlaywrightInteractor.ts","../src/createTestEngine.ts","../src/testRunnerAdapter.ts"],"sourcesContent":["import {\n byCssSelector,\n ClickOption,\n CssProperty,\n dateUtil,\n defaultWaitForOption,\n EnterTextOption,\n FocusOption,\n HoverOption,\n Interactor,\n interactorUtil,\n locatorUtil,\n MouseEnterOption,\n MouseLeaveOption,\n MouseOutOption,\n MouseDownOption,\n MouseMoveOption,\n MouseUpOption,\n Optional,\n PartLocator,\n timingUtil,\n WaitForOption,\n WaitUntilOption,\n} from '@atomic-testing/core';\nimport { Page } from '@playwright/test';\n\n/**\n * Implementation of the {@link Interactor} interface using Playwright.\n */\nexport class PlaywrightInteractor implements Interactor {\n /**\n * @param page - Playwright page instance used to drive the browser.\n */\n constructor(public readonly page: Page) {}\n\n /**\n * Select the given option values on a `<select>` element.\n *\n * @param locator - Locator to the `<select>` element.\n * @param values - Values to select.\n */\n async selectOptionValue(locator: PartLocator, values: string[]): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).selectOption(values);\n }\n\n /**\n * Get the value of an `<input>` element.\n *\n * @param locator - Locator pointing to the input element.\n * @returns The current value of the input or `undefined` if not present.\n */\n async getInputValue(locator: PartLocator): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.locator(cssLocator).inputValue();\n }\n\n /**\n * Retrieve the values of selected options within a `<select>` element.\n *\n * @param locator - Locator to the `<select>` element.\n * @returns Array of selected option values or `undefined` when no option is selected.\n */\n async getSelectValues(locator: PartLocator): Promise<Optional<readonly string[]>> {\n const optionLocator: PartLocator = byCssSelector('option:checked');\n const selectedOptionLocator = locatorUtil.append(locator, optionLocator);\n const cssLocator = await locatorUtil.toCssSelector(selectedOptionLocator, this);\n const allOptions = await this.page.locator(cssLocator).all();\n const values: string[] = [];\n for (const option of allOptions) {\n const value = await option.getAttribute('value');\n if (value != null) {\n values.push(value);\n }\n }\n return values;\n }\n\n async getSelectLabels(locator: PartLocator): Promise<Optional<readonly string[]>> {\n const optionLocator: PartLocator = byCssSelector('option:checked');\n const selectedOptionLocator = locatorUtil.append(locator, optionLocator);\n const cssLocator = await locatorUtil.toCssSelector(selectedOptionLocator, this);\n const allOptions = await this.page.locator(cssLocator).all();\n const labels: string[] = [];\n for (const option of allOptions) {\n const label = await option.textContent();\n if (label != null) {\n labels.push(label);\n }\n }\n return labels;\n }\n\n async getStyleValue(locator: PartLocator, propertyName: CssProperty): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const elLocator = this.page.locator(cssLocator);\n const value = await elLocator.evaluate((element, prop) => {\n return window.getComputedStyle(element).getPropertyValue(prop as string);\n }, propertyName);\n return value;\n }\n\n async enterText(locator: PartLocator, text: string, option?: Optional<Partial<EnterTextOption>>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n if (!option?.append) {\n await this.page.locator(cssLocator).clear();\n }\n\n // If it is a date, time or datetime-local input, validate the date format\n const type = (await this.getAttribute(locator, 'type')) ?? '';\n if (dateUtil.isHtmlDateInputType(type)) {\n const result = dateUtil.validateHtmlDateInput(type, text);\n if (!result.valid) {\n throw new Error(\n `Invalid date format for type: ${type}, expected format: ${result.format}, example: ${result.example}`\n );\n }\n }\n await this.page.locator(cssLocator).fill(text);\n }\n\n async click(locator: PartLocator, option?: Partial<ClickOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).click({ position: option?.position });\n }\n\n async hover(locator: PartLocator, option?: Partial<HoverOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).hover({ position: option?.position });\n }\n\n async mouseMove(locator: PartLocator, option?: Partial<MouseMoveOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.move(0, 0);\n }\n\n async mouseDown(locator: PartLocator, option?: Partial<MouseDownOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.down();\n }\n\n async mouseUp(locator: PartLocator, option?: Partial<MouseUpOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.up();\n }\n\n async mouseOver(locator: PartLocator, option?: Partial<HoverOption>): Promise<void> {\n return this.hover(locator, option);\n }\n\n async mouseOut(locator: PartLocator, _option?: Partial<MouseOutOption>): Promise<void> {\n await this.hover(locator, {\n position: {\n x: 0,\n y: 0,\n },\n });\n await this.page.mouse.move(-10, -10);\n }\n\n async mouseEnter(locator: PartLocator, _option?: Partial<MouseEnterOption>): Promise<void> {\n return this.hover(locator);\n }\n\n async mouseLeave(locator: PartLocator, _option?: Partial<MouseLeaveOption>): Promise<void> {\n return this.mouseOut(locator);\n }\n\n async focus(locator: PartLocator, _option: Partial<FocusOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.focus(cssLocator);\n }\n\n //#region wait conditions\n wait(ms: number): Promise<void> {\n return timingUtil.wait(ms);\n }\n\n async waitUntilComponentState(\n locator: PartLocator,\n option: Partial<Readonly<WaitForOption>> = defaultWaitForOption\n ): Promise<void> {\n return interactorUtil.interactorWaitUtil(locator, this, option);\n }\n\n waitUntil<T>(option: WaitUntilOption<T>): Promise<T> {\n return timingUtil.waitUntil(option);\n }\n //#endregion\n\n async getAttribute(locator: PartLocator, name: string, isMultiple: true): Promise<readonly string[]>;\n async getAttribute(locator: PartLocator, name: string, isMultiple: false): Promise<Optional<string>>;\n async getAttribute(locator: PartLocator, name: string): Promise<Optional<string>>;\n async getAttribute(\n locator: PartLocator,\n name: string,\n isMultiple?: boolean\n ): Promise<Optional<string> | readonly string[]> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const elLocator = this.page.locator(cssLocator);\n if (isMultiple) {\n const locators = await elLocator.all();\n const values: string[] = [];\n for (const locator of locators) {\n const value = await locator.getAttribute(name);\n if (value != null) {\n values.push(value);\n }\n }\n return values;\n }\n const value = await elLocator.getAttribute(name);\n return value ?? undefined;\n }\n\n async getText(locator: PartLocator): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const text = await this.page.locator(cssLocator).textContent();\n return text ?? undefined;\n }\n\n async exists(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const count = await this.page.locator(cssLocator).count();\n return count > 0;\n }\n\n async isChecked(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const checked = await this.page.locator(cssLocator).isChecked();\n return checked;\n }\n\n async isDisabled(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const isDisabled = await this.page.locator(cssLocator).isDisabled();\n return isDisabled;\n }\n\n async isReadonly(locator: PartLocator): Promise<boolean> {\n const readonly = await this.getAttribute(locator, 'readonly');\n return readonly != null;\n }\n\n async isVisible(locator: PartLocator): Promise<boolean> {\n const exists = await this.exists(locator);\n if (!exists) {\n return false;\n }\n\n async function checkCssVisibility(\n prop: CssProperty,\n invisibleValue: string,\n interactor: PlaywrightInteractor\n ): Promise<boolean> {\n try {\n const value = await interactor.getStyleValue(locator, prop);\n return value !== invisibleValue;\n } catch (e) {\n // Element may disappear or detached while being checked because of animation\n // when it happens, an error is thrown. In this case, if indeed the element\n // is not visible, we return false. Otherwise, we re-throw the error.\n if ((await interactor.exists(locator)) === false) {\n return false;\n }\n throw e;\n }\n }\n\n if ((await checkCssVisibility('opacity', '0', this)) === false) {\n return false;\n }\n\n if ((await checkCssVisibility('visibility', 'hidden', this)) === false) {\n return false;\n }\n\n if ((await checkCssVisibility('display', 'none', this)) === false) {\n return false;\n }\n\n return true;\n }\n\n async hasCssClass(locator: PartLocator, className: string): Promise<boolean> {\n const classNames = await this.getAttribute(locator, 'class');\n if (classNames == null) {\n return false;\n }\n\n const names = classNames.split(/\\s+/);\n return names.includes(className);\n }\n\n async hasAttribute(locator: PartLocator, name: string): Promise<boolean> {\n const attrValue = await this.getAttribute(locator, name);\n return attrValue != null;\n }\n\n //#region\n async innerHTML(locator: PartLocator): Promise<string> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.locator(cssLocator).innerHTML();\n }\n //#endregion\n\n clone(): Interactor {\n return new PlaywrightInteractor(this.page);\n }\n}\n","import { ScenePart, TestEngine } from '@atomic-testing/core';\nimport { Page } from '@playwright/test';\n\nimport { PlaywrightInteractor } from './PlaywrightInteractor';\n\n/**\n * Create a {@link TestEngine} instance backed by Playwright.\n *\n * @param page - Playwright page used for interaction.\n * @param partDefinitions - Scene part definitions describing the scene\n * structure for the engine.\n * @returns A configured {@link TestEngine} ready for use.\n */\nexport function createTestEngine<T extends ScenePart>(page: Page, partDefinitions: T): TestEngine<T> {\n const engine = new TestEngine([], new PlaywrightInteractor(page), {\n parts: partDefinitions,\n });\n\n return engine;\n}\n","import { ScenePart, TestEngine } from '@atomic-testing/core';\nimport {\n E2eTestInterface,\n E2eTestRunEnvironmentFixture,\n TestFrameworkMapper,\n} from '@atomic-testing/internal-test-runner';\nimport { expect, Page, test } from '@playwright/test';\n\nimport { createTestEngine } from './createTestEngine';\n\n/**\n * Navigate the current Playwright page to the provided URL.\n *\n * @param url - Destination URL to load.\n * @param fixture - Optional test fixture supplying the Playwright page.\n */\nexport async function goto(url: string): Promise<void>;\nexport async function goto(url: string, fixture: E2eTestRunEnvironmentFixture): Promise<void>;\nexport async function goto(url: string, fixture?: E2eTestRunEnvironmentFixture): Promise<void> {\n const page = fixture!.page as Page;\n await page.goto(url);\n}\n\n/**\n * Create a {@link TestEngine} bound to the Playwright page in the given fixture.\n *\n * @param scenePart - Scene definition to drive.\n * @param fixture - Fixture providing the Playwright page.\n */\nexport function playwrightGetTestEngine<T extends ScenePart>(\n scenePart: T,\n fixture: E2eTestRunEnvironmentFixture\n): TestEngine<T> {\n const page = fixture.page as Page;\n return createTestEngine(page, scenePart);\n}\n\nexport const playWrightTestFrameworkMapper: TestFrameworkMapper = {\n assertEqual: (a, b) => expect(a).toEqual(b),\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n describe: test.describe,\n\n beforeEach: test.beforeEach,\n afterEach: test.afterEach,\n beforeAll: test.beforeAll,\n afterAll: test.afterAll,\n\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n test: test,\n\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n it: test,\n};\n\n/**\n * Get a typed interface for running end-to-end tests with Playwright.\n */\nexport function getTestRunnerInterface<T extends ScenePart>(): E2eTestInterface<T> {\n return {\n getTestEngine: playwrightGetTestEngine,\n goto,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["page: Page","optionLocator: PartLocator","values: string[]","labels: string[]","locator","playWrightTestFrameworkMapper: TestFrameworkMapper"],"sources":["../src/PlaywrightInteractor.ts","../src/createTestEngine.ts","../src/testRunnerAdapter.ts"],"sourcesContent":["import {\n byCssSelector,\n ClickOption,\n CssProperty,\n dateUtil,\n defaultWaitForOption,\n EnterTextOption,\n FocusOption,\n HoverOption,\n Interactor,\n interactorUtil,\n locatorUtil,\n MouseEnterOption,\n MouseLeaveOption,\n MouseOutOption,\n MouseDownOption,\n MouseMoveOption,\n MouseUpOption,\n Optional,\n PartLocator,\n timingUtil,\n WaitForOption,\n WaitUntilOption,\n} from '@atomic-testing/core';\nimport { Page } from '@playwright/test';\n\n/**\n * Implementation of the {@link Interactor} interface using Playwright.\n */\nexport class PlaywrightInteractor implements Interactor {\n /**\n * @param page - Playwright page instance used to drive the browser.\n */\n constructor(public readonly page: Page) {}\n\n /**\n * Select the given option values on a `<select>` element.\n *\n * @param locator - Locator to the `<select>` element.\n * @param values - Values to select.\n */\n async selectOptionValue(locator: PartLocator, values: string[]): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).selectOption(values);\n }\n\n /**\n * Get the value of an `<input>` element.\n *\n * @param locator - Locator pointing to the input element.\n * @returns The current value of the input or `undefined` if not present.\n */\n async getInputValue(locator: PartLocator): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.locator(cssLocator).inputValue();\n }\n\n /**\n * Retrieve the values of selected options within a `<select>` element.\n *\n * @param locator - Locator to the `<select>` element.\n * @returns Array of selected option values or `undefined` when no option is selected.\n */\n async getSelectValues(locator: PartLocator): Promise<Optional<readonly string[]>> {\n const optionLocator: PartLocator = byCssSelector('option:checked');\n const selectedOptionLocator = locatorUtil.append(locator, optionLocator);\n const cssLocator = await locatorUtil.toCssSelector(selectedOptionLocator, this);\n const allOptions = await this.page.locator(cssLocator).all();\n const values: string[] = [];\n for (const option of allOptions) {\n const value = await option.getAttribute('value');\n if (value != null) {\n values.push(value);\n }\n }\n return values;\n }\n\n async getSelectLabels(locator: PartLocator): Promise<Optional<readonly string[]>> {\n const optionLocator: PartLocator = byCssSelector('option:checked');\n const selectedOptionLocator = locatorUtil.append(locator, optionLocator);\n const cssLocator = await locatorUtil.toCssSelector(selectedOptionLocator, this);\n const allOptions = await this.page.locator(cssLocator).all();\n const labels: string[] = [];\n for (const option of allOptions) {\n const label = await option.textContent();\n if (label != null) {\n labels.push(label);\n }\n }\n return labels;\n }\n\n async getStyleValue(locator: PartLocator, propertyName: CssProperty): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const elLocator = this.page.locator(cssLocator);\n const value = await elLocator.evaluate((element, prop) => {\n return window.getComputedStyle(element).getPropertyValue(prop as string);\n }, propertyName);\n return value;\n }\n\n async enterText(locator: PartLocator, text: string, option?: Optional<Partial<EnterTextOption>>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n if (!option?.append) {\n await this.page.locator(cssLocator).clear();\n }\n\n // If it is a date, time or datetime-local input, validate the date format\n const type = (await this.getAttribute(locator, 'type')) ?? '';\n if (dateUtil.isHtmlDateInputType(type)) {\n const result = dateUtil.validateHtmlDateInput(type, text);\n if (!result.valid) {\n throw new Error(\n `Invalid date format for type: ${type}, expected format: ${result.format}, example: ${result.example}`\n );\n }\n }\n await this.page.locator(cssLocator).fill(text);\n }\n\n async click(locator: PartLocator, option?: Partial<ClickOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).click({ position: option?.position });\n }\n\n async hover(locator: PartLocator, option?: Partial<HoverOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).hover({ position: option?.position });\n }\n\n async mouseMove(locator: PartLocator, option?: Partial<MouseMoveOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.move(0, 0);\n }\n\n async mouseDown(locator: PartLocator, option?: Partial<MouseDownOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.down();\n }\n\n async mouseUp(locator: PartLocator, option?: Partial<MouseUpOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.up();\n }\n\n async mouseOver(locator: PartLocator, option?: Partial<HoverOption>): Promise<void> {\n return this.hover(locator, option);\n }\n\n async mouseOut(locator: PartLocator, _option?: Partial<MouseOutOption>): Promise<void> {\n await this.hover(locator, {\n position: {\n x: 0,\n y: 0,\n },\n });\n await this.page.mouse.move(-10, -10);\n }\n\n async mouseEnter(locator: PartLocator, _option?: Partial<MouseEnterOption>): Promise<void> {\n return this.hover(locator);\n }\n\n async mouseLeave(locator: PartLocator, _option?: Partial<MouseLeaveOption>): Promise<void> {\n return this.mouseOut(locator);\n }\n\n async focus(locator: PartLocator, _option: Partial<FocusOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.focus(cssLocator);\n }\n\n //#region wait conditions\n wait(ms: number): Promise<void> {\n return timingUtil.wait(ms);\n }\n\n async waitUntilComponentState(\n locator: PartLocator,\n option: Partial<Readonly<WaitForOption>> = defaultWaitForOption\n ): Promise<void> {\n return interactorUtil.interactorWaitUtil(locator, this, option);\n }\n\n waitUntil<T>(option: WaitUntilOption<T>): Promise<T> {\n return timingUtil.waitUntil(option);\n }\n //#endregion\n\n async getAttribute(locator: PartLocator, name: string, isMultiple: true): Promise<readonly string[]>;\n async getAttribute(locator: PartLocator, name: string, isMultiple: false): Promise<Optional<string>>;\n async getAttribute(locator: PartLocator, name: string): Promise<Optional<string>>;\n async getAttribute(\n locator: PartLocator,\n name: string,\n isMultiple?: boolean\n ): Promise<Optional<string> | readonly string[]> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const elLocator = this.page.locator(cssLocator);\n if (isMultiple) {\n const locators = await elLocator.all();\n const values: string[] = [];\n for (const locator of locators) {\n const value = await locator.getAttribute(name);\n if (value != null) {\n values.push(value);\n }\n }\n return values;\n }\n const value = await elLocator.getAttribute(name);\n return value ?? undefined;\n }\n\n async getText(locator: PartLocator): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const text = await this.page.locator(cssLocator).textContent();\n return text ?? undefined;\n }\n\n async exists(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const count = await this.page.locator(cssLocator).count();\n return count > 0;\n }\n\n async isChecked(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const checked = await this.page.locator(cssLocator).isChecked();\n return checked;\n }\n\n async isDisabled(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const isDisabled = await this.page.locator(cssLocator).isDisabled();\n return isDisabled;\n }\n\n async isReadonly(locator: PartLocator): Promise<boolean> {\n const readonly = await this.getAttribute(locator, 'readonly');\n return readonly != null;\n }\n\n async isVisible(locator: PartLocator): Promise<boolean> {\n const exists = await this.exists(locator);\n if (!exists) {\n return false;\n }\n\n async function checkCssVisibility(\n prop: CssProperty,\n invisibleValue: string,\n interactor: PlaywrightInteractor\n ): Promise<boolean> {\n try {\n const value = await interactor.getStyleValue(locator, prop);\n return value !== invisibleValue;\n } catch (e) {\n // Element may disappear or detached while being checked because of animation\n // when it happens, an error is thrown. In this case, if indeed the element\n // is not visible, we return false. Otherwise, we re-throw the error.\n if ((await interactor.exists(locator)) === false) {\n return false;\n }\n throw e;\n }\n }\n\n if ((await checkCssVisibility('opacity', '0', this)) === false) {\n return false;\n }\n\n if ((await checkCssVisibility('visibility', 'hidden', this)) === false) {\n return false;\n }\n\n if ((await checkCssVisibility('display', 'none', this)) === false) {\n return false;\n }\n\n return true;\n }\n\n async hasCssClass(locator: PartLocator, className: string): Promise<boolean> {\n const classNames = await this.getAttribute(locator, 'class');\n if (classNames == null) {\n return false;\n }\n\n const names = classNames.split(/\\s+/);\n return names.includes(className);\n }\n\n async hasAttribute(locator: PartLocator, name: string): Promise<boolean> {\n const attrValue = await this.getAttribute(locator, name);\n return attrValue != null;\n }\n\n //#region\n async innerHTML(locator: PartLocator): Promise<string> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.locator(cssLocator).innerHTML();\n }\n //#endregion\n\n clone(): Interactor {\n return new PlaywrightInteractor(this.page);\n }\n}\n","import { ScenePart, TestEngine } from '@atomic-testing/core';\nimport { Page } from '@playwright/test';\n\nimport { PlaywrightInteractor } from './PlaywrightInteractor';\n\n/**\n * Create a {@link TestEngine} instance backed by Playwright.\n *\n * @param page - Playwright page used for interaction.\n * @param partDefinitions - Scene part definitions describing the scene\n * structure for the engine.\n * @returns A configured {@link TestEngine} ready for use.\n */\nexport function createTestEngine<T extends ScenePart>(page: Page, partDefinitions: T): TestEngine<T> {\n const engine = new TestEngine([], new PlaywrightInteractor(page), {\n parts: partDefinitions,\n });\n\n return engine;\n}\n","import { ScenePart, TestEngine } from '@atomic-testing/core';\nimport {\n E2eTestInterface,\n E2eTestRunEnvironmentFixture,\n TestFrameworkMapper,\n} from '@atomic-testing/internal-test-runner';\nimport { expect, Page, test } from '@playwright/test';\n\nimport { createTestEngine } from './createTestEngine';\n\n/**\n * Navigate the current Playwright page to the provided URL.\n *\n * @param url - Destination URL to load.\n * @param fixture - Optional test fixture supplying the Playwright page.\n */\nexport async function goto(url: string): Promise<void>;\nexport async function goto(url: string, fixture: E2eTestRunEnvironmentFixture): Promise<void>;\nexport async function goto(url: string, fixture?: E2eTestRunEnvironmentFixture): Promise<void> {\n const page = fixture!.page as Page;\n await page.goto(url);\n}\n\n/**\n * Create a {@link TestEngine} bound to the Playwright page in the given fixture.\n *\n * @param scenePart - Scene definition to drive.\n * @param fixture - Fixture providing the Playwright page.\n */\nexport function playwrightGetTestEngine<T extends ScenePart>(\n scenePart: T,\n fixture: E2eTestRunEnvironmentFixture\n): TestEngine<T> {\n const page = fixture.page as Page;\n return createTestEngine(page, scenePart);\n}\n\nexport const playWrightTestFrameworkMapper: TestFrameworkMapper = {\n assertEqual: (a, b) => expect(a).toEqual(b),\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n describe: test.describe,\n\n beforeEach: test.beforeEach,\n afterEach: test.afterEach,\n beforeAll: test.beforeAll,\n afterAll: test.afterAll,\n\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n test: test,\n\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n it: test,\n};\n\n/**\n * Get a typed interface for running end-to-end tests with Playwright.\n */\nexport function getTestRunnerInterface<T extends ScenePart>(): E2eTestInterface<T> {\n return {\n getTestEngine: playwrightGetTestEngine,\n goto,\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atomic-testing/playwright",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.79.0",
|
|
4
4
|
"description": "Atomic Testing Playwright Adapter",
|
|
5
|
-
"main": "dist/index.
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
|
-
"typings": "dist/index.d.ts",
|
|
8
7
|
"files": [
|
|
9
8
|
"dist",
|
|
10
9
|
"src"
|
|
@@ -18,12 +17,20 @@
|
|
|
18
17
|
"directory": "packages/playwright"
|
|
19
18
|
},
|
|
20
19
|
"dependencies": {
|
|
21
|
-
"@atomic-testing/core": "0.
|
|
22
|
-
"@atomic-testing/internal-test-runner": "0.
|
|
20
|
+
"@atomic-testing/core": "0.79.0",
|
|
21
|
+
"@atomic-testing/internal-test-runner": "0.79.0"
|
|
23
22
|
},
|
|
24
23
|
"peerDependencies": {
|
|
25
24
|
"@playwright/test": ">=1.50.0"
|
|
26
25
|
},
|
|
26
|
+
"types": "dist/index.d.cts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.mts",
|
|
30
|
+
"import": "./dist/index.mjs",
|
|
31
|
+
"require": "./dist/index.cjs"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
27
34
|
"scripts": {
|
|
28
35
|
"build": "tsdown",
|
|
29
36
|
"check:type": "tsc --noEmit"
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["page: Page","locator: PartLocator","values: string[]","optionLocator: PartLocator","labels: string[]","propertyName: CssProperty","text: string","option?: Optional<Partial<EnterTextOption>>","option?: Partial<ClickOption>","option?: Partial<HoverOption>","option?: Partial<MouseMoveOption>","option?: Partial<MouseDownOption>","option?: Partial<MouseUpOption>","_option?: Partial<MouseOutOption>","_option?: Partial<MouseEnterOption>","_option?: Partial<MouseLeaveOption>","_option: Partial<FocusOption>","ms: number","option: Partial<Readonly<WaitForOption>>","defaultWaitForOption","option: WaitUntilOption<T>","name: string","isMultiple?: boolean","locator","value","prop: CssProperty","invisibleValue: string","interactor: PlaywrightInteractor","className: string","page: Page","partDefinitions: T","TestEngine","url: string","fixture?: E2eTestRunEnvironmentFixture","scenePart: T","fixture: E2eTestRunEnvironmentFixture","playWrightTestFrameworkMapper: TestFrameworkMapper","test"],"sources":["../src/PlaywrightInteractor.ts","../src/createTestEngine.ts","../src/testRunnerAdapter.ts"],"sourcesContent":["import {\n byCssSelector,\n ClickOption,\n CssProperty,\n dateUtil,\n defaultWaitForOption,\n EnterTextOption,\n FocusOption,\n HoverOption,\n Interactor,\n interactorUtil,\n locatorUtil,\n MouseEnterOption,\n MouseLeaveOption,\n MouseOutOption,\n MouseDownOption,\n MouseMoveOption,\n MouseUpOption,\n Optional,\n PartLocator,\n timingUtil,\n WaitForOption,\n WaitUntilOption,\n} from '@atomic-testing/core';\nimport { Page } from '@playwright/test';\n\n/**\n * Implementation of the {@link Interactor} interface using Playwright.\n */\nexport class PlaywrightInteractor implements Interactor {\n /**\n * @param page - Playwright page instance used to drive the browser.\n */\n constructor(public readonly page: Page) {}\n\n /**\n * Select the given option values on a `<select>` element.\n *\n * @param locator - Locator to the `<select>` element.\n * @param values - Values to select.\n */\n async selectOptionValue(locator: PartLocator, values: string[]): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).selectOption(values);\n }\n\n /**\n * Get the value of an `<input>` element.\n *\n * @param locator - Locator pointing to the input element.\n * @returns The current value of the input or `undefined` if not present.\n */\n async getInputValue(locator: PartLocator): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.locator(cssLocator).inputValue();\n }\n\n /**\n * Retrieve the values of selected options within a `<select>` element.\n *\n * @param locator - Locator to the `<select>` element.\n * @returns Array of selected option values or `undefined` when no option is selected.\n */\n async getSelectValues(locator: PartLocator): Promise<Optional<readonly string[]>> {\n const optionLocator: PartLocator = byCssSelector('option:checked');\n const selectedOptionLocator = locatorUtil.append(locator, optionLocator);\n const cssLocator = await locatorUtil.toCssSelector(selectedOptionLocator, this);\n const allOptions = await this.page.locator(cssLocator).all();\n const values: string[] = [];\n for (const option of allOptions) {\n const value = await option.getAttribute('value');\n if (value != null) {\n values.push(value);\n }\n }\n return values;\n }\n\n async getSelectLabels(locator: PartLocator): Promise<Optional<readonly string[]>> {\n const optionLocator: PartLocator = byCssSelector('option:checked');\n const selectedOptionLocator = locatorUtil.append(locator, optionLocator);\n const cssLocator = await locatorUtil.toCssSelector(selectedOptionLocator, this);\n const allOptions = await this.page.locator(cssLocator).all();\n const labels: string[] = [];\n for (const option of allOptions) {\n const label = await option.textContent();\n if (label != null) {\n labels.push(label);\n }\n }\n return labels;\n }\n\n async getStyleValue(locator: PartLocator, propertyName: CssProperty): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const elLocator = this.page.locator(cssLocator);\n const value = await elLocator.evaluate((element, prop) => {\n return window.getComputedStyle(element).getPropertyValue(prop as string);\n }, propertyName);\n return value;\n }\n\n async enterText(locator: PartLocator, text: string, option?: Optional<Partial<EnterTextOption>>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n if (!option?.append) {\n await this.page.locator(cssLocator).clear();\n }\n\n // If it is a date, time or datetime-local input, validate the date format\n const type = (await this.getAttribute(locator, 'type')) ?? '';\n if (dateUtil.isHtmlDateInputType(type)) {\n const result = dateUtil.validateHtmlDateInput(type, text);\n if (!result.valid) {\n throw new Error(\n `Invalid date format for type: ${type}, expected format: ${result.format}, example: ${result.example}`\n );\n }\n }\n await this.page.locator(cssLocator).fill(text);\n }\n\n async click(locator: PartLocator, option?: Partial<ClickOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).click({ position: option?.position });\n }\n\n async hover(locator: PartLocator, option?: Partial<HoverOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).hover({ position: option?.position });\n }\n\n async mouseMove(locator: PartLocator, option?: Partial<MouseMoveOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.move(0, 0);\n }\n\n async mouseDown(locator: PartLocator, option?: Partial<MouseDownOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.down();\n }\n\n async mouseUp(locator: PartLocator, option?: Partial<MouseUpOption>): Promise<void> {\n await this.hover(locator, {\n position: option?.position,\n });\n await this.page.mouse.up();\n }\n\n async mouseOver(locator: PartLocator, option?: Partial<HoverOption>): Promise<void> {\n return this.hover(locator, option);\n }\n\n async mouseOut(locator: PartLocator, _option?: Partial<MouseOutOption>): Promise<void> {\n await this.hover(locator, {\n position: {\n x: 0,\n y: 0,\n },\n });\n await this.page.mouse.move(-10, -10);\n }\n\n async mouseEnter(locator: PartLocator, _option?: Partial<MouseEnterOption>): Promise<void> {\n return this.hover(locator);\n }\n\n async mouseLeave(locator: PartLocator, _option?: Partial<MouseLeaveOption>): Promise<void> {\n return this.mouseOut(locator);\n }\n\n async focus(locator: PartLocator, _option: Partial<FocusOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.focus(cssLocator);\n }\n\n //#region wait conditions\n wait(ms: number): Promise<void> {\n return timingUtil.wait(ms);\n }\n\n async waitUntilComponentState(\n locator: PartLocator,\n option: Partial<Readonly<WaitForOption>> = defaultWaitForOption\n ): Promise<void> {\n return interactorUtil.interactorWaitUtil(locator, this, option);\n }\n\n waitUntil<T>(option: WaitUntilOption<T>): Promise<T> {\n return timingUtil.waitUntil(option);\n }\n //#endregion\n\n async getAttribute(locator: PartLocator, name: string, isMultiple: true): Promise<readonly string[]>;\n async getAttribute(locator: PartLocator, name: string, isMultiple: false): Promise<Optional<string>>;\n async getAttribute(locator: PartLocator, name: string): Promise<Optional<string>>;\n async getAttribute(\n locator: PartLocator,\n name: string,\n isMultiple?: boolean\n ): Promise<Optional<string> | readonly string[]> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const elLocator = this.page.locator(cssLocator);\n if (isMultiple) {\n const locators = await elLocator.all();\n const values: string[] = [];\n for (const locator of locators) {\n const value = await locator.getAttribute(name);\n if (value != null) {\n values.push(value);\n }\n }\n return values;\n }\n const value = await elLocator.getAttribute(name);\n return value ?? undefined;\n }\n\n async getText(locator: PartLocator): Promise<Optional<string>> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const text = await this.page.locator(cssLocator).textContent();\n return text ?? undefined;\n }\n\n async exists(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const count = await this.page.locator(cssLocator).count();\n return count > 0;\n }\n\n async isChecked(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const checked = await this.page.locator(cssLocator).isChecked();\n return checked;\n }\n\n async isDisabled(locator: PartLocator): Promise<boolean> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n const isDisabled = await this.page.locator(cssLocator).isDisabled();\n return isDisabled;\n }\n\n async isReadonly(locator: PartLocator): Promise<boolean> {\n const readonly = await this.getAttribute(locator, 'readonly');\n return readonly != null;\n }\n\n async isVisible(locator: PartLocator): Promise<boolean> {\n const exists = await this.exists(locator);\n if (!exists) {\n return false;\n }\n\n async function checkCssVisibility(\n prop: CssProperty,\n invisibleValue: string,\n interactor: PlaywrightInteractor\n ): Promise<boolean> {\n try {\n const value = await interactor.getStyleValue(locator, prop);\n return value !== invisibleValue;\n } catch (e) {\n // Element may disappear or detached while being checked because of animation\n // when it happens, an error is thrown. In this case, if indeed the element\n // is not visible, we return false. Otherwise, we re-throw the error.\n if ((await interactor.exists(locator)) === false) {\n return false;\n }\n throw e;\n }\n }\n\n if ((await checkCssVisibility('opacity', '0', this)) === false) {\n return false;\n }\n\n if ((await checkCssVisibility('visibility', 'hidden', this)) === false) {\n return false;\n }\n\n if ((await checkCssVisibility('display', 'none', this)) === false) {\n return false;\n }\n\n return true;\n }\n\n async hasCssClass(locator: PartLocator, className: string): Promise<boolean> {\n const classNames = await this.getAttribute(locator, 'class');\n if (classNames == null) {\n return false;\n }\n\n const names = classNames.split(/\\s+/);\n return names.includes(className);\n }\n\n async hasAttribute(locator: PartLocator, name: string): Promise<boolean> {\n const attrValue = await this.getAttribute(locator, name);\n return attrValue != null;\n }\n\n //#region\n async innerHTML(locator: PartLocator): Promise<string> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n return this.page.locator(cssLocator).innerHTML();\n }\n //#endregion\n\n clone(): Interactor {\n return new PlaywrightInteractor(this.page);\n }\n}\n","import { ScenePart, TestEngine } from '@atomic-testing/core';\nimport { Page } from '@playwright/test';\n\nimport { PlaywrightInteractor } from './PlaywrightInteractor';\n\n/**\n * Create a {@link TestEngine} instance backed by Playwright.\n *\n * @param page - Playwright page used for interaction.\n * @param partDefinitions - Scene part definitions describing the scene\n * structure for the engine.\n * @returns A configured {@link TestEngine} ready for use.\n */\nexport function createTestEngine<T extends ScenePart>(page: Page, partDefinitions: T): TestEngine<T> {\n const engine = new TestEngine([], new PlaywrightInteractor(page), {\n parts: partDefinitions,\n });\n\n return engine;\n}\n","import { ScenePart, TestEngine } from '@atomic-testing/core';\nimport {\n E2eTestInterface,\n E2eTestRunEnvironmentFixture,\n TestFrameworkMapper,\n} from '@atomic-testing/internal-test-runner';\nimport { expect, Page, test } from '@playwright/test';\n\nimport { createTestEngine } from './createTestEngine';\n\n/**\n * Navigate the current Playwright page to the provided URL.\n *\n * @param url - Destination URL to load.\n * @param fixture - Optional test fixture supplying the Playwright page.\n */\nexport async function goto(url: string): Promise<void>;\nexport async function goto(url: string, fixture: E2eTestRunEnvironmentFixture): Promise<void>;\nexport async function goto(url: string, fixture?: E2eTestRunEnvironmentFixture): Promise<void> {\n const page = fixture!.page as Page;\n await page.goto(url);\n}\n\n/**\n * Create a {@link TestEngine} bound to the Playwright page in the given fixture.\n *\n * @param scenePart - Scene definition to drive.\n * @param fixture - Fixture providing the Playwright page.\n */\nexport function playwrightGetTestEngine<T extends ScenePart>(\n scenePart: T,\n fixture: E2eTestRunEnvironmentFixture\n): TestEngine<T> {\n const page = fixture.page as Page;\n return createTestEngine(page, scenePart);\n}\n\nexport const playWrightTestFrameworkMapper: TestFrameworkMapper = {\n assertEqual: (a, b) => expect(a).toEqual(b),\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n describe: test.describe,\n\n beforeEach: test.beforeEach,\n afterEach: test.afterEach,\n beforeAll: test.beforeAll,\n afterAll: test.afterAll,\n\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n test: test,\n\n // @ts-expect-error - expect type is not compatible with the type of the test framework\n it: test,\n};\n\n/**\n * Get a typed interface for running end-to-end tests with Playwright.\n */\nexport function getTestRunnerInterface<T extends ScenePart>(): E2eTestInterface<T> {\n return {\n getTestEngine: playwrightGetTestEngine,\n goto,\n };\n}\n"],"mappings":"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"}
|