pomwright 1.5.1 → 2.0.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +5 -5
  3. package/dist/index.d.mts +75 -970
  4. package/dist/index.d.ts +75 -970
  5. package/dist/index.js +585 -1872
  6. package/dist/index.mjs +598 -1880
  7. package/package.json +9 -11
  8. package/AGENTS.md +0 -37
  9. package/docs/v1/BaseApi-explanation.md +0 -63
  10. package/docs/v1/BasePage-explanation.md +0 -96
  11. package/docs/v1/LocatorSchema-explanation.md +0 -271
  12. package/docs/v1/LocatorSchemaPath-explanation.md +0 -165
  13. package/docs/v1/PlaywrightReportLogger-explanation.md +0 -56
  14. package/docs/v1/get-locator-methods-explanation.md +0 -250
  15. package/docs/v1/intro-to-using-pomwright.md +0 -899
  16. package/docs/v1/sessionStorage-methods-explanation.md +0 -38
  17. package/docs/v1/tips-folder-structure.md +0 -38
  18. package/docs/v1-to-v2-migration/bridge-migration-guide.md +0 -159
  19. package/docs/v1-to-v2-migration/direct-migration-guide.md +0 -238
  20. package/docs/v1-to-v2-migration/v1-to-v2-comparison.md +0 -547
  21. package/docs/v2/PageObject.md +0 -293
  22. package/docs/v2/composing-locator-modules.md +0 -93
  23. package/docs/v2/locator-registry.md +0 -695
  24. package/docs/v2/logging.md +0 -168
  25. package/docs/v2/overview.md +0 -515
  26. package/docs/v2/session-storage.md +0 -160
  27. package/index.ts +0 -75
  28. package/intTestV2/.env +0 -0
  29. package/intTestV2/fixtures/testApp.fixtures.ts +0 -43
  30. package/intTestV2/package.json +0 -22
  31. package/intTestV2/page-object-models/testApp/pages/iframe/iframe.locatorSchema.ts +0 -24
  32. package/intTestV2/page-object-models/testApp/pages/iframe/iframe.page.ts +0 -17
  33. package/intTestV2/page-object-models/testApp/pages/testPage.locatorSchema.ts +0 -32
  34. package/intTestV2/page-object-models/testApp/pages/testPage.page.ts +0 -119
  35. package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.locatorSchema.ts +0 -29
  36. package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.page.ts +0 -48
  37. package/intTestV2/page-object-models/testApp/pages/testPath/testPath.locatorSchema.ts +0 -9
  38. package/intTestV2/page-object-models/testApp/pages/testPath/testPath.page.ts +0 -23
  39. package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.locatorSchema.ts +0 -114
  40. package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.page.ts +0 -23
  41. package/intTestV2/page-object-models/testApp/testApp.base.ts +0 -20
  42. package/intTestV2/playwright.config.ts +0 -54
  43. package/intTestV2/server.js +0 -216
  44. package/intTestV2/test-data/staticPage/index.html +0 -280
  45. package/intTestV2/test-data/staticPage/w3images/avatar2.png +0 -0
  46. package/intTestV2/test-data/staticPage/w3images/avatar3.png +0 -0
  47. package/intTestV2/test-data/staticPage/w3images/avatar5.png +0 -0
  48. package/intTestV2/test-data/staticPage/w3images/avatar6.png +0 -0
  49. package/intTestV2/test-data/staticPage/w3images/forest.jpg +0 -0
  50. package/intTestV2/test-data/staticPage/w3images/lights.jpg +0 -0
  51. package/intTestV2/test-data/staticPage/w3images/mountains.jpg +0 -0
  52. package/intTestV2/test-data/staticPage/w3images/nature.jpg +0 -0
  53. package/intTestV2/test-data/staticPage/w3images/snow.jpg +0 -0
  54. package/intTestV2/tests/locatorRegistry/add/add.describe.spec.ts +0 -54
  55. package/intTestV2/tests/locatorRegistry/add/add.filter.spec.ts +0 -143
  56. package/intTestV2/tests/locatorRegistry/add/add.frameLocator.spec.ts +0 -23
  57. package/intTestV2/tests/locatorRegistry/add/add.get.clone.spec.ts +0 -76
  58. package/intTestV2/tests/locatorRegistry/add/add.getByAltText.spec.ts +0 -23
  59. package/intTestV2/tests/locatorRegistry/add/add.getById.spec.ts +0 -45
  60. package/intTestV2/tests/locatorRegistry/add/add.getByLabel.spec.ts +0 -23
  61. package/intTestV2/tests/locatorRegistry/add/add.getByPlaceholder.spec.ts +0 -23
  62. package/intTestV2/tests/locatorRegistry/add/add.getByRole.spec.ts +0 -23
  63. package/intTestV2/tests/locatorRegistry/add/add.getByTestId.spec.ts +0 -23
  64. package/intTestV2/tests/locatorRegistry/add/add.getByText.spec.ts +0 -23
  65. package/intTestV2/tests/locatorRegistry/add/add.getByTitle.spec.ts +0 -23
  66. package/intTestV2/tests/locatorRegistry/add/add.locator.spec.ts +0 -23
  67. package/intTestV2/tests/locatorRegistry/add/add.reuseExisting.spec.ts +0 -107
  68. package/intTestV2/tests/locatorRegistry/add/add.reuseReusable.spec.ts +0 -311
  69. package/intTestV2/tests/locatorRegistry/add/add.spec.ts +0 -159
  70. package/intTestV2/tests/locatorRegistry/filter.cycle.spec.ts +0 -39
  71. package/intTestV2/tests/locatorRegistry/getLocator/getLocator.spec.ts +0 -253
  72. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.clearSteps.spec.ts +0 -105
  73. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.describe.spec.ts +0 -23
  74. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.filter.spec.ts +0 -368
  75. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getLocator.spec.ts +0 -56
  76. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getNestedLocator.spec.ts +0 -175
  77. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.nth.spec.ts +0 -60
  78. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.remove.spec.ts +0 -32
  79. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.replace.spec.ts +0 -24
  80. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.spec.ts +0 -110
  81. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.update.spec.ts +0 -322
  82. package/intTestV2/tests/locatorRegistry/getNestedLocator/getNestedLocator.spec.ts +0 -412
  83. package/intTestV2/tests/locatorRegistry/registry/registry.binding.spec.ts +0 -50
  84. package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.spec.ts +0 -115
  85. package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.typecheck.ts +0 -86
  86. package/intTestV2/tests/locatorRegistry/validation/validation.sub-path.spec.ts +0 -45
  87. package/intTestV2/tests/step/step.spec.ts +0 -49
  88. package/intTestV2/tests/testApp/color.spec.ts +0 -15
  89. package/intTestV2/tests/testApp/iframe.spec.ts +0 -57
  90. package/intTestV2/tests/testApp/testFilters.spec.ts +0 -24
  91. package/intTestV2/tests/testApp/testPage.spec.ts +0 -161
  92. package/intTestV2/tests/testApp/testPath.spec.ts +0 -18
  93. package/pack-build.sh +0 -11
  94. package/pack-test-v2.sh +0 -36
  95. package/playwright.base.ts +0 -42
  96. package/skills/README.md +0 -56
  97. package/skills/pomwright-v1-5-bridge-migration/SKILL.md +0 -40
  98. package/skills/pomwright-v1-5-bridge-migration/references/call-site-migration.md +0 -178
  99. package/skills/pomwright-v1-5-bridge-migration/references/schema-translation.md +0 -183
  100. package/skills/pomwright-v2-migration/SKILL.md +0 -63
  101. package/skills/pomwright-v2-migration/references/call-site-migration.md +0 -265
  102. package/skills/pomwright-v2-migration/references/class-migration.md +0 -266
  103. package/skills/pomwright-v2-migration/references/fixture-and-helpers.md +0 -423
  104. package/skills/pomwright-v2-migration/references/locator-registration.md +0 -344
  105. package/srcV2/fixture/base.fixtures.ts +0 -23
  106. package/srcV2/helpers/navigation.ts +0 -153
  107. package/srcV2/helpers/playwrightReportLogger.ts +0 -196
  108. package/srcV2/helpers/sessionStorage.ts +0 -251
  109. package/srcV2/helpers/stepDecorator.ts +0 -106
  110. package/srcV2/locators/index.ts +0 -15
  111. package/srcV2/locators/locatorQueryBuilder.ts +0 -427
  112. package/srcV2/locators/locatorRegistrationBuilder.ts +0 -558
  113. package/srcV2/locators/locatorRegistry.ts +0 -583
  114. package/srcV2/locators/locatorUpdateBuilder.ts +0 -602
  115. package/srcV2/locators/reusableLocatorBuilder.ts +0 -200
  116. package/srcV2/locators/types.ts +0 -256
  117. package/srcV2/locators/utils.ts +0 -309
  118. package/srcV2/locators/v1SchemaTranslator.ts +0 -178
  119. package/srcV2/pageObject.ts +0 -105
package/dist/index.js CHANGED
@@ -20,1436 +20,626 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- BaseApi: () => BaseApi,
24
- BasePage: () => BasePage,
25
- BasePageV1toV2: () => BasePageV1toV2,
26
- GetByMethod: () => GetByMethod,
27
- GetLocatorBase: () => GetLocatorBase,
28
23
  PageObject: () => PageObject,
29
24
  PlaywrightReportLogger: () => PlaywrightReportLogger,
30
- SessionStorage: () => SessionStorage2,
25
+ SessionStorage: () => SessionStorage,
31
26
  createRegistryWithAccessors: () => createRegistryWithAccessors,
32
27
  step: () => step,
33
- test: () => test5
28
+ test: () => test
34
29
  });
35
30
  module.exports = __toCommonJS(index_exports);
36
31
 
37
- // src/helpers/locatorSchema.interface.ts
38
- var GetByMethod = /* @__PURE__ */ ((GetByMethod2) => {
39
- GetByMethod2["role"] = "role";
40
- GetByMethod2["text"] = "text";
41
- GetByMethod2["label"] = "label";
42
- GetByMethod2["placeholder"] = "placeholder";
43
- GetByMethod2["altText"] = "altText";
44
- GetByMethod2["title"] = "title";
45
- GetByMethod2["locator"] = "locator";
46
- GetByMethod2["frameLocator"] = "frameLocator";
47
- GetByMethod2["testId"] = "testId";
48
- GetByMethod2["dataCy"] = "dataCy";
49
- GetByMethod2["id"] = "id";
50
- return GetByMethod2;
51
- })(GetByMethod || {});
52
- var locatorSchemaDummy = {
53
- role: void 0,
54
- roleOptions: {
55
- checked: void 0,
56
- disabled: void 0,
57
- exact: void 0,
58
- expanded: void 0,
59
- includeHidden: void 0,
60
- level: void 0,
61
- name: void 0,
62
- pressed: void 0,
63
- selected: void 0
64
- },
65
- text: void 0,
66
- textOptions: {
67
- exact: void 0
68
- },
69
- label: void 0,
70
- labelOptions: {
71
- exact: void 0
72
- },
73
- placeholder: void 0,
74
- placeholderOptions: {
75
- exact: void 0
76
- },
77
- altText: void 0,
78
- altTextOptions: {
79
- exact: void 0
80
- },
81
- title: void 0,
82
- titleOptions: {
83
- exact: void 0
84
- },
85
- locator: void 0,
86
- locatorOptions: {
87
- has: void 0,
88
- hasNot: void 0,
89
- hasNotText: void 0,
90
- hasText: void 0
91
- },
92
- frameLocator: void 0,
93
- testId: void 0,
94
- dataCy: void 0,
95
- id: void 0,
96
- filter: {
97
- has: void 0,
98
- hasNot: void 0,
99
- hasNotText: void 0,
100
- hasText: void 0
101
- },
102
- locatorMethod: void 0,
103
- locatorSchemaPath: void 0
104
- };
105
- function getLocatorSchemaDummy() {
106
- return locatorSchemaDummy;
107
- }
32
+ // src/fixture/base.fixtures.ts
33
+ var import_test = require("@playwright/test");
108
34
 
