@nutin/cli 1.1.0 → 1.2.1

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 (92) hide show
  1. package/CHANGELOG.md +69 -6
  2. package/README.md +49 -2
  3. package/lib/index.mjs +9 -9
  4. package/lib/src/file-generator.mjs +24 -9
  5. package/lib/src/package-manager.mjs +72 -51
  6. package/lib/src/prompts.mjs +10 -10
  7. package/lib/src/utils.mjs +4 -1
  8. package/package.json +4 -3
  9. package/templates/base/.dockerignore.hbs +12 -2
  10. package/templates/base/README.md.hbs +23 -0
  11. package/templates/base/builder.config.js.hbs +28 -0
  12. package/templates/base/src/app/components/common/anchor/anchor.component.ts.hbs +11 -12
  13. package/templates/base/src/app/dom.test.js.hbs +8 -1
  14. package/templates/base/src/core/base-classes/base-component/base-component.ts.hbs +2 -1
  15. package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.ts.hbs +11 -11
  16. package/templates/base/src/core/base-classes/base-component/helpers/event.helper.ts.hbs +3 -0
  17. package/templates/base/src/core/base-classes/base-component/helpers/pipe.helper.ts.hbs +3 -0
  18. package/templates/base/src/core/base-classes/base-component/helpers/token.helper.ts.hbs +5 -4
  19. package/templates/base/src/core/services/event-bus/event-bus.ts.hbs +55 -27
  20. package/templates/base/src/core/services/http-client/http-client.ts.hbs +24 -17
  21. package/templates/base/src/core/services/router/helpers/navigation-manager.helper.ts.hbs +3 -3
  22. package/templates/base/src/core/services/router/helpers/route-guard-manager.helper.ts.hbs +2 -2
  23. package/templates/base/src/core/services/router/helpers/view-render-manager.helper.ts.hbs +25 -10
  24. package/templates/base/src/core/services/router/router.ts.hbs +1 -0
  25. package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.ts.hbs +4 -3
  26. package/templates/base/src/core/utils/button-manager/button-manager.utils.test.js.hbs +1 -1
  27. package/templates/base/src/index.html.hbs +2 -2
  28. package/templates/base/src/libs/popover/popover.ts.hbs +2 -1
  29. package/templates/base/src/styles/main.scss.hbs +4 -1
  30. package/templates/base/tools/builder/builder.js.hbs +19 -26
  31. package/templates/base/tools/builder/core/copy-static.js.hbs +41 -20
  32. package/templates/base/tools/builder/core/esbuild.js.hbs +26 -0
  33. package/templates/base/tools/builder/core/finalize-build.js.hbs +24 -0
  34. package/templates/base/tools/builder/core/minify-html.js.hbs +60 -0
  35. package/templates/base/tools/builder/core/paths.js.hbs +19 -0
  36. package/templates/base/tools/builder/core/sass.js.hbs +22 -0
  37. package/templates/base/tools/builder/core/tsc.js.hbs +12 -0
  38. package/templates/base/tools/builder/core/validate-html.js.hbs +32 -12
  39. package/templates/base/tools/deployment/Dockerfile.hbs +22 -0
  40. package/templates/base/tools/deployment/gzip.conf.hbs +19 -0
  41. package/templates/base/tools/deployment/nginx.conf.hbs +78 -0
  42. package/templates/base/tools/dev/dev-serve.js.hbs +32 -0
  43. package/templates/base/tools/dev/serve.js.hbs +23 -0
  44. package/templates/base/tools/{watcher.js.hbs → dev/watcher.js.hbs} +8 -8
  45. package/templates/base/tools/generator/generator.js.hbs +21 -6
  46. package/templates/base/tools/generator/handle-file.js.hbs +32 -2
  47. package/templates/base/tools/generator/templates/index.js.hbs +3 -0
  48. package/templates/base/tools/utils/export-flags.js.hbs +6 -0
  49. package/templates/base/tools/utils/get-files-recursive.js.hbs +1 -3
  50. package/templates/base/tools/utils/index.js.hbs +8 -1
  51. package/templates/base/tools/utils/prompt-boolean.js.hbs +15 -0
  52. package/templates/base/tools/utils/run-command.js.hbs +12 -0
  53. package/templates/base/tools/utils/run-script.js.hbs +22 -0
  54. package/templates/features/i18n/src/core/config.ts.hbs +3 -0
  55. package/templates/features/i18n/src/core/services/i18n/i18n.test.js.hbs +2 -0
  56. package/templates/features/i18n/src/core/services/i18n/i18n.ts.hbs +10 -1
  57. package/templates/features/i18n/src/core/services/i18n/languages.ts.hbs +7 -0
  58. package/templates/features/i18n/tools/builder/core/build-i18n.js.hbs +12 -17
  59. package/templates/features/i18n/tools/utils/languages.js.hbs +7 -0
  60. package/templates/features/stylinNutin/src/styles/_custom-classes.scss.hbs +1 -1
  61. package/templates/features/stylinNutin/src/styles/components/_index.scss.hbs +0 -0
  62. package/templates/features/stylinNutin/src/styles/views/_index.scss.hbs +0 -0
  63. package/templates/features/stylinNutin/tools/generator/templates/scss.template.js.hbs +4 -0
  64. package/templates/features/template/tools/builder/core/merge-templates.js.hbs +13 -26
  65. package/templates/features/testinNutin/{test → testin-nutin}/core/index.js.hbs +1 -1
  66. package/templates/features/testinNutin/testin-nutin/core/src/globals/assertion-lib.js.hbs +136 -0
  67. package/templates/features/testinNutin/testin-nutin/core/src/globals/jsdom-setup.js.hbs +101 -0
  68. package/templates/features/testinNutin/{test → testin-nutin}/core/src/globals/register-test-globals.js.hbs +15 -1
  69. package/templates/features/testinNutin/testin-nutin/core/src/globals/spyon.js.hbs +59 -0
  70. package/templates/features/testinNutin/{test → testin-nutin}/core/src/utils/print.js.hbs +3 -1
  71. package/templates/features/testinNutin/{test → testin-nutin}/core/src/utils/test-discovery.js.hbs +5 -1
  72. package/templates/features/testinNutin/{test → testin-nutin}/core/src/utils/test-queue.js.hbs +3 -1
  73. package/templates/features/testinNutin/{test → testin-nutin}/core/tests/assertions.test.js.hbs +26 -2
  74. package/templates/features/testinNutin/testin-nutin/runner.js.hbs +35 -0
  75. package/templates/features/testinNutin/{test → testin-nutin}/watch-tests.js.hbs +1 -1
  76. package/templates/features/testinNutin/testin-nutin.config.js.hbs +14 -0
  77. package/templates/base/Dockerfile.hbs +0 -13
  78. package/templates/base/tools/builder/core/sass.config.js.hbs +0 -17
  79. package/templates/base/tools/builder/docs.md.hbs +0 -9
  80. package/templates/features/testinNutin/test/core/src/globals/assertion-lib.js.hbs +0 -118
  81. package/templates/features/testinNutin/test/core/src/globals/spyon.js.hbs +0 -22
  82. package/templates/features/testinNutin/test/core/src/jsdom-setup.js.hbs +0 -12
  83. package/templates/features/testinNutin/test/docs.md.hbs +0 -39
  84. package/templates/features/testinNutin/test/runner.js.hbs +0 -36
  85. /package/templates/features/testinNutin/{test → testin-nutin}/core/src/utils/queue.js.hbs +0 -0
  86. /package/templates/features/testinNutin/{test → testin-nutin}/core/tests/globals-each-all.test.js.hbs +0 -0
  87. /package/templates/features/testinNutin/{test → testin-nutin}/mocks/create-mock-method.js.hbs +0 -0
  88. /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-event-bus.js.hbs +0 -0
  89. /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-http-client.js.hbs +0 -0
  90. /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-i18n.js.hbs +0 -0
  91. /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-router.js.hbs +0 -0
  92. /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-store.js.hbs +0 -0
