@rich-automation/lotto 0.1.3 → 0.1.5

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.
@@ -2,10 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createBrowserController = void 0;
4
4
  const puppeteer_1 = require("./puppeteer");
5
+ const playwright_1 = require("./playwright");
5
6
  function createBrowserController(name, configs, logger) {
6
7
  switch (name) {
7
8
  case 'puppeteer':
8
9
  return new puppeteer_1.PuppeteerController(configs, logger);
10
+ case 'playwright':
11
+ return new playwright_1.PlaywrightController(configs, logger);
9
12
  }
10
13
  }
11
14
  exports.createBrowserController = createBrowserController;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PlaywrightController = void 0;
13
+ const playwright_1 = require("playwright");
14
+ const deferred_1 = require("../../utils/deferred");
15
+ const playwright_page_1 = require("./playwright.page");
16
+ const constants_1 = require("../../constants");
17
+ class PlaywrightController {
18
+ constructor(configs, logger) {
19
+ this.getBrowser = () => __awaiter(this, void 0, void 0, function* () {
20
+ const p = (0, deferred_1.deferred)();
21
+ if (this.browser) {
22
+ p.resolve(this.browser);
23
+ }
24
+ else {
25
+ let retry = 0;
26
+ const interval = setInterval(() => {
27
+ if (constants_1.CONST.BROWSER_INIT_RETRY_COUNT < retry) {
28
+ clearInterval(interval);
29
+ p.reject(new Error('Browser is not initialized'));
30
+ }
31
+ else if (this.browser) {
32
+ clearInterval(interval);
33
+ p.resolve(this.browser);
34
+ }
35
+ retry++;
36
+ }, constants_1.CONST.BROWSER_INIT_RETRY_TIMEOUT);
37
+ }
38
+ return p.promise;
39
+ });
40
+ this.focus = (pageIndex = -1) => __awaiter(this, void 0, void 0, function* () {
41
+ const browser = yield this.getBrowser();
42
+ const pages = browser.pages();
43
+ if (pages.length === 0) {
44
+ const page = yield browser.newPage();
45
+ return new playwright_page_1.PlaywrightPage(browser, page, this.logger);
46
+ }
47
+ else {
48
+ const isWithinRange = Math.max(0, Math.min(pageIndex, pages.length - 1)) === pageIndex;
49
+ const page = pages.at(isWithinRange ? pageIndex : -1);
50
+ if (!page)
51
+ throw new Error('Page is not found');
52
+ return new playwright_page_1.PlaywrightPage(browser, page, this.logger);
53
+ }
54
+ });
55
+ this.close = () => __awaiter(this, void 0, void 0, function* () {
56
+ const browser = yield this.getBrowser();
57
+ return browser.close();
58
+ });
59
+ this.cleanPages = (remainingPageIndex) => __awaiter(this, void 0, void 0, function* () {
60
+ const browser = yield this.getBrowser();
61
+ const pages = browser.pages();
62
+ const promises = pages.map((page, index) => __awaiter(this, void 0, void 0, function* () {
63
+ if (!remainingPageIndex.includes(index)) {
64
+ return page.close();
65
+ }
66
+ }));
67
+ yield Promise.all(promises);
68
+ });
69
+ this.configs = configs;
70
+ this.logger = logger;
71
+ playwright_1.chromium.launch(this.configs).then((browser) => __awaiter(this, void 0, void 0, function* () { return (this.browser = yield browser.newContext()); }));
72
+ }
73
+ }
74
+ exports.PlaywrightController = PlaywrightController;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PlaywrightPage = void 0;
13
+ const deferred_1 = require("../../utils/deferred");
14
+ const lazyRun_1 = require("../../utils/lazyRun");
15
+ class PlaywrightPage {
16
+ constructor(context, page, logger) {
17
+ this.context = context;
18
+ this.page = page;
19
+ this.logger = logger;
20
+ }
21
+ url() {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ return this.page.url();
24
+ });
25
+ }
26
+ goto(url) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ yield this.page.goto(url, { waitUntil: 'load' });
29
+ });
30
+ }
31
+ fill(selector, value) {
32
+ return __awaiter(this, void 0, void 0, function* () {
33
+ yield this.page.type(selector, value.toString());
34
+ });
35
+ }
36
+ click(selector, domDirect = false) {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ if (domDirect) {
39
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
40
+ // @ts-ignore
41
+ yield this.page.evaluate(s => document.querySelector(s).click(), selector);
42
+ yield this.wait(250);
43
+ }
44
+ else {
45
+ yield this.page.click(selector, { timeout: 0 });
46
+ }
47
+ });
48
+ }
49
+ select(selector, value) {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ yield this.page.selectOption(selector, value);
52
+ });
53
+ }
54
+ querySelectorAll(selector, callback) {
55
+ return this.page.$$eval(selector, callback);
56
+ }
57
+ getCookies() {
58
+ return __awaiter(this, void 0, void 0, function* () {
59
+ const cookies = yield this.context.cookies();
60
+ return JSON.stringify(cookies);
61
+ });
62
+ }
63
+ setCookies(cookies) {
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ const cookieParams = JSON.parse(cookies);
66
+ yield this.context.addCookies(cookieParams);
67
+ });
68
+ }
69
+ wait(param) {
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ const p = (0, deferred_1.deferred)();
72
+ if (param === 'idle') {
73
+ yield this.page.waitForNavigation({ waitUntil: 'networkidle' });
74
+ p.resolve();
75
+ }
76
+ if (param === 'load') {
77
+ yield this.page.waitForNavigation({ waitUntil: 'load' });
78
+ p.resolve();
79
+ }
80
+ if (typeof param === 'number') {
81
+ yield (0, lazyRun_1.lazyRun)(() => __awaiter(this, void 0, void 0, function* () { return p.resolve(); }), param);
82
+ }
83
+ return p.promise;
84
+ });
85
+ }
86
+ on(event, callback) {
87
+ this.page.on(event, callback);
88
+ return () => this.page.off(event, callback);
89
+ }
90
+ }
91
+ exports.PlaywrightPage = PlaywrightPage;
@@ -71,7 +71,11 @@ class PuppeteerController {
71
71
  });
