automation_model 1.0.60 → 1.0.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/auto_page.d.ts +3 -0
- package/bin/auto_page.js +25 -2
- package/bin/browser_manager.d.ts +16 -0
- package/bin/environment.d.ts +4 -0
- package/bin/index.d.ts +6 -0
- package/bin/init_browser.d.ts +3 -0
- package/bin/init_browser.js +3 -1
- package/bin/locator.d.ts +21 -0
- package/bin/stable_browser.d.ts +61 -0
- package/bin/stable_browser.js +49 -27
- package/bin/table_analyze.d.ts +1 -0
- package/bin/test_context.d.ts +6 -0
- package/package.json +9 -4
package/bin/auto_page.js
CHANGED
|
@@ -12,12 +12,35 @@ const navigate = async (path = "") => {
|
|
|
12
12
|
await context.stable.goto(url);
|
|
13
13
|
await context.stable.waitForPageLoad();
|
|
14
14
|
};
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const _findEmptyFolder = (folder) => {
|
|
16
|
+
if (!folder) {
|
|
17
|
+
folder = "./runs";
|
|
18
|
+
}
|
|
19
|
+
if (!fs.existsSync(folder)) {
|
|
20
|
+
fs.mkdirSync(folder);
|
|
21
|
+
}
|
|
22
|
+
let nextIndex = 1;
|
|
23
|
+
while (fs.existsSync(path.join(folder, nextIndex))) {
|
|
24
|
+
nextIndex++;
|
|
25
|
+
}
|
|
26
|
+
return path.join(folder, nextIndex);
|
|
27
|
+
};
|
|
28
|
+
const initContext = async (path, doNavigate = true, headless = false, world = null) => {
|
|
17
29
|
if (context) {
|
|
18
30
|
return context;
|
|
19
31
|
}
|
|
20
32
|
context = await getContext(null, headless);
|
|
33
|
+
|
|
34
|
+
if (world) {
|
|
35
|
+
world.screenshot = true;
|
|
36
|
+
const reportFolder = _findEmptyFolder();
|
|
37
|
+
if (world.attach) {
|
|
38
|
+
world.attach(reportFolder, { mediaType: "text/plain" });
|
|
39
|
+
}
|
|
40
|
+
world.screenshotPath = reportFolder;
|
|
41
|
+
context.reportFolder = reportFolder;
|
|
42
|
+
}
|
|
43
|
+
|
|
21
44
|
if (doNavigate) {
|
|
22
45
|
await navigate(path);
|
|
23
46
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const browserManager: BrowserManager;
|
|
2
|
+
declare class BrowserManager {
|
|
3
|
+
browsers: any[];
|
|
4
|
+
closeAll(): Promise<void>;
|
|
5
|
+
closeBrowser(browser: any): Promise<void>;
|
|
6
|
+
createBrowser(headless?: boolean): Promise<Browser>;
|
|
7
|
+
getBrowser(headless?: boolean): Promise<any>;
|
|
8
|
+
}
|
|
9
|
+
declare class Browser {
|
|
10
|
+
browser: any;
|
|
11
|
+
context: any;
|
|
12
|
+
page: any;
|
|
13
|
+
init(headless?: boolean): Promise<void>;
|
|
14
|
+
close(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
package/bin/index.d.ts
ADDED
package/bin/init_browser.js
CHANGED
|
@@ -17,6 +17,7 @@ const getContext = async function (environment = null, headless = false, logger
|
|
|
17
17
|
context.playContext = browser.context;
|
|
18
18
|
context.page = browser.page;
|
|
19
19
|
context.environment = environment;
|
|
20
|
+
|
|
20
21
|
context.stable = new StableBrowser(context.browser, context.page, logger);
|
|
21
22
|
await _initCookies(context);
|
|
22
23
|
return context;
|
|
@@ -48,7 +49,8 @@ const initEnvoronment = function () {
|
|
|
48
49
|
const envObject = JSON.parse(data);
|
|
49
50
|
//console.log("envObject", envObject);
|
|
50
51
|
Object.assign(environment, envObject);
|
|
51
|
-
console.log("env", environment);
|
|
52
|
+
//console.log("env", environment);
|
|
53
|
+
console.log("Base url: " + environment.baseUrl);
|
|
52
54
|
} catch (err) {
|
|
53
55
|
console.error("Error reading env.json", err);
|
|
54
56
|
}
|
package/bin/locator.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare function processTableQuary(table: any, quary: any): {
|
|
2
|
+
cells: any[];
|
|
3
|
+
error?: undefined;
|
|
4
|
+
rect?: undefined;
|
|
5
|
+
} | {
|
|
6
|
+
error: string;
|
|
7
|
+
cells?: undefined;
|
|
8
|
+
rect?: undefined;
|
|
9
|
+
} | {
|
|
10
|
+
cells: any[];
|
|
11
|
+
rect: any;
|
|
12
|
+
error?: undefined;
|
|
13
|
+
};
|
|
14
|
+
declare const selectors: null;
|
|
15
|
+
declare const tableSelector: null;
|
|
16
|
+
declare function merge(rec1: any, rec2: any): {
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export class StableBrowser {
|
|
2
|
+
constructor(browser: any, page: any, logger: any);
|
|
3
|
+
browser: any;
|
|
4
|
+
page: any;
|
|
5
|
+
logger: any;
|
|
6
|
+
goto(url: any): Promise<void>;
|
|
7
|
+
_fixUsingParams(text: any, _params: any): any;
|
|
8
|
+
_getLocator(locator: any, scope: any, _params: any): any;
|
|
9
|
+
_locateElementByText(scope: any, text1: any, tag1: any, regex?: boolean, _params?: null): Promise<any>;
|
|
10
|
+
_collectLocatorInformation(selectorHierarchy: any, index: number | undefined, scope: any, foundLocators: any, _params: any): Promise<void>;
|
|
11
|
+
_locate(selectors: any, info: any, _params: any, timeout?: number): Promise<any>;
|
|
12
|
+
click(selector: any, _params?: null, options?: {}, world?: null): Promise<{
|
|
13
|
+
log: any[];
|
|
14
|
+
operation: string;
|
|
15
|
+
selector: any;
|
|
16
|
+
}>;
|
|
17
|
+
selectOption(selector: any, values: any, _params?: null, options?: {}, world?: null): Promise<{
|
|
18
|
+
log: any[];
|
|
19
|
+
operation: string;
|
|
20
|
+
selector: any;
|
|
21
|
+
}>;
|
|
22
|
+
fill(selector: any, value: any, enter?: boolean, _params?: null, options?: {}, world?: null): Promise<{
|
|
23
|
+
log: any[];
|
|
24
|
+
operation: string;
|
|
25
|
+
selector: any;
|
|
26
|
+
value: any;
|
|
27
|
+
}>;
|
|
28
|
+
getText(selector: any, _params?: null, options?: {}, info?: {}, world?: null): Promise<any>;
|
|
29
|
+
containsPattern(selector: any, pattern: any, text: any, _params?: null, options?: {}, world?: null): Promise<{
|
|
30
|
+
log: any[];
|
|
31
|
+
operation: string;
|
|
32
|
+
selector: any;
|
|
33
|
+
value: any;
|
|
34
|
+
pattern: any;
|
|
35
|
+
foundText: any;
|
|
36
|
+
}>;
|
|
37
|
+
containsText(selector: any, text: any, _params?: null, options?: {}, world?: null): Promise<{
|
|
38
|
+
log: any[];
|
|
39
|
+
operation: string;
|
|
40
|
+
selector: any;
|
|
41
|
+
value: any;
|
|
42
|
+
foundText: any;
|
|
43
|
+
}>;
|
|
44
|
+
_screenShot(options?: {}, world?: null): Promise<void>;
|
|
45
|
+
verifyElementExistInPage(selector: any, _params?: null, options?: {}, world?: null): Promise<{
|
|
46
|
+
log: any[];
|
|
47
|
+
operation: string;
|
|
48
|
+
selector: any;
|
|
49
|
+
}>;
|
|
50
|
+
analyzeTable(selector: any, query: any, operator: any, value: any, _params?: null, options?: {}, world?: null): Promise<{
|
|
51
|
+
log: any[];
|
|
52
|
+
operation: string;
|
|
53
|
+
selector: any;
|
|
54
|
+
query: any;
|
|
55
|
+
query_fixed: any;
|
|
56
|
+
operator: any;
|
|
57
|
+
value: any;
|
|
58
|
+
}>;
|
|
59
|
+
waitForPageLoad(options?: {}, world?: null): Promise<void>;
|
|
60
|
+
_reportToWorld(world: any, command: any, _params: any): void;
|
|
61
|
+
}
|
package/bin/stable_browser.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import reg_parser from "regex-parser";
|
|
2
2
|
import { expect } from "@playwright/test";
|
|
3
3
|
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
4
5
|
import { getTableCells } from "./table_analyze.js";
|
|
5
6
|
let configuration = null;
|
|
6
7
|
class StableBrowser {
|
|
@@ -186,7 +187,7 @@ class StableBrowser {
|
|
|
186
187
|
throw new Error("failed to locate first element no elements found, " + JSON.stringify(info));
|
|
187
188
|
}
|
|
188
189
|
|
|
189
|
-
async click(selector, _params = null, options = {}) {
|
|
190
|
+
async click(selector, _params = null, options = {}, world = null) {
|
|
190
191
|
const info = {};
|
|
191
192
|
info.log = [];
|
|
192
193
|
info.operation = "click";
|
|
@@ -195,7 +196,7 @@ class StableBrowser {
|
|
|
195
196
|
try {
|
|
196
197
|
let element = await this._locate(selector, info, _params);
|
|
197
198
|
|
|
198
|
-
await this._screenShot(options);
|
|
199
|
+
await this._screenShot(options, world);
|
|
199
200
|
try {
|
|
200
201
|
await element.click({ timeout: 5000 });
|
|
201
202
|
} catch (e) {
|
|
@@ -207,14 +208,14 @@ class StableBrowser {
|
|
|
207
208
|
} catch (e) {
|
|
208
209
|
this.logger.error("click failed " + JSON.stringify(info));
|
|
209
210
|
Object.assign(e, { info: info });
|
|
210
|
-
await this._screenShot(options);
|
|
211
|
+
await this._screenShot(options, world);
|
|
211
212
|
throw e;
|
|
212
213
|
|
|
213
214
|
this.logger.info("click failed, will try next selector");
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
217
|
|
|
217
|
-
async selectOption(selector, values, _params = null, options = {}) {
|
|
218
|
+
async selectOption(selector, values, _params = null, options = {}, world = null) {
|
|
218
219
|
const info = {};
|
|
219
220
|
info.log = [];
|
|
220
221
|
info.operation = "selectOptions";
|
|
@@ -223,7 +224,7 @@ class StableBrowser {
|
|
|
223
224
|
try {
|
|
224
225
|
let element = await this._locate(selector, info, _params);
|
|
225
226
|
|
|
226
|
-
await this._screenShot(options);
|
|
227
|
+
await this._screenShot(options, world);
|
|
227
228
|
try {
|
|
228
229
|
await element.selectOption(values, { timeout: 5000 });
|
|
229
230
|
} catch (e) {
|
|
@@ -235,14 +236,14 @@ class StableBrowser {
|
|
|
235
236
|
} catch (e) {
|
|
236
237
|
this.logger.error("selectOption failed " + JSON.stringify(info));
|
|
237
238
|
Object.assign(e, { info: info });
|
|
238
|
-
await this._screenShot(options);
|
|
239
|
+
await this._screenShot(options, world);
|
|
239
240
|
throw e;
|
|
240
241
|
|
|
241
242
|
this.logger.info("click failed, will try next selector");
|
|
242
243
|
}
|
|
243
244
|
}
|
|
244
245
|
|
|
245
|
-
async fill(selector, value, enter = false, _params = null, options = {}) {
|
|
246
|
+
async fill(selector, value, enter = false, _params = null, options = {}, world = null) {
|
|
246
247
|
const info = {};
|
|
247
248
|
info.log = [];
|
|
248
249
|
info.operation = "fill";
|
|
@@ -250,7 +251,7 @@ class StableBrowser {
|
|
|
250
251
|
info.value = value;
|
|
251
252
|
try {
|
|
252
253
|
let element = await this._locate(selector, info, _params);
|
|
253
|
-
await this._screenShot(options);
|
|
254
|
+
await this._screenShot(options, world);
|
|
254
255
|
await element.fill(value, { timeout: 10000 });
|
|
255
256
|
await element.dispatchEvent("change");
|
|
256
257
|
if (enter) {
|
|
@@ -261,17 +262,17 @@ class StableBrowser {
|
|
|
261
262
|
} catch (e) {
|
|
262
263
|
this.logger.error("fill failed " + JSON.stringify(info));
|
|
263
264
|
Object.assign(e, { info: info });
|
|
264
|
-
await this._screenShot(options);
|
|
265
|
+
await this._screenShot(options, world);
|
|
265
266
|
throw e;
|
|
266
267
|
}
|
|
267
268
|
}
|
|
268
269
|
|
|
269
|
-
async getText(selector, _params = null, options = {}, info = {}) {
|
|
270
|
+
async getText(selector, _params = null, options = {}, info = {}, world = null) {
|
|
270
271
|
if (!info.log) {
|
|
271
272
|
info.log = [];
|
|
272
273
|
}
|
|
273
274
|
let element = await this._locate(selector, info, _params);
|
|
274
|
-
await this._screenShot(options);
|
|
275
|
+
await this._screenShot(options, world);
|
|
275
276
|
try {
|
|
276
277
|
return await element.innerText();
|
|
277
278
|
} catch (e) {
|
|
@@ -279,7 +280,7 @@ class StableBrowser {
|
|
|
279
280
|
return await element.textContent();
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
|
-
async containsPattern(selector, pattern, text, _params = null, options = {}) {
|
|
283
|
+
async containsPattern(selector, pattern, text, _params = null, options = {}, world = null) {
|
|
283
284
|
const info = {};
|
|
284
285
|
info.log = [];
|
|
285
286
|
info.operation = "containsPattern";
|
|
@@ -288,7 +289,7 @@ class StableBrowser {
|
|
|
288
289
|
info.pattern = pattern;
|
|
289
290
|
let foundText = null;
|
|
290
291
|
try {
|
|
291
|
-
foundText = await this.getText(selector, _params, options, info);
|
|
292
|
+
foundText = await this.getText(selector, _params, options, info, world);
|
|
292
293
|
let escapedText = text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
|
293
294
|
pattern = pattern.replace("{text}", escapedText);
|
|
294
295
|
let regex = new RegExp(pattern, "m");
|
|
@@ -301,19 +302,19 @@ class StableBrowser {
|
|
|
301
302
|
this.logger.error("verify element contains text failed " + JSON.stringify(info));
|
|
302
303
|
this.logger.error("found text " + foundText + " pattern " + pattern);
|
|
303
304
|
Object.assign(e, { info: info });
|
|
304
|
-
await this._screenShot(options);
|
|
305
|
+
await this._screenShot(options, world);
|
|
305
306
|
throw e;
|
|
306
307
|
}
|
|
307
308
|
}
|
|
308
309
|
|
|
309
|
-
async containsText(selector, text, _params = null, options = {}) {
|
|
310
|
+
async containsText(selector, text, _params = null, options = {}, world = null) {
|
|
310
311
|
const info = {};
|
|
311
312
|
info.log = [];
|
|
312
313
|
info.operation = "containsText";
|
|
313
314
|
info.selector = selector;
|
|
314
315
|
info.value = text;
|
|
315
316
|
try {
|
|
316
|
-
let foundText = await this.getText(selector, _params, options, info);
|
|
317
|
+
let foundText = await this.getText(selector, _params, options, info, world);
|
|
317
318
|
if (!foundText.includes(text)) {
|
|
318
319
|
info.foundText = foundText;
|
|
319
320
|
throw new Error("element doesn't contain text " + text);
|
|
@@ -322,16 +323,31 @@ class StableBrowser {
|
|
|
322
323
|
} catch (e) {
|
|
323
324
|
this.logger.error("verify element contains text failed " + JSON.stringify(info));
|
|
324
325
|
Object.assign(e, { info: info });
|
|
325
|
-
await this._screenShot(options);
|
|
326
|
+
await this._screenShot(options, world);
|
|
326
327
|
throw e;
|
|
327
328
|
}
|
|
328
329
|
}
|
|
329
|
-
async _screenShot(options = {}) {
|
|
330
|
-
if (
|
|
330
|
+
async _screenShot(options = {}, world = null) {
|
|
331
|
+
if (world && world.attach && world.screenshot && world.screenshotPath) {
|
|
332
|
+
if (!fs.existsSync(world.screenshotPath)) {
|
|
333
|
+
fs.mkdirSync(world.screenshotPath, { recursive: true });
|
|
334
|
+
}
|
|
335
|
+
let nextIndex = 1;
|
|
336
|
+
while (fs.existsSync(path.join(world.screenshotPath, nextIndex + ".png"))) {
|
|
337
|
+
nextIndex++;
|
|
338
|
+
}
|
|
339
|
+
await this.page.screenshot({ path: path.join(world.screenshotPath, nextIndex + ".png") });
|
|
340
|
+
await world.attach(
|
|
341
|
+
{ path: world.screenshotPath },
|
|
342
|
+
{
|
|
343
|
+
mediaType: "application/json",
|
|
344
|
+
}
|
|
345
|
+
);
|
|
346
|
+
} else if (options.screenshot) {
|
|
331
347
|
await this.page.screenshot({ path: options.screenshotPath });
|
|
332
348
|
}
|
|
333
349
|
}
|
|
334
|
-
async verifyElementExistInPage(selector, _params = null, options = {}) {
|
|
350
|
+
async verifyElementExistInPage(selector, _params = null, options = {}, world = null) {
|
|
335
351
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
336
352
|
const info = {};
|
|
337
353
|
info.log = [];
|
|
@@ -339,17 +355,17 @@ class StableBrowser {
|
|
|
339
355
|
info.selector = selector;
|
|
340
356
|
try {
|
|
341
357
|
const element = await this._locate(selector, info, _params);
|
|
342
|
-
await this._screenShot(options);
|
|
358
|
+
await this._screenShot(options, world);
|
|
343
359
|
await expect(element).toHaveCount(1, { timeout: 10000 });
|
|
344
360
|
return info;
|
|
345
361
|
} catch (e) {
|
|
346
362
|
this.logger.error("verify failed " + JSON.stringify(info));
|
|
347
363
|
Object.assign(e, { info: info });
|
|
348
|
-
await this._screenShot(options);
|
|
364
|
+
await this._screenShot(options, world);
|
|
349
365
|
throw e;
|
|
350
366
|
}
|
|
351
367
|
}
|
|
352
|
-
async analyzeTable(selector, query, operator, value, _params = null, options = {}) {
|
|
368
|
+
async analyzeTable(selector, query, operator, value, _params = null, options = {}, world = null) {
|
|
353
369
|
const info = {};
|
|
354
370
|
info.log = [];
|
|
355
371
|
info.operation = "analyzeTable";
|
|
@@ -361,7 +377,7 @@ class StableBrowser {
|
|
|
361
377
|
info.value = value;
|
|
362
378
|
try {
|
|
363
379
|
let table = await this._locate(selector, info, _params);
|
|
364
|
-
await this._screenShot(options);
|
|
380
|
+
await this._screenShot(options, world);
|
|
365
381
|
const cells = await getTableCells(this.page, table, query, info);
|
|
366
382
|
|
|
367
383
|
if (cells.error) {
|
|
@@ -437,11 +453,11 @@ class StableBrowser {
|
|
|
437
453
|
} catch (e) {
|
|
438
454
|
this.logger.error("analyzeTable failed " + JSON.stringify(info));
|
|
439
455
|
Object.assign(e, { info: info });
|
|
440
|
-
await this._screenShot(options);
|
|
456
|
+
await this._screenShot(options, world);
|
|
441
457
|
throw e;
|
|
442
458
|
}
|
|
443
459
|
}
|
|
444
|
-
async waitForPageLoad(options = {}) {
|
|
460
|
+
async waitForPageLoad(options = {}, world = null) {
|
|
445
461
|
let timeout = 10000;
|
|
446
462
|
if (!configuration) {
|
|
447
463
|
try {
|
|
@@ -473,7 +489,13 @@ class StableBrowser {
|
|
|
473
489
|
console.log("waitForPageLoad error, ignored");
|
|
474
490
|
}
|
|
475
491
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
476
|
-
await this._screenShot(options);
|
|
492
|
+
await this._screenShot(options, world);
|
|
493
|
+
}
|
|
494
|
+
_reportToWorld(world, command, _params) {
|
|
495
|
+
if (!world || !world.attach) {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
world.attach({ command: command, params: _params });
|
|
477
499
|
}
|
|
478
500
|
}
|
|
479
501
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function getTableCells(page: any, element: any, tableSelector: any, info?: {}): Promise<any>;
|
package/package.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "automation_model",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.62",
|
|
4
4
|
"description": "An automation infrastructure module to be use for generative AI automation projects.",
|
|
5
5
|
"main": "bin/index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"types": "bin/index.d.ts",
|
|
7
8
|
"directories": {
|
|
8
9
|
"lib": "lib"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
|
-
"pack": "mkdir build && mkdir build/bin && cp ./src/auto_page.js ./build/bin/auto_page.js && cp ./src/environment.js ./build/bin/environment.js && cp ./src/browser_manager.js ./build/bin/browser_manager.js && cp ./src/test_context.js ./build/bin/test_context.js && cp ./src/init_browser.js ./build/bin/init_browser.js && cp ./src/stable_browser.js ./build/bin/stable_browser.js && cp ./src/index.js ./build/bin/index.js && cp ./package.json ./build/package.json && cp ./src/table_analyze.js ./build/bin/table_analyze.js && cp ./src/locator.js ./build/bin/locator.js",
|
|
12
|
-
"clean": "rm -rf ./build",
|
|
12
|
+
"pack": "npm run types && mkdir build && mkdir build/bin && cp ./src/auto_page.js ./build/bin/auto_page.js && cp ./src/environment.js ./build/bin/environment.js && cp ./src/browser_manager.js ./build/bin/browser_manager.js && cp ./src/test_context.js ./build/bin/test_context.js && cp ./src/init_browser.js ./build/bin/init_browser.js && cp ./src/stable_browser.js ./build/bin/stable_browser.js && cp ./src/index.js ./build/bin/index.js && cp ./package.json ./build/package.json && cp ./src/table_analyze.js ./build/bin/table_analyze.js && cp ./src/locator.js ./build/bin/locator.js && cp ./types/src/*.ts ./build/bin",
|
|
13
|
+
"clean": "rm -rf ./build && rm -rf ./types",
|
|
13
14
|
"build": "npm run clean && npm run pack",
|
|
14
|
-
"test": "node ./tests/launch_page.js"
|
|
15
|
+
"test": "node ./tests/launch_page.js",
|
|
16
|
+
"types": "npx tsc --declaration --allowJs --emitDeclarationOnly --outDir types"
|
|
15
17
|
},
|
|
16
18
|
"author": "",
|
|
17
19
|
"license": "ISC",
|
|
@@ -19,5 +21,8 @@
|
|
|
19
21
|
"@playwright/test": "^1.35.0",
|
|
20
22
|
"playwright": "^1.33.0",
|
|
21
23
|
"regex-parser": "^2.2.11"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"typescript": "^5.2.2"
|
|
22
27
|
}
|
|
23
28
|
}
|