109
- // src/helpers/deprecationWarnings.ts
110
- var warnedDeprecationsByScope = /* @__PURE__ */ new WeakMap();
111
- var getWarningScope = (logger) => {
112
- if (!logger) {
113
- return globalThis;
114
- }
115
- const maybeSharedLogEntries = logger.sharedLogEntry;
116
- if (Array.isArray(maybeSharedLogEntries)) {
117
- return maybeSharedLogEntries;
35
+ // src/helpers/playwrightReportLogger.ts
36
+ var PlaywrightReportLogger = class _PlaywrightReportLogger {
37
+ // Initializes the logger with shared log level, log entries, and a context name.
38
+ constructor(sharedLogLevel, sharedLogEntry, contextName) {
39
+ this.sharedLogLevel = sharedLogLevel;
40
+ this.sharedLogEntry = sharedLogEntry;
41
+ this.contextName = contextName;
118
42
  }
119
- return logger;
120
- };
121
- var warnDeprecationOncePerTest = (key, message, logger) => {
122
- const warningScope = getWarningScope(logger);
123
- const warnedDeprecations = warnedDeprecationsByScope.get(warningScope) ?? /* @__PURE__ */ new Set();
124
- if (warnedDeprecations.has(key)) {
125
- return;
126
- }
127
- warnedDeprecations.add(key);
128
- warnedDeprecationsByScope.set(warningScope, warnedDeprecations);
129
- logger?.warn(message);
130
- };
131
-
132
- // src/api/baseApi.ts
133
- var BaseApi = class {
134
- baseUrl;
135
- apiName;
136
- log;
137
- request;
138
- constructor(baseUrl, apiName, context, pwrl) {
139
- this.baseUrl = baseUrl;
140
- this.apiName = apiName;
141
- this.log = pwrl.getNewChildLogger(apiName);
142
- this.request = context;
143
- const classDeprecationMessage = "[POMWright] BaseApi is depricated and will be removed in 2.0.0 with no replacement. If you need a base API class, you can use the v1 pomwright/src/api/baseApi.ts implementation for reference to implement your own.";
144
- warnDeprecationOncePerTest(`${this.constructor.name}-class-deprecation`, classDeprecationMessage, this.log);
43
+ contextName;
44
+ logLevels = ["debug", "info", "warn", "error"];
45
+ /**
46
+ * Creates a child logger with a new contextual name, sharing the same log level and log entries with the parent logger.
47
+ *
48
+ * The root loggers log "level" is referenced by all child loggers and their child loggers and so on...
49
+ * Changing the log "level" of one, will change it for all.
50
+ */
51
+ getNewChildLogger(prefix) {
52
+ return new _PlaywrightReportLogger(this.sharedLogLevel, this.sharedLogEntry, `${this.contextName} -> ${prefix}`);
145
53
  }
146
- };
147
-
148
- // src/basePage.ts
149
- var import_test3 = require("@playwright/test");
150
-
151
- // src/helpers/getLocatorBase.ts
152
- var import_test = require("@playwright/test");
54
+ /**
55
+ * Logs a message with the specified log level, prefix, and additional arguments if the current log level permits.
56
+ */
57
+ // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
58
+ log(level, message, ...args) {
59
+ const logLevelIndex = this.logLevels.indexOf(level);
60
+ if (logLevelIndex < this.getCurrentLogLevelIndex()) {
61
+ return;
62
+ }
63
+ this.sharedLogEntry.push({
64
+ timestamp: /* @__PURE__ */ new Date(),
65
+ logLevel: level,
66
+ prefix: this.contextName,
67
+ message: `${message}
153
68
 
154
- // srcV2/locators/utils.ts
155
- var formatLocatorSchemaPathForError = (path) => {
156
- const json = JSON.stringify(path);
157
- return json.slice(1, -1);
158
- };
159
- var RUNTIME_WHITESPACE_REGEX = /[\s\u0085]/u;
160
- var validateLocatorSchemaPath = (path) => {
161
- if (!path) {
162
- throw new Error("LocatorSchemaPath string cannot be empty");
69
+ ${args.join("\n\n")}`
70
+ });
163
71
  }
164
- if (RUNTIME_WHITESPACE_REGEX.test(path)) {
165
- const escaped = formatLocatorSchemaPathForError(path);
166
- throw new Error(`LocatorSchemaPath string cannot contain whitespace chars: ${escaped}`);
72
+ /**
73
+ * Logs a debug-level message with the specified message and arguments.
74
+ */
75
+ // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
76
+ debug(message, ...args) {
77
+ this.log("debug", message, ...args);
167
78
  }
168
- if (path.startsWith(".")) {
169
- throw new Error(`LocatorSchemaPath string cannot start with a dot: ${path}`);
79
+ /**
80
+ * Logs a info-level message with the specified message and arguments.
81
+ */
82
+ // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
83
+ info(message, ...args) {
84
+ this.log("info", message, ...args);
170
85
  }
171
- if (path.endsWith(".")) {
172
- throw new Error(`LocatorSchemaPath string cannot end with a dot: ${path}`);
86
+ /**
87
+ * Logs a warn-level message with the specified message and arguments.
88
+ */
89
+ // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
90
+ warn(message, ...args) {
91
+ this.log("warn", message, ...args);
173
92
  }
174
- if (path.includes("..")) {
175
- throw new Error(`LocatorSchemaPath string cannot contain consecutive dots: ${path}`);
93
+ /**
94
+ * Logs a error-level message with the specified message and arguments.
95
+ */
96
+ // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
97
+ error(message, ...args) {
98
+ this.log("error", message, ...args);
176
99
  }
177
- };
178
- var expandSchemaPath = (path) => {
179
- validateLocatorSchemaPath(path);
180
- const parts = path.split(".");
181
- return parts.map((_part, index) => parts.slice(0, index + 1).join("."));
182
- };
183
- var cssEscape = (value) => {
184
- return value.replace(/([\\"'#.:;,?*+<>{}[\\]()])/g, "\\$1");
185
- };
186
- var normalizeSteps = (steps) => steps ? steps.map((step2) => ({ ...step2 })) : [];
187
- function normalizeIdValue(id) {
188
- if (typeof id !== "string") {
189
- return id;
100
+ /**
101
+ * Sets the current log level to the specified level during runTime.
102
+ */
103
+ setLogLevel(level) {
104
+ this.sharedLogLevel.current = level;
190
105
  }
191
- if (id.startsWith("#")) {
192
- return id.slice(1);
106
+ /**
107
+ * Retrieves the current log level during runtime.
108
+ */
109
+ getCurrentLogLevel() {
110
+ return this.sharedLogLevel.current;
193
111
  }
194
- if (id.startsWith("id=")) {
195
- return id.slice("id=".length);
112
+ /**
113
+ * Retrieves the index of the current log level in the logLevels array during runtime.
114
+ */
115
+ getCurrentLogLevelIndex() {
116
+ return this.logLevels.indexOf(this.sharedLogLevel.current);
196
117
  }
197
- return id;
198
- }
199
- var stringifyForLog = (value) => {
200
- const seen = /* @__PURE__ */ new WeakSet();
201
- return JSON.stringify(
202
- value,
203
- (_key, current) => {
204
- if (typeof current === "object" && current !== null) {
205
- if (seen.has(current)) {
206
- return "[Circular]";
207
- }
208
- seen.add(current);
209
- }
210
- if (current instanceof RegExp) {
211
- return { type: "RegExp", source: current.source, flags: current.flags };
212
- }
213
- return current;
214
- },
215
- 2
216
- );
217
- };
218
- var applyIndexSelector = (locator, selector) => {
219
- if (selector === void 0 || selector === null) {
220
- return locator;
118
+ /**
119
+ * Resets the current log level to the initial level during runtime.
120
+ */
121
+ resetLogLevel() {
122
+ this.sharedLogLevel.current = this.sharedLogLevel.initial;
221
123
  }
222
- if (selector === "first") {
223
- return locator.first();
124
+ /**
125
+ * Checks if the input log level is equal to the current log level of the PlaywrightReportLogger instance.
126
+ */
127
+ isCurrentLogLevel(level) {
128
+ return this.sharedLogLevel.current === level;
224
129
  }
225
- if (selector === "last") {
226
- return locator.last();
130
+ /**
131
+ * Returns 'true' if the "level" parameter provided has an equal or greater index than the current logLevel.
132
+ */
133
+ isLogLevelEnabled(level) {
134
+ const logLevelIndex = this.logLevels.indexOf(level);
135
+ if (logLevelIndex < this.getCurrentLogLevelIndex()) {
136
+ return false;
137
+ }
138
+ return true;
227
139
  }
228
- return locator.nth(selector);
229
- };
230
- var createLocator = (target, definition) => {
231
- switch (definition.type) {
232
- case "role":
233
- return target.getByRole(definition.role, definition.options);
234
- case "text":
235
- return target.getByText(definition.text, definition.options);
236
- case "label":
237
- return target.getByLabel(definition.text, definition.options);
238
- case "placeholder":
239
- return target.getByPlaceholder(definition.text, definition.options);
240
- case "altText":
241
- return target.getByAltText(definition.text, definition.options);
242
- case "title":
243
- return target.getByTitle(definition.text, definition.options);
244
- case "locator":
245
- return target.locator(definition.selector, definition.options);
246
- case "frameLocator":
247
- return target.frameLocator(definition.selector);
248
- case "testId":
249
- return target.getByTestId(definition.testId);
250
- case "id": {
251
- if (typeof definition.id === "string") {
252
- const normalized = normalizeIdValue(definition.id);
253
- return target.locator(`#${cssEscape(normalized ?? "")}`);
140
+ /**
141
+ * Attaches the recorded log entries to the Playwright HTML report in a sorted and formatted manner.
142
+ */
143
+ attachLogsToTest(testInfo) {
144
+ this.sharedLogEntry.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
145
+ for (const log of this.sharedLogEntry) {
146
+ const printTime = log.timestamp.toLocaleTimeString("nb-NO", {
147
+ hour: "2-digit",
148
+ minute: "2-digit",
149
+ second: "2-digit"
150
+ });
151
+ const printDate = log.timestamp.toLocaleDateString("nb-NO", {
152
+ day: "2-digit",
153
+ month: "2-digit",
154
+ year: "numeric"
155
+ });
156
+ const printLogLevel = `${log.logLevel.toUpperCase()}`;
157
+ const printPrefix = log.prefix ? `: [${log.prefix}]` : "";
158
+ let messageBody = "";
159
+ let messageContentType = "";
160
+ try {
161
+ const parsedMessage = JSON.parse(log.message);
162
+ messageContentType = "application/json";
163
+ messageBody = JSON.stringify(parsedMessage, null, 2);
164
+ } catch (_error) {
165
+ messageContentType = "text/plain";
166
+ messageBody = log.message;
254
167
  }
255
- const pattern = definition.id.source;
256
- const safePattern = cssEscape(pattern);
257
- return target.locator(`[id*="${safePattern}"]`);
258
- }
259
- default: {
260
- const exhaustive = definition;
261
- return exhaustive;
168
+ testInfo.attach(`${printTime} ${printDate} - ${printLogLevel} ${printPrefix}`, {
169
+ contentType: messageContentType,
170
+ body: Buffer.from(messageBody)
171
+ });
262
172
  }
263
173
  }
264
174
  };
265
- var cloneLocatorStrategyDefinition = (definition) => {
266
- switch (definition.type) {
267
- case "role":
268
- return {
269
- type: "role",
270
- role: definition.role,
271
- ...definition.options ? { options: { ...definition.options } } : {}
272
- };
273
- case "text":
274
- return {
275
- type: "text",
276
- text: definition.text,
277
- ...definition.options ? { options: { ...definition.options } } : {}
278
- };
279
- case "label":
280
- return {
281
- type: "label",
282
- text: definition.text,
283
- ...definition.options ? { options: { ...definition.options } } : {}
284
- };
285
- case "placeholder":
286
- return {
287
- type: "placeholder",
288
- text: definition.text,
289
- ...definition.options ? { options: { ...definition.options } } : {}
290
- };
291
- case "altText":
292
- return {
293
- type: "altText",
294
- text: definition.text,
295
- ...definition.options ? { options: { ...definition.options } } : {}
296
- };
297
- case "title":
298
- return {
299
- type: "title",
300
- text: definition.text,
301
- ...definition.options ? { options: { ...definition.options } } : {}
302
- };
303
- case "locator":
304
- return {
305
- type: "locator",
306
- selector: definition.selector,
307
- ...definition.options ? { options: { ...definition.options } } : {}
308
- };
309
- case "frameLocator":
310
- return { type: "frameLocator", selector: definition.selector };
311
- case "testId":
312
- return { type: "testId", testId: definition.testId };
313
- case "id":
314
- return { type: "id", id: definition.id };
315
- default: {
316
- const exhaustive = definition;
317
- return exhaustive;
318
- }
319
- }
320
- };
321
- var applyDefinitionPatch = (seed, patch) => {
322
- const base2 = cloneLocatorStrategyDefinition(seed);
323
- switch (patch.type) {
324
- case "locator": {
325
- const selector = patch.selector !== void 0 ? patch.selector : base2.selector;
326
- const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
327
- return { type: "locator", selector, ...options ? { options } : {} };
328
- }
329
- case "role": {
330
- const role = patch.role ?? base2.role;
331
- const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
332
- return { type: "role", role, ...options ? { options } : {} };
333
- }
334
- case "text": {
335
- const text = patch.text ?? base2.text;
336
- const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
337
- return { type: "text", text, ...options ? { options } : {} };
338
- }
339
- case "label": {
340
- const text = patch.text ?? base2.text;
341
- const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
342
- return { type: "label", text, ...options ? { options } : {} };
343
- }
344
- case "placeholder": {
345
- const text = patch.text ?? base2.text;
346
- const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
347
- return { type: "placeholder", text, ...options ? { options } : {} };
348
- }
349
- case "altText": {
350
- const text = patch.text ?? base2.text;
351
- const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
352
- return { type: "altText", text, ...options ? { options } : {} };
353
- }
354
- case "title": {
355
- const text = patch.text ?? base2.text;
356
- const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
357
- return { type: "title", text, ...options ? { options } : {} };
358
- }
359
- case "frameLocator": {
360
- const selector = patch.selector !== void 0 ? patch.selector : base2.selector;
361
- return { type: "frameLocator", selector };
362
- }
363
- case "testId": {
364
- const testId = patch.testId !== void 0 ? patch.testId : base2.testId;
365
- return { type: "testId", testId };
366
- }
367
- case "id": {
368
- const id = patch.id !== void 0 ? normalizeIdValue(patch.id) ?? base2.id : base2.id;
369
- return { type: "id", id };
370
- }
371
- default: {
372
- const exhaustive = patch;
373
- return exhaustive;
374
- }
175
+
176
+ // src/fixture/base.fixtures.ts
177
+ var test = import_test.test.extend({
178
+ // biome-ignore lint/correctness/noEmptyPattern: Playwright does not support the use of _
179
+ log: async ({}, use, testInfo) => {
180
+ const contextName = "TestCase";
181
+ const sharedLogEntry = [];
182
+ const sharedLogLevel = testInfo.retry === 0 ? { current: "warn", initial: "warn" } : { current: "debug", initial: "debug" };
183
+ const log = new PlaywrightReportLogger(sharedLogLevel, sharedLogEntry, contextName);
184
+ await use(log);
185
+ log.attachLogsToTest(testInfo);
375
186
  }
376
- };
377
- var isFrameLocatorDefinition = (definition) => definition.type === "frameLocator";
378
- var isLocatorInstance = (value) => {
379
- return !!value && typeof value === "object" && typeof value.filter === "function";
380
- };
187
+ });
381
188
 
382
- // srcV2/locators/v1SchemaTranslator.ts
383
- var getRegistryLookup = (registry) => registry;
384
- var logMissingDefinition = (path, field) => {
385
- console.warn(
386
- `[POMWright] Skipping v2 translation for "${path}" because "${field}" is missing. Rewrite this locator in defineLocators() using the v2 registry.`
387
- );
388
- };
389
- var logLocatorInstanceWarning = (path) => {
390
- console.warn(
391
- `[POMWright] Skipping v2 translation for "${path}" because v1 LocatorSchema.locator is a Locator instance. Rewrite this path in defineLocators() to avoid runtime gaps during migration.`
392
- );
393
- };
394
- var addV1SchemaToV2Registry = (registry, locatorSchema) => {
395
- const path = locatorSchema.locatorSchemaPath;
396
- validateLocatorSchemaPath(path);
397
- const registryWithLookup = getRegistryLookup(registry);
398
- const existing = registryWithLookup.getIfExists?.(path);
399
- if (existing) {
400
- return;
189
+ // src/helpers/sessionStorage.ts
190
+ var import_test2 = require("@playwright/test");
191
+ var SessionStorage = class {
192
+ // Initializes the class with a Playwright Page object and an optional label for step titles.
193
+ constructor(page, options = {}) {
194
+ this.page = page;
195
+ this.options = options;
401
196
  }
402
- console.info(
403
- `[POMWright] LocatorSchemaPath "${path}" is not registered in the v2 registry. Translating and adding v1 schema to v2 Locator Registry; update this path to use registry.add in defineLocators().`
404
- );
405
- const registration = registry.add(path);
406
- if (!registration) {
407
- return;
408
- }
409
- let postDefinition = null;
410
- switch (locatorSchema.locatorMethod) {
411
- case "role" /* role */: {
412
- if (!locatorSchema.role) {
413
- logMissingDefinition(path, "role");
414
- return;
415
- }
416
- postDefinition = registration.getByRole(locatorSchema.role, locatorSchema.roleOptions);
417
- break;
418
- }
419
- case "text" /* text */: {
420
- if (!locatorSchema.text) {
421
- logMissingDefinition(path, "text");
422
- return;
423
- }
424
- postDefinition = registration.getByText(locatorSchema.text, locatorSchema.textOptions);
425
- break;
426
- }
427
- case "label" /* label */: {
428
- if (!locatorSchema.label) {
429
- logMissingDefinition(path, "label");
430
- return;
431
- }
432
- postDefinition = registration.getByLabel(locatorSchema.label, locatorSchema.labelOptions);
433
- break;
434
- }
435
- case "placeholder" /* placeholder */: {
436
- if (!locatorSchema.placeholder) {
437
- logMissingDefinition(path, "placeholder");
438
- return;
439
- }
440
- postDefinition = registration.getByPlaceholder(locatorSchema.placeholder, locatorSchema.placeholderOptions);
441
- break;
442
- }
443
- case "altText" /* altText */: {
444
- if (!locatorSchema.altText) {
445
- logMissingDefinition(path, "altText");
446
- return;
447
- }
448
- postDefinition = registration.getByAltText(locatorSchema.altText, locatorSchema.altTextOptions);
449
- break;
450
- }
451
- case "title" /* title */: {
452
- if (!locatorSchema.title) {
453
- logMissingDefinition(path, "title");
454
- return;
455
- }
456
- postDefinition = registration.getByTitle(locatorSchema.title, locatorSchema.titleOptions);
457
- break;
458
- }
459
- case "locator" /* locator */: {
460
- if (!locatorSchema.locator) {
461
- logMissingDefinition(path, "locator");
462
- return;
463
- }
464
- if (isLocatorInstance(locatorSchema.locator)) {
465
- logLocatorInstanceWarning(path);
466
- return;
467
- }
468
- postDefinition = registration.locator(locatorSchema.locator, locatorSchema.locatorOptions);
469
- break;
470
- }
471
- case "frameLocator" /* frameLocator */: {
472
- if (!locatorSchema.frameLocator) {
473
- logMissingDefinition(path, "frameLocator");
474
- return;
475
- }
476
- postDefinition = registration.frameLocator(locatorSchema.frameLocator);
477
- break;
478
- }
479
- case "testId" /* testId */: {
480
- if (!locatorSchema.testId) {
481
- logMissingDefinition(path, "testId");
482
- return;
483
- }
484
- postDefinition = registration.getByTestId(locatorSchema.testId);
485
- break;
486
- }
487
- case "dataCy" /* dataCy */: {
488
- if (!locatorSchema.dataCy) {
489
- logMissingDefinition(path, "dataCy");
197
+ // Defines an object to hold states to be set in session storage, allowing any value type.
198
+ queuedStates = {};
199
+ // Indicates if the session storage manipulation has been initiated.
200
+ isInitiated = false;
201
+ getStepLabel(methodName) {
202
+ const prefix = this.options.label ? `${this.options.label}.` : "";
203
+ return `${prefix}SessionStorage.${methodName}:`;
204
+ }
205
+ async hasContext() {
206
+ return await this.page.evaluate(() => {
207
+ return typeof window !== "undefined" && window.sessionStorage !== void 0;
208
+ });
209
+ }
210
+ async waitForContextAvailability() {
211
+ try {
212
+ const contextExists = await this.hasContext();
213
+ if (contextExists) {
490
214
  return;
491
215
  }
492
- postDefinition = registration.locator(`[data-cy="${locatorSchema.dataCy}"]`);
493
- break;
216
+ } catch (_e) {
494
217
  }
495
- case "id" /* id */: {
496
- if (!locatorSchema.id) {
497
- logMissingDefinition(path, "id");
218
+ await new Promise((resolve) => {
219
+ const handler = async (frame) => {
220
+ if (frame !== this.page.mainFrame()) {
221
+ return;
222
+ }
223
+ try {
224
+ const contextExists = await this.hasContext();
225
+ if (!contextExists) {
226
+ return;
227
+ }
228
+ } catch (_e) {
229
+ return;
230
+ }
231
+ this.page.off("framenavigated", handler);
232
+ resolve();
233
+ };
234
+ this.page.on("framenavigated", handler);
235
+ });
236
+ }
237
+ async ensureContext({ waitForContext = false } = {}) {
238
+ try {
239
+ const contextExists = await this.hasContext();
240
+ if (contextExists) {
498
241
  return;
499
242
  }
500
- postDefinition = registration.getById(locatorSchema.id);
501
- break;
243
+ } catch (_e) {
502
244
  }
503
- default: {
504
- const exhaustive = locatorSchema.locatorMethod;
505
- return exhaustive;
245
+ if (!waitForContext) {
246
+ throw new Error("SessionStorage context is not available.");
506
247
  }
248
+ await this.waitForContextAvailability();
507
249
  }
508
- if (!postDefinition) {
509
- return;
510
- }
511
- if (locatorSchema.filter && locatorSchema.locatorMethod !== "frameLocator" /* frameLocator */) {
512
- const filter = locatorSchema.filter;
513
- postDefinition.filter(filter);
250
+ /** Writes states to session storage. Accepts an object with key-value pairs representing the states. */
251
+ async writeToSessionStorage(states) {
252
+ await this.page.evaluate((storage) => {
253
+ for (const [key, value] of Object.entries(storage)) {
254
+ window.sessionStorage.setItem(key, JSON.stringify(value));
255
+ }
256
+ }, states);
514
257
  }
515
- };
516
-
517
- // src/helpers/getBy.locator.ts
518
- var GetBy = class {
519
- constructor(page, pwrl) {
520
- this.page = page;
521
- this.log = pwrl.getNewChildLogger(this.constructor.name);
522
- this.methodMap = {
523
- ["role" /* role */]: this.role,
524
- ["text" /* text */]: this.text,
525
- ["label" /* label */]: this.label,
526
- ["placeholder" /* placeholder */]: this.placeholder,
527
- ["altText" /* altText */]: this.altText,
528
- ["title" /* title */]: this.title,
529
- ["locator" /* locator */]: this.locator,
530
- ["frameLocator" /* frameLocator */]: this.frameLocator,
531
- ["testId" /* testId */]: this.testId,
532
- ["dataCy" /* dataCy */]: this.dataCy,
533
- ["id" /* id */]: this.id
534
- };
535
- this.subMethodMap = {
536
- ["role" /* role */]: this.page.getByRole,
537
- ["text" /* text */]: this.page.getByText,
538
- ["label" /* label */]: this.page.getByLabel,
539
- ["placeholder" /* placeholder */]: this.page.getByPlaceholder,
540
- ["altText" /* altText */]: this.page.getByAltText,
541
- ["title" /* title */]: this.page.getByTitle,
542
- ["locator" /* locator */]: this.page.locator
543
- };
258
+ /** Reads all states from session storage and returns them as an object. */
259
+ async readFromSessionStorage() {
260
+ const storage = await this.page.evaluate(() => {
261
+ const storage2 = {};
262
+ for (let i = 0; i < sessionStorage.length; i++) {
263
+ const key = sessionStorage.key(i);
264
+ if (key !== null) {
265
+ const item = sessionStorage.getItem(key);
266
+ try {
267
+ storage2[key] = item ? JSON.parse(item) : null;
268
+ } catch (_e) {
269
+ storage2[key] = item;
270
+ }
271
+ }
272
+ }
273
+ return storage2;
274
+ });
275
+ return storage;
544
276
  }
545
- log;
546
- methodMap;
547
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
548
- subMethodMap;
549
- /**
550
- * Retrieves a Locator based on the details provided in a LocatorSchema.
551
- * The method identifies the appropriate locator creation function from methodMap and invokes it.
552
- * Throws an error if the locator method is unsupported.
553
- */
554
- getLocator = (locatorSchema) => {
555
- const methodName = locatorSchema.locatorMethod;
556
- const method = this.methodMap[methodName];
557
- if (method) {
558
- return method(locatorSchema);
559
- }
560
- throw new Error(`Unsupported locator method: ${methodName}`);
561
- };
562
277
  /**
563
- * Internal method to retrieve a Locator using a specified GetByMethodSubset and LocatorSchema.
564
- * It identifies the appropriate locator creation function from subMethodMap and invokes it.
565
- * Throws an error if the caller is unknown or if the initial locator is not found.
278
+ * Sets the specified states in session storage.
279
+ * Optionally waits for the next main-frame navigation to establish a valid context before writing,
280
+ * and reloads the page after setting the data.
281
+ *
282
+ * Parameters:
283
+ * states: Object representing the states to set in session storage.
284
+ * reload: Boolean indicating whether to reload the page after setting the session storage data.
285
+ * waitForContext: Boolean indicating whether to wait for a main-frame navigation and a valid context.
566
286
  */
567
- getBy = (caller, locator) => {
568
- const method = this.subMethodMap[caller];
569
- if (!method) {
570
- const errorText = "Error: unknown caller of method getBy(caller, locator) in getBy.locators.ts";
571
- this.log.error(errorText);
572
- throw new Error(errorText);
573
- }
574
- const initialPWLocator = locator[caller] ? method.call(this.page, locator[caller], locator?.[`${caller}Options`]) : null;
575
- if (!initialPWLocator) {
576
- const errorText = `Locator "${locator.locatorSchemaPath}" .${caller} is undefined.`;
577
- this.log.warn(errorText);
578
- throw new Error(errorText);
579
- }
580
- return initialPWLocator;
581
- };
287
+ async set(states, options = {}) {
288
+ await import_test2.test.step(this.getStepLabel("set"), async () => {
289
+ await this.ensureContext({ waitForContext: options.waitForContext });
290
+ await this.writeToSessionStorage(states);
291
+ if (options.reload) {
292
+ await this.page.reload();
293
+ }
294
+ });
295
+ }
582
296
  /**
583
- * Creates a method for generating a Locator using a specific GetByMethodSubset.
584
- * Returns a function that takes a LocatorSchema and returns a Locator.
585
- * The returned function is a locator creation function corresponding to the specified methodName.
297
+ * Queues states to be set in the sessionStorage before the next navigation occurs.
298
+ * Handles different scenarios based on multiple calls made before the navigation occurs.
299
+ *
300
+ * 1. No Context, Single Call: Queues and sets states upon the next navigation.
301
+ * 2. No Context, Multiple Calls: Merges states from multiple calls and sets them upon the next navigation.
302
+ * 3. With Context: Still queues until the next navigation.
303
+ *
304
+ * Parameters:
305
+ * states: Object representing the states to queue for setting in session storage.
586
306
  */
587
- createByMethod = (methodName) => {
588
- return (locator) => {
589
- return this.getBy(methodName, locator);
307
+ async setOnNextNavigation(states) {
308
+ this.queuedStates = { ...this.queuedStates, ...states };
309
+ const populateStorage = async () => {
310
+ await import_test2.test.step(this.getStepLabel("setOnNextNavigation"), async () => {
311
+ await this.writeToSessionStorage(this.queuedStates);
312
+ });
313
+ this.queuedStates = {};
590
314
  };
591
- };
592
- // Methods for creating locators using different locator methods.
593
- // These methods are generated using createByMethod and provide a unified way to create locators based on LocatorSchema.
594
- // Each method is responsible for creating a Locator based on a specific attribute (role, text, label, etc.) provided in LocatorSchema.
595
- // These methods return a Locator and throw an error if the necessary attribute is not defined in the LocatorSchema.
596
- role = this.createByMethod("role" /* role */);
597
- text = this.createByMethod("text" /* text */);
598
- label = this.createByMethod("label" /* label */);
599
- placeholder = this.createByMethod("placeholder" /* placeholder */);
600
- altText = this.createByMethod("altText" /* altText */);
601
- title = this.createByMethod("title" /* title */);
602
- locator = this.createByMethod("locator" /* locator */);
603
- /**
604
- * Returns a FrameLocator using the 'frameLocator' selector from a LocatorSchema.
605
- * Throws an error if the frameLocator is not defined.
606
- */
607
- frameLocator = (locatorSchema) => {
608
- const initialFrameLocator = locatorSchema.frameLocator ? this.page.frameLocator(locatorSchema.frameLocator) : null;
609
- if (!initialFrameLocator) {
610
- const errorText = `Locator "${locatorSchema.locatorSchemaPath}" .frameLocator is not defined.`;
611
- this.log.warn(errorText);
612
- throw new Error(errorText);
613
- }
614
- return initialFrameLocator;
615
- };
616
- /**
617
- * Returns a Locator using the 'testId' selector from a LocatorSchema.
618
- * Throws an error if the testId is not defined.
619
- */
620
- testId = (locator) => {
621
- const initialPWLocator = locator.testId ? this.page.getByTestId(locator.testId) : null;
622
- if (!initialPWLocator) {
623
- const errorText = `Locator "${locator.locatorSchemaPath}" .testId is not defined.`;
624
- this.log.warn(`Locator "${locator.locatorSchemaPath}" .testId is not defined.`);
625
- throw new Error(errorText);
626
- }
627
- return initialPWLocator;
628
- };
629
- /**
630
- * Returns a Locator using the 'dataCy' selector from a LocatorSchema.
631
- * Throws an error if the dataCy is undefined.
632
- */
633
- dataCy = (locator) => {
634
- let initialPWLocator = null;
635
- if (locator.dataCy) {
636
- initialPWLocator = locator.dataCy.startsWith("data-cy=") ? this.page.locator(locator.dataCy) : this.page.locator(`data-cy=${locator.dataCy}`);
637
- } else {
638
- const errorText = `Locator "${locator.locatorSchemaPath}" .dataCy is undefined.`;
639
- this.log.warn(errorText);
640
- throw new Error(errorText);
315
+ if (!this.isInitiated) {
316
+ this.isInitiated = true;
317
+ const handler = async (frame) => {
318
+ if (frame !== this.page.mainFrame()) {
319
+ return;
320
+ }
321
+ await populateStorage();
322
+ this.page.off("framenavigated", handler);
323
+ this.isInitiated = false;
324
+ };
325
+ this.page.on("framenavigated", handler);
641
326
  }
642
- return initialPWLocator;
643
- };
644
- /**
645
- * Returns a Locator using the 'id' selector from a LocatorSchema.
646
- * Throws an error if the id is not defined or the id type is unsupported.
647
- */
648
- id = (locator) => {
649
- let initialPWLocator = null;
650
- let selector;
651
- let regexPattern;
652
- if (!locator.id) {
653
- const errorText = `Locator "${locator.locatorSchemaPath}" .id is not defined.`;
654
- this.log.warn(errorText);
655
- throw new Error(errorText);
656
- }
657
- if (typeof locator.id === "string") {
658
- if (locator.id.startsWith("#")) {
659
- selector = locator.id;
660
- } else if (locator.id.startsWith("id=")) {
661
- selector = `#${locator.id.slice("id=".length)}`;
327
+ }
328
+ async get(keys, options = {}) {
329
+ let result = {};
330
+ await import_test2.test.step(this.getStepLabel("get"), async () => {
331
+ await this.ensureContext(options);
332
+ const allData = await this.readFromSessionStorage();
333
+ if (keys && keys.length > 0) {
334
+ for (const key of keys) {
335
+ if (Object.hasOwn(allData, key)) {
336
+ const value = allData[key];
337
+ if (value !== void 0) {
338
+ result[key] = value;
339
+ }
340
+ }
341
+ }
662
342
  } else {
663
- selector = `#${locator.id}`;
343
+ result = allData;
664
344
  }
665
- } else if (locator.id instanceof RegExp) {
666
- regexPattern = locator.id.source;
667
- selector = `*[id^="${regexPattern}"]`;
668
- } else {
669
- const errorText = `Unsupported id type: ${typeof locator.id}`;
670
- this.log.error(errorText);
671
- throw new Error(errorText);
672
- }
673
- initialPWLocator = this.page.locator(selector);
674
- return initialPWLocator;
675
- };
676
- };
677
-
678
- // src/helpers/getLocatorBase.ts
679
- var REQUIRED_PROPERTIES_FOR_LOCATOR_SCHEMA_WITH_METHODS = [
680
- "update",
681
- "addFilter",
682
- "getNestedLocator",
683
- "getLocator",
684
- "locatorSchemaPath",
685
- "locatorMethod",
686
- "schemasMap",
687
- "filterMap"
688
- ];
689
- var safeStringifyOfNestedLocatorResults = (obj) => {
690
- const seen = /* @__PURE__ */ new WeakSet();
691
- return JSON.stringify(
692
- obj,
693
- (key, value) => {
694
- if (value instanceof Map) {
695
- return Array.from(value.entries());
345
+ });
346
+ return result;
347
+ }
348
+ async clear(keyOrOptions, options = {}) {
349
+ const { keys, waitForContext } = (() => {
350
+ if (Array.isArray(keyOrOptions)) {
351
+ return { keys: keyOrOptions, waitForContext: options.waitForContext };
696
352
  }
697
- if (value instanceof RegExp) {
698
- return { type: "RegExp", source: value.source, flags: value.flags };
353
+ if (typeof keyOrOptions === "string") {
354
+ return { keys: [keyOrOptions], waitForContext: options.waitForContext };
699
355
  }
700
- if (value && typeof value === "object" && value.constructor && value.constructor.name === "Locator") {
701
- return { type: "Locator", note: "Custom placeholder - Locators are complex." };
356
+ if (keyOrOptions) {
357
+ return { keys: void 0, waitForContext: keyOrOptions.waitForContext };
702
358
  }
703
- if (typeof value === "object" && value !== null) {
704
- if (seen.has(value)) return "[Circular]";
705
- seen.add(value);
359
+ return { keys: void 0, waitForContext: options.waitForContext };
360
+ })();
361
+ await import_test2.test.step(this.getStepLabel("clear"), async () => {
362
+ await this.ensureContext({ waitForContext });
363
+ if (!keys || keys.length === 0) {
364
+ await this.page.evaluate(() => sessionStorage.clear());
365
+ return;
706
366
  }
707
- return value;
708
- },
709
- 2
710
- );
367
+ await this.page.evaluate((keysToClear) => {
368
+ for (const key of keysToClear) {
369
+ sessionStorage.removeItem(key);
370
+ }
371
+ }, keys);
372
+ });
373
+ }
711
374
  };
712
- var GetLocatorBase = class {
713
- constructor(pageObjectClass, log, locatorSubstring) {
714
- this.pageObjectClass = pageObjectClass;
715
- this.log = log;
716
- this.locatorSubstring = locatorSubstring;
717
- this.locatorSchemas = /* @__PURE__ */ new Map();
718
- this.getBy = new GetBy(this.pageObjectClass.page, this.log.getNewChildLogger("GetBy"));
719
- }
720
- getBy;
721
- locatorSchemas;
722
- /**
723
- * getLocatorSchema:
724
- * Given a path P, we:
725
- * 1. Collect deep copies of the schemas involved.
726
- * 2. Create a WithMethodsClass instance with LocatorSubstring = P.
727
- * 3. Return a locator schema copy enriched with chainable methods.
728
- */
729
- getLocatorSchema(locatorSchemaPath) {
730
- const pathIndexPairs = this.extractPathsFromSchema(locatorSchemaPath);
731
- const schemasMap = this.collectDeepCopies(locatorSchemaPath, pathIndexPairs);
732
- const locatorSchemaCopy = schemasMap.get(locatorSchemaPath);
733
- locatorSchemaCopy.schemasMap = schemasMap;
734
- locatorSchemaCopy.filterMap = /* @__PURE__ */ new Map();
735
- const wrapper = new WithMethodsClass(
736
- this.pageObjectClass,
737
- this.log,
738
- locatorSchemaPath,
739
- schemasMap
740
- );
741
- return wrapper.init(locatorSchemaPath, locatorSchemaCopy);
375
+
376
+ // src/helpers/stepDecorator.ts
377
+ var import_test3 = require("@playwright/test");
378
+ var isMethodDecoratorArgs = (args) => args.length === 3 && typeof args[0] === "object" && (typeof args[1] === "string" || typeof args[1] === "symbol");
379
+ var isStage3MethodDecoratorArgs = (args) => args.length === 2 && typeof args[0] === "function" && args[1] !== null && typeof args[1] === "object";
380
+ var normalizeStepArguments = (args) => {
381
+ const [titleOrOptions, maybeOptions] = args;
382
+ const title = typeof titleOrOptions === "string" ? titleOrOptions : void 0;
383
+ const options = typeof titleOrOptions === "string" ? maybeOptions : titleOrOptions;
384
+ return { title, options };
385
+ };
386
+ var createWrappedMethod = (original, methodName, title, options) => function(...methodArgs) {
387
+ const rawClassName = this.constructor?.name ?? "";
388
+ const className = rawClassName && rawClassName !== "Object" ? rawClassName : "Anonymous";
389
+ const resolvedTitle = title ?? `${className}.${String(methodName)}`;
390
+ return import_test3.test.step(resolvedTitle, () => original.apply(this, methodArgs), options);
391
+ };
392
+ var createStepDecorator = ({ title, options }) => (valueOrTarget, contextOrKey, descriptor) => {
393
+ if (typeof valueOrTarget === "function" && isStage3MethodDecoratorArgs([valueOrTarget, contextOrKey])) {
394
+ const [original2, context] = [valueOrTarget, contextOrKey];
395
+ return createWrappedMethod(original2, context.name, title, options);
742
396
  }
743
- /**
744
- * collectDeepCopies:
745
- * Clones and stores all schemas related to the chosen path and its sub-paths.
746
- * Ensures updates and filters don't affect original schema definitions.
747
- */
748
- collectDeepCopies(locatorSchemaPath, pathIndexPairs) {
749
- const schemasMap = /* @__PURE__ */ new Map();
750
- const fullSchemaFunc = this.safeGetLocatorSchema(locatorSchemaPath);
751
- if (!fullSchemaFunc) {
752
- const errorMessage = `LocatorSchema not found for path: '${locatorSchemaPath}'`;
753
- this.log.error(errorMessage);
754
- throw new Error(`[${this.pageObjectClass.pocName}] ${errorMessage}`);
755
- }
756
- schemasMap.set(locatorSchemaPath, structuredClone(fullSchemaFunc()));
757
- for (const { path } of pathIndexPairs) {
758
- if (path !== locatorSchemaPath) {
759
- const schemaFunc = this.safeGetLocatorSchema(path);
760
- if (schemaFunc) {
761
- schemasMap.set(path, structuredClone(schemaFunc()));
762
- }
763
- }
764
- }
765
- return schemasMap;
397
+ if (!descriptor || typeof descriptor.value !== "function") {
398
+ throw new Error("@step decorator can only be applied to methods.");
766
399
  }
767
- isLocatorSchemaWithMethods(schema) {
768
- return REQUIRED_PROPERTIES_FOR_LOCATOR_SCHEMA_WITH_METHODS.every((p) => p in schema);
400
+ const original = descriptor.value;
401
+ descriptor.value = createWrappedMethod(original, contextOrKey, title, options);
402
+ return descriptor;
403
+ };
404
+ function step(...args) {
405
+ if (isStage3MethodDecoratorArgs(args)) {
406
+ return createStepDecorator(normalizeStepArguments([]))(...args);
769
407
  }
770
- /**
771
- * applyUpdateToSubPath:
772
- * Applies updates to a specific sub-path schema within schemasMap.
773
- * Similar to applyUpdate, but we locate the sub-path schema directly by its path.
774
- */
775
- applyUpdateToSubPath(schemasMap, subPath, updates) {
776
- const schema = schemasMap.get(subPath);
777
- if (!schema) {
778
- throw new Error(`No schema found for sub-path: '${subPath}'`);
779
- }
780
- const updatedSchema = this.deepMerge(schema, updates);
781
- if (this.isLocatorSchemaWithMethods(schema)) {
782
- Object.assign(schema, updatedSchema);
783
- } else {
784
- schemasMap.set(subPath, updatedSchema);
785
- }
408
+ if (isMethodDecoratorArgs(args)) {
409
+ return createStepDecorator(normalizeStepArguments([]))(...args);
786
410
  }
787
- /**
788
- * createLocatorSchema:
789
- * Creates a fresh LocatorSchema object by merging provided schemaDetails with a required locatorSchemaPath.
790
- */
791
- createLocatorSchema(schemaDetails, locatorSchemaPath) {
792
- const schema = { ...schemaDetails, locatorSchemaPath };
793
- return schema;
411
+ return createStepDecorator(normalizeStepArguments(args));
412
+ }
413
+
414
+ // src/locators/utils.ts
415
+ var formatLocatorSchemaPathForError = (path) => {
416
+ const json = JSON.stringify(path);
417
+ return json.slice(1, -1);
418
+ };
419
+ var RUNTIME_WHITESPACE_REGEX = /[\s\u0085]/u;
420
+ var validateLocatorSchemaPath = (path) => {
421
+ if (!path) {
422
+ throw new Error("LocatorSchemaPath string cannot be empty");
794
423
  }
795
- /**
796
- * addSchema:
797
- * Registers a new LocatorSchema under the given locatorSchemaPath.
798
- * Throws an error if a schema already exists at that path.
799
- */
800
- addSchema(locatorSchemaPath, schemaDetails) {
801
- if (locatorSchemaPath.length === 0 || locatorSchemaPath.startsWith(".") || locatorSchemaPath.endsWith(".") || locatorSchemaPath.includes("..")) {
802
- throw new Error(
803
- `[${this.pageObjectClass.pocName}] Invalid LocatorSchemaPath '${locatorSchemaPath}'. LocatorSchemaPath must not be empty, start or end with a '.', or contain consecutive '.'.`
804
- );
805
- }
806
- const newLocatorSchema = this.createLocatorSchema(schemaDetails, locatorSchemaPath);
807
- const existingSchemaFunc = this.safeGetLocatorSchema(locatorSchemaPath);
808
- if (existingSchemaFunc) {
809
- const existingLocatorSchema = existingSchemaFunc();
810
- throw new Error(
811
- `[${this.pageObjectClass.pocName}] A LocatorSchema with the path '${locatorSchemaPath}' already exists.
812
- Existing Schema: ${JSON.stringify(existingLocatorSchema, null, 2)}
813
- Attempted to Add Schema: ${JSON.stringify(newLocatorSchema, null, 2)}`
814
- );
815
- }
816
- this.locatorSchemas.set(locatorSchemaPath, () => newLocatorSchema);
817
- const v2Registry = this.pageObjectClass.locatorRegistry;
818
- if (v2Registry) {
819
- addV1SchemaToV2Registry(v2Registry, newLocatorSchema);
820
- }
424
+ if (RUNTIME_WHITESPACE_REGEX.test(path)) {
425
+ const escaped = formatLocatorSchemaPathForError(path);
426
+ throw new Error(`LocatorSchemaPath string cannot contain whitespace chars: ${escaped}`);
821
427
  }
822
- /**
823
- * safeGetLocatorSchema:
824
- * Safely retrieves a schema function if available for the given path.
825
- */
826
- safeGetLocatorSchema(path) {
827
- return this.locatorSchemas.get(path);
428
+ if (path.startsWith(".")) {
429
+ throw new Error(`LocatorSchemaPath string cannot start with a dot: ${path}`);
828
430
  }
829
- /**
830
- * extractPathsFromSchema:
831
- * Splits a path into incremental sub-paths and associates them with optional indices.
832
- * Used by getNestedLocator methods.
833
- */
834
- extractPathsFromSchema = (paths, indices = {}) => {
835
- const schemaParts = paths.split(".");
836
- let cumulativePath = "";
837
- return schemaParts.map((part, index) => {
838
- cumulativePath = cumulativePath ? `${cumulativePath}.${part}` : part;
839
- return {
840
- path: cumulativePath,
841
- index: indices[index] ?? void 0
842
- };
843
- });
844
- };
845
- /**
846
- * logError:
847
- * Logs detailed error information and re-throws the error to ensure tests fail as expected.
848
- */
849
- logError = (error, locatorSchemaPath, currentLocator, currentPath, pathIndexPairs, nestedLocatorResults) => {
850
- const errorDetails = {
851
- error: error.message,
852
- locatorSchemaPath,
853
- currentPath,
854
- pathIndexPairs: JSON.stringify(pathIndexPairs, null, 2),
855
- currentLocatorDetails: currentLocator ? {
856
- locatorString: currentLocator,
857
- isNotNull: true
858
- } : { isNotNull: false },
859
- nestedLocatorResults: safeStringifyOfNestedLocatorResults(nestedLocatorResults)
860
- };
861
- this.log.error(
862
- "An error occurred during nested locator construction.\n",
863
- "Error details:\n",
864
- JSON.stringify(errorDetails, null, 2)
865
- );
866
- throw error;
867
- };
868
- /**
869
- * deepMerge:
870
- * Recursively merges source properties into target, validating them against LocatorSchema to ensure no invalid keys.
871
- * Ensures immutability by creating a new object rather than modifying in place.
872
- */
873
- deepMerge(target, source, schema = getLocatorSchemaDummy()) {
874
- const merged = { ...target };
875
- for (const key of Object.keys(source)) {
876
- if (key === "locatorSchemaPath") {
877
- throw new Error(
878
- `[${this.pageObjectClass.pocName}] Invalid property: 'locatorSchemaPath' cannot be updated. Attempted to update LocatorSchemaPath from '${target[key]}' to '${source[key]}'.`
879
- );
880
- }
881
- if (!(key in schema)) {
882
- throw new Error(`Invalid property: '${key}' is not a valid property of LocatorSchema`);
883
- }
884
- const sourceValue = source[key];
885
- const targetValue = target[key];
886
- if (typeof sourceValue === "object" && sourceValue !== null && schema[key] && typeof schema[key] === "object") {
887
- if (targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
888
- merged[key] = this.deepMerge(
889
- targetValue,
890
- // Updated type here
891
- sourceValue,
892
- schema[key]
893
- );
894
- } else {
895
- merged[key] = this.deepMerge(
896
- {},
897
- sourceValue,
898
- schema[key]
899
- );
900
- }
901
- } else {
902
- if (Array.isArray(sourceValue)) {
903
- merged[key] = Array.isArray(targetValue) ? targetValue.concat(sourceValue) : [...sourceValue];
904
- } else if (typeof sourceValue === "object" && sourceValue !== null && Object.prototype.toString.call(sourceValue) === "[object RegExp]") {
905
- merged[key] = new RegExp(
906
- sourceValue.source,
907
- sourceValue.flags
908
- );
909
- } else {
910
- merged[key] = sourceValue;
911
- }
912
- }
913
- }
914
- return merged;
431
+ if (path.endsWith(".")) {
432
+ throw new Error(`LocatorSchemaPath string cannot end with a dot: ${path}`);
915
433
  }
916
- /**
917
- * buildNestedLocator:
918
- * Constructs a nested locator by iterating through each sub-path of locatorSchemaPath and chaining locators.
919
- * Applies filters, indexing (nth), and logs details for debugging during test retries.
920
- */
921
- buildNestedLocator = async (locatorSchemaPath, schemasMap, filterMap, indices = {}) => {
922
- return await import_test.test.step(`${this.pageObjectClass.pocName}: Build Nested Locator`, async () => {
923
- const pathIndexPairs = this.extractPathsFromSchema(locatorSchemaPath, indices);
924
- let currentLocator = null;
925
- let currentIFrame = null;
926
- const nestedLocatorResults = {
927
- LocatorSchema: null,
928
- NestingSteps: []
929
- };
930
- for (const { path, index } of pathIndexPairs) {
931
- const currentSchema = schemasMap.get(path);
932
- if (!currentSchema) continue;
933
- try {
934
- const nextLocator = this.getBy.getLocator(currentSchema);
935
- currentLocator = currentLocator ? currentLocator.locator(nextLocator) : nextLocator;
936
- if (currentSchema.locatorMethod !== "frameLocator" /* frameLocator */ && currentSchema.filter) {
937
- currentLocator = currentLocator.filter({
938
- has: currentSchema.filter.has,
939
- hasNot: currentSchema.filter.hasNot,
940
- hasNotText: currentSchema.filter.hasNotText,
941
- hasText: currentSchema.filter.hasText
942
- });
943
- }
944
- const filterEntries = filterMap.get(path);
945
- if (filterEntries) {
946
- for (const filterData of filterEntries) {
947
- currentLocator = currentLocator.filter({
948
- has: filterData.has,
949
- hasNot: filterData.hasNot,
950
- hasNotText: filterData.hasNotText,
951
- hasText: filterData.hasText
952
- });
953
- }
954
- }
955
- if (index != null) {
956
- currentLocator = currentLocator.nth(index);
957
- }
958
- if (this.log.isLogLevelEnabled("debug")) {
959
- if (!nestedLocatorResults.LocatorSchema) {
960
- const schemaFromMap = schemasMap.get(locatorSchemaPath);
961
- if (schemaFromMap) {
962
- nestedLocatorResults.LocatorSchema = schemaFromMap;
963
- }
964
- }
965
- if (currentSchema.locatorMethod === "frameLocator" /* frameLocator */) {
966
- if (!currentIFrame) {
967
- currentIFrame = currentSchema.frameLocator;
968
- }
969
- if (currentIFrame && currentSchema.frameLocator && currentIFrame.endsWith(currentSchema.frameLocator)) {
970
- currentIFrame += ` -> ${currentSchema.frameLocator}`;
971
- }
972
- }
973
- if (currentIFrame !== void 0) {
974
- await this.evaluateCurrentLocator(currentLocator, nestedLocatorResults.NestingSteps, currentIFrame);
975
- } else {
976
- await this.evaluateCurrentLocator(currentLocator, nestedLocatorResults.NestingSteps, null);
977
- }
978
- }
979
- } catch (error) {
980
- this.logError(error, locatorSchemaPath, currentLocator, path, pathIndexPairs, nestedLocatorResults);
981
- break;
982
- }
983
- }
984
- if (!currentLocator) {
985
- this.logError(
986
- new Error(`Failed to build nested locator for path: ${locatorSchemaPath}`),
987
- locatorSchemaPath,
988
- currentLocator,
989
- locatorSchemaPath,
990
- pathIndexPairs
991
- );
992
- }
993
- if (this.log.isLogLevelEnabled("debug")) {
994
- this.log.debug("Nested locator evaluation results:", safeStringifyOfNestedLocatorResults(nestedLocatorResults));
995
- }
996
- if (currentLocator != null) {
997
- return currentLocator;
998
- }
999
- });
1000
- };
1001
- /**
1002
- * evaluateCurrentLocator:
1003
- * Gathers debug information about the current locator's resolved elements.
1004
- * Helps with logging and debugging complex locator chains.
1005
- */
1006
- evaluateCurrentLocator = async (currentLocator, resultsArray, currentIFrame) => {
1007
- if (currentIFrame) {
1008
- resultsArray.push({
1009
- currentLocatorString: currentLocator,
1010
- currentIFrame,
1011
- Note: "iFrame locators evaluation not implemented"
1012
- });
1013
- } else {
1014
- const elementCount = await currentLocator.count();
1015
- resultsArray.push({
1016
- currentLocatorString: `${currentLocator}`,
1017
- resolved: elementCount > 0,
1018
- elementCount
1019
- });
1020
- }
1021
- };
1022
- };
1023
- var WithMethodsClass = class extends GetLocatorBase {
1024
- constructor(pageObjectClass, log, locatorSubstring, schemasMap) {
1025
- super(pageObjectClass, log, locatorSubstring);
1026
- this.pageObjectClass = pageObjectClass;
1027
- this.log = log;
1028
- this.schemasMap = schemasMap;
1029
- }
1030
- locatorSchemaPath;
1031
- /**
1032
- * init:
1033
- * Assigns the locatorSchemaPath and binds methods (update, addFilter, getNestedLocator, getLocator)
1034
- * directly on the locatorSchemaCopy. Returns the modified copy, now fully chainable and type-safe.
1035
- */
1036
- init(locatorSchemaPath, locatorSchemaCopy) {
1037
- this.locatorSchemaPath = locatorSchemaPath;
1038
- const self = this;
1039
- locatorSchemaCopy.update = function(subPath, updates) {
1040
- const fullPath = this.locatorSchemaPath;
1041
- if (!(subPath === fullPath || fullPath.startsWith(`${subPath}.`))) {
1042
- throw new Error(`Invalid sub-path: '${subPath}' is not a valid sub-path of '${fullPath}'.`);
1043
- }
1044
- self.applyUpdateToSubPath(self.schemasMap, subPath, updates);
1045
- return this;
1046
- };
1047
- locatorSchemaCopy.addFilter = function(subPath, filterData) {
1048
- const fullPath = this.locatorSchemaPath;
1049
- if (!self.schemasMap.has(subPath)) {
1050
- const allowedPaths = self.extractPathsFromSchema(fullPath).map((p) => p.path).filter((path) => self.schemasMap.has(path));
1051
- throw new Error(
1052
- `Invalid sub-path '${subPath}' in addFilter. Allowed sub-paths are:
1053
- ${allowedPaths.join(",\n")}`
1054
- );
1055
- }
1056
- if (!this.filterMap) {
1057
- this.filterMap = /* @__PURE__ */ new Map();
1058
- }
1059
- const existingFilters = this.filterMap.get(subPath) || [];
1060
- existingFilters.push(filterData);
1061
- this.filterMap.set(subPath, existingFilters);
1062
- return this;
1063
- };
1064
- locatorSchemaCopy.getNestedLocator = async function(arg) {
1065
- if (arg !== void 0 && arg !== null && typeof arg !== "object") {
1066
- throw new Error("Invalid argument passed to getNestedLocator: Expected an object or null.");
1067
- }
1068
- if (!arg || Object.keys(arg).length === 0) {
1069
- return await self.buildNestedLocator(
1070
- self.locatorSchemaPath,
1071
- self.schemasMap,
1072
- this.filterMap,
1073
- {}
1074
- );
1075
- }
1076
- const numericIndices = {};
1077
- const pathIndexPairs = self.extractPathsFromSchema(self.locatorSchemaPath);
1078
- const pathToIndexMap = new Map(pathIndexPairs.map((pair, idx) => [pair.path, idx]));
1079
- for (const [subPath, value] of Object.entries(arg)) {
1080
- if (!self.schemasMap.has(subPath)) {
1081
- const validPaths = Array.from(self.schemasMap.keys());
1082
- throw new Error(
1083
- `Invalid sub-path '${subPath}' in getNestedLocator. Allowed sub-paths are:
1084
- ${validPaths.join(",\n")}`
1085
- );
1086
- }
1087
- if (!pathToIndexMap.has(subPath)) {
1088
- const validPaths = pathIndexPairs.map((p) => p.path).filter((path) => self.schemasMap.has(path));
1089
- throw new Error(
1090
- `Invalid sub-path '${subPath}' in getNestedLocator. Allowed sub-paths are:
1091
- ${validPaths.join(",\n")}`
1092
- );
1093
- }
1094
- const numericIndex = pathToIndexMap.get(subPath);
1095
- if (numericIndex === void 0) {
1096
- throw new Error(`Sub-path '${subPath}' not found in pathToIndexMap.`);
1097
- }
1098
- if (value !== null && (typeof value !== "number" || value < 0)) {
1099
- throw new Error(`Invalid index for sub-path '${subPath}': Expected a positive number or null.`);
1100
- }
1101
- if (value !== null) {
1102
- numericIndices[numericIndex] = value;
1103
- }
1104
- }
1105
- return await self.buildNestedLocator(
1106
- self.locatorSchemaPath,
1107
- self.schemasMap,
1108
- this.filterMap,
1109
- numericIndices
1110
- );
1111
- };
1112
- locatorSchemaCopy.getLocator = async () => {
1113
- return self.getBy.getLocator(locatorSchemaCopy);
1114
- };
1115
- return locatorSchemaCopy;
434
+ if (path.includes("..")) {
435
+ throw new Error(`LocatorSchemaPath string cannot contain consecutive dots: ${path}`);
1116
436
  }
1117
437
  };
1118
-
1119
- // src/helpers/sessionStorage.actions.ts
1120
- var import_test2 = require("@playwright/test");
1121
- var SessionStorage = class {
1122
- // Initializes the class with a Playwright Page object and a name for the Page Object Class.
1123
- constructor(page, pocName) {
1124
- this.page = page;
1125
- this.pocName = pocName;
438
+ var expandSchemaPath = (path) => {
439
+ validateLocatorSchemaPath(path);
440
+ const parts = path.split(".");
441
+ return parts.map((_part, index) => parts.slice(0, index + 1).join("."));
442
+ };
443
+ var cssEscape = (value) => {
444
+ return value.replace(/([\\"'#.:;,?*+<>{}[\\]()])/g, "\\$1");
445
+ };
446
+ var normalizeSteps = (steps) => steps ? steps.map((step2) => ({ ...step2 })) : [];
447
+ function normalizeIdValue(id) {
448
+ if (typeof id !== "string") {
449
+ return id;
1126
450
  }
1127
- // Defines an object to hold states to be set in session storage, allowing any value type.
1128
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
1129
- queuedStates = {};
1130
- // Indicates if the session storage manipulation has been initiated.
1131
- isInitiated = false;
1132
- /** Writes states to session storage. Accepts an object with key-value pairs representing the states. */
1133
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
1134
- async writeToSessionStorage(states) {
1135
- await this.page.evaluate((storage) => {
1136
- for (const [key, value] of Object.entries(storage)) {
1137
- window.sessionStorage.setItem(key, JSON.stringify(value));
1138
- }
1139
- }, states);
451
+ if (id.startsWith("#")) {
452
+ return id.slice(1);
1140
453
  }
1141
- /** Reads all states from session storage and returns them as an object. */
1142
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
1143
- async readFromSessionStorage() {
1144
- return await this.page.evaluate(() => {
1145
- const storage = {};
1146
- for (let i = 0; i < sessionStorage.length; i++) {
1147
- const key = sessionStorage.key(i);
1148
- if (key !== null) {
1149
- const item = sessionStorage.getItem(key);
1150
- try {
1151
- storage[key] = item ? JSON.parse(item) : null;
1152
- } catch (_e) {
1153
- storage[key] = item;
1154
- }
454
+ if (id.startsWith("id=")) {
455
+ return id.slice("id=".length);
456
+ }
457
+ return id;
458
+ }
459
+ var stringifyForLog = (value) => {
460
+ const seen = /* @__PURE__ */ new WeakSet();
461
+ return JSON.stringify(
462
+ value,
463
+ (_key, current) => {
464
+ if (typeof current === "object" && current !== null) {
465
+ if (seen.has(current)) {
466
+ return "[Circular]";
1155
467
  }
468
+ seen.add(current);
1156
469
  }
1157
- return storage;
1158
- });
1159
- }
1160
- /**
1161
- * Sets the specified states in session storage.
1162
- * Optionally reloads the page after setting the data to ensure the new session storage state is active.
1163
- *
1164
- * Parameters:
1165
- * states: Object representing the states to set in session storage.
1166
- * reload: Boolean indicating whether to reload the page after setting the session storage data.
1167
- */
1168
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
1169
- async set(states, reload) {
1170
- await import_test2.test.step(`${this.pocName}: setSessionStorage`, async () => {
1171
- await this.writeToSessionStorage(states);
1172
- if (reload) {
1173
- await this.page.reload();
470
+ if (current instanceof RegExp) {
471
+ return { type: "RegExp", source: current.source, flags: current.flags };
1174
472
  }
1175
- });
473
+ return current;
474
+ },
475
+ 2
476
+ );
477
+ };
478
+ var applyIndexSelector = (locator, selector) => {
479
+ if (selector === void 0 || selector === null) {
480
+ return locator;
1176
481
  }
1177
- /**
1178
- * Queues states to be set in the sessionStorage before the next navigation occurs.
1179
- * Handles different scenarios based on whether the context exists or multiple calls are made.
1180
- *
1181
- * 1. No Context, Single Call: Queues and sets states upon the next navigation.
1182
- * 2. No Context, Multiple Calls: Merges states from multiple calls and sets them upon the next navigation.
1183
- * 3. With Context: Directly sets states in sessionStorage if the context already exists.
1184
- *
1185
- * Parameters:
1186
- * states: Object representing the states to queue for setting in session storage.
1187
- */
1188
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
1189
- async setOnNextNavigation(states) {
1190
- this.queuedStates = { ...this.queuedStates, ...states };
1191
- const populateStorage = async () => {
1192
- await import_test2.test.step(`${this.pocName}: setSessionStorageBeforeNavigation`, async () => {
1193
- await this.writeToSessionStorage(this.queuedStates);
1194
- });
1195
- this.queuedStates = {};
1196
- };
1197
- let contextExists = false;
1198
- try {
1199
- contextExists = await this.page.evaluate(() => {
1200
- return typeof window !== "undefined" && window.sessionStorage !== void 0;
1201
- });
1202
- } catch (_e) {
1203
- contextExists = false;
1204
- }
1205
- if (contextExists) {
1206
- await populateStorage();
1207
- return;
1208
- }
1209
- if (!this.isInitiated) {
1210
- this.isInitiated = true;
1211
- this.page.once("framenavigated", async () => {
1212
- await populateStorage();
1213
- });
1214
- }
482
+ if (selector === "first") {
483
+ return locator.first();
1215
484
  }
1216
- /**
1217
- * Fetches states from session storage.
1218
- * If specific keys are provided, fetches only those states; otherwise, fetches all states.
1219
- *
1220
- * Parameters:
1221
- * keys: Optional array of keys to specify which states to fetch from session storage.
1222
- *
1223
- * Returns:
1224
- * Object containing the fetched states.
1225
- */
1226
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
1227
- async get(keys) {
1228
- let result = {};
1229
- await import_test2.test.step(`${this.pocName}: getSessionStorage`, async () => {
1230
- const allData = await this.readFromSessionStorage();
1231
- if (keys && keys.length > 0) {
1232
- for (const key of keys) {
1233
- if (Object.hasOwn(allData, key)) {
1234
- result[key] = allData[key];
1235
- }
1236
- }
1237
- } else {
1238
- result = allData;
485
+ if (selector === "last") {
486
+ return locator.last();
487
+ }
488
+ return locator.nth(selector);
489
+ };
490
+ var createLocator = (target, definition) => {
491
+ switch (definition.type) {
492
+ case "role":
493
+ return target.getByRole(definition.role, definition.options);
494
+ case "text":
495
+ return target.getByText(definition.text, definition.options);
496
+ case "label":
497
+ return target.getByLabel(definition.text, definition.options);
498
+ case "placeholder":
499
+ return target.getByPlaceholder(definition.text, definition.options);
500
+ case "altText":
501
+ return target.getByAltText(definition.text, definition.options);
502
+ case "title":
503
+ return target.getByTitle(definition.text, definition.options);
504
+ case "locator":
505
+ return target.locator(definition.selector, definition.options);
506
+ case "frameLocator":
507
+ return target.frameLocator(definition.selector);
508
+ case "testId":
509
+ return target.getByTestId(definition.testId);
510
+ case "id": {
511
+ if (typeof definition.id === "string") {
512
+ const normalized = normalizeIdValue(definition.id);
513
+ return target.locator(`#${cssEscape(normalized ?? "")}`);
1239
514
  }
1240
- });
1241
- return result;
515
+ const pattern = definition.id.source;
516
+ const safePattern = cssEscape(pattern);
517
+ return target.locator(`[id*="${safePattern}"]`);
518
+ }
519
+ default: {
520
+ const exhaustive = definition;
521
+ return exhaustive;
522
+ }
1242
523
  }
1243
- /**
1244
- * Clears all states in sessionStorage.
1245
- */
1246
- async clear() {
1247
- await import_test2.test.step(`${this.pocName}: clear SessionStorage`, async () => {
1248
- await this.page.evaluate(() => sessionStorage.clear());
1249
- });
524
+ };
525
+ var cloneLocatorStrategyDefinition = (definition) => {
526
+ switch (definition.type) {
527
+ case "role":
528
+ return {
529
+ type: "role",
530
+ role: definition.role,
531
+ ...definition.options ? { options: { ...definition.options } } : {}
532
+ };
533
+ case "text":
534
+ return {
535
+ type: "text",
536
+ text: definition.text,
537
+ ...definition.options ? { options: { ...definition.options } } : {}
538
+ };
539
+ case "label":
540
+ return {
541
+ type: "label",
542
+ text: definition.text,
543
+ ...definition.options ? { options: { ...definition.options } } : {}
544
+ };
545
+ case "placeholder":
546
+ return {
547
+ type: "placeholder",
548
+ text: definition.text,
549
+ ...definition.options ? { options: { ...definition.options } } : {}
550
+ };
551
+ case "altText":
552
+ return {
553
+ type: "altText",
554
+ text: definition.text,
555
+ ...definition.options ? { options: { ...definition.options } } : {}
556
+ };
557
+ case "title":
558
+ return {
559
+ type: "title",
560
+ text: definition.text,
561
+ ...definition.options ? { options: { ...definition.options } } : {}
562
+ };
563
+ case "locator":
564
+ return {
565
+ type: "locator",
566
+ selector: definition.selector,
567
+ ...definition.options ? { options: { ...definition.options } } : {}
568
+ };
569
+ case "frameLocator":
570
+ return { type: "frameLocator", selector: definition.selector };
571
+ case "testId":
572
+ return { type: "testId", testId: definition.testId };
573
+ case "id":
574
+ return { type: "id", id: definition.id };
575
+ default: {
576
+ const exhaustive = definition;
577
+ return exhaustive;
578
+ }
1250
579
  }
1251
580
  };
1252
-
1253
- // src/utils/selectorEngines.ts
1254
- function createCypressIdEngine() {
1255
- return {
1256
- /**
1257
- * Uses the document's querySelector method to find the first element with a specific 'data-cy' attribute.
1258
- * Constructs a selector string for the 'data-cy' attribute and searches the DOM for the first match.
1259
- *
1260
- * Parameters:
1261
- * - document: An object that mimics the global document, having a querySelector method.
1262
- * - selector: A string representing the value of the 'data-cy' attribute to search for.
1263
- *
1264
- * Returns the first HTML element matching the 'data-cy' attribute, or null if no match is found.
1265
- */
1266
- query(document, selector) {
1267
- const attr = `[data-cy="${selector}"]`;
1268
- const el = document.querySelector(attr);
1269
- return el;
1270
- },
1271
- /**
1272
- * Uses the document's querySelectorAll method to find all elements with a specific 'data-cy' attribute.
1273
- * Constructs a selector string for the 'data-cy' attribute and retrieves all matching elements in the DOM.
1274
- * Converts the NodeList from querySelectorAll into an array for easier handling and manipulation.
1275
- *
1276
- * Parameters:
1277
- * - document: An object that mimics the global document, having a querySelectorAll method.
1278
- * - selector: A string representing the value of the 'data-cy' attribute to search for.
1279
- *
1280
- * Returns an array of HTML elements matching the 'data-cy' attribute. Returns an empty array if no matches are found.
1281
- */
1282
- queryAll(document, selector) {
1283
- const attr = `[data-cy="${selector}"]`;
1284
- const els = Array.from(document.querySelectorAll(attr));
1285
- return els;
581
+ var applyDefinitionPatch = (seed, patch) => {
582
+ const base2 = cloneLocatorStrategyDefinition(seed);
583
+ switch (patch.type) {
584
+ case "locator": {
585
+ const selector = patch.selector !== void 0 ? patch.selector : base2.selector;
586
+ const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
587
+ return { type: "locator", selector, ...options ? { options } : {} };
1286
588
  }
1287
- };
1288
- }
1289
-
1290
- // src/basePage.ts
1291
- var selectorRegistered = false;
1292
- var BasePage = class {
1293
- /** Provides Playwright page methods */
1294
- page;
1295
- /** Playwright TestInfo contains information about currently running test, available to any test function */
1296
- testInfo;
1297
- /** Selectors can be used to install custom selector engines.*/
1298
- selector;
1299
- /** The base URL of the Page Object Class */
1300
- baseUrl;
1301
- /** The URL path of the Page Object Class */
1302
- urlPath;
1303
- /** The full URL of the Page Object Class */
1304
- fullUrl;
1305
- /** The name of the Page Object Class */
1306
- pocName;
1307
- /** The Page Object Class' PlaywrightReportLogger instance, prefixed with its name. Log levels: debug, info, warn, and error. */
1308
- log;
1309
- /** The SessionStorage class provides methods for setting and getting session storage data in Playwright.*/
1310
- sessionStorage;
1311
- /**
1312
- * locators:
1313
- * An instance of GetLocatorBase that handles schema management and provides getLocatorSchema calls.
1314
- * Initially, LocatorSubstring is undefined. Once getLocatorSchema(path) is called,
1315
- * we get a chainable object typed with LocatorSubstring = P.
1316
- */
1317
- locators;
1318
- constructor(page, testInfo, baseUrl, urlPath, pocName, pwrl, locatorSubstring) {
1319
- this.page = page;
1320
- this.testInfo = testInfo;
1321
- this.selector = import_test3.selectors;
1322
- this.baseUrl = baseUrl;
1323
- this.urlPath = urlPath;
1324
- this.fullUrl = this.constructFullUrl(baseUrl, urlPath);
1325
- this.pocName = pocName;
1326
- this.log = pwrl.getNewChildLogger(pocName);
1327
- const classDeprecationMessage = "[POMWright] BasePage is depricated and will be removed in 2.0.0. Migrate to v2, preferably directly to PageObject or through the transitional bridge BasePageV1toV2 and then to PageObject.";
1328
- warnDeprecationOncePerTest(`${this.constructor.name}-class-deprecation`, classDeprecationMessage, this.log);
1329
- this.locators = new GetLocatorBase(
1330
- this,
1331
- this.log.getNewChildLogger("GetLocator"),
1332
- locatorSubstring
1333
- );
1334
- this.initLocatorSchemas();
1335
- this.sessionStorage = new SessionStorage(this.page, this.pocName);
1336
- if (!selectorRegistered) {
1337
- import_test3.selectors.register("data-cy", createCypressIdEngine);
1338
- selectorRegistered = true;
589
+ case "role": {
590
+ const role = patch.role ?? base2.role;
591
+ const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
592
+ return { type: "role", role, ...options ? { options } : {} };
1339
593
  }
1340
- }
1341
- /**
1342
- * constructFullUrl:
1343
- * Combines baseUrl and urlPath, handling both strings and RegExps.
1344
- * Ensures a flexible approach to URL matching (string or regex-based).
1345
- */
1346
- constructFullUrl(baseUrl, urlPath) {
1347
- const escapeStringForRegExp = (str) => str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
1348
- if (typeof baseUrl === "string" && typeof urlPath === "string") {
1349
- return `${baseUrl}${urlPath}`;
594
+ case "text": {
595
+ const text = patch.text ?? base2.text;
596
+ const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
597
+ return { type: "text", text, ...options ? { options } : {} };
1350
598
  }
1351
- if (typeof baseUrl === "string" && urlPath instanceof RegExp) {
1352
- return new RegExp(`^${escapeStringForRegExp(baseUrl)}${urlPath.source}`);
599
+ case "label": {
600
+ const text = patch.text ?? base2.text;
601
+ const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
602
+ return { type: "label", text, ...options ? { options } : {} };
1353
603
  }
1354
- if (baseUrl instanceof RegExp && typeof urlPath === "string") {
1355
- return new RegExp(`${baseUrl.source}${escapeStringForRegExp(urlPath)}$`);
604
+ case "placeholder": {
605
+ const text = patch.text ?? base2.text;
606
+ const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
607
+ return { type: "placeholder", text, ...options ? { options } : {} };
608
+ }
609
+ case "altText": {
610
+ const text = patch.text ?? base2.text;
611
+ const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
612
+ return { type: "altText", text, ...options ? { options } : {} };
613
+ }
614
+ case "title": {
615
+ const text = patch.text ?? base2.text;
616
+ const options = patch.options || base2.options ? { ...base2.options, ...patch.options } : void 0;
617
+ return { type: "title", text, ...options ? { options } : {} };
618
+ }
619
+ case "frameLocator": {
620
+ const selector = patch.selector !== void 0 ? patch.selector : base2.selector;
621
+ return { type: "frameLocator", selector };
622
+ }
623
+ case "testId": {
624
+ const testId = patch.testId !== void 0 ? patch.testId : base2.testId;
625
+ return { type: "testId", testId };
626
+ }
627
+ case "id": {
628
+ const id = patch.id !== void 0 ? normalizeIdValue(patch.id) ?? base2.id : base2.id;
629
+ return { type: "id", id };
1356
630
  }
1357
- if (baseUrl instanceof RegExp && urlPath instanceof RegExp) {
1358
- return new RegExp(`${baseUrl.source}${urlPath.source}`);
631
+ default: {
632
+ const exhaustive = patch;
633
+ return exhaustive;
1359
634
  }
1360
- throw new Error("Invalid baseUrl or urlPath types. Expected string or RegExp.");
1361
- }
1362
- /**
1363
- * Implementation of getNestedLocator.
1364
- */
1365
- async getNestedLocator(locatorSchemaPath, subPathIndices) {
1366
- const withValidation = new WithSubPathValidation(
1367
- this,
1368
- this.log.getNewChildLogger("SubPathValidation"),
1369
- locatorSchemaPath
1370
- );
1371
- return await withValidation.getNestedLocator(subPathIndices);
1372
- }
1373
- /**
1374
- * Short-hand wrapper method for calling .getLocatorSchema(LocatorSchemaPath).getLocator()
1375
- *
1376
- * This method does not perform nesting,and will return the locator for which the full LocatorSchemaPath resolves to,
1377
- * provided by getLocatorSchema("...")
1378
- *
1379
- * Note: This short-hand wrapper method is useful for quickly getting a locator without having to call
1380
- * getLocatorSchema("...") first. On the other hand, it can't be used to update or add filters to the LocatorSchema.
1381
- *
1382
- * @example
1383
- * // Usage:
1384
- * const submitButton = await poc.getLocator("main.form.button@submit");
1385
- * await expect(submitButton, "should only exist one submit button").toHaveCount(1);
1386
- */
1387
- getLocator = async (locatorSchemaPath) => {
1388
- return await this.getLocatorSchema(locatorSchemaPath).getLocator();
1389
- };
1390
- /**
1391
- * getLocatorSchema:
1392
- * Delegates to this.locators.getLocatorSchema.
1393
- * Returns a chainable schema object for the given path.
1394
- * Once called with a specific path P, the update and addFilter methods are restricted to sub-paths of P.
1395
- *
1396
- * The "getLocatorSchema" method is used to retrieve an updatable deep copy of a LocatorSchema defined in the
1397
- * GetLocatorBase class. It enriches the returned schema with additional methods to handle updates and retrieval of
1398
- * deep copy locators.
1399
- *
1400
- * getLocatorSchema adds the following chainable methods to the returned LocatorSchemaWithMethods object:
1401
- *
1402
- * update
1403
- * - Allows updating any schema in the chain by specifying the subPath directly.
1404
- * - Gives compile-time suggestions for valid sub-paths of the LocatorSchemaPath provided to .getLocatorSchema().
1405
- * - If you want to update multiple schemas, chain multiple .update() calls.
1406
- *
1407
- * addFilter(subPath: SubPaths<LocatorSchemaPathType, LocatorSubstring>, filterData: FilterEntry)
1408
- * - The equivalent of the Playwright locator.filter() method
1409
- * - This method is used for filtering the specified locator based on the provided filterData.
1410
- * - Can be chained multiple times to add multiple filters to the same or different LocatorSchema.
1411
- *
1412
- * getNestedLocator
1413
- * - Asynchronously builds a nested locator based on the LocatorSchemaPath provided by getLocatorSchema("...")
1414
- * - Can be chained once after the update and addFilter methods or directly on the .getLocatorSchema method.
1415
- * - getNestedLocator will end the method chain and return a nested Playwright Locator.
1416
- * - Optionally parameter takes a list of key(subPath)-value(index) pairs, the locator constructed from the LocatorSchema
1417
- * with the specified subPath will resolve to the .nth(n) occurrence of the element, within the chain.
1418
- *
1419
- * getLocator()
1420
- * - Asynchronously retrieves a locator based on the current LocatorSchemaPath.
1421
- * - This method does not perform nesting and will return the locator for which the full LocatorSchemaPath resolves to, provided by getLocatorSchema("...")
1422
- * - Can be chained once after the update and addFilter methods or directly on the .getLocatorSchema method.
1423
- * - getLocator will end the method chain and return a Playwright Locator.
1424
- *
1425
- * Note: Calling getLocator() and getNestedLocator() on the same LocatorSchemaPath will return a Locator for the same
1426
- * element, but the Locator returned by getNestedLocator() will be a locator resolving to said same element through
1427
- * a chain of locators. While the Locator returned by getLocator() will be a single locator which resolves directly
1428
- * to said element. Thus getLocator() is rarely used, while getNestedLocator() is used extensively.
1429
- *
1430
- * That said, for certain use cases, getLocator() can be useful, and you could use it to manually chain locators
1431
- * yourself if some edge case required it. Though, it would be likely be more prudent to expand your LocatorSchemaPath
1432
- * type and initLocatorSchemas() method to include the additional locators you need for the given POC, and then use
1433
- * getNestedLocator() instead, or by implementing a helper method on your Page Object Class.
1434
- */
1435
- getLocatorSchema(path) {
1436
- return this.locators.getLocatorSchema(path);
1437
635
  }
1438
636
  };
1439
- var WithSubPathValidation = class extends GetLocatorBase {
1440
- constructor(pageObjectClass, log, locatorSchemaPath) {
1441
- super(pageObjectClass, log, locatorSchemaPath);
1442
- this.locatorSchemaPath = locatorSchemaPath;
1443
- }
1444
- async getNestedLocator(arg) {
1445
- return await this.pageObjectClass.getLocatorSchema(this.locatorSchemaPath).getNestedLocator(arg);
1446
- }
637
+ var isFrameLocatorDefinition = (definition) => definition.type === "frameLocator";
638
+ var isLocatorInstance = (value) => {
639
+ return !!value && typeof value === "object" && typeof value.filter === "function";
1447
640
  };
1448
641
 
1449
- // src/basePageV1toV2.ts
1450
- var import_test4 = require("@playwright/test");
1451
-
1452
- // srcV2/locators/locatorUpdateBuilder.ts
642
+ // src/locators/locatorUpdateBuilder.ts
1453
643
  var parseUpdateArguments = (primaryOrOptions, options, optionsProvided) => {
1454
644
  let primary;
1455
645
  let parsedOptions;
@@ -1939,7 +1129,7 @@ var LocatorUpdateBuilder = class {
1939
1129
  }
1940
1130
  };
1941
1131
 
1942
- // srcV2/locators/locatorQueryBuilder.ts
1132
+ // src/locators/locatorQueryBuilder.ts
1943
1133
  var LocatorQueryBuilder = class {
1944
1134
  constructor(registry, path) {
1945
1135
  this.registry = registry;
@@ -2162,7 +1352,7 @@ var LocatorQueryBuilder = class {
2162
1352
  }
2163
1353
  };
2164
1354
 
2165
- // srcV2/locators/locatorRegistrationBuilder.ts
1355
+ // src/locators/locatorRegistrationBuilder.ts
2166
1356
  var LocatorRegistrationBuilder = class {
2167
1357
  constructor(registry, path, seed) {
2168
1358
  this.registry = registry;
@@ -2386,7 +1576,7 @@ var LocatorRegistrationBuilder = class {
2386
1576
  }
2387
1577
  };
2388
1578
 
2389
- // srcV2/locators/reusableLocatorBuilder.ts
1579
+ // src/locators/reusableLocatorBuilder.ts
2390
1580
  var ReusableLocatorBuilder = class {
2391
1581
  stepsList;
2392
1582
  definitionValue;
@@ -2462,7 +1652,7 @@ var ReusableLocatorFactory = class {
2462
1652
  }
2463
1653
  };
2464
1654
 
2465
- // srcV2/locators/locatorRegistry.ts
1655
+ // src/locators/locatorRegistry.ts
2466
1656
  var LocatorRegistryInternal = class {
2467
1657
  constructor(page) {
2468
1658
  this.page = page;
@@ -2796,98 +1986,8 @@ var createRegistryWithAccessors = (page) => {
2796
1986
  return { registry, add, getLocator, getNestedLocator, getLocatorSchema };
2797
1987
  };
2798
1988
 
2799
- // src/basePageV1toV2.ts
2800
- var BasePageV1toV2 = class {
2801
- /** Provides Playwright page methods */
2802
- page;
2803
- /** Playwright TestInfo contains information about currently running test, available to any test function */
2804
- testInfo;
2805
- /** Selectors can be used to install custom selector engines.*/
2806
- selector;
2807
- /** The base URL of the Page Object Class */
2808
- baseUrl;
2809
- /** The URL path of the Page Object Class */
2810
- urlPath;
2811
- /** The full URL of the Page Object Class */
2812
- fullUrl;
2813
- /** The name of the Page Object Class */
2814
- pocName;
2815
- /** The Page Object Class' PlaywrightReportLogger instance, prefixed with its name. Log levels: debug, info, warn, and error. */
2816
- log;
2817
- /** The SessionStorage class provides methods for setting and getting session storage data in Playwright.*/
2818
- sessionStorage;
2819
- /**
2820
- * locators:
2821
- * An instance of GetLocatorBase that handles schema management and provides getLocatorSchema calls.
2822
- * Initially, LocatorSubstring is undefined. Once getLocatorSchema(path) is called,
2823
- * we get a chainable object typed with LocatorSubstring = P.
2824
- */
2825
- locators;
2826
- /**
2827
- * v2 locator registry and accessors, used for migration to the fluent registry DSL.
2828
- */
2829
- locatorRegistry;
2830
- add;
2831
- getLocator;
2832
- getLocatorSchema;
2833
- getNestedLocator;
2834
- constructor(page, testInfo, baseUrl, urlPath, pocName, pwrl, locatorSubstring) {
2835
- this.page = page;
2836
- this.testInfo = testInfo;
2837
- this.selector = import_test4.selectors;
2838
- this.baseUrl = baseUrl;
2839
- this.urlPath = urlPath;
2840
- this.fullUrl = this.constructFullUrl(baseUrl, urlPath);
2841
- this.pocName = pocName;
2842
- this.log = pwrl.getNewChildLogger(pocName);
2843
- const classDeprecationMessage = "[POMWright] BasePageV1toV2 is a transitional bridge and will be removed in 2.0.0. Prefer PageObject for new work and migrate existing classes to PageObject.";
2844
- warnDeprecationOncePerTest(`${this.constructor.name}-class-deprecation`, classDeprecationMessage, this.log);
2845
- const { registry, add, getLocator, getNestedLocator, getLocatorSchema } = createRegistryWithAccessors(page);
2846
- this.locatorRegistry = registry;
2847
- this.add = add;
2848
- this.getLocator = getLocator;
2849
- this.getLocatorSchema = getLocatorSchema;
2850
- this.getNestedLocator = getNestedLocator;
2851
- this.defineLocators();
2852
- this.locators = new GetLocatorBase(
2853
- this,
2854
- this.log.getNewChildLogger("GetLocator"),
2855
- locatorSubstring
2856
- );
2857
- const initLocatorSchemasDeprecationMessage = "[POMWright] initLocatorSchemas is deprecated and will be removed in 2.0.0. Define locators with the v2 registry DSL in defineLocators instead.";
2858
- warnDeprecationOncePerTest(
2859
- `${this.constructor.name}-initLocatorSchemas-deprecation`,
2860
- initLocatorSchemasDeprecationMessage,
2861
- this.log
2862
- );
2863
- this.initLocatorSchemas();
2864
- this.sessionStorage = new SessionStorage(this.page, this.pocName);
2865
- }
2866
- /**
2867
- * constructFullUrl:
2868
- * Combines baseUrl and urlPath, handling both strings and RegExps.
2869
- * Ensures a flexible approach to URL matching (string or regex-based).
2870
- */
2871
- constructFullUrl(baseUrl, urlPath) {
2872
- const escapeStringForRegExp = (str) => str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
2873
- if (typeof baseUrl === "string" && typeof urlPath === "string") {
2874
- return `${baseUrl}${urlPath}`;
2875
- }
2876
- if (typeof baseUrl === "string" && urlPath instanceof RegExp) {
2877
- return new RegExp(`^${escapeStringForRegExp(baseUrl)}${urlPath.source}`);
2878
- }
2879
- if (baseUrl instanceof RegExp && typeof urlPath === "string") {
2880
- return new RegExp(`${baseUrl.source}${escapeStringForRegExp(urlPath)}$`);
2881
- }
2882
- if (baseUrl instanceof RegExp && urlPath instanceof RegExp) {
2883
- return new RegExp(`${baseUrl.source}${urlPath.source}`);
2884
- }
2885
- throw new Error("Invalid baseUrl or urlPath types. Expected string or RegExp.");
2886
- }
2887
- };
2888
-
2889
- // srcV2/helpers/navigation.ts
2890
- var import_test5 = require("@playwright/test");
1989
+ // src/helpers/navigation.ts
1990
+ var import_test4 = require("@playwright/test");
2891
1991
  var DEFAULT_WAIT_UNTIL = "load";
2892
1992
  var DEFAULT_LOAD_STATE = "load";
2893
1993
  var Navigation = class {
@@ -2922,7 +2022,7 @@ var Navigation = class {
2922
2022
  if (typeof this.baseUrl !== "string" || typeof this.urlPath !== "string") {
2923
2023
  throw new Error("goto() is not supported when baseUrl or urlPath is a RegExp.");
2924
2024
  }
2925
- await import_test5.test.step(`${this.label}: Navigate to the provided URL or URL Path`, async () => {
2025
+ await import_test4.test.step(`${this.label}: Navigate to the provided URL or URL Path`, async () => {
2926
2026
  const targetUrl = urlPathOrUrl.startsWith("/") ? `${this.baseUrl}${urlPathOrUrl}` : urlPathOrUrl;
2927
2027
  await this.page.goto(targetUrl, { waitUntil });
2928
2028
  });
@@ -2937,242 +2037,55 @@ var Navigation = class {
2937
2037
  }
2938
2038
  const waitUntil = this.resolveWaitUntil(options);
2939
2039
  const fullUrl = this.fullUrl;
2940
- await import_test5.test.step(`${this.label}: Navigate to this Page`, async () => {
2941
- await this.page.goto(fullUrl, { waitUntil });
2942
- await this.executeActions();
2943
- });
2944
- }
2945
- /**
2946
- * Expect to be on this page. Works with both string and RegExp fullUrl values.
2947
- * Uses waitUntil from navigation options when waiting for URL.
2948
- */
2949
- async expectThisPage(options) {
2950
- const waitUntil = this.resolveWaitUntil(options);
2951
- await import_test5.test.step(`${this.label}: Expect this Page`, async () => {
2952
- await this.page.waitForURL(this.fullUrl, { waitUntil });
2953
- await (0, import_test5.expect)(async () => {
2954
- if (this.fullUrl instanceof RegExp) {
2955
- (0, import_test5.expect)(this.page.url(), `expected '${this.fullUrl}', found '${this.page.url()}'`).toMatch(this.fullUrl);
2956
- } else {
2957
- (0, import_test5.expect)(this.page.url(), `expected '${this.fullUrl}', found '${this.page.url()}'`).toBe(this.fullUrl);
2958
- }
2959
- }).toPass();
2960
- await this.executeActions();
2961
- });
2962
- }
2963
- /**
2964
- * Expect to be on any other page (i.e. not this page).
2965
- * Uses waitForLoadState from navigation options before validating URL.
2966
- */
2967
- async expectAnotherPage(options) {
2968
- const waitForLoadState = this.resolveWaitForLoadState(options);
2969
- await import_test5.test.step(`${this.label}: Expect any other Page`, async () => {
2970
- await this.page.waitForLoadState(waitForLoadState);
2971
- if (this.fullUrl instanceof RegExp) {
2972
- await import_test5.expect.poll(async () => this.page.url(), {
2973
- message: `expected url to not match '${this.fullUrl}'`
2974
- }).not.toMatch(this.fullUrl);
2975
- } else {
2976
- await import_test5.expect.poll(async () => this.page.url(), {
2977
- message: `expected url to not be '${this.fullUrl}', found '${this.page.url()}'`
2978
- }).not.toBe(this.fullUrl);
2979
- }
2980
- });
2981
- }
2982
- };
2983
- function createNavigation(page, baseUrl, urlPath, fullUrl, label, actions = null, defaultOptions) {
2984
- const navigation = new Navigation(page, baseUrl, urlPath, fullUrl, label, actions, defaultOptions);
2985
- return navigation;
2986
- }
2987
-
2988
- // srcV2/helpers/sessionStorage.ts
2989
- var import_test6 = require("@playwright/test");
2990
- var SessionStorage2 = class {
2991
- // Initializes the class with a Playwright Page object and an optional label for step titles.
2992
- constructor(page, options = {}) {
2993
- this.page = page;
2994
- this.options = options;
2995
- }
2996
- // Defines an object to hold states to be set in session storage, allowing any value type.
2997
- queuedStates = {};
2998
- // Indicates if the session storage manipulation has been initiated.
2999
- isInitiated = false;
3000
- getStepLabel(methodName) {
3001
- const prefix = this.options.label ? `${this.options.label}.` : "";
3002
- return `${prefix}SessionStorage.${methodName}:`;
3003
- }
3004
- async hasContext() {
3005
- return await this.page.evaluate(() => {
3006
- return typeof window !== "undefined" && window.sessionStorage !== void 0;
3007
- });
3008
- }
3009
- async waitForContextAvailability() {
3010
- try {
3011
- const contextExists = await this.hasContext();
3012
- if (contextExists) {
3013
- return;
3014
- }
3015
- } catch (_e) {
3016
- }
3017
- await new Promise((resolve) => {
3018
- const handler = async (frame) => {
3019
- if (frame !== this.page.mainFrame()) {
3020
- return;
3021
- }
3022
- try {
3023
- const contextExists = await this.hasContext();
3024
- if (!contextExists) {
3025
- return;
3026
- }
3027
- } catch (_e) {
3028
- return;
3029
- }
3030
- this.page.off("framenavigated", handler);
3031
- resolve();
3032
- };
3033
- this.page.on("framenavigated", handler);
3034
- });
3035
- }
3036
- async ensureContext({ waitForContext = false } = {}) {
3037
- try {
3038
- const contextExists = await this.hasContext();
3039
- if (contextExists) {
3040
- return;
3041
- }
3042
- } catch (_e) {
3043
- }
3044
- if (!waitForContext) {
3045
- throw new Error("SessionStorage context is not available.");
3046
- }
3047
- await this.waitForContextAvailability();
3048
- }
3049
- /** Writes states to session storage. Accepts an object with key-value pairs representing the states. */
3050
- async writeToSessionStorage(states) {
3051
- await this.page.evaluate((storage) => {
3052
- for (const [key, value] of Object.entries(storage)) {
3053
- window.sessionStorage.setItem(key, JSON.stringify(value));
3054
- }
3055
- }, states);
3056
- }
3057
- /** Reads all states from session storage and returns them as an object. */
3058
- async readFromSessionStorage() {
3059
- const storage = await this.page.evaluate(() => {
3060
- const storage2 = {};
3061
- for (let i = 0; i < sessionStorage.length; i++) {
3062
- const key = sessionStorage.key(i);
3063
- if (key !== null) {
3064
- const item = sessionStorage.getItem(key);
3065
- try {
3066
- storage2[key] = item ? JSON.parse(item) : null;
3067
- } catch (_e) {
3068
- storage2[key] = item;
3069
- }
3070
- }
3071
- }
3072
- return storage2;
3073
- });
3074
- return storage;
3075
- }
3076
- /**
3077
- * Sets the specified states in session storage.
3078
- * Optionally waits for the next main-frame navigation to establish a valid context before writing,
3079
- * and reloads the page after setting the data.
3080
- *
3081
- * Parameters:
3082
- * states: Object representing the states to set in session storage.
3083
- * reload: Boolean indicating whether to reload the page after setting the session storage data.
3084
- * waitForContext: Boolean indicating whether to wait for a main-frame navigation and a valid context.
3085
- */
3086
- async set(states, options = {}) {
3087
- await import_test6.test.step(this.getStepLabel("set"), async () => {
3088
- await this.ensureContext({ waitForContext: options.waitForContext });
3089
- await this.writeToSessionStorage(states);
3090
- if (options.reload) {
3091
- await this.page.reload();
3092
- }
3093
- });
3094
- }
3095
- /**
3096
- * Queues states to be set in the sessionStorage before the next navigation occurs.
3097
- * Handles different scenarios based on multiple calls made before the navigation occurs.
3098
- *
3099
- * 1. No Context, Single Call: Queues and sets states upon the next navigation.
3100
- * 2. No Context, Multiple Calls: Merges states from multiple calls and sets them upon the next navigation.
3101
- * 3. With Context: Still queues until the next navigation.
3102
- *
3103
- * Parameters:
3104
- * states: Object representing the states to queue for setting in session storage.
3105
- */
3106
- async setOnNextNavigation(states) {
3107
- this.queuedStates = { ...this.queuedStates, ...states };
3108
- const populateStorage = async () => {
3109
- await import_test6.test.step(this.getStepLabel("setOnNextNavigation"), async () => {
3110
- await this.writeToSessionStorage(this.queuedStates);
3111
- });
3112
- this.queuedStates = {};
3113
- };
3114
- if (!this.isInitiated) {
3115
- this.isInitiated = true;
3116
- const handler = async (frame) => {
3117
- if (frame !== this.page.mainFrame()) {
3118
- return;
3119
- }
3120
- await populateStorage();
3121
- this.page.off("framenavigated", handler);
3122
- this.isInitiated = false;
3123
- };
3124
- this.page.on("framenavigated", handler);
3125
- }
2040
+ await import_test4.test.step(`${this.label}: Navigate to this Page`, async () => {
2041
+ await this.page.goto(fullUrl, { waitUntil });
2042
+ await this.executeActions();
2043
+ });
3126
2044
  }
3127
- async get(keys, options = {}) {
3128
- let result = {};
3129
- await import_test6.test.step(this.getStepLabel("get"), async () => {
3130
- await this.ensureContext(options);
3131
- const allData = await this.readFromSessionStorage();
3132
- if (keys && keys.length > 0) {
3133
- for (const key of keys) {
3134
- if (Object.hasOwn(allData, key)) {
3135
- const value = allData[key];
3136
- if (value !== void 0) {
3137
- result[key] = value;
3138
- }
3139
- }
2045
+ /**
2046
+ * Expect to be on this page. Works with both string and RegExp fullUrl values.
2047
+ * Uses waitUntil from navigation options when waiting for URL.
2048
+ */
2049
+ async expectThisPage(options) {
2050
+ const waitUntil = this.resolveWaitUntil(options);
2051
+ await import_test4.test.step(`${this.label}: Expect this Page`, async () => {
2052
+ await this.page.waitForURL(this.fullUrl, { waitUntil });
2053
+ await (0, import_test4.expect)(async () => {
2054
+ if (this.fullUrl instanceof RegExp) {
2055
+ (0, import_test4.expect)(this.page.url(), `expected '${this.fullUrl}', found '${this.page.url()}'`).toMatch(this.fullUrl);
2056
+ } else {
2057
+ (0, import_test4.expect)(this.page.url(), `expected '${this.fullUrl}', found '${this.page.url()}'`).toBe(this.fullUrl);
3140
2058
  }
3141
- } else {
3142
- result = allData;
3143
- }
2059
+ }).toPass();
2060
+ await this.executeActions();
3144
2061
  });
3145
- return result;
3146
2062
  }
3147
- async clear(keyOrOptions, options = {}) {
3148
- const { keys, waitForContext } = (() => {
3149
- if (Array.isArray(keyOrOptions)) {
3150
- return { keys: keyOrOptions, waitForContext: options.waitForContext };
3151
- }
3152
- if (typeof keyOrOptions === "string") {
3153
- return { keys: [keyOrOptions], waitForContext: options.waitForContext };
3154
- }
3155
- if (keyOrOptions) {
3156
- return { keys: void 0, waitForContext: keyOrOptions.waitForContext };
3157
- }
3158
- return { keys: void 0, waitForContext: options.waitForContext };
3159
- })();
3160
- await import_test6.test.step(this.getStepLabel("clear"), async () => {
3161
- await this.ensureContext({ waitForContext });
3162
- if (!keys || keys.length === 0) {
3163
- await this.page.evaluate(() => sessionStorage.clear());
3164
- return;
2063
+ /**
2064
+ * Expect to be on any other page (i.e. not this page).
2065
+ * Uses waitForLoadState from navigation options before validating URL.
2066
+ */
2067
+ async expectAnotherPage(options) {
2068
+ const waitForLoadState = this.resolveWaitForLoadState(options);
2069
+ await import_test4.test.step(`${this.label}: Expect any other Page`, async () => {
2070
+ await this.page.waitForLoadState(waitForLoadState);
2071
+ if (this.fullUrl instanceof RegExp) {
2072
+ await import_test4.expect.poll(async () => this.page.url(), {
2073
+ message: `expected url to not match '${this.fullUrl}'`
2074
+ }).not.toMatch(this.fullUrl);
2075
+ } else {
2076
+ await import_test4.expect.poll(async () => this.page.url(), {
2077
+ message: `expected url to not be '${this.fullUrl}', found '${this.page.url()}'`
2078
+ }).not.toBe(this.fullUrl);
3165
2079
  }
3166
- await this.page.evaluate((keysToClear) => {
3167
- for (const key of keysToClear) {
3168
- sessionStorage.removeItem(key);
3169
- }
3170
- }, keys);
3171
2080
  });
3172
2081
  }
3173
2082
  };
2083
+ function createNavigation(page, baseUrl, urlPath, fullUrl, label, actions = null, defaultOptions) {
2084
+ const navigation = new Navigation(page, baseUrl, urlPath, fullUrl, label, actions, defaultOptions);
2085
+ return navigation;
2086
+ }
3174
2087
 
3175
- // srcV2/pageObject.ts
2088
+ // src/pageObject.ts
3176
2089
  var PageObject = class {
3177
2090
  page;
3178
2091
  baseUrl;
@@ -3199,7 +2112,7 @@ var PageObject = class {
3199
2112
  this.getLocator = getLocator;
3200
2113
  this.getLocatorSchema = getLocatorSchema;
3201
2114
  this.getNestedLocator = getNestedLocator;
3202
- this.sessionStorage = new SessionStorage2(page, { label });
2115
+ this.sessionStorage = new SessionStorage(page, { label });
3203
2116
  this.defineLocators();
3204
2117
  this.navigation = createNavigation(
3205
2118
  this.page,
@@ -3228,208 +2141,8 @@ var PageObject = class {
3228
2141
  throw new Error("Invalid baseUrl or urlPath types. Expected string or RegExp.");
3229
2142
  }
3230
2143
  };
3231
-
3232
- // srcV2/fixture/base.fixtures.ts
3233
- var import_test7 = require("@playwright/test");
3234
-
3235
- // srcV2/helpers/playwrightReportLogger.ts
3236
- var PlaywrightReportLogger = class _PlaywrightReportLogger {
3237
- // Initializes the logger with shared log level, log entries, and a context name.
3238
- constructor(sharedLogLevel, sharedLogEntry, contextName) {
3239
- this.sharedLogLevel = sharedLogLevel;
3240
- this.sharedLogEntry = sharedLogEntry;
3241
- this.contextName = contextName;
3242
- }
3243
- contextName;
3244
- logLevels = ["debug", "info", "warn", "error"];
3245
- /**
3246
- * Creates a child logger with a new contextual name, sharing the same log level and log entries with the parent logger.
3247
- *
3248
- * The root loggers log "level" is referenced by all child loggers and their child loggers and so on...
3249
- * Changing the log "level" of one, will change it for all.
3250
- */
3251
- getNewChildLogger(prefix) {
3252
- return new _PlaywrightReportLogger(this.sharedLogLevel, this.sharedLogEntry, `${this.contextName} -> ${prefix}`);
3253
- }
3254
- /**
3255
- * Logs a message with the specified log level, prefix, and additional arguments if the current log level permits.
3256
- */
3257
- // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
3258
- log(level, message, ...args) {
3259
- const logLevelIndex = this.logLevels.indexOf(level);
3260
- if (logLevelIndex < this.getCurrentLogLevelIndex()) {
3261
- return;
3262
- }
3263
- this.sharedLogEntry.push({
3264
- timestamp: /* @__PURE__ */ new Date(),
3265
- logLevel: level,
3266
- prefix: this.contextName,
3267
- message: `${message}
3268
-
3269
- ${args.join("\n\n")}`
3270
- });
3271
- }
3272
- /**
3273
- * Logs a debug-level message with the specified message and arguments.
3274
- */
3275
- // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
3276
- debug(message, ...args) {
3277
- this.log("debug", message, ...args);
3278
- }
3279
- /**
3280
- * Logs a info-level message with the specified message and arguments.
3281
- */
3282
- // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
3283
- info(message, ...args) {
3284
- this.log("info", message, ...args);
3285
- }
3286
- /**
3287
- * Logs a warn-level message with the specified message and arguments.
3288
- */
3289
- // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
3290
- warn(message, ...args) {
3291
- this.log("warn", message, ...args);
3292
- }
3293
- /**
3294
- * Logs a error-level message with the specified message and arguments.
3295
- */
3296
- // biome-ignore lint/suspicious/noExplicitAny: logger accepts arbitrary payloads for debug output.
3297
- error(message, ...args) {
3298
- this.log("error", message, ...args);
3299
- }
3300
- /**
3301
- * Sets the current log level to the specified level during runTime.
3302
- */
3303
- setLogLevel(level) {
3304
- this.sharedLogLevel.current = level;
3305
- }
3306
- /**
3307
- * Retrieves the current log level during runtime.
3308
- */
3309
- getCurrentLogLevel() {
3310
- return this.sharedLogLevel.current;
3311
- }
3312
- /**
3313
- * Retrieves the index of the current log level in the logLevels array during runtime.
3314
- */
3315
- getCurrentLogLevelIndex() {
3316
- return this.logLevels.indexOf(this.sharedLogLevel.current);
3317
- }
3318
- /**
3319
- * Resets the current log level to the initial level during runtime.
3320
- */
3321
- resetLogLevel() {
3322
- this.sharedLogLevel.current = this.sharedLogLevel.initial;
3323
- }
3324
- /**
3325
- * Checks if the input log level is equal to the current log level of the PlaywrightReportLogger instance.
3326
- */
3327
- isCurrentLogLevel(level) {
3328
- return this.sharedLogLevel.current === level;
3329
- }
3330
- /**
3331
- * Returns 'true' if the "level" parameter provided has an equal or greater index than the current logLevel.
3332
- */
3333
- isLogLevelEnabled(level) {
3334
- const logLevelIndex = this.logLevels.indexOf(level);
3335
- if (logLevelIndex < this.getCurrentLogLevelIndex()) {
3336
- return false;
3337
- }
3338
- return true;
3339
- }
3340
- /**
3341
- * Attaches the recorded log entries to the Playwright HTML report in a sorted and formatted manner.
3342
- */
3343
- attachLogsToTest(testInfo) {
3344
- this.sharedLogEntry.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
3345
- for (const log of this.sharedLogEntry) {
3346
- const printTime = log.timestamp.toLocaleTimeString("nb-NO", {
3347
- hour: "2-digit",
3348
- minute: "2-digit",
3349
- second: "2-digit"
3350
- });
3351
- const printDate = log.timestamp.toLocaleDateString("nb-NO", {
3352
- day: "2-digit",
3353
- month: "2-digit",
3354
- year: "numeric"
3355
- });
3356
- const printLogLevel = `${log.logLevel.toUpperCase()}`;
3357
- const printPrefix = log.prefix ? `: [${log.prefix}]` : "";
3358
- let messageBody = "";
3359
- let messageContentType = "";
3360
- try {
3361
- const parsedMessage = JSON.parse(log.message);
3362
- messageContentType = "application/json";
3363
- messageBody = JSON.stringify(parsedMessage, null, 2);
3364
- } catch (_error) {
3365
- messageContentType = "text/plain";
3366
- messageBody = log.message;
3367
- }
3368
- testInfo.attach(`${printTime} ${printDate} - ${printLogLevel} ${printPrefix}`, {
3369
- contentType: messageContentType,
3370
- body: Buffer.from(messageBody)
3371
- });
3372
- }
3373
- }
3374
- };
3375
-
3376
- // srcV2/fixture/base.fixtures.ts
3377
- var test5 = import_test7.test.extend({
3378
- // biome-ignore lint/correctness/noEmptyPattern: Playwright does not support the use of _
3379
- log: async ({}, use, testInfo) => {
3380
- const contextName = "TestCase";
3381
- const sharedLogEntry = [];
3382
- const sharedLogLevel = testInfo.retry === 0 ? { current: "warn", initial: "warn" } : { current: "debug", initial: "debug" };
3383
- const log = new PlaywrightReportLogger(sharedLogLevel, sharedLogEntry, contextName);
3384
- await use(log);
3385
- log.attachLogsToTest(testInfo);
3386
- }
3387
- });
3388
-
3389
- // srcV2/helpers/stepDecorator.ts
3390
- var import_test8 = require("@playwright/test");
3391
- var isMethodDecoratorArgs = (args) => args.length === 3 && typeof args[0] === "object" && (typeof args[1] === "string" || typeof args[1] === "symbol");
3392
- var isStage3MethodDecoratorArgs = (args) => args.length === 2 && typeof args[0] === "function" && args[1] !== null && typeof args[1] === "object";
3393
- var normalizeStepArguments = (args) => {
3394
- const [titleOrOptions, maybeOptions] = args;
3395
- const title = typeof titleOrOptions === "string" ? titleOrOptions : void 0;
3396
- const options = typeof titleOrOptions === "string" ? maybeOptions : titleOrOptions;
3397
- return { title, options };
3398
- };
3399
- var createWrappedMethod = (original, methodName, title, options) => function(...methodArgs) {
3400
- const rawClassName = this.constructor?.name ?? "";
3401
- const className = rawClassName && rawClassName !== "Object" ? rawClassName : "Anonymous";
3402
- const resolvedTitle = title ?? `${className}.${String(methodName)}`;
3403
- return import_test8.test.step(resolvedTitle, () => original.apply(this, methodArgs), options);
3404
- };
3405
- var createStepDecorator = ({ title, options }) => (valueOrTarget, contextOrKey, descriptor) => {
3406
- if (typeof valueOrTarget === "function" && isStage3MethodDecoratorArgs([valueOrTarget, contextOrKey])) {
3407
- const [original2, context] = [valueOrTarget, contextOrKey];
3408
- return createWrappedMethod(original2, context.name, title, options);
3409
- }
3410
- if (!descriptor || typeof descriptor.value !== "function") {
3411
- throw new Error("@step decorator can only be applied to methods.");
3412
- }
3413
- const original = descriptor.value;
3414
- descriptor.value = createWrappedMethod(original, contextOrKey, title, options);
3415
- return descriptor;
3416
- };
3417
- function step(...args) {
3418
- if (isStage3MethodDecoratorArgs(args)) {
3419
- return createStepDecorator(normalizeStepArguments([]))(...args);
3420
- }
3421
- if (isMethodDecoratorArgs(args)) {
3422
- return createStepDecorator(normalizeStepArguments([]))(...args);
3423
- }
3424
- return createStepDecorator(normalizeStepArguments(args));
3425
- }
3426
2144
  // Annotate the CommonJS export names for ESM import in node:
3427
2145
  0 && (module.exports = {
3428
- BaseApi,
3429
- BasePage,
3430
- BasePageV1toV2,
3431
- GetByMethod,
3432
- GetLocatorBase,
3433
2146
  PageObject,
3434
2147
  PlaywrightReportLogger,
3435
2148
  SessionStorage,