@brillout/test-e2e 0.1.4 → 0.1.6

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/dist/Logs.d.ts CHANGED
@@ -6,24 +6,18 @@ export declare const Logs: {
6
6
  getBrowserErrors: typeof getBrowserErrors;
7
7
  flushEagerly: boolean;
8
8
  };
9
- declare type LogType = 'stdout' | 'stderr' | 'Browser Error' | 'Browser Log' | 'Run Start' | 'Jest' | 'process' | 'Connection Error';
10
- declare type TestContext = null | {
11
- testName: string;
12
- cmd: string;
13
- };
9
+ declare type LogSource = 'stdout' | 'stderr' | 'Browser Error' | 'Browser Log' | 'Playwright' | 'run()' | 'test()' | 'Connection Error';
14
10
  declare type LogEntry = {
15
- logType: LogType;
11
+ logSource: LogSource;
16
12
  logText: string;
17
13
  logTimestamp: string;
18
- testContext: TestContext;
19
14
  isExpectedError: boolean;
20
15
  };
21
16
  declare function getBrowserErrors(): LogEntry[];
22
17
  declare function clear(): void;
23
18
  declare function flush(): void;
24
- declare function add({ logType, logText, testContext }: {
25
- logType: LogType;
19
+ declare function add({ logSource, logText }: {
20
+ logSource: LogSource;
26
21
  logText: string;
27
- testContext: TestContext;
28
22
  }): void;
29
23
  declare function expectBrowserError(browserLogFilter: (browserLog: LogEntry) => boolean): void;
package/dist/Logs.js CHANGED
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Logs = exports.expectBrowserError = void 0;
4
7
  exports.Logs = {
@@ -9,11 +12,12 @@ exports.Logs = {
9
12
  flushEagerly: false,
10
13
  };
11
14
  const utils_1 = require("./utils");
12
- const picocolors_1 = require("picocolors");
15
+ const picocolors_1 = __importDefault(require("picocolors"));
16
+ const getCurrentTest_1 = require("./getCurrentTest");
13
17
  let logEntries = [];
14
18
  let logEntriesNotPrinted = [];
15
19
  function getBrowserErrors() {
16
- return logEntries.filter(({ logType, isExpectedError }) => logType === 'Browser Error' && !isExpectedError);
20
+ return logEntries.filter(({ logSource, isExpectedError }) => logSource === 'Browser Error' && !isExpectedError);
17
21
  }
18
22
  function clear() {
19
23
  logEntries = [];
@@ -23,12 +27,11 @@ function flush() {
23
27
  logEntriesNotPrinted.forEach((logEntry) => printLog(logEntry));
24
28
  logEntriesNotPrinted = [];
25
29
  }
26
- function add({ logType, logText, testContext }) {
30
+ function add({ logSource, logText }) {
27
31
  const logTimestamp = getTimestamp();
28
32
  const logEntry = {
29
- logType,
33
+ logSource,
30
34
  logText,
31
- testContext,
32
35
  logTimestamp,
33
36
  isExpectedError: false,
34
37
  };
@@ -58,20 +61,35 @@ function getTimestamp() {
58
61
  return timestamp;
59
62
  }
60
63
  function printLog(logEntry) {
61
- const { logType, logText, logTimestamp, testContext } = logEntry;
62
- let prefix = logType;
63
- if (logType === 'stderr' || logType === 'Browser Error')
64
- prefix = (0, picocolors_1.bold)((0, picocolors_1.red)(logType));
65
- if (logType === 'stdout' || logType === 'Browser Log')
66
- prefix = (0, picocolors_1.bold)((0, picocolors_1.blue)(logType));
64
+ const { logSource, logText, logTimestamp } = logEntry;
65
+ let logSourceLabel = colorize(logSource);
66
+ const testInfo = (0, getCurrentTest_1.getCurrentTestOptional)();
67
+ // See https://github.com/nodejs/node/issues/8033#issuecomment-388323687
68
+ if (!(0, utils_1.ensureNewTerminalLine)()) {
69
+ process.stderr.write(`\n`);
70
+ }
67
71
  let msg = logText;
68
- if (!msg)
69
- msg = ''; // don't know why but sometimes `logText` is `undefined`
72
+ // I don't know why but sometimes `logText` is `undefined`
73
+ if (msg === undefined)
74
+ msg = '';
70
75
  if (!msg.endsWith('\n'))
71
76
  msg = msg + '\n';
72
- if (testContext) {
73
- const { testName, cmd } = testContext;
74
- msg = `[${testName}][${cmd}] ${msg}`;
77
+ let testInfoLabels = '';
78
+ if (testInfo) {
79
+ (0, utils_1.assert)(testInfo.runInfo);
80
+ testInfoLabels = `[${testInfo.testName}][${testInfo.runInfo.cmd}]`;
75
81
  }
76
- process.stderr.write(`[${logTimestamp}][${prefix}]${msg}`);
82
+ process.stderr.write(`[${logTimestamp}]${testInfoLabels}[${logSourceLabel}] ${msg}`);
83
+ }
84
+ function colorize(logSource) {
85
+ const { bold } = picocolors_1.default;
86
+ if (logSource === 'stderr' || logSource === 'Browser Error' || logSource === 'Connection Error')
87
+ return bold(picocolors_1.default.red(logSource));
88
+ if (logSource === 'stdout' || logSource === 'Browser Log')
89
+ return bold(picocolors_1.default.blue(logSource));
90
+ if (logSource === 'Playwright')
91
+ return bold(picocolors_1.default.magenta(logSource));
92
+ if (logSource === 'run()' || logSource === 'test()')
93
+ return bold(picocolors_1.default.yellow(logSource));
94
+ (0, utils_1.assert)(false);
77
95
  }
package/dist/buildTs.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export { buildTs };
2
- declare function buildTs(entry: string, outfile: string): Promise<void>;
2
+ declare function buildTs(entry: string, outfile: string): Promise<() => void>;
package/dist/buildTs.js CHANGED
@@ -5,6 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.buildTs = void 0;
7
7
  const esbuild_1 = __importDefault(require("esbuild"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const utils_1 = require("./utils");
8
10
  async function buildTs(entry, outfile) {
9
11
  await esbuild_1.default.build({
10
12
  platform: 'node',
@@ -18,5 +20,13 @@ async function buildTs(entry, outfile) {
18
20
  external: ['./node_modules/*', '@brillout/test-e2e'],
19
21
  minify: false,
20
22
  });
23
+ const clean = () => {
24
+ if (utils_1.cliConfig.debugEsbuild) {
25
+ return;
26
+ }
27
+ fs_1.default.unlinkSync(`${outfile}`);
28
+ fs_1.default.unlinkSync(`${outfile}.map`);
29
+ };
30
+ return clean;
21
31
  }
22
32
  exports.buildTs = buildTs;
@@ -1,3 +1,4 @@
1
+ /// <reference types="chai-subset" />
1
2
  export type { ChaiPlugin };
2
3
  export type { Expect };
3
4
  import type { use as chaiUse } from 'chai';
package/dist/cli.js CHANGED
@@ -2,38 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  // @ts-ignore
4
4
  require("source-map-support/register");
5
+ const utils_1 = require("./utils");
5
6
  const runTestSuites_1 = require("./runTestSuites");
6
7
  initPromiseRejectionHandler();
7
8
  cli();
8
9
  function cli() {
9
- const { filter, debug } = parseArgs();
10
- (0, runTestSuites_1.runTestSuites)({ filter, debug });
11
- }
12
- function parseArgs() {
13
- let debug = false;
14
- const terms = [];
15
- let exclude = false;
16
- process.argv.slice(2).forEach((arg) => {
17
- if (arg === '--debug') {
18
- debug = true;
19
- }
20
- else if (arg === '--exclude') {
21
- exclude = true;
22
- }
23
- else {
24
- terms.push(arg);
25
- }
26
- });
27
- const filter = terms.length === 0
28
- ? null
29
- : {
30
- terms,
31
- exclude,
32
- };
33
- return {
34
- filter,
35
- debug,
36
- };
10
+ const filter = (0, utils_1.findFilesParseCliArgs)();
11
+ (0, runTestSuites_1.runTestSuites)(filter);
37
12
  }
38
13
  function initPromiseRejectionHandler() {
39
14
  process.on('unhandledRejection', function (err) {
package/dist/editFile.js CHANGED
@@ -7,7 +7,7 @@ exports.editFileAssertReverted = exports.editFileRevert = exports.editFile = voi
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const utils_1 = require("./utils");
10
- const getTestInfo_1 = require("./getTestInfo");
10
+ const getCurrentTest_1 = require("./getCurrentTest");
11
11
  const filesContentOriginal = {};
12
12
  function editFile(filePathRelative, replacer) {
13
13
  const filePath = getFilePath(filePathRelative);
@@ -42,7 +42,7 @@ function editFileAssertReverted() {
42
42
  }
43
43
  exports.editFileAssertReverted = editFileAssertReverted;
44
44
  function getFilePath(filePathRelative) {
45
- const { testFile } = (0, getTestInfo_1.getTestInfo)();
45
+ const { testFile } = (0, getCurrentTest_1.getCurrentTest)();
46
46
  const cwd = path_1.default.dirname(testFile);
47
47
  const filePath = require.resolve(filePathRelative, { paths: [cwd] });
48
48
  return filePath;
@@ -2,12 +2,26 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getBrowser = void 0;
4
4
  const playwright_chromium_1 = require("playwright-chromium");
5
+ const Logs_1 = require("./Logs");
5
6
  const utils_1 = require("./utils");
6
7
  let browser;
7
8
  async function getBrowser() {
8
9
  if (!browser) {
9
10
  const done = (0, utils_1.logProgress)('Launch Browser');
10
- browser = await playwright_chromium_1.chromium.launch({ headless: true });
11
+ browser = await playwright_chromium_1.chromium.launch({
12
+ headless: true,
13
+ logger: {
14
+ isEnabled: () => true,
15
+ log: (name, _severity, message, args, _hint, ...rest) => {
16
+ (0, utils_1.assert)(args.length === 0);
17
+ (0, utils_1.assert)(rest.length === 0);
18
+ Logs_1.Logs.add({
19
+ logSource: 'Playwright',
20
+ logText: `${name} ${message}`,
21
+ });
22
+ },
23
+ },
24
+ });
11
25
  done();
12
26
  }
13
27
  return browser;
@@ -0,0 +1,30 @@
1
+ export { getCurrentTest };
2
+ export { getCurrentTestOptional };
3
+ export { setCurrentTest };
4
+ import type { Page } from 'playwright-chromium';
5
+ declare type TestInfo = {
6
+ testFile: string;
7
+ testName: string;
8
+ tests?: {
9
+ testDesc: string;
10
+ testFn: Function;
11
+ }[];
12
+ runInfo?: {
13
+ cmd: string;
14
+ cwd: string;
15
+ testTimeout: number;
16
+ additionalTimeout: number;
17
+ serverIsReadyMessage?: string;
18
+ serverIsReadyDelay: number;
19
+ debug: boolean;
20
+ };
21
+ hasStartedRunning?: boolean;
22
+ skipped?: string;
23
+ startServer?: () => Promise<void>;
24
+ terminateServer?: () => Promise<void>;
25
+ afterEach?: (hasFailed: boolean) => void;
26
+ page?: Page;
27
+ };
28
+ declare function getCurrentTest(): TestInfo;
29
+ declare function getCurrentTestOptional(): null | TestInfo;
30
+ declare function setCurrentTest(testFile: null | string): void;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setCurrentTest = exports.getCurrentTestOptional = exports.getCurrentTest = void 0;
7
+ const utils_1 = require("./utils");
8
+ const path_1 = __importDefault(require("path"));
9
+ let testInfo = null;
10
+ function getCurrentTest() {
11
+ (0, utils_1.assert)(testInfo);
12
+ return testInfo;
13
+ }
14
+ exports.getCurrentTest = getCurrentTest;
15
+ function getCurrentTestOptional() {
16
+ return testInfo;
17
+ }
18
+ exports.getCurrentTestOptional = getCurrentTestOptional;
19
+ function setCurrentTest(testFile) {
20
+ if (testFile) {
21
+ testInfo = {
22
+ testFile,
23
+ testName: getTestName(testFile),
24
+ };
25
+ }
26
+ else {
27
+ testInfo = null;
28
+ }
29
+ }
30
+ exports.setCurrentTest = setCurrentTest;
31
+ function getTestName(testFile) {
32
+ const pathRelative = removeRootDir(testFile);
33
+ if (testFile.includes('examples')) {
34
+ return path_1.default.dirname(pathRelative);
35
+ }
36
+ else {
37
+ return pathRelative;
38
+ }
39
+ }
40
+ function removeRootDir(filePath) {
41
+ const rootDir = process.cwd();
42
+ (0, utils_1.assert)(filePath.startsWith(rootDir));
43
+ return filePath.slice(rootDir.length);
44
+ }
package/dist/page.js CHANGED
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.page = void 0;
4
4
  const utils_1 = require("./utils");
5
- const getTestInfo_1 = require("./getTestInfo");
5
+ const getCurrentTest_1 = require("./getCurrentTest");
6
6
  const page = new Proxy({}, {
7
7
  get(_, prop) {
8
- const { page } = (0, getTestInfo_1.getTestInfo)();
8
+ const { page } = (0, getCurrentTest_1.getCurrentTest)();
9
9
  (0, utils_1.assert)(page);
10
10
  return page[prop];
11
11
  },
@@ -1,6 +1,3 @@
1
1
  export { runTestSuites };
2
2
  import { FindFilter } from './utils';
3
- declare function runTestSuites({ filter, debug }: {
4
- filter: null | FindFilter;
5
- debug: boolean;
6
- }): Promise<void>;
3
+ declare function runTestSuites(filter: null | FindFilter): Promise<void>;
@@ -1,35 +1,28 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.runTestSuites = void 0;
7
4
  const utils_1 = require("./utils");
8
- const fs_1 = __importDefault(require("fs"));
9
- const getTestInfo_1 = require("./getTestInfo");
5
+ const getCurrentTest_1 = require("./getCurrentTest");
10
6
  const runTests_1 = require("./runTests");
11
7
  const getBrowser_1 = require("./getBrowser");
12
8
  const buildTs_1 = require("./buildTs");
13
9
  const findTestFiles_1 = require("./findTestFiles");
14
- async function runTestSuites({ filter, debug }) {
10
+ async function runTestSuites(filter) {
15
11
  const testFiles = await (0, findTestFiles_1.findTestFiles)(filter);
16
12
  const browser = await (0, getBrowser_1.getBrowser)();
17
13
  for (const testFile of testFiles) {
18
14
  (0, utils_1.assert)(testFile.endsWith('.ts'));
19
15
  const testFileJs = testFile.replace('.ts', '.mjs');
20
- await (0, buildTs_1.buildTs)(testFile, testFileJs);
21
- (0, getTestInfo_1.setTestInfo)({ testFile });
16
+ const clean = await (0, buildTs_1.buildTs)(testFile, testFileJs);
17
+ (0, getCurrentTest_1.setCurrentTest)(testFile);
22
18
  try {
23
19
  await import(workaroundBug(testFileJs));
24
- await (0, runTests_1.runTests)(browser);
25
20
  }
26
21
  finally {
27
- if (!debug) {
28
- fs_1.default.unlinkSync(`${testFileJs}`);
29
- fs_1.default.unlinkSync(`${testFileJs}.map`);
30
- }
22
+ clean();
31
23
  }
32
- (0, getTestInfo_1.setTestInfo)(null);
24
+ await (0, runTests_1.runTests)(browser);
25
+ (0, getCurrentTest_1.setCurrentTest)(null);
33
26
  (0, utils_1.assert)(testFileJs.endsWith('.mjs'));
34
27
  }
35
28
  await browser.close();
package/dist/runTests.js CHANGED
@@ -1,13 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runTests = void 0;
4
- const getTestInfo_1 = require("./getTestInfo");
4
+ const getCurrentTest_1 = require("./getCurrentTest");
5
5
  const Logs_1 = require("./Logs");
6
6
  const utils_1 = require("./utils");
7
- const expect_1 = require("./chai/expect");
8
7
  const picocolors_1 = require("picocolors");
9
8
  async function runTests(browser) {
10
- const testInfo = (0, getTestInfo_1.getTestInfo)();
9
+ const testInfo = (0, getCurrentTest_1.getCurrentTest)();
11
10
  if (utils_1.isTTY) {
12
11
  console.log();
13
12
  console.log(testInfo.testFile);
@@ -16,25 +15,37 @@ async function runTests(browser) {
16
15
  testInfo.page = page;
17
16
  // Set when user calls `skip()`
18
17
  if (testInfo.skipped) {
19
- (0, utils_1.assertUsage)(!testInfo.runWasCalled, 'You cannot call `run()` after calling `skip()`');
18
+ (0, utils_1.assertUsage)(!testInfo.runInfo, 'You cannot call `run()` after calling `skip()`');
20
19
  (0, utils_1.assertUsage)(testInfo.tests === undefined, 'You cannot call `test()` after calling `skip()`');
21
20
  logTestsResult(false);
22
21
  return;
23
22
  }
24
23
  // Set when user calls `run()`
25
- (0, utils_1.assert)(testInfo.runWasCalled);
26
- (0, utils_1.assert)(testInfo.beforeAll);
27
- (0, utils_1.assert)(testInfo.afterAll);
24
+ (0, utils_1.assert)(testInfo.runInfo);
25
+ (0, utils_1.assert)(testInfo.startServer);
26
+ (0, utils_1.assert)(testInfo.terminateServer);
28
27
  (0, utils_1.assert)(testInfo.afterEach);
29
- (0, utils_1.assert)(testInfo.testTimeout);
30
28
  // Set when user calls `test()`
31
29
  (0, utils_1.assert)(testInfo.tests);
32
- await testInfo.beforeAll();
30
+ // TODO: resolve a success flag instead rejecting
31
+ try {
32
+ await testInfo.startServer();
33
+ }
34
+ catch (err) {
35
+ console.log(err);
36
+ Logs_1.Logs.flush();
37
+ logTestsResult(false);
38
+ process.exit(1);
39
+ }
33
40
  for (const { testDesc, testFn } of testInfo.tests) {
41
+ Logs_1.Logs.add({
42
+ logSource: 'test()',
43
+ logText: testDesc,
44
+ });
34
45
  const done = (0, utils_1.logProgress)(` | [test] ${testDesc}`);
35
46
  let err;
36
47
  try {
37
- await runTest(testFn, testInfo.testTimeout);
48
+ await runTest(testFn, testInfo.runInfo.testTimeout);
38
49
  }
39
50
  catch (err_) {
40
51
  err = err_;
@@ -42,27 +53,24 @@ async function runTests(browser) {
42
53
  done(!!err);
43
54
  testInfo.afterEach(!!err);
44
55
  const browserErrors = Logs_1.Logs.getBrowserErrors();
45
- const isFailure = err || browserErrors.length > 0;
46
- if (isFailure) {
47
- Logs_1.Logs.flush();
48
- }
49
- Logs_1.Logs.clear();
56
+ const browserThrewError = browserErrors.length > 0;
57
+ const isFailure = err || browserThrewError;
50
58
  if (isFailure) {
51
- logTestsResult(false);
52
- if (browserErrors.length === 0) {
53
- throw err;
59
+ if (err) {
60
+ console.error(err);
54
61
  }
55
- else {
56
- if (err) {
57
- console.error(err);
58
- }
59
- // Display all browser errors
60
- (0, expect_1.expect)(browserErrors).deep.equal([]);
61
- (0, utils_1.assert)(false);
62
+ if (browserThrewError) {
63
+ console.log(new Error('The browser threw one or more error'));
62
64
  }
65
+ Logs_1.Logs.flush();
66
+ logTestsResult(false);
67
+ process.exit(1);
68
+ }
69
+ else {
70
+ Logs_1.Logs.clear();
63
71
  }
64
72
  }
65
- await testInfo.afterAll();
73
+ await testInfo.terminateServer();
66
74
  await page.close();
67
75
  logTestsResult(true);
68
76
  }
@@ -75,7 +83,7 @@ function runTest(testFn, testTimeout) {
75
83
  reject = reject_;
76
84
  });
77
85
  const timeout = setTimeout(() => {
78
- reject(new Error(`[test][timeout after ${(0, utils_1.humanizeTime)(testTimeout)}]`));
86
+ reject(new Error(`[test] Timeout after ${(0, utils_1.humanizeTime)(testTimeout)}`));
79
87
  }, testTimeout);
80
88
  const ret = testFn();
81
89
  (async () => {
@@ -93,7 +101,7 @@ function runTest(testFn, testTimeout) {
93
101
  return promise;
94
102
  }
95
103
  function logTestsResult(success) {
96
- const testInfo = (0, getTestInfo_1.getTestInfo)();
104
+ const testInfo = (0, getCurrentTest_1.getCurrentTest)();
97
105
  const passStyle = (t) => (0, picocolors_1.white)((0, picocolors_1.bgGreen)(t));
98
106
  const failStyle = (t) => (0, picocolors_1.white)((0, picocolors_1.bgRed)(t));
99
107
  const skipStyle = (t) => (0, picocolors_1.white)((0, picocolors_1.bgYellow)(t));
package/dist/setup.js CHANGED
@@ -13,7 +13,7 @@ const utils_2 = require("./utils");
13
13
  const Logs_1 = require("./Logs");
14
14
  const strip_ansi_1 = __importDefault(require("strip-ansi"));
15
15
  const editFile_1 = require("./editFile");
16
- const getTestInfo_1 = require("./getTestInfo");
16
+ const getCurrentTest_1 = require("./getCurrentTest");
17
17
  const page_1 = require("./page");
18
18
  var part_regex_1 = require("@brillout/part-regex");
19
19
  Object.defineProperty(exports, "partRegex", { enumerable: true, get: function () { return part_regex_1.partRegex; } });
@@ -31,45 +31,30 @@ const TIMEOUT_AUTORETRY = 10 * 1000 * (!isGithubAction() || isLinux() ? 1 : 20);
31
31
  const TIMEOUT_PROCESS_TERMINATION = 10 * 1000 * (!isGithubAction() ? 1 : isLinux() ? 1 : 4);
32
32
  const TIMEOUT_PLAYWRIGHT = TIMEOUT_JEST;
33
33
  function skip(reason) {
34
- const testInfo = (0, getTestInfo_1.getTestInfo)();
34
+ const testInfo = (0, getCurrentTest_1.getCurrentTest)();
35
35
  testInfo.skipped = reason;
36
36
  }
37
37
  exports.skip = skip;
38
38
  function run(cmd, {
39
39
  //baseUrl = '',
40
- additionalTimeout = 0, serverIsReadyMessage, serverIsReadyDelay = 1000, debug = !!process.env.DEBUG, cwd, } = {}) {
40
+ additionalTimeout = 0, serverIsReadyMessage, serverIsReadyDelay = 1000, debug = utils_1.cliConfig.debug, cwd, } = {}) {
41
41
  additionalTimeout += serverIsReadyDelay;
42
- const testInfo = (0, getTestInfo_1.getTestInfo)();
43
- testInfo.runWasCalled = true;
44
- testInfo.testCmd = cmd;
45
- testInfo.testTimeout = TIMEOUT_JEST + additionalTimeout;
46
- /*
47
- const browser = await getBrowser()
48
- const page = await browser.newPage()
49
- testInfo.page = page
50
-
51
- const { page } = testInfo
52
- // Set by `./runTests`
53
- assert(page)
54
- */
55
- if (debug) {
56
- Logs_1.Logs.flushEagerly = true;
57
- }
58
- const testContext = {
42
+ const testInfo = (0, getCurrentTest_1.getCurrentTest)();
43
+ testInfo.runInfo = {
59
44
  cmd,
60
45
  cwd: cwd || getCwd(),
61
- testName: getTestName(),
62
46
  additionalTimeout,
47
+ testTimeout: TIMEOUT_JEST + additionalTimeout,
63
48
  serverIsReadyMessage,
64
49
  serverIsReadyDelay,
65
50
  debug,
66
51
  };
67
- logJestStep('run start');
52
+ if (debug) {
53
+ Logs_1.Logs.flushEagerly = true;
54
+ }
68
55
  let runProcess = null;
69
- testInfo.beforeAll = async () => {
70
- logJestStep('beforeAll start');
71
- runProcess = await start(testContext);
72
- logJestStep('run done');
56
+ testInfo.startServer = async () => {
57
+ runProcess = await start();
73
58
  page_1.page.on('console', onConsole);
74
59
  page_1.page.on('pageerror', onPageError);
75
60
  // This setting will change the default maximum time for all the methods accepting timeout option.
@@ -83,7 +68,6 @@ additionalTimeout = 0, serverIsReadyMessage, serverIsReadyDelay = 1000, debug =
83
68
  { timeout: TIMEOUT_PAGE_LOAD + additionalTimeout },
84
69
  )
85
70
  */
86
- logJestStep('beforeAll end');
87
71
  };
88
72
  testInfo.afterEach = (hasFailed) => {
89
73
  if (!hasFailed) {
@@ -93,63 +77,58 @@ additionalTimeout = 0, serverIsReadyMessage, serverIsReadyDelay = 1000, debug =
93
77
  (0, editFile_1.editFileRevert)();
94
78
  }
95
79
  };
96
- testInfo.afterAll = async () => {
97
- logJestStep('afterAll start');
80
+ testInfo.terminateServer = async () => {
98
81
  page_1.page.off('console', onConsole);
99
82
  page_1.page.off('pageerror', onPageError);
100
83
  // `runProcess` is `undefined` if `start()` failed.
101
84
  if (runProcess) {
102
85
  await runProcess.terminate('SIGINT');
103
86
  }
104
- logJestStep('afterAll end');
105
87
  };
106
- // return { page }
107
88
  return;
108
89
  // Also called when the page throws an error or a warning
109
90
  function onConsole(msg) {
110
91
  const type = msg.type();
111
92
  Logs_1.Logs.add({
112
- logType: type === 'error' ? 'Browser Error' : 'Browser Log',
93
+ logSource: type === 'error' ? 'Browser Error' : 'Browser Log',
113
94
  logText: JSON.stringify({
114
95
  type,
115
96
  text: msg.text(),
116
97
  location: msg.location(),
117
98
  args: msg.args(),
118
99
  }, null, 2),
119
- testContext,
120
100
  });
121
101
  }
122
102
  // For uncaught exceptions
123
103
  function onPageError(err) {
124
104
  Logs_1.Logs.add({
125
- logType: 'Browser Error',
105
+ logSource: 'Browser Error',
126
106
  logText: JSON.stringify({
127
107
  text: err.message,
128
108
  location: err.stack,
129
109
  }, null, 2),
130
- testContext,
131
- });
132
- }
133
- function logJestStep(stepName) {
134
- if (!debug) {
135
- return;
136
- }
137
- Logs_1.Logs.add({
138
- logType: 'Jest',
139
- logText: stepName,
140
- testContext,
141
110
  });
142
111
  }
143
112
  }
144
113
  exports.run = run;
145
- async function start(testContext) {
146
- const { cmd, additionalTimeout, serverIsReadyMessage, serverIsReadyDelay } = testContext;
147
- let hasStarted = false;
114
+ function getRunInfo() {
115
+ const testInfo = (0, getCurrentTest_1.getCurrentTest)();
116
+ (0, utils_2.assert)(testInfo.runInfo);
117
+ return testInfo.runInfo;
118
+ }
119
+ async function start() {
120
+ const { cmd, additionalTimeout, serverIsReadyMessage, serverIsReadyDelay } = getRunInfo();
121
+ const done = (0, utils_1.logProgress)(` | [run] ${cmd}`);
122
+ let hasSuccessfullyStarted = false;
148
123
  let resolveServerStart;
149
124
  let rejectServerStart;
150
125
  const promise = new Promise((_resolve, _reject) => {
151
126
  resolveServerStart = () => {
152
- hasStarted = true;
127
+ Logs_1.Logs.add({
128
+ logSource: 'run()',
129
+ logText: 'server is ready',
130
+ });
131
+ hasSuccessfullyStarted = true;
153
132
  clearTimeout(serverStartTimeout);
154
133
  const runProcess = { terminate };
155
134
  _resolve(runProcess);
@@ -157,9 +136,8 @@ async function start(testContext) {
157
136
  rejectServerStart = async (err) => {
158
137
  done(true);
159
138
  Logs_1.Logs.add({
160
- logType: 'stderr',
139
+ logSource: 'stderr',
161
140
  logText: String(err),
162
- testContext,
163
141
  });
164
142
  clearTimeout(serverStartTimeout);
165
143
  try {
@@ -167,35 +145,35 @@ async function start(testContext) {
167
145
  }
168
146
  catch (err) {
169
147
  Logs_1.Logs.add({
170
- logType: 'process',
148
+ logSource: 'run()',
171
149
  logText: String(err),
172
- testContext,
173
150
  });
174
151
  }
175
152
  _reject(err);
176
153
  };
177
154
  });
178
155
  const timeoutTotal = TIMEOUT_NPM_SCRIPT + additionalTimeout;
156
+ let hasTimedout = false;
179
157
  const serverStartTimeout = setTimeout(() => {
180
158
  let errMsg = '';
181
- errMsg += `Server still didn't start after ${timeoutTotal / 1000} seconds of running the npm script \`${cmd}\`.`;
159
+ errMsg += `Server still didn't start after ${(0, utils_1.humanizeTime)(timeoutTotal)} of running the npm script \`${cmd}\`.`;
182
160
  if (serverIsReadyMessage) {
183
161
  errMsg += ` (The stdout of the npm script did not include: "${serverIsReadyMessage}".)`;
184
162
  }
163
+ hasTimedout = true;
185
164
  rejectServerStart(new Error(errMsg));
186
165
  }, timeoutTotal);
187
166
  // Kill any process that listens to port `3000`
188
167
  if (!process.env.CI && isLinux()) {
189
168
  await (0, utils_1.runCommand)('fuser -k 3000/tcp', { swallowError: true, timeout: 10 * 1000 });
190
169
  }
191
- const done = (0, utils_1.logProgress)(` | [run] ${cmd}`);
192
- const { terminate } = startScript(cmd, testContext, {
170
+ const { terminate } = execRunScript({
193
171
  onError(err) {
194
172
  rejectServerStart(err);
195
173
  },
196
174
  onExit() {
197
- const exitIsExpected = hasStarted === true;
198
- return exitIsExpected;
175
+ const exitIsPossible = hasSuccessfullyStarted === true || hasTimedout;
176
+ return exitIsPossible;
199
177
  },
200
178
  async onStdout(data) {
201
179
  const text = (0, strip_ansi_1.default)(data);
@@ -268,7 +246,8 @@ function stopProcess({ proc, cwd, cmd, signal, }) {
268
246
  }
269
247
  return promise;
270
248
  }
271
- function startScript(cmd, testContext, { onStdout, onStderr, onError, onExit, }) {
249
+ function execRunScript({ onStdout, onStderr, onError, onExit, }) {
250
+ const { cwd, cmd } = getRunInfo();
272
251
  let [command, ...args] = cmd.split(' ');
273
252
  let detached = true;
274
253
  if (isWindows()) {
@@ -277,40 +256,39 @@ function startScript(cmd, testContext, { onStdout, onStderr, onError, onExit, })
277
256
  command = command + '.cmd';
278
257
  }
279
258
  }
280
- const { cwd } = testContext;
259
+ Logs_1.Logs.add({
260
+ logSource: 'run()',
261
+ logText: `Spawn command \`${cmd}\``,
262
+ });
281
263
  const proc = (0, child_process_1.spawn)(command, args, { cwd, detached });
282
- const prefix = `[Run Start][${cwd}][${cmd}]`;
283
264
  proc.stdin.on('data', async (data) => {
284
265
  onError(new Error(`Command is \`${cmd}\` (${cwd}) is invoking \`stdin\`: ${data}.`));
285
266
  });
286
267
  proc.stdout.on('data', async (data) => {
287
268
  data = data.toString();
288
269
  Logs_1.Logs.add({
289
- logType: 'stdout',
270
+ logSource: 'stdout',
290
271
  logText: data,
291
- testContext,
292
272
  });
293
273
  onStdout?.(data);
294
274
  });
295
275
  proc.stderr.on('data', async (data) => {
296
276
  data = data.toString();
297
277
  Logs_1.Logs.add({
298
- logType: 'stderr',
278
+ logSource: 'stderr',
299
279
  logText: data,
300
- testContext,
301
280
  });
302
281
  onStderr?.(data);
303
282
  });
304
283
  proc.on('exit', async (code) => {
305
- const exitIsExpected = onExit();
284
+ const exitIsPossible = onExit();
306
285
  const isSuccessCode = [0, null].includes(code) || (isWindows() && code === 1);
307
- const isExpected = isSuccessCode && exitIsExpected;
286
+ const isExpected = isSuccessCode && exitIsPossible;
308
287
  if (!isExpected) {
309
- const errMsg = `${prefix} Unexpected premature process termination, exit code: ${code}`;
288
+ const errMsg = `Unexpected premature process termination, exit code: ${code}`;
310
289
  Logs_1.Logs.add({
311
290
  logText: errMsg,
312
- logType: 'stderr',
313
- testContext,
291
+ logSource: 'stderr',
314
292
  });
315
293
  onError(new Error(errMsg));
316
294
  /*
@@ -325,9 +303,8 @@ function startScript(cmd, testContext, { onStdout, onStderr, onError, onExit, })
325
303
  }
326
304
  else {
327
305
  Logs_1.Logs.add({
328
- logText: `${prefix} Process termination. (Nominal. Exit code: ${code}.)`,
329
- logType: 'process',
330
- testContext,
306
+ logText: `Process termination. (Nominal, exit code: ${code}.)`,
307
+ logSource: 'run()',
331
308
  });
332
309
  }
333
310
  });
@@ -385,11 +362,10 @@ async function fetch(...args) {
385
362
  }
386
363
  catch (err) {
387
364
  Logs_1.Logs.add({
388
- logType: 'Connection Error',
365
+ logSource: 'Connection Error',
389
366
  logText: `Couldn't connect to \`${args[0]}\`. Args: \`${JSON.stringify(args.slice(1))}\`. Err: \`${
390
367
  // @ts-ignore
391
368
  err.message}\``,
392
- testContext: null,
393
369
  });
394
370
  throw new Error("Couldn't connect to server. See `Connection Error` log for more details.");
395
371
  }
@@ -443,22 +419,7 @@ function isGithubAction() {
443
419
  }
444
420
  exports.isGithubAction = isGithubAction;
445
421
  function getCwd() {
446
- const { testFile } = (0, getTestInfo_1.getTestInfo)();
422
+ const { testFile } = (0, getCurrentTest_1.getCurrentTest)();
447
423
  const cwd = (0, path_1.dirname)(testFile);
448
424
  return cwd;
449
425
  }
450
- function getTestName() {
451
- const { testFile } = (0, getTestInfo_1.getTestInfo)();
452
- const pathRelative = removeRootDir(testFile);
453
- if (testFile.includes('examples')) {
454
- return (0, path_1.dirname)(pathRelative);
455
- }
456
- else {
457
- return pathRelative;
458
- }
459
- }
460
- function removeRootDir(filePath) {
461
- const rootDir = process.cwd();
462
- (0, utils_2.assert)(filePath.startsWith(rootDir));
463
- return filePath.slice(rootDir.length);
464
- }
package/dist/test.js CHANGED
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.test = void 0;
4
4
  const utils_1 = require("./utils");
5
- const getTestInfo_1 = require("./getTestInfo");
5
+ const getCurrentTest_1 = require("./getCurrentTest");
6
6
  function test(testDesc, testFn) {
7
- const testInfo = (0, getTestInfo_1.getTestInfo)();
7
+ const testInfo = (0, getCurrentTest_1.getCurrentTest)();
8
8
  (0, utils_1.assert)(!testInfo.hasStartedRunning);
9
9
  testInfo.tests = testInfo.tests ?? [];
10
10
  testInfo.tests.push({
@@ -26,7 +26,7 @@ function assert(condition, debugInfo) {
26
26
  `Reach out at ${projectInfo_1.projectInfo.githubRepository}/issues/new and include this error stack (the error stack is usually enough to fix the problem).`,
27
27
  'A maintainer will fix the bug (usually under 24 hours).',
28
28
  `Do not hesitate to reach out as it makes ${projectInfo_1.projectInfo.projectName} more robust.`,
29
- debugStr
29
+ debugStr,
30
30
  ].join(' '), numberOfStackTraceLinesToRemove);
31
31
  throw internalError;
32
32
  }
@@ -0,0 +1,4 @@
1
+ export declare const cliConfig: {
2
+ debugEsbuild: boolean;
3
+ debug: boolean;
4
+ };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cliConfig = void 0;
4
+ const cliArgs = process.argv.slice(2);
5
+ exports.cliConfig = {
6
+ debugEsbuild: cliArgs.includes('--debug-esbuild'),
7
+ debug: cliArgs.includes('--debug'),
8
+ };
@@ -1,7 +1,9 @@
1
1
  export { findFiles };
2
+ export { findFilesParseCliArgs };
2
3
  export type { FindFilter };
3
4
  declare type FindFilter = {
4
5
  terms: string[];
5
6
  exclude: boolean;
6
7
  };
7
8
  declare function findFiles(pattern: string, findFilter: null | FindFilter): Promise<string[]>;
9
+ declare function findFilesParseCliArgs(): null | FindFilter;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.findFiles = void 0;
6
+ exports.findFilesParseCliArgs = exports.findFiles = void 0;
7
7
  const fast_glob_1 = __importDefault(require("fast-glob"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const runCommand_1 = require("./runCommand");
@@ -44,3 +44,23 @@ function applyFilter(filePathRelative, findFilter) {
44
44
  }
45
45
  return true;
46
46
  }
47
+ function findFilesParseCliArgs() {
48
+ const terms = [];
49
+ let exclude = false;
50
+ process.argv.slice(2).forEach((arg) => {
51
+ if (arg === '--exclude') {
52
+ exclude = true;
53
+ }
54
+ if (!arg.startsWith('--')) {
55
+ terms.push(arg);
56
+ }
57
+ });
58
+ const filter = terms.length === 0
59
+ ? null
60
+ : {
61
+ terms,
62
+ exclude,
63
+ };
64
+ return filter;
65
+ }
66
+ exports.findFilesParseCliArgs = findFilesParseCliArgs;
@@ -11,5 +11,8 @@ function humanizeTime(milliseconds) {
11
11
  }
12
12
  exports.humanizeTime = humanizeTime;
13
13
  function round(n) {
14
- return n.toFixed(1);
14
+ let rounded = n.toFixed(1);
15
+ if (rounded.endsWith('.0'))
16
+ rounded = rounded.slice(0, -2);
17
+ return rounded;
15
18
  }
@@ -5,3 +5,4 @@ export * from './humanizeTime';
5
5
  export * from './isTTY';
6
6
  export * from './findFiles';
7
7
  export * from './logProgress';
8
+ export * from './cliConfig';
@@ -21,3 +21,4 @@ __exportStar(require("./humanizeTime"), exports);
21
21
  __exportStar(require("./isTTY"), exports);
22
22
  __exportStar(require("./findFiles"), exports);
23
23
  __exportStar(require("./logProgress"), exports);
24
+ __exportStar(require("./cliConfig"), exports);
@@ -1,2 +1,4 @@
1
1
  export { logProgress };
2
+ export { ensureNewTerminalLine };
2
3
  declare function logProgress(text: string): (failed?: boolean) => void;
4
+ declare function ensureNewTerminalLine(): boolean;
@@ -1,16 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.logProgress = void 0;
3
+ exports.ensureNewTerminalLine = exports.logProgress = void 0;
4
4
  const isTTY_1 = require("./isTTY");
5
5
  const iconSuccess = '🟢';
6
6
  const iconPending = '🟠';
7
7
  const iconFail = '🔴';
8
+ let terminalLineIsEmtpy = true;
8
9
  function logProgress(text) {
9
10
  if (!isTTY_1.isTTY) {
10
11
  const done = () => { };
11
12
  return done;
12
13
  }
13
14
  process.stdout.write(`${iconPending} ${text}`);
15
+ terminalLineIsEmtpy = false;
14
16
  let alreadyDone = false;
15
17
  const done = (failed) => {
16
18
  if (alreadyDone)
@@ -19,10 +21,17 @@ function logProgress(text) {
19
21
  clear();
20
22
  const iconDone = failed ? iconFail : iconSuccess;
21
23
  process.stdout.write(`${iconDone} ${text}\n`);
24
+ terminalLineIsEmtpy = true;
22
25
  };
23
26
  return done;
24
27
  }
25
28
  exports.logProgress = logProgress;
29
+ function ensureNewTerminalLine() {
30
+ const val = terminalLineIsEmtpy;
31
+ terminalLineIsEmtpy = true;
32
+ return val;
33
+ }
34
+ exports.ensureNewTerminalLine = ensureNewTerminalLine;
26
35
  function clear() {
27
36
  // @ts-ignore
28
37
  process.stdout.clearLine();
@@ -4,5 +4,5 @@ exports.projectInfo = void 0;
4
4
  exports.projectInfo = {
5
5
  projectName: '@brillout/test-e2e',
6
6
  npmPackageName: '@brillout/test-e2e',
7
- githubRepository: 'https://github.com/brillout/test-e2e'
7
+ githubRepository: 'https://github.com/brillout/test-e2e',
8
8
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brillout/test-e2e",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "bin": "./bin.js",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -1,21 +0,0 @@
1
- export { getTestInfo };
2
- export { setTestInfo };
3
- import type { Page } from 'playwright-chromium';
4
- declare type TestInfo = {
5
- testFile: string;
6
- tests?: {
7
- testDesc: string;
8
- testFn: Function;
9
- }[];
10
- testCmd?: string;
11
- testTimeout?: number;
12
- hasStartedRunning?: boolean;
13
- runWasCalled?: true;
14
- skipped?: string;
15
- beforeAll?: () => Promise<void>;
16
- afterAll?: () => Promise<void>;
17
- afterEach?: (hasFailed: boolean) => void;
18
- page?: Page;
19
- };
20
- declare function getTestInfo(): TestInfo;
21
- declare function setTestInfo(testInfo_: null | TestInfo): void;
@@ -1,14 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setTestInfo = exports.getTestInfo = void 0;
4
- const utils_1 = require("./utils");
5
- let testInfo = null;
6
- function getTestInfo() {
7
- (0, utils_1.assert)(testInfo);
8
- return testInfo;
9
- }
10
- exports.getTestInfo = getTestInfo;
11
- function setTestInfo(testInfo_) {
12
- testInfo = testInfo_;
13
- }
14
- exports.setTestInfo = setTestInfo;