@elliemae/smoked-suite 26.2.15

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 (35) hide show
  1. package/README.md +58 -0
  2. package/dist/cjs/auth/index.js +153 -0
  3. package/dist/cjs/base-page/index.js +58 -0
  4. package/dist/cjs/browserstack/index.js +97 -0
  5. package/dist/cjs/global-setup/index.js +71 -0
  6. package/dist/cjs/index.js +47 -0
  7. package/dist/cjs/monocartCoverage/index.js +125 -0
  8. package/dist/cjs/package.json +7 -0
  9. package/dist/cjs/page-setup/index.js +116 -0
  10. package/dist/cjs/playwright-config/index.js +116 -0
  11. package/dist/cjs/routes/index.js +27 -0
  12. package/dist/cjs/types.js +16 -0
  13. package/dist/esm/auth/index.js +123 -0
  14. package/dist/esm/base-page/index.js +38 -0
  15. package/dist/esm/browserstack/index.js +67 -0
  16. package/dist/esm/global-setup/index.js +41 -0
  17. package/dist/esm/index.js +20 -0
  18. package/dist/esm/monocartCoverage/index.js +95 -0
  19. package/dist/esm/package.json +7 -0
  20. package/dist/esm/page-setup/index.js +96 -0
  21. package/dist/esm/playwright-config/index.js +92 -0
  22. package/dist/esm/routes/index.js +7 -0
  23. package/dist/esm/types.js +0 -0
  24. package/dist/types/lib/auth/index.d.ts +41 -0
  25. package/dist/types/lib/base-page/index.d.ts +27 -0
  26. package/dist/types/lib/browserstack/index.d.ts +59 -0
  27. package/dist/types/lib/global-setup/index.d.ts +16 -0
  28. package/dist/types/lib/index.d.ts +10 -0
  29. package/dist/types/lib/monocartCoverage/index.d.ts +57 -0
  30. package/dist/types/lib/page-setup/index.d.ts +39 -0
  31. package/dist/types/lib/playwright-config/index.d.ts +3 -0
  32. package/dist/types/lib/routes/index.d.ts +16 -0
  33. package/dist/types/lib/types.d.ts +77 -0
  34. package/dist/types/tsconfig.tsbuildinfo +1 -0
  35. package/package.json +78 -0
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var page_setup_exports = {};
20
+ __export(page_setup_exports, {
21
+ PageSetup: () => PageSetup
22
+ });
23
+ module.exports = __toCommonJS(page_setup_exports);
24
+ class PageSetup {
25
+ /**
26
+ * Apply all page-level setup. Call once per test — each test
27
+ * receives a fresh Playwright page, so init scripts and route
28
+ * blocks do not carry over.
29
+ * @param page
30
+ */
31
+ async apply(page) {
32
+ await Promise.all([
33
+ this.stubDiagnostics(page),
34
+ this.suppressErrorOverlays(page)
35
+ ]);
36
+ await this.blockThirdPartyScripts(page);
37
+ }
38
+ /**
39
+ * Provide a no-op fallback for the emuiDiagnostics webpack external.
40
+ * @param page
41
+ */
42
+ async stubDiagnostics(page) {
43
+ await page.addInitScript(() => {
44
+ if (typeof window.emuiDiagnostics === "undefined") {
45
+ const noop = () => {
46
+ };
47
+ const noopTransport = { log: async () => true };
48
+ const fallbackLogger = new Proxy({}, {
49
+ get(_target, prop) {
50
+ if (typeof prop === "string" && typeof console[prop] === "function") {
51
+ return console[prop].bind(console);
52
+ }
53
+ return prop === "setOptions" ? noop : console.log.bind(console);
54
+ }
55
+ });
56
+ window.emuiDiagnostics = {
57
+ http: () => noopTransport,
58
+ logger: () => fallbackLogger,
59
+ Console: () => noopTransport,
60
+ logUnhandledErrors: noop,
61
+ webvitals: noop,
62
+ parentApp: () => noopTransport,
63
+ redactPii: (val) => val,
64
+ LogLevels: { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, FATAL: 4 }
65
+ };
66
+ }
67
+ });
68
+ }
69
+ /**
70
+ * Auto-hide webpack / react-error-overlay iframes that obscure
71
+ * the page during tests.
72
+ * @param page
73
+ */
74
+ async suppressErrorOverlays(page) {
75
+ await page.addInitScript(() => {
76
+ const hideOverlayIframes = () => {
77
+ document.querySelectorAll("body > iframe").forEach((el) => {
78
+ el.style.display = "none";
79
+ });
80
+ };
81
+ const start = () => {
82
+ hideOverlayIframes();
83
+ new MutationObserver(hideOverlayIframes).observe(document.body, {
84
+ childList: true
85
+ });
86
+ };
87
+ if (document.body) start();
88
+ else document.addEventListener("DOMContentLoaded", start);
89
+ });
90
+ }
91
+ /** Domains that are blocked during tests to speed up page loads. */
92
+ static BLOCKED_DOMAINS = [
93
+ "googletagmanager.com",
94
+ "google-analytics.com",
95
+ "fonts.googleapis.com",
96
+ "fonts.gstatic.com",
97
+ "hotjar.com",
98
+ "newrelic.com",
99
+ "nr-data.net",
100
+ "sentry.io",
101
+ "fullstory.com",
102
+ "pendo.io"
103
+ ];
104
+ /** Single regex matching all {@link BLOCKED_DOMAINS}. */
105
+ static BLOCKED_PATTERN = new RegExp(
106
+ PageSetup.BLOCKED_DOMAINS.map((d) => d.replace(/\./g, "\\.")).join("|")
107
+ );
108
+ /**
109
+ * Block analytics, fonts, and monitoring scripts that slow page loads.
110
+ * Uses a single route handler instead of one per domain.
111
+ * @param page
112
+ */
113
+ async blockThirdPartyScripts(page) {
114
+ await page.route(PageSetup.BLOCKED_PATTERN, (route) => route.abort());
115
+ }
116
+ }
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var playwright_config_exports = {};
30
+ __export(playwright_config_exports, {
31
+ createPlaywrightConfig: () => createPlaywrightConfig
32
+ });
33
+ module.exports = __toCommonJS(playwright_config_exports);
34
+ var path = __toESM(require("path"), 1);
35
+ var import_test = require("@playwright/test");
36
+ var import_global_setup = require("../global-setup/index.js");
37
+ var import_monocartCoverage = require("../monocartCoverage/index.js");
38
+ const DEFAULT_ACTION_TIMEOUT = 3e4;
39
+ const DEFAULT_NAVIGATION_TIMEOUT = 45e3;
40
+ const DEFAULT_TEST_TIMEOUT = 12e4;
41
+ const DEFAULT_EXPECT_TIMEOUT = 3e4;
42
+ const FAST_MODE_USE = {
43
+ trace: "off",
44
+ screenshot: "off",
45
+ video: "off"
46
+ };
47
+ const DEFAULT_USE = {
48
+ trace: "retain-on-failure",
49
+ screenshot: "only-on-failure",
50
+ video: "retain-on-failure"
51
+ };
52
+ const CI_CONFIG = {
53
+ workers: "100%",
54
+ forbidOnly: true,
55
+ retries: 2,
56
+ reporter: [
57
+ ["list"],
58
+ ["junit", { outputFile: "playwright-report/junit.xml" }]
59
+ ]
60
+ };
61
+ const LOCAL_CONFIG = {
62
+ workers: "50%",
63
+ forbidOnly: false,
64
+ retries: 0,
65
+ reporter: [
66
+ ["html", { outputFolder: "playwright-report" }],
67
+ ["list"]
68
+ ]
69
+ };
70
+ function createPlaywrightConfig(params = {}) {
71
+ const {
72
+ overrides = {},
73
+ globalAuth = true,
74
+ fastMode = false,
75
+ coverage
76
+ } = params;
77
+ const { use: useOverrides, expect: expectOverrides, ...rest } = overrides;
78
+ const isCoverage = !!coverage;
79
+ if (isCoverage) (0, import_monocartCoverage.configureCoverage)();
80
+ const globalSetup = path.resolve(__dirname, "../global-setup/index.js");
81
+ const globalAuthConfig = globalAuth ? { globalSetup } : {};
82
+ const storageStateConfig = globalAuth ? { storageState: path.join(process.cwd(), import_global_setup.STORAGE_FILE) } : {};
83
+ const envConfig = process.env.CI ? CI_CONFIG : LOCAL_CONFIG;
84
+ const coverageReporter = isCoverage ? { reporter: (0, import_monocartCoverage.buildCoverageReporters)(coverage) } : {};
85
+ return (0, import_test.defineConfig)({
86
+ testMatch: "**/*Spec.ts",
87
+ fullyParallel: true,
88
+ ...envConfig,
89
+ ...coverageReporter,
90
+ projects: [
91
+ {
92
+ name: "chromium",
93
+ use: { ...import_test.devices["Desktop Chrome"] }
94
+ }
95
+ ],
96
+ outputDir: "test-results",
97
+ timeout: DEFAULT_TEST_TIMEOUT,
98
+ ...globalAuthConfig,
99
+ ...rest,
100
+ use: {
101
+ ...fastMode ? FAST_MODE_USE : DEFAULT_USE,
102
+ viewport: { width: 1280, height: 720 },
103
+ actionTimeout: DEFAULT_ACTION_TIMEOUT,
104
+ navigationTimeout: DEFAULT_NAVIGATION_TIMEOUT,
105
+ ...storageStateConfig,
106
+ ...useOverrides,
107
+ ...{
108
+ baseURL: process.env.BASE_URL ?? useOverrides?.baseURL ?? "http://localhost:3000"
109
+ }
110
+ },
111
+ expect: {
112
+ timeout: DEFAULT_EXPECT_TIMEOUT,
113
+ ...expectOverrides
114
+ }
115
+ });
116
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var routes_exports = {};
20
+ __export(routes_exports, {
21
+ getRoutePath: () => getRoutePath
22
+ });
23
+ module.exports = __toCommonJS(routes_exports);
24
+ function getRoutePath(routes, route) {
25
+ if (route in routes) return routes[route];
26
+ return route;
27
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var types_exports = {};
16
+ module.exports = __toCommonJS(types_exports);
@@ -0,0 +1,123 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ const AUTH_CAPTURE_TIMEOUT = 3e4;
4
+ const LOGIN_PAGE_TIMEOUT = 9e4;
5
+ const LOGIN_FIELD_TIMEOUT = 6e4;
6
+ const LOGIN_BUTTON_TIMEOUT = 3e4;
7
+ const AUTH_SHELL_TIMEOUT = 12e4;
8
+ const AUTH_TTL_MS = 25 * 60 * 1e3;
9
+ const AUTH_FILE = ".smoked-suite-auth.json";
10
+ class AuthManager {
11
+ static authState = null;
12
+ /** Whether a cached session exists and is still valid. */
13
+ hasValidAuth() {
14
+ const state = AuthManager.authState;
15
+ if (!state) return false;
16
+ return Date.now() - state.capturedAt < AUTH_TTL_MS;
17
+ }
18
+ /** Expose current auth state (used by global setup to serialise). */
19
+ static getAuthState() {
20
+ return AuthManager.authState;
21
+ }
22
+ /**
23
+ * Load auth state from the file written by globalSetup.
24
+ * Returns `true` if a valid (non-expired) session was loaded.
25
+ */
26
+ static loadFromFile() {
27
+ const filePath = path.join(process.cwd(), AUTH_FILE);
28
+ try {
29
+ if (!fs.existsSync(filePath)) return false;
30
+ const raw = fs.readFileSync(filePath, "utf-8");
31
+ const state = JSON.parse(raw);
32
+ if (!state?.sessionEntries || !state?.capturedAt) return false;
33
+ if (Date.now() - state.capturedAt >= AUTH_TTL_MS) return false;
34
+ AuthManager.authState = state;
35
+ return true;
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
40
+ /**
41
+ * Restore every session-storage entry that was captured after
42
+ * the initial login so encw and its micro-apps find the data
43
+ * they need (Authorization, cred, user, userSettings, etc.).
44
+ * @param page
45
+ */
46
+ async inject(page) {
47
+ const state = AuthManager.authState;
48
+ if (!state) {
49
+ throw new Error("No auth state available to inject");
50
+ }
51
+ await page.evaluate((entries) => {
52
+ for (const [key, value] of Object.entries(entries)) {
53
+ sessionStorage.setItem(key, value);
54
+ }
55
+ }, state.sessionEntries);
56
+ }
57
+ /**
58
+ * Snapshot every session-storage entry after a successful login.
59
+ * @param page
60
+ */
61
+ async capture(page) {
62
+ await page.waitForFunction(
63
+ () => sessionStorage.getItem("Authorization") !== null,
64
+ { timeout: AUTH_CAPTURE_TIMEOUT }
65
+ );
66
+ const sessionEntries = await page.evaluate(() => {
67
+ const entries = {};
68
+ for (let i = 0; i < sessionStorage.length; i++) {
69
+ const key = sessionStorage.key(i);
70
+ if (key) entries[key] = sessionStorage.getItem(key) ?? "";
71
+ }
72
+ return entries;
73
+ });
74
+ if (sessionEntries?.Authorization) {
75
+ AuthManager.authState = { sessionEntries, capturedAt: Date.now() };
76
+ }
77
+ }
78
+ /**
79
+ * Perform the encw login flow (Instance ID -> User / Password).
80
+ * @param page - Playwright page to drive.
81
+ * @param creds - Credentials to use.
82
+ */
83
+ async login(page, creds) {
84
+ await page.goto("", { waitUntil: "load", timeout: LOGIN_PAGE_TIMEOUT });
85
+ const instanceIdField = page.getByPlaceholder("Instance ID");
86
+ await instanceIdField.waitFor({
87
+ state: "visible",
88
+ timeout: LOGIN_PAGE_TIMEOUT
89
+ });
90
+ await instanceIdField.click();
91
+ await instanceIdField.fill(creds.instanceId ?? "BE11226875");
92
+ const userIdField = page.getByPlaceholder("User ID");
93
+ await userIdField.waitFor({
94
+ state: "visible",
95
+ timeout: LOGIN_FIELD_TIMEOUT
96
+ });
97
+ await userIdField.click();
98
+ await userIdField.fill(creds.username);
99
+ await userIdField.press("Tab");
100
+ const passwordField = page.getByRole("textbox", { name: "Password" });
101
+ await passwordField.waitFor({
102
+ state: "visible",
103
+ timeout: LOGIN_BUTTON_TIMEOUT
104
+ });
105
+ await passwordField.fill(creds.password);
106
+ const loginButton = page.getByRole("button", { name: "Log In" });
107
+ await loginButton.waitFor({
108
+ state: "visible",
109
+ timeout: LOGIN_BUTTON_TIMEOUT
110
+ });
111
+ await loginButton.click();
112
+ await page.waitForLoadState("domcontentloaded", {
113
+ timeout: AUTH_SHELL_TIMEOUT
114
+ });
115
+ await page.waitForFunction(
116
+ () => sessionStorage.getItem("Authorization") !== null,
117
+ { polling: 1e3, timeout: AUTH_SHELL_TIMEOUT }
118
+ );
119
+ }
120
+ }
121
+ export {
122
+ AuthManager
123
+ };
@@ -0,0 +1,38 @@
1
+ class BasePage {
2
+ _contextProvider;
3
+ /** The current Page context, resolved lazily. */
4
+ get page() {
5
+ return typeof this._contextProvider === "function" ? this._contextProvider() : this._contextProvider;
6
+ }
7
+ constructor(context) {
8
+ this._contextProvider = context;
9
+ }
10
+ // ─── Locator helpers ─────────────────────────────────────────────────────────
11
+ getByTestId(testId) {
12
+ return this.page.getByTestId(testId);
13
+ }
14
+ locator(selector) {
15
+ return this.page.locator(selector);
16
+ }
17
+ getByRole(role, options) {
18
+ return this.page.getByRole(role, options);
19
+ }
20
+ getByText(text, options) {
21
+ return this.page.getByText(text, options);
22
+ }
23
+ getByLabel(text, options) {
24
+ return this.page.getByLabel(text, options);
25
+ }
26
+ getByPlaceholder(text, options) {
27
+ return this.page.getByPlaceholder(text, options);
28
+ }
29
+ getByAltText(text, options) {
30
+ return this.page.getByAltText(text, options);
31
+ }
32
+ getByTitle(text, options) {
33
+ return this.page.getByTitle(text, options);
34
+ }
35
+ }
36
+ export {
37
+ BasePage
38
+ };
@@ -0,0 +1,67 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ const DEFAULT_PLATFORMS = [
4
+ {
5
+ os: "OS X",
6
+ osVersion: "Sequoia",
7
+ browserName: "chrome",
8
+ browserVersion: "latest"
9
+ }
10
+ ];
11
+ function createBrowserStackConfig(options = {}) {
12
+ const {
13
+ projectName = "encw-app",
14
+ buildName = "playwright-tests",
15
+ // eslint-disable-next-line no-template-curly-in-string
16
+ buildIdentifier = "#${BUILD_NUMBER}",
17
+ platforms = DEFAULT_PLATFORMS,
18
+ parallelsPerPlatform = 1,
19
+ browserstackLocal = true,
20
+ forceLocal = true,
21
+ debug = true,
22
+ networkLogs = true,
23
+ consoleLogs = "info"
24
+ } = options;
25
+ const platformsYaml = platforms.map((p) => {
26
+ const lines = [
27
+ ` - os: ${p.os}`,
28
+ ` osVersion: ${p.osVersion}`,
29
+ ` browserName: ${p.browserName}`
30
+ ];
31
+ if (p.browserVersion) {
32
+ lines.push(` browserVersion: ${p.browserVersion}`);
33
+ }
34
+ return lines.join("\n");
35
+ }).join("\n");
36
+ return `userName: "\${BROWSERSTACK_USERNAME}"
37
+ accessKey: "\${BROWSERSTACK_ACCESS_KEY}"
38
+
39
+ projectName: ${projectName}
40
+ buildName: ${buildName}
41
+ buildIdentifier: "${buildIdentifier}"
42
+ framework: playwright
43
+
44
+ platforms:
45
+ ${platformsYaml}
46
+
47
+ parallelsPerPlatform: ${parallelsPerPlatform}
48
+
49
+ browserstackLocal: ${String(browserstackLocal)}
50
+ browserStackLocalOptions:
51
+ forceLocal: ${String(forceLocal)}
52
+
53
+ debug: ${String(debug)}
54
+ networkLogs: ${String(networkLogs)}
55
+ consoleLogs: ${consoleLogs}
56
+ `;
57
+ }
58
+ function writeBrowserStackConfig(options = {}, targetDir = process.cwd()) {
59
+ const content = createBrowserStackConfig(options);
60
+ const filePath = path.join(targetDir, "browserstack.yml");
61
+ fs.writeFileSync(filePath, content, "utf-8");
62
+ return filePath;
63
+ }
64
+ export {
65
+ createBrowserStackConfig,
66
+ writeBrowserStackConfig
67
+ };
@@ -0,0 +1,41 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { chromium } from "@playwright/test";
4
+ import { AuthManager } from "../auth/index.js";
5
+ import { PageSetup } from "../page-setup/index.js";
6
+ const AUTH_FILE = ".smoked-suite-auth.json";
7
+ const STORAGE_FILE = ".smoked-suite-storage.json";
8
+ async function globalSetup(config) {
9
+ const baseURL = config.projects[0]?.use?.baseURL ?? process.env.BASE_URL;
10
+ if (!baseURL) {
11
+ throw new Error(
12
+ "smoked-suite globalSetup: baseURL is required. Set BASE_URL env var or configure use.baseURL in createPlaywrightConfig."
13
+ );
14
+ }
15
+ const browser = await chromium.launch();
16
+ const context = await browser.newContext({ baseURL });
17
+ const page = await context.newPage();
18
+ const pageSetup = new PageSetup();
19
+ await pageSetup.apply(page);
20
+ const auth = new AuthManager();
21
+ const credentials = {
22
+ instanceId: process.env.ENCW_INSTANCE_ID ?? "BE11226875",
23
+ username: process.env.ENCW_USER_ID ?? "admin",
24
+ password: process.env.ENCW_PASSWORD ?? "Password#!23"
25
+ };
26
+ await auth.login(page, credentials);
27
+ await auth.capture(page);
28
+ const authState = AuthManager.getAuthState();
29
+ if (authState) {
30
+ const authPath = path.join(process.cwd(), AUTH_FILE);
31
+ fs.writeFileSync(authPath, JSON.stringify(authState), "utf-8");
32
+ }
33
+ const storagePath = path.join(process.cwd(), STORAGE_FILE);
34
+ await context.storageState({ path: storagePath });
35
+ await browser.close();
36
+ }
37
+ export {
38
+ AUTH_FILE,
39
+ STORAGE_FILE,
40
+ globalSetup as default
41
+ };
@@ -0,0 +1,20 @@
1
+ import { BasePage } from "./base-page/index.js";
2
+ import { AuthManager } from "./auth/index.js";
3
+ import { PageSetup } from "./page-setup/index.js";
4
+ import { getRoutePath } from "./routes/index.js";
5
+ import { createPlaywrightConfig } from "./playwright-config/index.js";
6
+ import { default as default2 } from "./global-setup/index.js";
7
+ import {
8
+ createBrowserStackConfig,
9
+ writeBrowserStackConfig
10
+ } from "./browserstack/index.js";
11
+ export {
12
+ AuthManager,
13
+ BasePage,
14
+ PageSetup,
15
+ createBrowserStackConfig,
16
+ createPlaywrightConfig,
17
+ getRoutePath,
18
+ default2 as globalSetup,
19
+ writeBrowserStackConfig
20
+ };
@@ -0,0 +1,95 @@
1
+ import { test } from "@playwright/test";
2
+ let coverageConfigured = false;
3
+ let coverageEnabled = false;
4
+ const trackedPages = /* @__PURE__ */ new Set();
5
+ function configureCoverage() {
6
+ coverageConfigured = true;
7
+ }
8
+ function startCoverage() {
9
+ if (!coverageConfigured) return;
10
+ coverageEnabled = true;
11
+ trackedPages.clear();
12
+ }
13
+ async function stopCoverage() {
14
+ if (!coverageEnabled) return;
15
+ await Promise.allSettled(
16
+ [...trackedPages].map((page) => flushPageCoverage(page))
17
+ );
18
+ trackedPages.clear();
19
+ coverageEnabled = false;
20
+ }
21
+ async function trackPage(page) {
22
+ if (!coverageEnabled) return;
23
+ trackedPages.add(page);
24
+ await page.coverage.startJSCoverage({ resetOnNavigation: false });
25
+ }
26
+ async function untrackPage(page) {
27
+ if (!coverageEnabled || !trackedPages.has(page)) return;
28
+ await flushPageCoverage(page);
29
+ trackedPages.delete(page);
30
+ }
31
+ async function flushPageCoverage(page) {
32
+ const entries = await page.coverage.stopJSCoverage();
33
+ const { addCoverageReport } = await import("monocart-reporter");
34
+ await addCoverageReport(entries, test.info());
35
+ }
36
+ function buildCoverageReporter(configs) {
37
+ const repoName = process.cwd().split("/").pop() ?? "";
38
+ const segments = configs.map(
39
+ (c) => c.sourceDir.replace(/^\.\//, "").replace(/\/$/, "")
40
+ );
41
+ const firstBase = configs[0].sourceDir.split("/").filter(Boolean).pop() ?? "app";
42
+ const reportName = configs.length === 1 ? `${toTitleCase(firstBase)} Coverage Report` : "Coverage Report";
43
+ const outputDir = configs[0].outputDir ?? `./coverage/${firstBase}`;
44
+ const fileFilter = {
45
+ "**/*.{ts,tsx}": true,
46
+ "**/*.test.*": false,
47
+ "**/*.spec.*": false,
48
+ "**/tests/**": false
49
+ };
50
+ const allEntries = configs.map((c) => ({
51
+ dir: c.sourceDir,
52
+ filter: fileFilter
53
+ }));
54
+ return [
55
+ "monocart-reporter",
56
+ {
57
+ name: reportName,
58
+ outputFile: `${outputDir}/report.html`,
59
+ coverage: {
60
+ reports: ["v8", "console-details", "lcovonly"],
61
+ all: allEntries.length === 1 ? allEntries[0] : allEntries,
62
+ sourcePath: (filePath) => {
63
+ let p = filePath;
64
+ if (repoName) {
65
+ p = p.replace(new RegExp(`^${repoName}/`), "");
66
+ }
67
+ p = p.replace(/-[0-9a-f]{4}$/, "");
68
+ return p;
69
+ },
70
+ sourceFilter: (sourcePath) => {
71
+ if (sourcePath.includes("node_modules")) return false;
72
+ return segments.some((seg) => sourcePath.includes(seg));
73
+ },
74
+ entryFilter: (entry) => {
75
+ if (entry.url.startsWith("http")) return false;
76
+ return segments.some((seg) => entry.url.includes(seg));
77
+ }
78
+ }
79
+ }
80
+ ];
81
+ }
82
+ function toTitleCase(s) {
83
+ return s.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
84
+ }
85
+ function buildCoverageReporters(configs) {
86
+ return [["list"], buildCoverageReporter(configs)];
87
+ }
88
+ export {
89
+ buildCoverageReporters,
90
+ configureCoverage,
91
+ startCoverage,
92
+ stopCoverage,
93
+ trackPage,
94
+ untrackPage
95
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "type": "module",
3
+ "sideEffects": false,
4
+ "publishConfig": {
5
+ "access": "public"
6
+ }
7
+ }