72
72
  this.configs = configs;
73
73
  this.logger = logger;
74
- puppeteer_1.default.launch(this.configs).then(browser => (this.browser = browser));
74
+ puppeteer_1.default
75
+ .launch(Object.assign(Object.assign({}, this.configs), { headless: this.configs.headless === true ? 'new' : this.configs.headless }))
76
+ .then((browser) => __awaiter(this, void 0, void 0, function* () {
77
+ this.browser = browser;
78
+ }));
75
79
  }
76
80
  }
77
81
  exports.PuppeteerController = PuppeteerController;
@@ -16,7 +16,6 @@ class PuppeteerPage {
16
16
  constructor(page, logger) {
17
17
  this.page = page;
18
18
  this.logger = logger;
19
- this.page = page;
20
19
  }
21
20
  url() {
22
21
  return __awaiter(this, void 0, void 0, function* () {
@@ -33,13 +32,13 @@ class PuppeteerPage {
33
32
  yield this.page.type(selector, value.toString());
34
33
  });
35
34
  }
36
- click(selector, useWaitForSelector = false) {
37
- var _a;
35
+ click(selector, domDirect = false) {
38
36
  return __awaiter(this, void 0, void 0, function* () {
39
- if (useWaitForSelector) {
40
- const handle = yield this.page.waitForSelector(selector, { timeout: 15000 });
41
- (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug('[PuppeteerPage]', '[click]', 'handle', handle);
42
- handle === null || handle === void 0 ? void 0 : handle.click();
37
+ if (domDirect) {
38
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
39
+ // @ts-ignore
40
+ yield this.page.evaluate(s => document.querySelector(s).click(), selector);
41
+ yield this.wait(250);
43
42
  }
44
43
  else {
45
44
  yield this.page.click(selector);
@@ -29,6 +29,7 @@ const validatePurchaseAvailability_1 = require("./utils/validatePurchaseAvailabi
29
29
  const getCheckWinningLink_1 = require("./utils/getCheckWinningLink");
30
30
  class LottoService {
31
31
  constructor(configs) {
32
+ var _a;
32
33
  this.context = {
33
34
  authenticated: false
34
35
  };
@@ -117,17 +118,7 @@ class LottoService {
117
118
  this.logger.debug('[purchase]', 'click purchase button');
118
119
  yield page.click(selectors_1.SELECTORS.PURCHASE_BTN);
119
120
  this.logger.debug('[purchase]', 'click purchase confirm button');
120
- try {
121
- yield page.click(selectors_1.SELECTORS.PURCHASE_CONFIRM_BTN, true);
122
- }
123
- catch (e) {
124
- this.logger.debug('[purchase]', 'purchase confirm failure', e);
125
- this.logger.debug('[purchase]', 'print node');
126
- yield page.querySelectorAll(selectors_1.SELECTORS.PURCHASE_CONFIRM_BTN, elems => {
127
- this.logger.debug('[purchase]', elems);
128
- });
129
- throw e;
130
- }
121
+ yield page.click(selectors_1.SELECTORS.PURCHASE_CONFIRM_BTN);
131
122
  yield page.wait(1000);
132
123
  // game result
133
124
  this.logger.debug('[purchase]', 'print result');
@@ -146,7 +137,7 @@ class LottoService {
146
137
  return (0, getCheckWinningLink_1.getCheckWinningLink)(round, numbers);
147
138
  };
148
139
  this.logger = new logger_1.default(configs === null || configs === void 0 ? void 0 : configs.logLevel, '[LottoService]');
149
- this.browserController = (0, factory_1.createBrowserController)('puppeteer', Object.assign(Object.assign({ defaultViewport: { width: 1080, height: 1024 } }, configs), { headless: (configs === null || configs === void 0 ? void 0 : configs.headless) === false ? false : 'new' }), this.logger);
140
+ this.browserController = (0, factory_1.createBrowserController)((_a = configs === null || configs === void 0 ? void 0 : configs.controller) !== null && _a !== void 0 ? _a : 'playwright', Object.assign({ defaultViewport: { width: 1080, height: 1024 } }, configs), this.logger);
150
141
  }
151
142
  }
152
143
  exports.LottoService = LottoService;
@@ -1,7 +1,10 @@
1
1
  import { PuppeteerController } from './puppeteer';
2
+ import { PlaywrightController } from './playwright';
2
3
  export function createBrowserController(name, configs, logger) {
3
4
  switch (name) {
4
5
  case 'puppeteer':
5
6
  return new PuppeteerController(configs, logger);
7
+ case 'playwright':
8
+ return new PlaywrightController(configs, logger);
6
9
  }
7
10
  }
@@ -0,0 +1,71 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { chromium } from 'playwright';
11
+ import { deferred } from '../../utils/deferred';
12
+ import { PlaywrightPage } from './playwright.page';
13
+ import { CONST } from '../../constants';
14
+ import {} from '../../logger';
15
+ export class PlaywrightController {
16
+ constructor(configs, logger) {
17
+ this.getBrowser = () => __awaiter(this, void 0, void 0, function* () {
18
+ const p = deferred();
19
+ if (this.browser) {
20
+ p.resolve(this.browser);
21
+ }
22
+ else {
23
+ let retry = 0;
24
+ const interval = setInterval(() => {
25
+ if (CONST.BROWSER_INIT_RETRY_COUNT < retry) {
26
+ clearInterval(interval);
27
+ p.reject(new Error('Browser is not initialized'));
28
+ }
29
+ else if (this.browser) {
30
+ clearInterval(interval);
31
+ p.resolve(this.browser);
32
+ }
33
+ retry++;
34
+ }, CONST.BROWSER_INIT_RETRY_TIMEOUT);
35
+ }
36
+ return p.promise;
37
+ });
38
+ this.focus = (pageIndex = -1) => __awaiter(this, void 0, void 0, function* () {
39
+ const browser = yield this.getBrowser();
40
+ const pages = browser.pages();
41
+ if (pages.length === 0) {
42
+ const page = yield browser.newPage();
43
+ return new PlaywrightPage(browser, page, this.logger);
44
+ }
45
+ else {
46
+ const isWithinRange = Math.max(0, Math.min(pageIndex, pages.length - 1)) === pageIndex;
47
+ const page = pages.at(isWithinRange ? pageIndex : -1);
48
+ if (!page)
49
+ throw new Error('Page is not found');
50
+ return new PlaywrightPage(browser, page, this.logger);
51
+ }
52
+ });
53
+ this.close = () => __awaiter(this, void 0, void 0, function* () {
54
+ const browser = yield this.getBrowser();
55
+ return browser.close();
56
+ });
57
+ this.cleanPages = (remainingPageIndex) => __awaiter(this, void 0, void 0, function* () {
58
+ const browser = yield this.getBrowser();
59
+ const pages = browser.pages();
60
+ const promises = pages.map((page, index) => __awaiter(this, void 0, void 0, function* () {
61
+ if (!remainingPageIndex.includes(index)) {
62
+ return page.close();
63
+ }
64
+ }));
65
+ yield Promise.all(promises);
66
+ });
67
+ this.configs = configs;
68
+ this.logger = logger;
69
+ chromium.launch(this.configs).then((browser) => __awaiter(this, void 0, void 0, function* () { return (this.browser = yield browser.newContext()); }));
70
+ }
71
+ }
@@ -0,0 +1,87 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { deferred } from '../../utils/deferred';
11
+ import { lazyRun } from '../../utils/lazyRun';
12
+ export class PlaywrightPage {
13
+ constructor(context, page, logger) {
14
+ this.context = context;
15
+ this.page = page;
16
+ this.logger = logger;
17
+ }
18
+ url() {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ return this.page.url();
21
+ });
22
+ }
23
+ goto(url) {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ yield this.page.goto(url, { waitUntil: 'load' });
26
+ });
27
+ }
28
+ fill(selector, value) {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ yield this.page.type(selector, value.toString());
31
+ });
32
+ }
33
+ click(selector, domDirect = false) {
34
+ return __awaiter(this, void 0, void 0, function* () {
35
+ if (domDirect) {
36
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
37
+ // @ts-ignore
38
+ yield this.page.evaluate(s => document.querySelector(s).click(), selector);
39
+ yield this.wait(250);
40
+ }
41
+ else {
42
+ yield this.page.click(selector, { timeout: 0 });
43
+ }
44
+ });
45
+ }
46
+ select(selector, value) {
47
+ return __awaiter(this, void 0, void 0, function* () {
48
+ yield this.page.selectOption(selector, value);
49
+ });
50
+ }
51
+ querySelectorAll(selector, callback) {
52
+ return this.page.$$eval(selector, callback);
53
+ }
54
+ getCookies() {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ const cookies = yield this.context.cookies();
57
+ return JSON.stringify(cookies);
58
+ });
59
+ }
60
+ setCookies(cookies) {
61
+ return __awaiter(this, void 0, void 0, function* () {
62
+ const cookieParams = JSON.parse(cookies);
63
+ yield this.context.addCookies(cookieParams);
64
+ });
65
+ }
66
+ wait(param) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ const p = deferred();
69
+ if (param === 'idle') {
70
+ yield this.page.waitForNavigation({ waitUntil: 'networkidle' });
71
+ p.resolve();
72
+ }
73
+ if (param === 'load') {
74
+ yield this.page.waitForNavigation({ waitUntil: 'load' });
75
+ p.resolve();
76
+ }
77
+ if (typeof param === 'number') {
78
+ yield lazyRun(() => __awaiter(this, void 0, void 0, function* () { return p.resolve(); }), param);
79
+ }
80
+ return p.promise;
81
+ });
82
+ }
83
+ on(event, callback) {
84
+ this.page.on(event, callback);
85
+ return () => this.page.off(event, callback);
86
+ }
87
+ }
@@ -66,6 +66,10 @@ export class PuppeteerController {
66
66
  });
