@atomic-testing/playwright 0.78.0 → 0.80.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.
@@ -1,28 +1,5 @@
1
- //#region rolldown:runtime
2
- var __create = Object.create;
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 __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
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 __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
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, __atomic_testing_core.byCssSelector)("option:checked");
66
- const selectedOptionLocator = __atomic_testing_core.locatorUtil.append(locator, optionLocator);
67
- const cssLocator = await __atomic_testing_core.locatorUtil.toCssSelector(selectedOptionLocator, this);
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, __atomic_testing_core.byCssSelector)("option:checked");
78
- const selectedOptionLocator = __atomic_testing_core.locatorUtil.append(locator, optionLocator);
79
- const cssLocator = await __atomic_testing_core.locatorUtil.toCssSelector(selectedOptionLocator, this);
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 __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
90
- const elLocator = this.page.locator(cssLocator);
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 __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
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 (__atomic_testing_core.dateUtil.isHtmlDateInputType(type)) {
101
- const result = __atomic_testing_core.dateUtil.validateHtmlDateInput(type, text);
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 __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
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 __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
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,60 @@ var PlaywrightInteractor = class PlaywrightInteractor {
140
115
  return this.mouseOut(locator);
141
116
  }
142
117
  async focus(locator, _option) {
143
- const cssLocator = await __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
118
+ const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
144
119
  return this.page.focus(cssLocator);
145
120
  }
121
+ async blur(locator, _option) {
122
+ const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
123
+ await this.page.locator(cssLocator).blur();
124
+ }
146
125
  wait(ms) {
147
- return __atomic_testing_core.timingUtil.wait(ms);
126
+ return _atomic_testing_core.timingUtil.wait(ms);
148
127
  }
149
- async waitUntilComponentState(locator, option = __atomic_testing_core.defaultWaitForOption) {
150
- return __atomic_testing_core.interactorUtil.interactorWaitUtil(locator, this, option);
128
+ async waitUntilComponentState(locator, option = _atomic_testing_core.defaultWaitForOption) {
129
+ return _atomic_testing_core.interactorUtil.interactorWaitUtil(locator, this, option);
151
130
  }
152
131
  waitUntil(option) {
153
- return __atomic_testing_core.timingUtil.waitUntil(option);
132
+ return _atomic_testing_core.timingUtil.waitUntil(option);
154
133
  }
155
134
  async getAttribute(locator, name, isMultiple) {
156
- const cssLocator = await __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
135
+ const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
157
136
  const elLocator = this.page.locator(cssLocator);
158
137
  if (isMultiple) {
159
138
  const locators = await elLocator.all();
160
139
  const values = [];
161
140
  for (const locator$1 of locators) {
162
- const value$1 = await locator$1.getAttribute(name);
163
- if (value$1 != null) values.push(value$1);
141
+ const value = await locator$1.getAttribute(name);
142
+ if (value != null) values.push(value);
164
143
  }
165
144
  return values;
166
145
  }
167
- const value = await elLocator.getAttribute(name);
168
- return value ?? void 0;
146
+ return await elLocator.getAttribute(name) ?? void 0;
169
147
  }
170
148
  async getText(locator) {
171
- const cssLocator = await __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
172
- const text = await this.page.locator(cssLocator).textContent();
173
- return text ?? void 0;
149
+ const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
150
+ return await this.page.locator(cssLocator).textContent() ?? void 0;
174
151
  }
175
152
  async exists(locator) {
176
- const cssLocator = await __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
177
- const count = await this.page.locator(cssLocator).count();
178
- return count > 0;
153
+ const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
154
+ return await this.page.locator(cssLocator).count() > 0;
179
155
  }
180
156
  async isChecked(locator) {
181
- const cssLocator = await __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
182
- const checked = await this.page.locator(cssLocator).isChecked();
183
- return checked;
157
+ const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
158
+ return await this.page.locator(cssLocator).isChecked();
184
159
  }
185
160
  async isDisabled(locator) {
186
- const cssLocator = await __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
187
- const isDisabled = await this.page.locator(cssLocator).isDisabled();
188
- return isDisabled;
161
+ const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
162
+ return await this.page.locator(cssLocator).isDisabled();
189
163
  }
190
164
  async isReadonly(locator) {
191
- const readonly = await this.getAttribute(locator, "readonly");
192
- return readonly != null;
165
+ return await this.getAttribute(locator, "readonly") != null;
193
166
  }
194
167
  async isVisible(locator) {
195
- const exists = await this.exists(locator);
196
- if (!exists) return false;
168
+ if (!await this.exists(locator)) return false;
197
169
  async function checkCssVisibility(prop, invisibleValue, interactor) {
198
170
  try {
199
- const value = await interactor.getStyleValue(locator, prop);
200
- return value !== invisibleValue;
171
+ return await interactor.getStyleValue(locator, prop) !== invisibleValue;
201
172
  } catch (e) {
202
173
  if (await interactor.exists(locator) === false) return false;
203
174
  throw e;
@@ -211,15 +182,13 @@ var PlaywrightInteractor = class PlaywrightInteractor {
211
182
  async hasCssClass(locator, className) {
212
183
  const classNames = await this.getAttribute(locator, "class");
213
184
  if (classNames == null) return false;
214
- const names = classNames.split(/\s+/);
215
- return names.includes(className);
185
+ return classNames.split(/\s+/).includes(className);
216
186
  }
217
187
  async hasAttribute(locator, name) {
218
- const attrValue = await this.getAttribute(locator, name);
219
- return attrValue != null;
188
+ return await this.getAttribute(locator, name) != null;
220
189
  }
221
190
  async innerHTML(locator) {
222
- const cssLocator = await __atomic_testing_core.locatorUtil.toCssSelector(locator, this);
191
+ const cssLocator = await _atomic_testing_core.locatorUtil.toCssSelector(locator, this);
223
192
  return this.page.locator(cssLocator).innerHTML();
224
193
  }
225
194
  clone() {
@@ -238,15 +207,13 @@ var PlaywrightInteractor = class PlaywrightInteractor {
238
207
  * @returns A configured {@link TestEngine} ready for use.
239
208
  */
240
209
  function createTestEngine(page, partDefinitions) {
241
- const engine = new __atomic_testing_core.TestEngine([], new PlaywrightInteractor(page), { parts: partDefinitions });
242
- return engine;
210
+ return new _atomic_testing_core.TestEngine([], new PlaywrightInteractor(page), { parts: partDefinitions });
243
211
  }
244
212
 
245
213
  //#endregion
246
214
  //#region src/testRunnerAdapter.ts
247
215
  async function goto(url, fixture) {
248
- const page = fixture.page;
249
- await page.goto(url);
216
+ await fixture.page.goto(url);
250
217
  }
251
218
  /**
252
219
  * Create a {@link TestEngine} bound to the Playwright page in the given fixture.
@@ -259,14 +226,14 @@ function playwrightGetTestEngine(scenePart, fixture) {
259
226
  return createTestEngine(page, scenePart);
260
227
  }
261
228
  const playWrightTestFrameworkMapper = {
262
- assertEqual: (a, b) => (0, __playwright_test.expect)(a).toEqual(b),
263
- describe: __playwright_test.test.describe,
264
- beforeEach: __playwright_test.test.beforeEach,
265
- afterEach: __playwright_test.test.afterEach,
266
- beforeAll: __playwright_test.test.beforeAll,
267
- afterAll: __playwright_test.test.afterAll,
268
- test: __playwright_test.test,
269
- it: __playwright_test.test
229
+ assertEqual: (a, b) => (0, _playwright_test.expect)(a).toEqual(b),
230
+ describe: _playwright_test.test.describe,
231
+ beforeEach: _playwright_test.test.beforeEach,
232
+ afterEach: _playwright_test.test.afterEach,
233
+ beforeAll: _playwright_test.test.beforeAll,
234
+ afterAll: _playwright_test.test.afterAll,
235
+ test: _playwright_test.test,
236
+ it: _playwright_test.test
270
237
  };
271
238
  /**
272
239
  * Get a typed interface for running end-to-end tests with Playwright.
@@ -285,4 +252,4 @@ exports.getTestRunnerInterface = getTestRunnerInterface;
285
252
  exports.goto = goto;
286
253
  exports.playWrightTestFrameworkMapper = playWrightTestFrameworkMapper;
287
254
  exports.playwrightGetTestEngine = playwrightGetTestEngine;
288
- //# sourceMappingURL=index.js.map
255
+ //# 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 BlurOption,\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 async blur(locator: PartLocator, _option?: Partial<BlurOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).blur();\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,4 +1,4 @@
1
- import { ClickOption, CssProperty, EnterTextOption, FocusOption, HoverOption, Interactor, MouseDownOption, MouseEnterOption, MouseLeaveOption, MouseMoveOption, MouseOutOption, MouseUpOption, Optional, PartLocator, ScenePart, TestEngine, WaitForOption, WaitUntilOption } from "@atomic-testing/core";
1
+ import { BlurOption, ClickOption, CssProperty, EnterTextOption, FocusOption, HoverOption, Interactor, MouseDownOption, MouseEnterOption, MouseLeaveOption, MouseMoveOption, MouseOutOption, MouseUpOption, Optional, PartLocator, ScenePart, TestEngine, WaitForOption, WaitUntilOption } from "@atomic-testing/core";
2
2
  import { Page } from "@playwright/test";
3
3
  import { E2eTestInterface, E2eTestRunEnvironmentFixture, TestFrameworkMapper } from "@atomic-testing/internal-test-runner";
4
4
 
@@ -57,7 +57,8 @@ declare class PlaywrightInteractor implements Interactor {
57
57
  mouseOut(locator: PartLocator, _option?: Partial<MouseOutOption>): Promise<void>;
58
58
  mouseEnter(locator: PartLocator, _option?: Partial<MouseEnterOption>): Promise<void>;
59
59
  mouseLeave(locator: PartLocator, _option?: Partial<MouseLeaveOption>): Promise<void>;
60
- focus(locator: PartLocator, _option: Partial<FocusOption>): Promise<void>;
60
+ focus(locator: PartLocator, _option?: Partial<FocusOption>): Promise<void>;
61
+ blur(locator: PartLocator, _option?: Partial<BlurOption>): Promise<void>;
61
62
  wait(ms: number): Promise<void>;
62
63
  waitUntilComponentState(locator: PartLocator, option?: Partial<Readonly<WaitForOption>>): Promise<void>;
63
64
  waitUntil<T>(option: WaitUntilOption<T>): Promise<T>;
@@ -99,4 +100,4 @@ declare const playWrightTestFrameworkMapper: TestFrameworkMapper;
99
100
  declare function getTestRunnerInterface<T extends ScenePart>(): E2eTestInterface<T>;
100
101
  //#endregion
101
102
  export { PlaywrightInteractor, createTestEngine, getTestRunnerInterface, goto, playWrightTestFrameworkMapper, playwrightGetTestEngine };
102
- //# sourceMappingURL=index.d.ts.map
103
+ //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { ClickOption, CssProperty, EnterTextOption, FocusOption, HoverOption, Interactor, MouseDownOption, MouseEnterOption, MouseLeaveOption, MouseMoveOption, MouseOutOption, MouseUpOption, Optional, PartLocator, ScenePart, TestEngine, WaitForOption, WaitUntilOption } from "@atomic-testing/core";
1
+ import { BlurOption, ClickOption, CssProperty, EnterTextOption, FocusOption, HoverOption, Interactor, MouseDownOption, MouseEnterOption, MouseLeaveOption, MouseMoveOption, MouseOutOption, MouseUpOption, Optional, PartLocator, ScenePart, TestEngine, WaitForOption, WaitUntilOption } from "@atomic-testing/core";
2
2
  import { Page } from "@playwright/test";
3
3
  import { E2eTestInterface, E2eTestRunEnvironmentFixture, TestFrameworkMapper } from "@atomic-testing/internal-test-runner";
4
4
 
@@ -57,7 +57,8 @@ declare class PlaywrightInteractor implements Interactor {
57
57
  mouseOut(locator: PartLocator, _option?: Partial<MouseOutOption>): Promise<void>;
58
58
  mouseEnter(locator: PartLocator, _option?: Partial<MouseEnterOption>): Promise<void>;
59
59
  mouseLeave(locator: PartLocator, _option?: Partial<MouseLeaveOption>): Promise<void>;
60
- focus(locator: PartLocator, _option: Partial<FocusOption>): Promise<void>;
60
+ focus(locator: PartLocator, _option?: Partial<FocusOption>): Promise<void>;
61
+ blur(locator: PartLocator, _option?: Partial<BlurOption>): Promise<void>;
61
62
  wait(ms: number): Promise<void>;
62
63
  waitUntilComponentState(locator: PartLocator, option?: Partial<Readonly<WaitForOption>>): Promise<void>;
63
64
  waitUntil<T>(option: WaitUntilOption<T>): Promise<T>;
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
- const elLocator = this.page.locator(cssLocator);
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);
@@ -120,6 +118,10 @@ var PlaywrightInteractor = class PlaywrightInteractor {
120
118
  const cssLocator = await locatorUtil.toCssSelector(locator, this);
121
119
  return this.page.focus(cssLocator);
122
120
  }
121
+ async blur(locator, _option) {
122
+ const cssLocator = await locatorUtil.toCssSelector(locator, this);
123
+ await this.page.locator(cssLocator).blur();
124
+ }
123
125
  wait(ms) {
124
126
  return timingUtil.wait(ms);
125
127
  }
@@ -136,45 +138,37 @@ var PlaywrightInteractor = class PlaywrightInteractor {
136
138
  const locators = await elLocator.all();
137
139
  const values = [];
138
140
  for (const locator$1 of locators) {
139
- const value$1 = await locator$1.getAttribute(name);
140
- if (value$1 != null) values.push(value$1);
141
+ const value = await locator$1.getAttribute(name);
142
+ if (value != null) values.push(value);
141
143
  }
142
144
  return values;
143
145
  }
144
- const value = await elLocator.getAttribute(name);
145
- return value ?? void 0;
146
+ return await elLocator.getAttribute(name) ?? void 0;
146
147
  }
147
148
  async getText(locator) {
148
149
  const cssLocator = await locatorUtil.toCssSelector(locator, this);
149
- const text = await this.page.locator(cssLocator).textContent();
150
- return text ?? void 0;
150
+ return await this.page.locator(cssLocator).textContent() ?? void 0;
151
151
  }
152
152
  async exists(locator) {
153
153
  const cssLocator = await locatorUtil.toCssSelector(locator, this);
154
- const count = await this.page.locator(cssLocator).count();
155
- return count > 0;
154
+ return await this.page.locator(cssLocator).count() > 0;
156
155
  }
157
156
  async isChecked(locator) {
158
157
  const cssLocator = await locatorUtil.toCssSelector(locator, this);
159
- const checked = await this.page.locator(cssLocator).isChecked();
160
- return checked;
158
+ return await this.page.locator(cssLocator).isChecked();
161
159
  }
162
160
  async isDisabled(locator) {
163
161
  const cssLocator = await locatorUtil.toCssSelector(locator, this);
164
- const isDisabled = await this.page.locator(cssLocator).isDisabled();
165
- return isDisabled;
162
+ return await this.page.locator(cssLocator).isDisabled();
166
163
  }
167
164
  async isReadonly(locator) {
168
- const readonly = await this.getAttribute(locator, "readonly");
169
- return readonly != null;
165
+ return await this.getAttribute(locator, "readonly") != null;
170
166
  }
171
167
  async isVisible(locator) {
172
- const exists = await this.exists(locator);
173
- if (!exists) return false;
168
+ if (!await this.exists(locator)) return false;
174
169
  async function checkCssVisibility(prop, invisibleValue, interactor) {
175
170
  try {
176
- const value = await interactor.getStyleValue(locator, prop);
177
- return value !== invisibleValue;
171
+ return await interactor.getStyleValue(locator, prop) !== invisibleValue;
178
172
  } catch (e) {
179
173
  if (await interactor.exists(locator) === false) return false;
180
174
  throw e;
@@ -188,12 +182,10 @@ var PlaywrightInteractor = class PlaywrightInteractor {
188
182
  async hasCssClass(locator, className) {
189
183
  const classNames = await this.getAttribute(locator, "class");
190
184
  if (classNames == null) return false;
191
- const names = classNames.split(/\s+/);
192
- return names.includes(className);
185
+ return classNames.split(/\s+/).includes(className);
193
186
  }
194
187
  async hasAttribute(locator, name) {
195
- const attrValue = await this.getAttribute(locator, name);
196
- return attrValue != null;
188
+ return await this.getAttribute(locator, name) != null;
197
189
  }
198
190
  async innerHTML(locator) {
199
191
  const cssLocator = await locatorUtil.toCssSelector(locator, this);
@@ -215,15 +207,13 @@ var PlaywrightInteractor = class PlaywrightInteractor {
215
207
  * @returns A configured {@link TestEngine} ready for use.
216
208
  */
217
209
  function createTestEngine(page, partDefinitions) {
218
- const engine = new TestEngine([], new PlaywrightInteractor(page), { parts: partDefinitions });
219
- return engine;
210
+ return new TestEngine([], new PlaywrightInteractor(page), { parts: partDefinitions });
220
211
  }
221
212
 
222
213
  //#endregion
223
214
  //#region src/testRunnerAdapter.ts
224
215
  async function goto(url, fixture) {
225
- const page = fixture.page;
226
- await page.goto(url);
216
+ await fixture.page.goto(url);
227
217
  }
228
218
  /**
229
219
  * Create a {@link TestEngine} bound to the Playwright page in the given fixture.
@@ -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 BlurOption,\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 async blur(locator: PartLocator, _option?: Partial<BlurOption>): Promise<void> {\n const cssLocator = await locatorUtil.toCssSelector(locator, this);\n await this.page.locator(cssLocator).blur();\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.78.0",
3
+ "version": "0.80.0",
4
4
  "description": "Atomic Testing Playwright Adapter",
5
- "main": "dist/index.js",
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.78.0",
22
- "@atomic-testing/internal-test-runner": "0.78.0"
20
+ "@atomic-testing/core": "0.80.0",
21
+ "@atomic-testing/internal-test-runner": "0.80.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"
@@ -1,4 +1,5 @@
1
1
  import {
2
+ BlurOption,
2
3
  byCssSelector,
3
4
  ClickOption,
4
5
  CssProperty,
@@ -172,11 +173,16 @@ export class PlaywrightInteractor implements Interactor {
172
173
  return this.mouseOut(locator);
173
174
  }
174
175
 
175
- async focus(locator: PartLocator, _option: Partial<FocusOption>): Promise<void> {
176
+ async focus(locator: PartLocator, _option?: Partial<FocusOption>): Promise<void> {
176
177
  const cssLocator = await locatorUtil.toCssSelector(locator, this);
177
178
  return this.page.focus(cssLocator);
178
179
  }
179
180
 
181
+ async blur(locator: PartLocator, _option?: Partial<BlurOption>): Promise<void> {
182
+ const cssLocator = await locatorUtil.toCssSelector(locator, this);
183
+ await this.page.locator(cssLocator).blur();
184
+ }
185
+
180
186
  //#region wait conditions
181
187
  wait(ms: number): Promise<void> {
182
188
  return timingUtil.wait(ms);
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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"}