@@ -0,0 +1,59 @@
1
+ global.spyOn = (obj, methodName) => {
2
+ if (!obj || typeof methodName !== 'string') {
3
+ throw new Error('spyOn requires an object and a method name');
4
+ }
5
+
6
+ const originalFn = obj[methodName];
7
+
8
+ if (typeof originalFn !== 'function') {
9
+ throw new Error(`Cannot spy on ${methodName} – not a function`);
10
+ }
11
+
12
+ const calls = [];
13
+
14
+ function spyFunction(...args) {
15
+ calls.push(args.slice());
16
+ if (spyFunction._fake) {
17
+ return spyFunction._fake.apply(this, args);
18
+ }
19
+ if (spyFunction._hasReturn) {
20
+ return spyFunction._returnValue;
21
+ }
22
+ return originalFn.apply(this, args);
23
+ }
24
+
25
+ spyFunction._isSpy = true;
26
+ spyFunction._fake = null;
27
+ spyFunction._hasReturn = false;
28
+ spyFunction._returnValue = undefined;
29
+
30
+ obj[methodName] = spyFunction;
31
+
32
+ const handle = {
33
+ restore() {
34
+ if (obj[methodName] === spyFunction) {
35
+ obj[methodName] = originalFn;
36
+ }
37
+ },
38
+ get calls() {
39
+ return calls;
40
+ },
41
+ get callCount() {
42
+ return calls.length;
43
+ },
44
+ get lastCall() {
45
+ return calls.length ? calls[calls.length - 1] : undefined;
46
+ },
47
+ andCallFake(fn) {
48
+ spyFunction._fake = fn;
49
+ spyFunction._hasReturn = false;
50
+ },
51
+ andReturn(value) {
52
+ spyFunction._returnValue = value;
53
+ spyFunction._hasReturn = true;
54
+ spyFunction._fake = null;
55
+ }
56
+ };
57
+
58
+ return handle;
59
+ };
@@ -1,3 +1,5 @@
1
+ import config from '#root/testin-nutin.config.js';
2
+
1
3
  export function printSummary(passed, failed, time) {
2
4
  const totalTime = time.toFixed(2);
3
5
  const total = passed + failed;
@@ -17,7 +19,7 @@ export function printResults(results) {
17
19
 
18
20
  sortedResults.forEach(result => {
19
21
  if (result.status === 'passed') {
20
- console.log(`${chalk.green('✓')} ${chalk.cyan(`${result.suiteName}`)} - ${chalk.green(`${result.name}`)}`);
22
+ if (config.verbose ) console.log(`${chalk.green('✓')} ${chalk.cyan(`${result.suiteName}`)} - ${chalk.green(`${result.name}`)}`);
21
23
  } else {
22
24
  print.error(`✗ ${result.suiteName} - ${result.name}`);
23
25
  print.grayError(result.error);
@@ -3,9 +3,13 @@ import path from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
 
5
5
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+ const relativeToCwd = path.relative(process.cwd(), __dirname);
7
+ const levelsUp = relativeToCwd.split(path.sep).length-1;
8
+ const projectRoot = path.resolve(__dirname, ...Array(levelsUp).fill('..'));
6
9
 
7
10
  export function getTestFiles(dir) {
8
- const fullDir = path.resolve(__dirname,'../', '../', '../', dir);
11
+ const fullDir = path.join(projectRoot, dir);
12
+
9
13
  if (!fs.existsSync(fullDir)) return [];
10
14
 
11
15
  function findTestFilesRecursively(currentDir) {
@@ -34,9 +34,11 @@ export async function runQueuedTests() {
34
34
  previousSuiteAfterAll = test.afterAll;
35
35
  }
36
36
 
37
+ setupJsdom();
37
38
  if (test.beforeEach) await test.beforeEach();
38
39
  await test.testFn();
39
40
  if (test.afterEach) await test.afterEach();
41
+ teardownJsdom();
40
42
 
41
43
  passed++;
42
44
  results.push({
@@ -50,7 +52,7 @@ export async function runQueuedTests() {
50
52
  suiteName: test.suiteName,
51
53
  status: 'failed',
52
54
  name: test.testName,
53
- error: err.stack
55
+ error: err.stack
54
56
  });
55
57
  }
56
58
  }
@@ -8,11 +8,17 @@ describe('assertions', () => {
8
8
  it('should check if value matches expected', () => {
9
9
  const five = obj.add(2,3);
10
10
  const ten = obj.add(3,7);
11
+ const object = { five: five, ten: ten };
12
+ const arr = [ five, ten ];
11
13
 
12
14
  expect(five).toEqual(5);
13
- expect(five).toBe('5');
15
+ expect(five).toBe(5);
14
16
  expect(ten).not.toEqual(11);
15
- expect(ten).not.toBe('11');
17
+ expect(ten).not.toBe(11);
18
+ expect(object).toEqual({ five: five, ten: ten });
19
+ expect(object).not.toBe({ five: five, ten: ten });
20
+ expect(arr).toEqual([five, ten]);
21
+ expect(arr).not.toBe([five, ten]);
16
22
  });
17
23
  it('should check if function has been called', () => {
18
24
  const spy = spyOn(obj, 'add');
@@ -29,6 +35,12 @@ describe('assertions', () => {
29
35
  expect(null).toBeUndefined();
30
36
  expect(null).not.toBeDefined();
31
37
  });
38
+ it('should check for if an element is true / false', () => {
39
+ const isTrue = 1 == '1';
40
+ const isFalse = 1 === '1';
41
+ expect(isTrue).toBeTruthy();
42
+ expect(isFalse).toBeFalsy();
43
+ });
32
44
  it('should check if substring is contained within string', () => {
33
45
  const str1 = 'Creativity is allowing yourself to make mistakes.';
34
46
  const str2 = 'Art is knowing which ones to keep.';
@@ -40,7 +52,19 @@ describe('assertions', () => {
40
52
  });
41
53
  it('should check for instance', () => {
42
54
  const date = new Date();
55
+ const fn = () => {};
43
56
  expect(date).toBeInstanceOf(Date);
57
+ expect(fn).toBeInstanceOf(Function);
44
58
  expect(date).not.toBeInstanceOf(Function);
59
+ expect(fn).not.toBeInstanceOf(Date);
60
+ });
61
+ it('should check for error throw', () => {
62
+ const err = () => { throw new Error('message'); };
63
+ const notErr = () => {};
64
+ expect(err).toThrow();
65
+ expect(err).toThrow('message');
66
+ expect(err).not.toThrow('another message');
67
+ expect(notErr).not.toThrow();
68
+ expect(notErr).not.toThrow('messsage');
45
69
  });
46
70
  });
@@ -0,0 +1,35 @@
1
+ import { registerTestGlobals, getTestFiles, runQueuedTests, print } from './core/index.js';
2
+ import config from '#root/testin-nutin.config.js';
3
+
4
+ registerTestGlobals();
5
+
6
+ let testFiles = config.origins.flatMap(
7
+ origin => getTestFiles(`../${origin}`)
8
+ );
9
+
10
+ const args = process.argv.slice(2);
11
+ if (args.length) {
12
+ testFiles = testFiles.filter(file => args.some(f => file.includes(f)));
13
+ }
14
+
15
+ async function loadTestFile(file) {
16
+ setupJsdom();
17
+ await import(file);
18
+ teardownJsdom();
19
+ }
20
+
21
+ async function runTests() {
22
+ if (config.verbose) print.head('Test suites :');
23
+ for (const file of testFiles) {
24
+ try {
25
+ await loadTestFile(file);
26
+ } catch (error) {
27
+ print.boldError(`✗ ${file} failed to load:`);
28
+ print.grayError(error.stack);
29
+ }
30
+ }
31
+
32
+ await runQueuedTests();
33
+ }
34
+
35
+ runTests();
@@ -14,7 +14,7 @@ watcher.on('change', (filePath) => {
14
14
  console.clear();
15
15
  print.boldInfo(`\n🔄 File changed: ${path.relative(process.cwd(), filePath)}\n`);
16
16
 
17
- exec('node --experimental-modules test/runner.js', (err, stdout, stderr) => {
17
+ exec('node --experimental-modules testin-nutin/runner.js', (err, stdout, stderr) => {
18
18
  if (stdout) process.stdout.write(stdout);
19
19
  if (stderr) process.stderr.write(stderr);
20
20
  });
@@ -0,0 +1,14 @@
1
+ export default {
2
+ origins: [
3
+ 'src/app', // actual app code
4
+ // 'src/core', // toolkit core logic
5
+ // 'testin-nutin/core/tests', // test globals
6
+ ],
7
+ verbose: false,
8
+ jsdomOptions: {
9
+ runScripts: false, // or true ("dangerously") if needed
10
+ resources: false, // or true ("usable") if needed
11
+ freezeGlobals: false,
12
+ pretendToBeVisual: true,
13
+ }
14
+ }
@@ -1,13 +0,0 @@
1
- FROM node:22.3.0 AS builder
2
- WORKDIR /usr/src/app
3
- COPY . .
4
- RUN npm ci && \
5
- npm run build
6
-
7
- FROM nginx:1.21-alpine
8
- RUN sed -i 's/listen .*/listen 9090;/' /etc/nginx/conf.d/default.conf && \
9
- sed -i 's|index index.html index.htm;|index index.html index.htm;\n try_files \$uri /index.html;|' /etc/nginx/conf.d/default.conf && \
10
- mkdir -p /usr/share/nginx/html
11
- COPY --from=builder /usr/src/app/dist/src /usr/share/nginx/html
12
-
13
- CMD ["nginx", "-g", "daemon off;"]
@@ -1,17 +0,0 @@
1
- import * as sass from 'sass';
2
- import * as fs from 'fs';
3
- import { print } from '../../utils/index.js';
4
- {{#if template}}
5
- const stylesOutput = 'dist-build/src'
6
- {{else}}
7
- const stylesOutput = 'dist/src';
8
- {{/if}}
9
- if (!fs.existsSync(stylesOutput)) fs.mkdirSync(stylesOutput);
10
-
11
- sass.compileAsync('src/styles/main.scss', {
12
- loadPaths: ['src/styles/base', 'src/styles/core'],
13
- style: 'compressed'
14
- }).then(result => {
15
- print.info('Global styles compiled.');
16
- fs.writeFileSync(`${stylesOutput}/main.css`, result.css);
17
- });
@@ -1,9 +0,0 @@
1
- - Adding additnal file formats to the build
2
- Default file formats are `"html" "json" "ttf" "avif" "png" "jpg"`.
3
- Only the files in src/ that match one of the format are copied.
4
- In `tools/builder/variables/file-types.js`, add desired format to existing list. Adding a file extension with no match in src/ will have no effect.
5
-
6
- - Build Sequence
7
-
8
-
9
- [**Back to index**](../../README.md)
@@ -1,118 +0,0 @@
1
- global.expect = (actual) => {
2
- const expectObj = {
3
- toBe(expected) {
4
- if (actual != expected) {
5
- throw new Error(`Expected ${actual} to be ${expected}`);
6
- }
7
- },
8
- toEqual(expected) {
9
- if (actual !== expected) {
10
- throw new Error(`Expected ${actual} to be ${expected}`);
11
- }
12
- },
13
- toContain(substring) {
14
- if (!actual.includes(substring)) {
15
- throw new Error(`Expected '${actual}' to contain '${substring}'`);
16
- }
17
- },
18
- toBeDefined() {
19
- if (actual === null || actual === undefined) {
20
- throw new Error(`Expected value to be defined, but got ${actual}`);
21
- }
22
- },
23
- toBeUndefined() {
24
- if (actual !== null && actual !== undefined) {
25
- throw new Error(`Expected value to be undefined, but got ${actual}`);
26
- }
27
- },
28
- toBeInstanceOf(constructor) {
29
- if (!(actual instanceof constructor)) {
30
- throw new Error(`Expected ${actual} to be instance of ${constructor.name}`);
31
- }
32
- },
33
- toHaveBeenCalled() {
34
- if (!actual?.calls || actual.calls.length === 0) {
35
- throw new Error(`Expected function to have been called, but it was not`);
36
- }
37
- },
38
- toHaveBeenCalledWith(...expectedArgs) {
39
- const matched = actual?.calls?.some(args =>
40
- args.length === expectedArgs.length &&
41
- args.every((arg, i) => arg === expectedArgs[i])
42
- );
43
- if (!matched) {
44
- throw new Error(`Expected function to have been called with ${JSON.stringify(expectedArgs)}, but it was not`);
45
- }
46
- },
47
- toBeLessThan(expected) {
48
- if (actual > expected) {
49
- throw new Error(`Expected ${actual} to be less than ${expected}`)
50
- }
51
- },
52
- toBeGreaterThan(expected) {
53
- if (actual < expected) {
54
- throw new Error(`Expected ${actual} to be greater than ${expected}`)
55
- }
56
- }
57
- };
58
-
59
- // 'not' variants
60
- expectObj.not = {
61
- toBe(expected) {
62
- if (actual == expected) {
63
- throw new Error(`Expected ${actual} not to be ${expected}`);
64
- }
65
- },
66
- toEqual(expected) {
67
- if (actual === expected) {
68
- throw new Error(`Expected ${actual} not to be ${expected}`);
69
- }
70
- },
71
- toContain(substring) {
72
- if (actual.includes(substring)) {
73
- throw new Error(`Expected '${actual}' not to contain '${substring}'`);
74
- }
75
- },
76
- toBeDefined() {
77
- if (actual !== null && actual !== undefined) {
78
- throw new Error(`Expected value to be undefined, but got ${actual}`);
79
- }
80
- },
81
- toBeUndefined() {
82
- if (actual === null || actual === undefined) {
83
- throw new Error(`Expected value to be defined, but got ${actual}`);
84
- }
85
- },
86
- toBeInstanceOf(constructor) {
87
- if (actual instanceof constructor) {
88
- throw new Error(`Expected ${actual} not to be instance of ${constructor.name}`);
89
- }
90
- },
91
- toHaveBeenCalled() {
92
- if (actual?.calls && actual.calls.length > 0) {
93
- throw new Error(`Expected function not to have been called, but it was`);
94
- }
95
- },
96
- toHaveBeenCalledWith(...expectedArgs) {
97
- const matched = actual?.calls?.some(args =>
98
- args.length === expectedArgs.length &&
99
- args.every((arg, i) => arg === expectedArgs[i])
100
- );
101
- if (matched) {
102
- throw new Error(`Expected function not to have been called with ${JSON.stringify(expectedArgs)}, but it was`);
103
- }
104
- },
105
- toBeLessThan(expected) {
106
- if (actual < expected) {
107
- throw new Error(`Expected ${actual} not to be less than ${expected}`)
108
- }
109
- },
110
- toBeGreaterThan(expected) {
111
- if (actual > expected) {
112
- throw new Error(`Expected ${actual} not to be greater than ${expected}`)
113
- }
114
- }
115
- };
116
-
117
- return expectObj;
118
- };
@@ -1,22 +0,0 @@
1
- global.spyOn = (obj, methodName) => {
2
- const originalFn = obj[methodName];
3
-
4
- const calls = [];
5
- const spy = function (...args) {
6
- calls.push(args);
7
- return originalFn.apply(this, args);
8
- };
9
-
10
- spy.calls = calls;
11
-
12
- obj[methodName] = spy;
13
-
14
- return {
15
- restore() {
16
- obj[methodName] = originalFn;
17
- },
18
- get calls() {
19
- return calls;
20
- }
21
- };
22
- };
@@ -1,12 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { JSDOM } from 'jsdom';
4
-
5
- export function setupJsdomEnvironment(htmlPath = 'dist/src/index.html') {
6
- const html = fs.readFileSync(path.resolve(process.cwd(), htmlPath), 'utf8');
7
- const dom = new JSDOM(html, { url: 'http://localhost' });
8
-
9
- global.window = dom.window;
10
- global.document = dom.window.document;
11
- global.localStorage = dom.window.localStorage;
12
- }
@@ -1,39 +0,0 @@
1
- # testin-nutin
2
-
3
- ***The test runner uses a Queue data structure, for which all credit goes to ThePrimeagen and his [amazing Data Structures and Algorithms course on frontendmasters.com](https://frontendmasters.com/courses/algorithms/)***
4
-
5
- ## Run tests
6
-
7
- The code needs to be compiled for the tests to run.
8
-
9
- ```sh
10
- npm run test
11
- npm run test:watch # NOTE: will rerun all tests on change.
12
- npm run test--rebuild # = npm run build && npm run test
13
- ```
14
- Accepts a filter argument *ex: e2e, unit, file-name*.
15
-
16
- ## Built-in features (minimalistic)
17
-
18
- - *Test globals* : describe, it, beforeEach/All, afterEach/All.
19
-
20
- - *Assertions library* : toBe(), toContain(string), toBeDefined, toBeUndefined, toBeInstanceOf(instance).
21
- All assertions can be used with `not.` prefix.
22
-
23
- - *JSDOM initial setup for DOM testing*.
24
-
25
- - *HTTP client mock* (In progress)
26
-
27
- - *Automated tests discovery* : Recursively scans e2e/ unit/ and utils/ folders for .test.js files.
28
-
29
- It is always possible to add new paths in test/runner.js `testFiles` array (`...getTestFiles('path/to/folder')`) or remove one to disable its tests.
30
-
31
- - *mini-chalk* to color console outputs.
32
-
33
- ## How to use
34
-
35
- Syntax is very similar to Jest, only with way less features.
36
- Import statements from 'dist' folder can be simplified by using `#root/dist/src` and by regrouping exports in indexes.
37
- Please refer to examples in utils/\*.test.js and unit/i18n.test.js.
38
-
39
- [**Back to index**](../README.md)
@@ -1,36 +0,0 @@
1
- import { setupJsdomEnvironment, registerTestGlobals, getTestFiles, runQueuedTests, print } from './core/index.js';
2
-
3
- setupJsdomEnvironment();
4
- registerTestGlobals();
5
-
6
- let testFiles = [
7
- // globals & assertions
8
- // ...getTestFiles('core/tests'),
9
- // toolkit core logic
10
- // ...getTestFiles('../src/core'),
11
- // built-in libs
12
- // ...getTestFiles('../src/libs'),
13
- // actual application code
14
- ...getTestFiles('../src/app')
15
- ];
16
-
17
- const args = process.argv.slice(2);
18
- if (args.length) {
19
- testFiles = testFiles.filter(file => args.some(f => file.includes(f)));
20
- }
21
-
22
- async function runTests() {
23
- print.head('Test suites :');
24
- for (const file of testFiles) {
25
- try {
26
- await import(file);
27
- } catch (error) {
28
- print.boldError(`✗ ${file} failed to load:`);
29
- print.grayError(error.stack);
30
- }
31
- }
32
-
33
- await runQueuedTests();
34
- }
35
-
36
- runTests();