qunitx-cli 0.5.1 → 0.5.3

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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # qunitx-cli
2
2
 
3
3
  [![CI](https://github.com/izelnakri/qunitx-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/izelnakri/qunitx-cli/actions/workflows/ci.yml)
4
+ [![codecov](https://codecov.io/gh/izelnakri/qunitx-cli/branch/main/graph/badge.svg)](https://codecov.io/gh/izelnakri/qunitx-cli)
4
5
  [![npm](https://img.shields.io/npm/v/qunitx-cli)](https://www.npmjs.com/package/qunitx-cli)
5
6
  [![npm downloads](https://img.shields.io/npm/dm/qunitx-cli)](https://www.npmjs.com/package/qunitx-cli)
6
7
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
@@ -8,7 +9,7 @@
8
9
  Browser-based test runner for [QUnitX](https://github.com/izelnakri/qunitx) — bundles your JS/TS tests
9
10
  with esbuild, runs them in headless Chrome, and streams TAP output to the terminal.
10
11
 
11
- ![qunitx-cli demo](demo/demo.gif)
12
+ ![qunitx-cli demo](docs/demo.gif)
12
13
 
13
14
  ## Features
14
15
 
@@ -154,7 +155,7 @@ Options:
154
155
  npm install
155
156
  make check # lint + test (run before every commit)
156
157
  make test # run tests only
157
- make demo # regenerate demo output
158
+ make demo # regenerate docs/demo.gif
158
159
  make release LEVEL=patch # bump version, update changelog, tag, push
159
160
  ```
160
161
 
package/cli.js CHANGED
@@ -19,7 +19,7 @@ process.title = 'qunitx';
19
19
  return await initializeProject();
20
20
  }
21
21
 
22
- let config = await setupConfig();
22
+ const config = await setupConfig();
23
23
 
24
24
  return await run(config);
25
25
  })();
package/deno.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "lint": {
3
+ "rules": {
4
+ "exclude": ["no-process-global", "no-node-globals", "no-window"]
5
+ }
6
+ }
7
+ }
@@ -1,6 +1,6 @@
1
1
  import { module, test } from 'qunitx';
2
2
 
3
- module('{{moduleName}}', function (hooks) {
3
+ module('{{moduleName}}', function (_hooks) {
4
4
  test('assert true works', function (assert) {
5
5
  assert.expect(3);
6
6
  assert.ok(true);
@@ -11,11 +11,11 @@ module('{{moduleName}}', function (hooks) {
11
11
  test('async test finishes', async function (assert) {
12
12
  assert.expect(3);
13
13
 
14
- let wait = () =>
15
- new Promise((resolve, reject) => {
14
+ const wait = () =>
15
+ new Promise((resolve) => {
16
16
  setTimeout(() => resolve(true), 50);
17
17
  });
18
- let result = await wait();
18
+ const result = await wait();
19
19
 
20
20
  assert.ok(true);
21
21
  assert.equal(true, result);
@@ -8,9 +8,9 @@ import pathExists from '../utils/path-exists.js';
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
9
 
10
10
  export default async function () {
11
- let projectRoot = await findProjectRoot();
12
- let moduleName = process.argv[3]; // TODO: classify this maybe in future
13
- let path =
11
+ const projectRoot = await findProjectRoot();
12
+ const moduleName = process.argv[3]; // TODO: classify this maybe in future
13
+ const path =
14
14
  process.argv[3].endsWith('.js') || process.argv[3].endsWith('.ts')
15
15
  ? `${projectRoot}/${process.argv[3]}`
16
16
  : `${projectRoot}/${process.argv[3]}.js`;
@@ -19,8 +19,8 @@ export default async function () {
19
19
  return console.log(`${path} already exists!`);
20
20
  }
21
21
 
22
- let testJSContent = await fs.readFile(`${__dirname}/../boilerplates/test.js`);
23
- let targetFolderPaths = path.split('/');
22
+ const testJSContent = await fs.readFile(`${__dirname}/../boilerplates/test.js`);
23
+ const targetFolderPaths = path.split('/');
24
24
 
25
25
  targetFolderPaths.pop();
26
26
 
@@ -8,9 +8,9 @@ import defaultProjectConfigValues from '../boilerplates/default-project-config-v
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
9
 
10
10
  export default async function () {
11
- let projectRoot = await findProjectRoot();
12
- let oldPackageJSON = JSON.parse(await fs.readFile(`${projectRoot}/package.json`));
13
- let htmlPaths = process.argv.slice(2).reduce(
11
+ const projectRoot = await findProjectRoot();
12
+ const oldPackageJSON = JSON.parse(await fs.readFile(`${projectRoot}/package.json`));
13
+ const htmlPaths = process.argv.slice(2).reduce(
14
14
  (result, arg) => {
15
15
  if (arg.endsWith('.html')) {
16
16
  result.push(arg);
@@ -20,7 +20,7 @@ export default async function () {
20
20
  },
21
21
  oldPackageJSON.qunitx && oldPackageJSON.qunitx.htmlPaths ? oldPackageJSON.qunitx.htmlPaths : [],
22
22
  );
23
- let newQunitxConfig = Object.assign(
23
+ const newQunitxConfig = Object.assign(
24
24
  defaultProjectConfigValues,
25
25
  htmlPaths.length > 0 ? { htmlPaths } : { htmlPaths: ['test/tests.html'] },
26
26
  oldPackageJSON.qunitx,
@@ -34,20 +34,20 @@ export default async function () {
34
34
  }
35
35
 
36
36
  async function writeTestsHTML(projectRoot, newQunitxConfig, oldPackageJSON) {
37
- let testHTMLTemplateBuffer = await fs.readFile(`${__dirname}/../boilerplates/setup/tests.hbs`);
37
+ const testHTMLTemplateBuffer = await fs.readFile(`${__dirname}/../boilerplates/setup/tests.hbs`);
38
38
 
39
39
  return await Promise.all(
40
40
  newQunitxConfig.htmlPaths.map(async (htmlPath) => {
41
- let targetPath = `${projectRoot}/${htmlPath}`;
41
+ const targetPath = `${projectRoot}/${htmlPath}`;
42
42
  if (await pathExists(targetPath)) {
43
43
  return console.log(`${htmlPath} already exists`);
44
44
  } else {
45
- let targetDirectory = path.dirname(targetPath);
46
- let targetOutputPath = path.relative(
45
+ const targetDirectory = path.dirname(targetPath);
46
+ const _targetOutputPath = path.relative(
47
47
  targetDirectory,
48
48
  `${projectRoot}/${newQunitxConfig.output}/tests.js`,
49
49
  );
50
- let testHTMLTemplate = testHTMLTemplateBuffer
50
+ const testHTMLTemplate = testHTMLTemplateBuffer
51
51
  .toString()
52
52
  .replace('{{applicationName}}', oldPackageJSON.name);
53
53
 
@@ -61,15 +61,15 @@ async function writeTestsHTML(projectRoot, newQunitxConfig, oldPackageJSON) {
61
61
  }
62
62
 
63
63
  async function rewritePackageJSON(projectRoot, newQunitxConfig, oldPackageJSON) {
64
- let newPackageJSON = Object.assign(oldPackageJSON, { qunitx: newQunitxConfig });
64
+ const newPackageJSON = Object.assign(oldPackageJSON, { qunitx: newQunitxConfig });
65
65
 
66
66
  await fs.writeFile(`${projectRoot}/package.json`, JSON.stringify(newPackageJSON, null, 2));
67
67
  }
68
68
 
69
69
  async function writeTSConfigIfNeeded(projectRoot) {
70
- let targetPath = `${projectRoot}/tsconfig.json`;
70
+ const targetPath = `${projectRoot}/tsconfig.json`;
71
71
  if (!(await pathExists(targetPath))) {
72
- let tsConfigTemplateBuffer = await fs.readFile(
72
+ const tsConfigTemplateBuffer = await fs.readFile(
73
73
  `${__dirname}/../boilerplates/setup/tsconfig.json`,
74
74
  );
75
75
 
@@ -146,7 +146,7 @@ export default async function (config) {
146
146
  async function buildCachedContent(config, htmlPaths) {
147
147
  const htmlBuffers = await Promise.all(config.htmlPaths.map((htmlPath) => fs.readFile(htmlPath)));
148
148
  const cachedContent = htmlPaths.reduce(
149
- (result, htmlPath, index) => {
149
+ (result, _htmlPath, index) => {
150
150
  const filePath = config.htmlPaths[index];
151
151
  const html = htmlBuffers[index].toString();
152
152
 
@@ -208,7 +208,7 @@ function splitIntoGroups(files, groupCount) {
208
208
  return groups.filter((g) => g.length > 0);
209
209
  }
210
210
 
211
- function logWatcherAndKeyboardShortcutInfo(config, server) {
211
+ function logWatcherAndKeyboardShortcutInfo(config, _server) {
212
212
  console.log(
213
213
  '#',
214
214
  kleur.blue(`Watching files... You can browse the tests on http://localhost:${config.port} ...`),
@@ -15,14 +15,13 @@ export const MIME_TYPES = {
15
15
 
16
16
  export default class HTTPServer {
17
17
  static serve(config = { port: 1234 }, handler) {
18
- let onListen = config.onListen || ((server) => {});
19
- let onError = config.onError || ((error) => {});
18
+ const onListen = config.onListen || ((_server) => {});
19
+ const onError = config.onError || ((_error) => {});
20
20
 
21
21
  return new Promise((resolve, reject) => {
22
- let server = http.createServer((req, res) => {
22
+ const server = http.createServer((req, res) => {
23
23
  return handler(req, res);
24
24
  });
25
- server = server;
26
25
  server
27
26
  .on('error', (error) => {
28
27
  onError(error);
@@ -221,7 +220,7 @@ export default class HTTPServer {
221
220
  return true;
222
221
  }
223
222
 
224
- buildRegexPattern(path, paramNames) {
223
+ buildRegexPattern(path, _paramNames) {
225
224
  let regexPattern = path.replace(/:[^/]+/g, '([^/]+)');
226
225
  regexPattern = regexPattern.replace(/\//g, '\\/');
227
226
 
@@ -235,7 +234,7 @@ export default class HTTPServer {
235
234
  return paramMatches ? paramMatches.map((match) => match.slice(1)) : [];
236
235
  }
237
236
 
238
- extractParams(route, url) {
237
+ extractParams(route, _url) {
239
238
  const { paramNames, paramValues } = route;
240
239
  const params = {};
241
240
 
@@ -13,7 +13,7 @@ export default async function setupBrowser(
13
13
  cachedContent,
14
14
  existingBrowser = null,
15
15
  ) {
16
- let [server, browser] = await Promise.all([
16
+ const [server, browser] = await Promise.all([
17
17
  setupWebServer(config, cachedContent),
18
18
  existingBrowser
19
19
  ? Promise.resolve(existingBrowser)
@@ -29,7 +29,7 @@ export default async function setupBrowser(
29
29
  headless: true,
30
30
  }),
31
31
  ]);
32
- let [page, _] = await Promise.all([browser.newPage(), bindServerToPort(server, config)]);
32
+ const [page] = await Promise.all([browser.newPage(), bindServerToPort(server, config)]);
33
33
 
34
34
  page.on('console', async (msg) => {
35
35
  if (config.debug) {
@@ -39,20 +39,12 @@ export default async function setupBrowser(
39
39
  }
40
40
  });
41
41
  page.on('error', (msg) => {
42
- try {
43
- throw msg;
44
- } catch (e) {
45
- console.error(e, e.stack);
46
- console.log(e, e.stack);
47
- }
42
+ console.error(msg, msg.stack);
43
+ console.log(msg, msg.stack);
48
44
  });
49
- page.on('pageerror', async (error) => {
50
- try {
51
- throw error;
52
- } catch (e) {
53
- console.log(e.toString());
54
- console.error(e.toString());
55
- }
45
+ page.on('pageerror', (error) => {
46
+ console.log(error.toString());
47
+ console.error(error.toString());
56
48
  });
57
49
 
58
50
  return { server, browser, page };
@@ -6,11 +6,11 @@ import setupTestFilePaths from './test-file-paths.js';
6
6
  import parseCliFlags from '../utils/parse-cli-flags.js';
7
7
 
8
8
  export default async function setupConfig() {
9
- let projectRoot = await findProjectRoot();
10
- let cliConfigFlags = parseCliFlags(projectRoot);
11
- let projectPackageJSON = await readConfigFromPackageJSON(projectRoot);
12
- let inputs = cliConfigFlags.inputs.concat(readInputsFromPackageJSON(projectPackageJSON));
13
- let config = {
9
+ const projectRoot = await findProjectRoot();
10
+ const cliConfigFlags = parseCliFlags(projectRoot);
11
+ const projectPackageJSON = await readConfigFromPackageJSON(projectRoot);
12
+ const inputs = cliConfigFlags.inputs.concat(readInputsFromPackageJSON(projectPackageJSON));
13
+ const config = {
14
14
  ...defaultProjectConfigValues,
15
15
  htmlPaths: [],
16
16
  ...projectPackageJSON.qunitx,
@@ -28,7 +28,7 @@ export default async function setupConfig() {
28
28
  }
29
29
 
30
30
  async function readConfigFromPackageJSON(projectRoot) {
31
- let packageJSON = await fs.readFile(`${projectRoot}/package.json`);
31
+ const packageJSON = await fs.readFile(`${projectRoot}/package.json`);
32
32
 
33
33
  return JSON.parse(packageJSON.toString());
34
34
  }
@@ -38,7 +38,7 @@ function normalizeHTMLPaths(projectRoot, htmlPaths) {
38
38
  }
39
39
 
40
40
  function readInputsFromPackageJSON(packageJSON) {
41
- let qunitx = packageJSON.qunitx;
41
+ const qunitx = packageJSON.qunitx;
42
42
 
43
43
  return qunitx && qunitx.inputs ? qunitx.inputs : [];
44
44
  }
@@ -1,14 +1,9 @@
1
1
  import chokidar from 'chokidar';
2
2
  import kleur from 'kleur';
3
3
 
4
- export default async function setupFileWatchers(
5
- testFileLookupPaths,
6
- config,
7
- onEventFunc,
8
- onFinishFunc,
9
- ) {
10
- let extensions = ['js', 'ts'];
11
- let fileWatchers = testFileLookupPaths.reduce((watcher, watchPath) => {
4
+ export default function setupFileWatchers(testFileLookupPaths, config, onEventFunc, onFinishFunc) {
5
+ const extensions = ['js', 'ts'];
6
+ const fileWatchers = testFileLookupPaths.reduce((watcher, watchPath) => {
12
7
  return Object.assign(watcher, {
13
8
  [watchPath]: chokidar.watch(watchPath, { ignoreInitial: true }).on('all', (event, path) => {
14
9
  if (extensions.some((extension) => path.endsWith(extension))) {
@@ -31,7 +26,7 @@ export default async function setupFileWatchers(
31
26
  if (!global.chokidarBuild) {
32
27
  global.chokidarBuild = true;
33
28
 
34
- let result = extensions.some((extension) => path.endsWith(extension))
29
+ const result = extensions.some((extension) => path.endsWith(extension))
35
30
  ? onEventFunc(event, path)
36
31
  : null;
37
32
 
@@ -72,7 +67,7 @@ function mutateFSTree(fsTree, event, path) {
72
67
  } else if (event === 'unlink') {
73
68
  delete fsTree[path];
74
69
  } else if (event === 'unlinkDir') {
75
- let targetPaths = Object.keys(config.fsTree).filter((treePath) => treePath.startsWith(path));
70
+ const targetPaths = Object.keys(config.fsTree).filter((treePath) => treePath.startsWith(path));
76
71
 
77
72
  targetPaths.forEach((path) => delete config.fsTree[path]);
78
73
  }
@@ -2,19 +2,19 @@ import fs from 'node:fs/promises';
2
2
  import picomatch from 'picomatch';
3
3
  import recursiveLookup from 'recursive-lookup';
4
4
 
5
- export default async function buildFSTree(fileAbsolutePaths, config = {}) {
6
- let targetExtensions = ['js', 'ts'];
7
- let fsTree = {};
5
+ export default async function buildFSTree(fileAbsolutePaths, _config = {}) {
6
+ const targetExtensions = ['js', 'ts'];
7
+ const fsTree = {};
8
8
 
9
9
  await Promise.all(
10
10
  fileAbsolutePaths.map(async (fileAbsolutePath) => {
11
- let glob = picomatch.scan(fileAbsolutePath);
11
+ const glob = picomatch.scan(fileAbsolutePath);
12
12
 
13
13
  // TODO: maybe allow absolute path references
14
14
 
15
15
  try {
16
16
  if (glob.isGlob) {
17
- let fileNames = await recursiveLookup(glob.base, (path) => {
17
+ const fileNames = await recursiveLookup(glob.base, (path) => {
18
18
  return targetExtensions.some((extension) => path.endsWith(extension));
19
19
  });
20
20
 
@@ -24,12 +24,12 @@ export default async function buildFSTree(fileAbsolutePaths, config = {}) {
24
24
  }
25
25
  });
26
26
  } else {
27
- let entry = await fs.stat(fileAbsolutePath);
27
+ const entry = await fs.stat(fileAbsolutePath);
28
28
 
29
29
  if (entry.isFile()) {
30
30
  fsTree[fileAbsolutePath] = null;
31
31
  } else if (entry.isDirectory()) {
32
- let fileNames = await recursiveLookup(glob.base, (path) => {
32
+ const fileNames = await recursiveLookup(glob.base, (path) => {
33
33
  return targetExtensions.some((extension) => path.endsWith(extension));
34
34
  });
35
35
 
@@ -27,11 +27,6 @@ export default function setupKeyboardEvents(config, cachedContent, connections)
27
27
  });
28
28
  }
29
29
 
30
- function abortBrowserQUnit(config, connections) {
30
+ function abortBrowserQUnit(_config, connections) {
31
31
  connections.server.publish('abort', 'abort');
32
32
  }
33
-
34
- function abortNodejsQUnit(config) {
35
- window.QUnit.config.queue.length = 0;
36
- config.aborted = true;
37
- }
@@ -1,10 +1,10 @@
1
1
  import picomatch from 'picomatch';
2
2
 
3
- export default function setupTestFilePaths(projectRoot, inputs) {
3
+ export default function setupTestFilePaths(_projectRoot, inputs) {
4
4
  // NOTE: very complex algorithm, order is very important
5
- let [folders, filesWithGlob, filesWithoutGlob] = inputs.reduce(
5
+ const [folders, filesWithGlob, filesWithoutGlob] = inputs.reduce(
6
6
  (result, input) => {
7
- let isGlob = picomatch.scan(input).isGlob;
7
+ const isGlob = picomatch.scan(input).isGlob;
8
8
 
9
9
  if (!pathIsFile(input)) {
10
10
  result[0].push({
@@ -25,7 +25,7 @@ export default function setupTestFilePaths(projectRoot, inputs) {
25
25
  [[], [], []],
26
26
  );
27
27
 
28
- let result = folders.reduce((folderResult, folder) => {
28
+ const result = folders.reduce((folderResult, folder) => {
29
29
  if (!pathIsIncludedInPaths(folders, folder)) {
30
30
  folderResult.push(folder);
31
31
  }
@@ -48,7 +48,7 @@ export default function setupTestFilePaths(projectRoot, inputs) {
48
48
  }
49
49
 
50
50
  function pathIsFile(path) {
51
- let inputs = path.split('/');
51
+ const inputs = path.split('/');
52
52
 
53
53
  return inputs[inputs.length - 1].includes('.');
54
54
  }
@@ -59,7 +59,7 @@ function pathIsIncludedInPaths(paths, targetPath) {
59
59
  return false;
60
60
  }
61
61
 
62
- let globFormat = buildGlobFormat(path);
62
+ const globFormat = buildGlobFormat(path);
63
63
 
64
64
  return picomatch.isMatch(targetPath.input, globFormat, { bash: true });
65
65
  });
@@ -7,7 +7,7 @@ import HTTPServer, { MIME_TYPES } from '../servers/http.js';
7
7
 
8
8
  const fsPromise = fs.promises;
9
9
 
10
- export default async function setupWebServer(
10
+ export default function setupWebServer(
11
11
  config = {
12
12
  port: 1234,
13
13
  debug: false,
@@ -16,8 +16,8 @@ export default async function setupWebServer(
16
16
  },
17
17
  cachedContent,
18
18
  ) {
19
- let STATIC_FILES_PATH = path.join(config.projectRoot, config.output);
20
- let server = new HTTPServer();
19
+ const STATIC_FILES_PATH = path.join(config.projectRoot, config.output);
20
+ const server = new HTTPServer();
21
21
 
22
22
  server.wss.on('connection', function connection(socket) {
23
23
  socket.on('message', function message(data) {
@@ -42,9 +42,9 @@ export default async function setupWebServer(
42
42
  });
43
43
  });
44
44
 
45
- server.get('/', async (req, res) => {
46
- let TEST_RUNTIME_TO_INJECT = testRuntimeToInject(config.port, config);
47
- let htmlContent = escapeAndInjectTestsToHTML(
45
+ server.get('/', async (_req, res) => {
46
+ const TEST_RUNTIME_TO_INJECT = testRuntimeToInject(config.port, config);
47
+ const htmlContent = escapeAndInjectTestsToHTML(
48
48
  replaceAssetPaths(
49
49
  cachedContent.mainHTML.html,
50
50
  cachedContent.mainHTML.filePath,
@@ -63,9 +63,9 @@ export default async function setupWebServer(
63
63
  );
64
64
  });
65
65
 
66
- server.get('/qunitx.html', async (req, res) => {
67
- let TEST_RUNTIME_TO_INJECT = testRuntimeToInject(config.port, config);
68
- let htmlContent = escapeAndInjectTestsToHTML(
66
+ server.get('/qunitx.html', async (_req, res) => {
67
+ const TEST_RUNTIME_TO_INJECT = testRuntimeToInject(config.port, config);
68
+ const htmlContent = escapeAndInjectTestsToHTML(
69
69
  replaceAssetPaths(
70
70
  cachedContent.mainHTML.html,
71
71
  cachedContent.mainHTML.filePath,
@@ -85,10 +85,11 @@ export default async function setupWebServer(
85
85
  });
86
86
 
87
87
  server.get('/*', async (req, res) => {
88
- let possibleDynamicHTML = cachedContent.dynamicContentHTMLs[`${config.projectRoot}${req.path}`];
88
+ const possibleDynamicHTML =
89
+ cachedContent.dynamicContentHTMLs[`${config.projectRoot}${req.path}`];
89
90
  if (possibleDynamicHTML) {
90
- let TEST_RUNTIME_TO_INJECT = testRuntimeToInject(config.port, config);
91
- let htmlContent = escapeAndInjectTestsToHTML(
91
+ const TEST_RUNTIME_TO_INJECT = testRuntimeToInject(config.port, config);
92
+ const htmlContent = escapeAndInjectTestsToHTML(
92
93
  possibleDynamicHTML,
93
94
  TEST_RUNTIME_TO_INJECT,
94
95
  cachedContent.allTestCode,
@@ -103,12 +104,12 @@ export default async function setupWebServer(
103
104
  );
104
105
  }
105
106
 
106
- let url = req.url;
107
- let requestStartedAt = new Date();
108
- let filePath = (
107
+ const url = req.url;
108
+ const requestStartedAt = new Date();
109
+ const filePath = (
109
110
  url.endsWith('/') ? [STATIC_FILES_PATH, url, 'index.html'] : [STATIC_FILES_PATH, url]
110
111
  ).join('');
111
- let statusCode = (await pathExists(filePath)) ? 200 : 404;
112
+ const statusCode = (await pathExists(filePath)) ? 200 : 404;
112
113
 
113
114
  res.writeHead(statusCode, {
114
115
  'Content-Type': req.headers.accept?.includes('text/html')
@@ -129,11 +130,11 @@ export default async function setupWebServer(
129
130
  }
130
131
 
131
132
  function replaceAssetPaths(html, htmlPath, projectRoot) {
132
- let assetPaths = findInternalAssetsFromHTML(html);
133
- let htmlDirectory = htmlPath.split('/').slice(0, -1).join('/');
133
+ const assetPaths = findInternalAssetsFromHTML(html);
134
+ const htmlDirectory = htmlPath.split('/').slice(0, -1).join('/');
134
135
 
135
136
  return assetPaths.reduce((result, assetPath) => {
136
- let normalizedFullAbsolutePath = path.normalize(`${htmlDirectory}/${assetPath}`);
137
+ const normalizedFullAbsolutePath = path.normalize(`${htmlDirectory}/${assetPath}`);
137
138
 
138
139
  return result.replace(assetPath, normalizedFullAbsolutePath.replace(projectRoot, '.'));
139
140
  }, html);
@@ -1,8 +1,8 @@
1
1
  import fs from 'node:fs/promises';
2
2
 
3
3
  export default async function writeOutputStaticFiles({ projectRoot, output }, cachedContent) {
4
- let staticHTMLPromises = Object.keys(cachedContent.staticHTMLs).map(async (staticHTMLKey) => {
5
- let htmlRelativePath = staticHTMLKey.replace(`${projectRoot}/`, '');
4
+ const staticHTMLPromises = Object.keys(cachedContent.staticHTMLs).map(async (staticHTMLKey) => {
5
+ const htmlRelativePath = staticHTMLKey.replace(`${projectRoot}/`, '');
6
6
 
7
7
  await ensureFolderExists(`${projectRoot}/${output}/${htmlRelativePath}`);
8
8
  await fs.writeFile(
@@ -10,8 +10,8 @@ export default async function writeOutputStaticFiles({ projectRoot, output }, ca
10
10
  cachedContent.staticHTMLs[staticHTMLKey],
11
11
  );
12
12
  });
13
- let assetPromises = Array.from(cachedContent.assets).map(async (assetAbsolutePath) => {
14
- let assetRelativePath = assetAbsolutePath.replace(`${projectRoot}/`, '');
13
+ const assetPromises = Array.from(cachedContent.assets).map(async (assetAbsolutePath) => {
14
+ const assetRelativePath = assetAbsolutePath.replace(`${projectRoot}/`, '');
15
15
 
16
16
  await ensureFolderExists(`${projectRoot}/${output}/${assetRelativePath}`);
17
17
  await fs.copyFile(assetAbsolutePath, `${projectRoot}/${output}/${assetRelativePath}`);
@@ -22,7 +22,7 @@ export default function (COUNTER, details) {
22
22
  details.assertions.reduce((errorCount, assertion, index) => {
23
23
  if (!assertion.passed && assertion.todo === false) {
24
24
  COUNTER.errorCount++;
25
- let stack = assertion.stack?.match(/\(.+\)/g);
25
+ const stack = assertion.stack?.match(/\(.+\)/g);
26
26
 
27
27
  console.log(' ---');
28
28
  console.log(
@@ -59,7 +59,7 @@ export default function (COUNTER, details) {
59
59
 
60
60
  function getCircularReplacer() {
61
61
  const ancestors = [];
62
- return function (key, value) {
62
+ return function (_key, value) {
63
63
  if (typeof value !== 'object' || value === null) {
64
64
  return value;
65
65
  }
@@ -2,8 +2,8 @@ import { exec } from 'node:child_process';
2
2
 
3
3
  const CANDIDATES = ['google-chrome-stable', 'google-chrome', 'chromium', 'chromium-browser'];
4
4
 
5
- export default async function findChrome() {
6
- if (process.env.CHROME_BIN) return process.env.CHROME_BIN;
5
+ export default function findChrome() {
6
+ if (process.env.CHROME_BIN) return Promise.resolve(process.env.CHROME_BIN);
7
7
 
8
8
  return Promise.any(
9
9
  CANDIDATES.map(
@@ -3,13 +3,13 @@ import searchInParentDirectories from './search-in-parent-directories.js';
3
3
 
4
4
  export default async function () {
5
5
  try {
6
- let absolutePath = await searchInParentDirectories('.', 'package.json');
6
+ const absolutePath = await searchInParentDirectories('.', 'package.json');
7
7
  if (!absolutePath.includes('package.json')) {
8
8
  throw new Error('package.json mising');
9
9
  }
10
10
 
11
11
  return absolutePath.replace('/package.json', '');
12
- } catch (error) {
12
+ } catch (_error) {
13
13
  console.log('couldnt find projects package.json, did you run $ npm init ??');
14
14
  process.exit(1);
15
15
  }
@@ -1,8 +1,8 @@
1
1
  import process from 'node:process';
2
2
 
3
- let stdin = process.stdin;
4
- let targetInputs = {};
5
- let inputs = [];
3
+ const stdin = process.stdin;
4
+ const targetInputs = {};
5
+ const inputs = [];
6
6
  let listenerAdded = false;
7
7
 
8
8
  export default function listenToKeyboardKey(
@@ -22,10 +22,10 @@ export default function listenToKeyboardKey(
22
22
  inputs.shift();
23
23
  inputs.push(key);
24
24
 
25
- let inputString = inputs.join('');
26
- let targetListener = targetInputs[inputString.toUpperCase()];
27
- if (targetListener && targetListenerConformsToCase(targetListener, inputString)) {
28
- targetListener.closure(inputString);
25
+ const currentInput = inputs.join('');
26
+ const targetListener = targetInputs[currentInput.toUpperCase()];
27
+ if (targetListener && targetListenerConformsToCase(targetListener, currentInput)) {
28
+ targetListener.closure(currentInput);
29
29
  inputs.fill(undefined);
30
30
  }
31
31
  });
@@ -6,15 +6,13 @@ export default async function resolvePortNumberFor(portNumber) {
6
6
  return await resolvePortNumberFor(portNumber + 1);
7
7
  }
8
8
 
9
- function portIsAvailable(portNumber) {
10
- return new Promise(async (resolve) => {
11
- const net = await import('net');
9
+ async function portIsAvailable(portNumber) {
10
+ const net = await import('net');
11
+ return new Promise((resolve) => {
12
12
  const server = net.createServer();
13
13
 
14
- server.once('error', function (err) {
15
- if (err.code === 'EADDRINUSE') {
16
- resolve(false);
17
- }
14
+ server.once('error', function (_err) {
15
+ resolve(false);
18
16
  });
19
17
 
20
18
  server.once('listening', function () {
@@ -2,7 +2,7 @@ import kleur from 'kleur';
2
2
 
3
3
  export default async function runUserModule(modulePath, params, scriptPosition) {
4
4
  try {
5
- let func = await import(modulePath);
5
+ const func = await import(modulePath);
6
6
  if (func) {
7
7
  func.default
8
8
  ? await func.default(params)
@@ -1,16 +1,16 @@
1
1
  import pathExists from './path-exists.js';
2
2
 
3
3
  async function searchInParentDirectories(directory, targetEntry) {
4
- directory = directory === '.' ? process.cwd() : directory;
4
+ const resolvedDirectory = directory === '.' ? process.cwd() : directory;
5
5
 
6
- if (await pathExists(`${directory}/${targetEntry}`)) {
7
- return `${directory}/${targetEntry}`;
8
- } else if (directory === '') {
6
+ if (await pathExists(`${resolvedDirectory}/${targetEntry}`)) {
7
+ return `${resolvedDirectory}/${targetEntry}`;
8
+ } else if (resolvedDirectory === '') {
9
9
  return;
10
10
  }
11
11
 
12
12
  return await searchInParentDirectories(
13
- directory.slice(0, directory.lastIndexOf('/')),
13
+ resolvedDirectory.slice(0, resolvedDirectory.lastIndexOf('/')),
14
14
  targetEntry,
15
15
  );
16
16
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "qunitx-cli",
3
3
  "type": "module",
4
- "version": "0.5.1",
4
+ "version": "0.5.3",
5
5
  "description": "Browser runner for QUnitx: run your qunitx tests in google-chrome",
6
6
  "main": "cli.js",
7
7
  "author": "Izel Nakri",
@@ -16,14 +16,15 @@
16
16
  ],
17
17
  "scripts": {
18
18
  "bin": "chmod +x cli.js && ./cli.js",
19
- "lint": "prettier --check \"lib/**/*.js\" \"test/**/*.js\" \"*.js\" \"package.json\" \".github/**/*.yml\"",
20
- "lint:fix": "prettier --write \"lib/**/*.js\" \"test/**/*.js\" \"*.js\" \"package.json\" \".github/**/*.yml\"",
19
+ "format": "prettier --check \"lib/**/*.js\" \"test/**/*.js\" \"*.js\" \"package.json\" \".github/**/*.yml\"",
20
+ "format:fix": "prettier --write \"lib/**/*.js\" \"test/**/*.js\" \"*.js\" \"package.json\" \".github/**/*.yml\"",
21
+ "lint": "deno lint lib/ cli.js",
21
22
  "build": "node build.js",
22
23
  "changelog:unreleased": "git-cliff --unreleased --strip all",
23
24
  "changelog:preview": "git-cliff",
24
25
  "changelog:update": "git-cliff --output CHANGELOG.md",
25
26
  "prepack": "npm run build",
26
- "test": "node test/setup.js && node --test test/**/*-test.js",
27
+ "test": "node test/setup.js && FORCE_COLOR=0 node --test test/**/*-test.js",
27
28
  "test:sanity-first": "./cli.js test/helpers/failing-tests.js test/helpers/failing-tests.ts",
28
29
  "test:sanity-second": "./cli.js test/helpers/passing-tests.js test/helpers/passing-tests.ts"
29
30
  },
@@ -53,7 +54,7 @@
53
54
  "express": "^5.2.1",
54
55
  "prettier": "^3.8.1",
55
56
  "qunit": "^2.25.0",
56
- "qunitx": "^0.9.3"
57
+ "qunitx": "^1.0.0"
57
58
  },
58
59
  "volta": {
59
60
  "node": "24.14.0"