@rich-automation/lotto 0.1.4 → 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.
- package/lib/cjs/controllers/factory.js +3 -0
- package/lib/cjs/controllers/playwright/index.js +74 -0
- package/lib/cjs/controllers/playwright/playwright.page.js +91 -0
- package/lib/cjs/controllers/puppeteer/index.js +5 -1
- package/lib/cjs/controllers/puppeteer/puppeteer.page.js +1 -0
- package/lib/cjs/lottoService.js +4 -3
- package/lib/esm/controllers/factory.js +3 -0
- package/lib/esm/controllers/playwright/index.js +71 -0
- package/lib/esm/controllers/playwright/playwright.page.js +87 -0
- package/lib/esm/controllers/puppeteer/index.js +5 -1
- package/lib/esm/controllers/puppeteer/puppeteer.page.js +1 -0
- package/lib/esm/lottoService.js +4 -3
- package/lib/typescript/controllers/factory.d.ts +1 -1
- package/lib/typescript/controllers/playwright/index.d.ts +14 -0
- package/lib/typescript/controllers/playwright/playwright.page.d.ts +20 -0
- package/lib/typescript/types.d.ts +3 -2
- package/package.json +6 -2
- package/playwright.config.ts +66 -0
|
@@ -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
|
|
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;
|
|
@@ -35,6 +35,7 @@ class PuppeteerPage {
|
|
|
35
35
|
click(selector, domDirect = false) {
|
|
36
36
|
return __awaiter(this, void 0, void 0, function* () {
|
|
37
37
|
if (domDirect) {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
38
39
|
// @ts-ignore
|
|
39
40
|
yield this.page.evaluate(s => document.querySelector(s).click(), selector);
|
|
40
41
|
yield this.wait(250);
|
package/lib/cjs/lottoService.js
CHANGED
|
@@ -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
|
};
|
|
@@ -115,9 +116,9 @@ class LottoService {
|
|
|
115
116
|
yield page.click(selectors_1.SELECTORS.PURCHASE_AMOUNT_CONFIRM_BTN);
|
|
116
117
|
// click purchase button
|
|
117
118
|
this.logger.debug('[purchase]', 'click purchase button');
|
|
118
|
-
yield page.click(selectors_1.SELECTORS.PURCHASE_BTN
|
|
119
|
+
yield page.click(selectors_1.SELECTORS.PURCHASE_BTN);
|
|
119
120
|
this.logger.debug('[purchase]', 'click purchase confirm button');
|
|
120
|
-
yield page.click(selectors_1.SELECTORS.PURCHASE_CONFIRM_BTN
|
|
121
|
+
yield page.click(selectors_1.SELECTORS.PURCHASE_CONFIRM_BTN);
|
|
121
122
|
yield page.wait(1000);
|
|
122
123
|
// game result
|
|
123
124
|
this.logger.debug('[purchase]', 'print result');
|
|
@@ -136,7 +137,7 @@ class LottoService {
|
|
|
136
137
|
return (0, getCheckWinningLink_1.getCheckWinningLink)(round, numbers);
|
|
137
138
|
};
|
|
138
139
|
this.logger = new logger_1.default(configs === null || configs === void 0 ? void 0 : configs.logLevel, '[LottoService]');
|
|
139
|
-
this.browserController = (0, factory_1.createBrowserController)(
|
|
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);
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
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
|
|
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
|
}
|
|
@@ -33,6 +33,7 @@ export class PuppeteerPage {
|
|
|
33
33
|
click(selector, domDirect = false) {
|
|
34
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
35
|
if (domDirect) {
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
36
37
|
// @ts-ignore
|
|
37
38
|
yield this.page.evaluate(s => document.querySelector(s).click(), selector);
|
|
38
39
|
yield this.wait(250);
|
package/lib/esm/lottoService.js
CHANGED
|
@@ -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
|
};
|
|
@@ -109,9 +110,9 @@ export class LottoService {
|
|
|
109
110
|
yield page.click(SELECTORS.PURCHASE_AMOUNT_CONFIRM_BTN);
|
|
110
111
|
// click purchase button
|
|
111
112
|
this.logger.debug('[purchase]', 'click purchase button');
|
|
112
|
-
yield page.click(SELECTORS.PURCHASE_BTN
|
|
113
|
+
yield page.click(SELECTORS.PURCHASE_BTN);
|
|
113
114
|
this.logger.debug('[purchase]', 'click purchase confirm button');
|
|
114
|
-
yield page.click(SELECTORS.PURCHASE_CONFIRM_BTN
|
|
115
|
+
yield page.click(SELECTORS.PURCHASE_CONFIRM_BTN);
|
|
115
116
|
yield page.wait(1000);
|
|
116
117
|
// game result
|
|
117
118
|
this.logger.debug('[purchase]', 'print result');
|
|
@@ -130,6 +131,6 @@ export class LottoService {
|
|
|
130
131
|
return getCheckWinningLink(round, numbers);
|
|
131
132
|
};
|
|
132
133
|
this.logger = new Logger(configs === null || configs === void 0 ? void 0 : configs.logLevel, '[LottoService]');
|
|
133
|
-
this.browserController = createBrowserController(
|
|
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);
|
|
134
135
|
}
|
|
135
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
|
+
}
|
|
@@ -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
|
|
16
|
+
headless?: boolean;
|
|
16
17
|
defaultViewport?: {
|
|
17
18
|
width: number;
|
|
18
19
|
height: number;
|
|
@@ -45,7 +46,7 @@ export type FakeDOMElement = {
|
|
|
45
46
|
innerHTML: string;
|
|
46
47
|
children: FakeDOMElement[];
|
|
47
48
|
};
|
|
48
|
-
export type BrowserPageEvents = '
|
|
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
|
+
"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:
|
|
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
|
+
});
|