67
67
  this.configs = configs;
68
68
  this.logger = logger;
69
- puppeteer.launch(this.configs).then(browser => (this.browser = browser));
69
+ puppeteer
70
+ .launch(Object.assign(Object.assign({}, this.configs), { headless: this.configs.headless === true ? 'new' : this.configs.headless }))
71
+ .then((browser) => __awaiter(this, void 0, void 0, function* () {
72
+ this.browser = browser;
73
+ }));
70
74
  }
71
75
  }
@@ -14,7 +14,6 @@ export class PuppeteerPage {
14
14
  constructor(page, logger) {
15
15
  this.page = page;
16
16
  this.logger = logger;
17
- this.page = page;
18
17
  }
19
18
  url() {
20
19
  return __awaiter(this, void 0, void 0, function* () {
@@ -31,13 +30,13 @@ export class PuppeteerPage {
31
30
  yield this.page.type(selector, value.toString());
32
31
  });
33
32
  }
34
- click(selector, useWaitForSelector = false) {
35
- var _a;
33
+ click(selector, domDirect = false) {
36
34
  return __awaiter(this, void 0, void 0, function* () {
37
- if (useWaitForSelector) {
38
- const handle = yield this.page.waitForSelector(selector, { timeout: 15000 });
39
- (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug('[PuppeteerPage]', '[click]', 'handle', handle);
40
- handle === null || handle === void 0 ? void 0 : handle.click();
35
+ if (domDirect) {
36
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
37
+ // @ts-ignore
38
+ yield this.page.evaluate(s => document.querySelector(s).click(), selector);
39
+ yield this.wait(250);
41
40
  }
42
41
  else {
43
42
  yield this.page.click(selector);
@@ -23,6 +23,7 @@ import { validatePurchaseAvailability } from './utils/validatePurchaseAvailabili
23
23
  import { getCheckWinningLink } from './utils/getCheckWinningLink';
24
24
  export class LottoService {
25
25
  constructor(configs) {
26
+ var _a;
26
27
  this.context = {
27
28
  authenticated: false
28
29
  };
@@ -111,17 +112,7 @@ export class LottoService {
111
112
  this.logger.debug('[purchase]', 'click purchase button');
112
113
  yield page.click(SELECTORS.PURCHASE_BTN);
113
114
  this.logger.debug('[purchase]', 'click purchase confirm button');
114
- try {
115
- yield page.click(SELECTORS.PURCHASE_CONFIRM_BTN, true);
116
- }
117
- catch (e) {
118
- this.logger.debug('[purchase]', 'purchase confirm failure', e);
119
- this.logger.debug('[purchase]', 'print node');
120
- yield page.querySelectorAll(SELECTORS.PURCHASE_CONFIRM_BTN, elems => {
121
- this.logger.debug('[purchase]', elems);
122
- });
123
- throw e;
124
- }
115
+ yield page.click(SELECTORS.PURCHASE_CONFIRM_BTN);
125
116
  yield page.wait(1000);
126
117
  // game result
127
118
  this.logger.debug('[purchase]', 'print result');
@@ -140,6 +131,6 @@ export class LottoService {
140
131
  return getCheckWinningLink(round, numbers);
141
132
  };
142
133
  this.logger = new Logger(configs === null || configs === void 0 ? void 0 : configs.logLevel, '[LottoService]');
143
- this.browserController = createBrowserController('puppeteer', Object.assign(Object.assign({ defaultViewport: { width: 1080, height: 1024 } }, configs), { headless: (configs === null || configs === void 0 ? void 0 : configs.headless) === false ? false : 'new' }), this.logger);
134
+ this.browserController = createBrowserController((_a = configs === null || configs === void 0 ? void 0 : configs.controller) !== null && _a !== void 0 ? _a : 'playwright', Object.assign({ defaultViewport: { width: 1080, height: 1024 } }, configs), this.logger);
144
135
  }
145
136
  }
@@ -1,3 +1,3 @@
1
1
  import type { BrowserConfigs, BrowserControllerInterface } from '../types';
2
2
  import type { LoggerInterface } from '../logger';
3
- export declare function createBrowserController(name: 'puppeteer', configs: BrowserConfigs, logger: LoggerInterface): BrowserControllerInterface;
3
+ export declare function createBrowserController(name: 'puppeteer' | 'playwright', configs: BrowserConfigs, logger: LoggerInterface): BrowserControllerInterface;
@@ -0,0 +1,14 @@
1
+ import type { BrowserConfigs, BrowserControllerInterface } from '../../types';
2
+ import type { BrowserContext } from 'playwright';
3
+ import { PlaywrightPage } from './playwright.page';
4
+ import { type LoggerInterface } from '../../logger';
5
+ export declare class PlaywrightController implements BrowserControllerInterface {
6
+ configs: BrowserConfigs;
7
+ logger: LoggerInterface;
8
+ browser: BrowserContext;
9
+ constructor(configs: BrowserConfigs, logger: LoggerInterface);
10
+ private getBrowser;
11
+ focus: (pageIndex?: number) => Promise<PlaywrightPage>;
12
+ close: () => Promise<void>;
13
+ cleanPages: (remainingPageIndex: number[]) => Promise<void>;
14
+ }
@@ -0,0 +1,20 @@
1
+ import type { BrowserPageEvents, BrowserPageInterface, FakeDOMElement, StringifiedCookies } from '../../types';
2
+ import type { Page } from 'playwright-core';
3
+ import type { LoggerInterface } from '../../logger';
4
+ import type { BrowserContext } from 'playwright';
5
+ export declare class PlaywrightPage implements BrowserPageInterface {
6
+ context: BrowserContext;
7
+ page: Page;
8
+ logger?: LoggerInterface;
9
+ constructor(context: BrowserContext, page: Page, logger?: LoggerInterface);
10
+ url(): Promise<string>;
11
+ goto(url: string): Promise<void>;
12
+ fill(selector: string, value: string | number): Promise<void>;
13
+ click(selector: string, domDirect?: boolean): Promise<void>;
14
+ select(selector: string, value: string): Promise<void>;
15
+ querySelectorAll<T>(selector: string, callback: (elems: FakeDOMElement[]) => T): Promise<T>;
16
+ getCookies(): Promise<string>;
17
+ setCookies(cookies: StringifiedCookies): Promise<void>;
18
+ wait(param: 'idle' | 'load' | number): Promise<void>;
19
+ on(event: BrowserPageEvents, callback: (...args: unknown[]) => void): () => Page;
20
+ }
@@ -3,12 +3,12 @@ import { Page } from 'puppeteer';
3
3
  import type { LoggerInterface } from '../../logger';
4
4
  export declare class PuppeteerPage implements BrowserPageInterface {
5
5
  page: Page;
6
- logger?: LoggerInterface | undefined;
7
- constructor(page: Page, logger?: LoggerInterface | undefined);
6
+ logger?: LoggerInterface;
7
+ constructor(page: Page, logger?: LoggerInterface);
8
8
  url(): Promise<string>;
9
9
  goto(url: string): Promise<void>;
10
10
  fill(selector: string, value: string | number): Promise<void>;
11
- click(selector: string, useWaitForSelector?: boolean): Promise<void>;
11
+ click(selector: string, domDirect?: boolean): Promise<void>;
12
12
  select(selector: string, value: string): Promise<void>;
13
13
  querySelectorAll<T>(selector: string, callback: (elems: FakeDOMElement[]) => T): Promise<T>;
14
14
  getCookies(): Promise<string>;
@@ -11,8 +11,9 @@ export interface LottoServiceInterface {
11
11
  getCheckWinningLink(round: number, numbers: number[][]): string;
12
12
  }
13
13
  export interface BrowserConfigs {
14
+ controller?: 'puppeteer' | 'playwright';
14
15
  logLevel?: LogLevel;
15
- headless?: boolean | 'new';
16
+ headless?: boolean;
16
17
  defaultViewport?: {
17
18
  width: number;
18
19
  height: number;
@@ -30,7 +31,7 @@ export interface BrowserPageInterface {
30
31
  url(): Promise<string>;
31
32
  goto(url: string): Promise<void>;
32
33
  fill(selector: string, value: string | number): Promise<void>;
33
- click(selector: string, useWaitForSelector?: boolean): Promise<void>;
34
+ click(selector: string, domDirect?: boolean): Promise<void>;
34
35
  select(selector: string, value: string): Promise<void>;
35
36
  querySelectorAll<T>(selector: string, callback: (elems: FakeDOMElement[]) => T): Promise<T>;
36
37
  wait(time: number): Promise<void>;
@@ -45,7 +46,7 @@ export type FakeDOMElement = {
45
46
  innerHTML: string;
46
47
  children: FakeDOMElement[];
47
48
  };
48
- export type BrowserPageEvents = 'load' | 'close' | 'dialog' | 'response';
49
+ export type BrowserPageEvents = 'response';
49
50
  export type Unsubscribe = () => void;
50
51
  export type StringifiedCookies = string;
51
52
  export type GetWinningNumbersResponse = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rich-automation/lotto",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Lotto module",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -22,6 +22,7 @@
22
22
  "files": [
23
23
  "lib",
24
24
  "package.json",
25
+ "playwright.config.ts",
25
26
  "README.md"
26
27
  ],
27
28
  "packageManager": "yarn@1.22.19",
@@ -35,7 +36,8 @@
35
36
  "build:esm": "tsc --project tsconfig.esm.json && echo '{\"type\": \"module\"}' > lib/esm/package.json",
36
37
  "build:dts": "tsc --project tsconfig.json --emitDeclarationOnly --declaration --declarationDir lib/typescript",
37
38
  "test": "jest --forceExit --detectOpenHandles",
38
- "install:chrome": "node ./node_modules/puppeteer/install.js",
39
+ "install:puppeteer": "node ./node_modules/puppeteer/install.js",
40
+ "install:playwright": "npx playwright install --with-deps",
39
41
  "fix": "yarn fix:eslint && yarn fix:prettier",
40
42
  "fix:eslint": "eslint --fix src --ext js,jsx,ts,tsx ",
41
43
  "fix:prettier": "prettier --write \"src/**/*.{ts,tsx,js}\"",
@@ -47,12 +49,14 @@
47
49
  "dependencies": {
48
50
  "axios": "^1.3.5",
49
51
  "dayjs": "^1.11.7",
52
+ "playwright": "^1.35.0",
50
53
  "puppeteer": "^20.5.0"
51
54
  },
52
55
  "devDependencies": {
53
56
  "@babel/core": "^7.21.4",
54
57
  "@babel/preset-env": "^7.21.4",
55
58
  "@babel/preset-typescript": "^7.21.4",
59
+ "@playwright/test": "^1.35.0",
56
60
  "@types/jest": "^29.5.0",
57
61
  "@typescript-eslint/eslint-plugin": "^5.58.0",
58
62
  "@typescript-eslint/parser": "^5.58.0",
@@ -0,0 +1,66 @@
1
+ import { defineConfig, devices } from '@playwright/test';
2
+
3
+ /**
4
+ * Read environment variables from file.
5
+ * https://github.com/motdotla/dotenv
6
+ */
7
+ // require('dotenv').config();
8
+
9
+ /**
10
+ * See https://playwright.dev/docs/test-configuration.
11
+ */
12
+ export default defineConfig({
13
+ testDir: './src/__tests__',
14
+ /* Run tests in files in parallel */
15
+ fullyParallel: true,
16
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
17
+ forbidOnly: !!process.env.CI,
18
+ /* Retry on CI only */
19
+ retries: process.env.CI ? 2 : 0,
20
+ /* Opt out of parallel tests on CI. */
21
+ workers: process.env.CI ? 1 : undefined,
22
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
23
+ reporter: 'html',
24
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
25
+ use: {
26
+ /* Base URL to use in actions like `await page.goto('/')`. */
27
+ // baseURL: 'http://127.0.0.1:3000',
28
+
29
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
30
+ trace: 'on-first-retry',
31
+ },
32
+
33
+ /* Configure projects for major browsers */
34
+ projects: [
35
+ {
36
+ name: 'Google Chrome',
37
+ use: { ...devices['Desktop Chrome'], channel: 'chrome' },
38
+ },
39
+ // {
40
+ // name: 'chromium',
41
+ // use: { ...devices['Desktop Chrome'] },
42
+ // },
43
+ /* Test against mobile viewports. */
44
+ // {
45
+ // name: 'Mobile Chrome',
46
+ // use: { ...devices['Pixel 5'] },
47
+ // },
48
+ // {
49
+ // name: 'Mobile Safari',
50
+ // use: { ...devices['iPhone 12'] },
51
+ // },
52
+
53
+ /* Test against branded browsers. */
54
+ // {
55
+ // name: 'Microsoft Edge',
56
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
57
+ // },
58
+ ],
59
+
60
+ /* Run your local dev server before starting the tests */
61
+ // webServer: {
62
+ // command: 'npm run start',
63
+ // url: 'http://127.0.0.1:3000',
64
+ // reuseExistingServer: !process.env.CI,
65
+ // },
66
+ });