ember-exam 9.0.0 → 10.0.0
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/.release-plan.json +30 -0
- package/README.md +65 -2
- package/addon-test-support/-private/async-iterator.js +0 -1
- package/addon-test-support/-private/ember-exam-test-loader.js +63 -5
- package/addon-test-support/index.js +1 -0
- package/addon-test-support/load.js +0 -1
- package/addon-test-support/start.js +8 -5
- package/docs-app/.vitepress/config.mts +54 -0
- package/docs-app/.vitepress/theme/index.ts +17 -0
- package/docs-app/.vitepress/theme/style.css +170 -0
- package/docs-app/ember-try-and-ci.md +38 -0
- package/docs-app/filtering.md +47 -0
- package/docs-app/index.md +46 -0
- package/docs-app/load-balancing.md +96 -0
- package/docs-app/module-metadata.md +48 -0
- package/docs-app/package.json +26 -0
- package/docs-app/preserve-test-name.md +26 -0
- package/docs-app/quickstart.md +128 -0
- package/docs-app/randomization-iterator.md +22 -0
- package/docs-app/randomization.md +29 -0
- package/docs-app/split-parallel.md +33 -0
- package/docs-app/splitting.md +19 -0
- package/docs-app/test-suite-segmentation.md +14 -0
- package/docs-app/tsconfig.json +23 -0
- package/lib/commands/exam/iterate.js +1 -1
- package/lib/commands/exam.js +1 -1
- package/lib/commands/task/test-server.js +0 -1
- package/lib/commands/task/test.js +9 -1
- package/lib/utils/config-reader.js +4 -1
- package/lib/utils/test-page-helper.js +0 -1
- package/lib/utils/tests-options-validator.js +0 -1
- package/package.json +40 -75
- package/pnpm-workspace.yaml +76 -0
- package/test-apps/broccoli/.editorconfig +19 -0
- package/test-apps/broccoli/.ember-cli +7 -0
- package/test-apps/broccoli/.github/workflows/ci.yml +47 -0
- package/test-apps/broccoli/.prettierignore +13 -0
- package/test-apps/broccoli/.prettierrc.js +12 -0
- package/test-apps/broccoli/.stylelintignore +8 -0
- package/test-apps/broccoli/.stylelintrc.js +5 -0
- package/test-apps/broccoli/.template-lintrc.js +5 -0
- package/test-apps/broccoli/.watchmanconfig +3 -0
- package/test-apps/broccoli/README.md +56 -0
- package/test-apps/broccoli/app/app.js +12 -0
- package/test-apps/broccoli/app/index.html +24 -0
- package/test-apps/broccoli/app/router.js +9 -0
- package/test-apps/broccoli/app/styles/app.css +1 -0
- package/test-apps/broccoli/app/templates/application.hbs +7 -0
- package/test-apps/broccoli/config/ember-cli-update.json +20 -0
- package/test-apps/broccoli/config/environment.js +48 -0
- package/test-apps/broccoli/config/optional-features.json +7 -0
- package/test-apps/broccoli/config/targets.js +11 -0
- package/test-apps/broccoli/ember-cli-build.js +11 -0
- package/test-apps/broccoli/package.json +71 -0
- package/test-apps/broccoli/public/robots.txt +3 -0
- package/test-apps/broccoli/testem.js +23 -0
- package/test-apps/broccoli/tests/index.html +39 -0
- package/test-apps/broccoli/tests/test-helper.js +12 -0
- package/test-apps/embroider3-webpack/.editorconfig +19 -0
- package/test-apps/embroider3-webpack/.ember-cli +19 -0
- package/test-apps/embroider3-webpack/.github/workflows/ci.yml +47 -0
- package/test-apps/embroider3-webpack/.prettierignore +13 -0
- package/test-apps/embroider3-webpack/.prettierrc.js +14 -0
- package/test-apps/embroider3-webpack/.stylelintignore +5 -0
- package/test-apps/embroider3-webpack/.stylelintrc.js +5 -0
- package/test-apps/embroider3-webpack/.template-lintrc.js +5 -0
- package/test-apps/embroider3-webpack/.watchmanconfig +3 -0
- package/test-apps/embroider3-webpack/README.md +56 -0
- package/test-apps/embroider3-webpack/app/app.js +17 -0
- package/test-apps/embroider3-webpack/app/deprecation-workflow.js +24 -0
- package/test-apps/embroider3-webpack/app/index.html +24 -0
- package/test-apps/embroider3-webpack/app/router.js +9 -0
- package/test-apps/embroider3-webpack/app/styles/app.css +1 -0
- package/test-apps/embroider3-webpack/app/templates/application.hbs +7 -0
- package/test-apps/embroider3-webpack/config/ember-cli-update.json +21 -0
- package/test-apps/embroider3-webpack/config/environment.js +48 -0
- package/test-apps/embroider3-webpack/config/optional-features.json +7 -0
- package/test-apps/embroider3-webpack/config/targets.js +11 -0
- package/test-apps/embroider3-webpack/ember-cli-build.js +31 -0
- package/test-apps/embroider3-webpack/package.json +74 -0
- package/test-apps/embroider3-webpack/public/robots.txt +3 -0
- package/test-apps/embroider3-webpack/testem.js +23 -0
- package/test-apps/embroider3-webpack/tests/index.html +39 -0
- package/test-apps/embroider3-webpack/tests/test-helper.js +9 -0
- package/test-apps/vite-with-compat/.editorconfig +19 -0
- package/test-apps/vite-with-compat/.ember-cli +19 -0
- package/test-apps/vite-with-compat/.env.development +8 -0
- package/test-apps/vite-with-compat/.env.test +8 -0
- package/test-apps/vite-with-compat/.prettierignore +13 -0
- package/test-apps/vite-with-compat/.prettierrc.mjs +37 -0
- package/test-apps/vite-with-compat/.template-lintrc.mjs +3 -0
- package/test-apps/vite-with-compat/.watchmanconfig +3 -0
- package/test-apps/vite-with-compat/README.md +57 -0
- package/test-apps/vite-with-compat/app/app.js +10 -0
- package/test-apps/vite-with-compat/app/config/environment.js +27 -0
- package/test-apps/vite-with-compat/app/router.js +9 -0
- package/test-apps/vite-with-compat/babel.config.cjs +42 -0
- package/test-apps/vite-with-compat/config/ember-cli-update.json +19 -0
- package/test-apps/vite-with-compat/config/environment.js +48 -0
- package/test-apps/vite-with-compat/config/optional-features.json +7 -0
- package/test-apps/vite-with-compat/config/targets.js +11 -0
- package/test-apps/vite-with-compat/ember-cli-build.js +22 -0
- package/test-apps/vite-with-compat/index.html +9 -0
- package/test-apps/vite-with-compat/package.json +81 -0
- package/test-apps/vite-with-compat/public/robots.txt +3 -0
- package/test-apps/vite-with-compat/testem.cjs +27 -0
- package/test-apps/vite-with-compat/tests/index.html +46 -0
- package/test-apps/vite-with-compat/tests/integration/a-test.gjs +28 -0
- package/test-apps/vite-with-compat/tests/integration/b-test.gjs +28 -0
- package/test-apps/vite-with-compat/tests/test-helper.js +14 -0
- package/test-apps/vite-with-compat/vite.config.mjs +59 -0
- package/.codeclimate.yml +0 -20
- package/addon-test-support/.eslintrc +0 -6
- package/lib/.eslintrc +0 -5
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"solution": {
|
|
3
|
+
"ember-exam": {
|
|
4
|
+
"impact": "major",
|
|
5
|
+
"oldVersion": "9.1.0",
|
|
6
|
+
"newVersion": "10.0.0",
|
|
7
|
+
"tagName": "latest",
|
|
8
|
+
"constraints": [
|
|
9
|
+
{
|
|
10
|
+
"impact": "major",
|
|
11
|
+
"reason": "Appears in changelog section :boom: Breaking Change"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"impact": "patch",
|
|
15
|
+
"reason": "Appears in changelog section :bug: Bug Fix"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"impact": "patch",
|
|
19
|
+
"reason": "Appears in changelog section :memo: Documentation"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"impact": "patch",
|
|
23
|
+
"reason": "Appears in changelog section :house: Internal"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"pkgJSONPath": "./package.json"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"description": "## Release (2025-08-26)\n\n* ember-exam 10.0.0 (major)\n\n#### :boom: Breaking Change\n* `ember-exam`\n * [#1430](https://github.com/ember-cli/ember-exam/pull/1430) Support vite ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### :bug: Bug Fix\n* `ember-exam`\n * [#1450](https://github.com/ember-cli/ember-exam/pull/1450) Support cjs testem configs ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### :memo: Documentation\n* `ember-exam`\n * [#1347](https://github.com/ember-cli/ember-exam/pull/1347) Update setup example for new qunit requirements ([@elwayman02](https://github.com/elwayman02))\n\n#### :house: Internal\n* `ember-exam`\n * [#1449](https://github.com/ember-cli/ember-exam/pull/1449) Spit node-tests in to parallel jobs for easier retries (we have a very short testem timeout) ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1451](https://github.com/ember-cli/ember-exam/pull/1451) Delete test duplication and use symlinks instead ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1452](https://github.com/ember-cli/ember-exam/pull/1452) Remove extraneous command in CI workflow ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1448](https://github.com/ember-cli/ember-exam/pull/1448) Split out try scenarios in to real apps for easier debugging ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1443](https://github.com/ember-cli/ember-exam/pull/1443) Remove unused deps ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1442](https://github.com/ember-cli/ember-exam/pull/1442) Get rid of custom resolver form an older era of the blueprint ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1439](https://github.com/ember-cli/ember-exam/pull/1439) Update renovate-config (move to weekly) ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1441](https://github.com/ember-cli/ember-exam/pull/1441) Set base for pages deployment ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1440](https://github.com/ember-cli/ember-exam/pull/1440) Fix static files path for gh-pages deploy ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1435](https://github.com/ember-cli/ember-exam/pull/1435) Strict dep management settings + re-roll lockfile, remove addon-docs, add vitepress ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1434](https://github.com/ember-cli/ember-exam/pull/1434) Add prettier to lint, don't run lint with tests ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1431](https://github.com/ember-cli/ember-exam/pull/1431) Upgrade eslint / prettier ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### Committers: 2\n- Jordan Hawker ([@elwayman02](https://github.com/elwayman02))\n- [@NullVoxPopuli](https://github.com/NullVoxPopuli)\n"
|
|
30
|
+
}
|
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ The [documentation website](https://ember-cli.github.io/ember-exam/) contains ex
|
|
|
39
39
|
Installation is as easy as running:
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
$
|
|
42
|
+
$ npm install --save-dev ember-exam
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
## How To Use
|
|
@@ -72,12 +72,75 @@ To get the unique features of Ember Exam (described in-depth below), you will ne
|
|
|
72
72
|
|
|
73
73
|
```js
|
|
74
74
|
// test-helper.js
|
|
75
|
-
import start from 'ember-
|
|
75
|
+
- import { start, setupEmberOnerrorValidation } from 'ember-qunit';
|
|
76
|
+
+ import { setupEmberOnerrorValidation } from 'ember-qunit';
|
|
77
|
+
+ import { start } from 'ember-exam/test-support';
|
|
76
78
|
|
|
77
79
|
// Options passed to `start` will be passed-through to ember-qunit
|
|
78
80
|
start();
|
|
79
81
|
```
|
|
80
82
|
|
|
83
|
+
## How to use with Vite
|
|
84
|
+
|
|
85
|
+
All of the above applies, but we need to tell vite to build the app before telling ember/exam to run tests on that output.
|
|
86
|
+
|
|
87
|
+
Update your test-helper.js or test-helper.ts, to have add the ember-exam `start` function:
|
|
88
|
+
```diff
|
|
89
|
+
// ...
|
|
90
|
+
import { setApplication } from '@ember/test-helpers';
|
|
91
|
+
import { setup } from 'qunit-dom';
|
|
92
|
+
- import { start as qunitStart, setupEmberOnerrorValidation } from 'ember-qunit';
|
|
93
|
+
+ import { setupEmberOnerrorValidation } from 'ember-qunit';
|
|
94
|
+
+ import { start as startEmberExam } from 'ember-exam/test-support';
|
|
95
|
+
|
|
96
|
+
- export function start() {
|
|
97
|
+
+ export async function start({ availableModules }) {
|
|
98
|
+
setApplication(Application.create(config.APP));
|
|
99
|
+
|
|
100
|
+
setup(QUnit.assert);
|
|
101
|
+
setupEmberOnerrorValidation();
|
|
102
|
+
|
|
103
|
+
- qunitStart();
|
|
104
|
+
+ // Options passed to `start` will be passed-through to ember-qunit
|
|
105
|
+
+ await startEmberExam({ availableModules });
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Then, update your tests/index.html to pass availableModules to start:
|
|
110
|
+
```html
|
|
111
|
+
<script type="module">
|
|
112
|
+
import { start } from './test-helper.js';
|
|
113
|
+
|
|
114
|
+
const availableModules = {
|
|
115
|
+
...import.meta.glob('./application/**/*-test.{js,ts,gjs,gts}'),
|
|
116
|
+
...import.meta.glob('./rendering/**/*-test.{js,ts,gjs,gts}'),
|
|
117
|
+
...import.meta.glob('./unit/**/*-test.{js,ts,gjs,gts}'),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
start({ availableModules });
|
|
121
|
+
</script>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
Testing development:
|
|
126
|
+
```bash
|
|
127
|
+
NODE_ENV=development vite build --mode development
|
|
128
|
+
ember exam --path dist --config-file ./testem.cjs
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Testing production:
|
|
132
|
+
```bash
|
|
133
|
+
vite build --mode test
|
|
134
|
+
ember exam --path dist --config-file ./testem.cjs
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
> [!NOTE]
|
|
138
|
+
> Specifying the `--path` is important because otherwise ember-cli will try to build your vite app, and it will error.
|
|
139
|
+
|
|
140
|
+
> [!NOTE]
|
|
141
|
+
> Specifying the `--config-path` is important because ember-cli (what backs ember-exam) doesn't know about cjs files.
|
|
142
|
+
|
|
143
|
+
|
|
81
144
|
### Version < `3.0.0`
|
|
82
145
|
|
|
83
146
|
|
|
@@ -115,7 +115,6 @@ export default class AsyncIterator {
|
|
|
115
115
|
);
|
|
116
116
|
reject(err);
|
|
117
117
|
} else {
|
|
118
|
-
// eslint-disable-next-line no-console
|
|
119
118
|
console.error(
|
|
120
119
|
`EmberExam: Promise timed out after ${this._timeout} s while waiting for response for ${this._request}. Closing browser to exit gracefully.`,
|
|
121
120
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assert } from '@ember/debug';
|
|
1
2
|
import getUrlParams from './get-url-params';
|
|
2
3
|
import splitTestModules from './split-test-modules';
|
|
3
4
|
import weightTestModules from './weight-test-modules';
|
|
@@ -59,7 +60,7 @@ export default class EmberExamTestLoader extends TestLoader {
|
|
|
59
60
|
*
|
|
60
61
|
* @method loadModules
|
|
61
62
|
*/
|
|
62
|
-
loadModules() {
|
|
63
|
+
async loadModules({ availableModules } = {}) {
|
|
63
64
|
const loadBalance = this._urlParams.get('loadBalance');
|
|
64
65
|
const browserId = this._urlParams.get('browser');
|
|
65
66
|
const modulePath = this._urlParams.get('modulePath');
|
|
@@ -75,7 +76,18 @@ export default class EmberExamTestLoader extends TestLoader {
|
|
|
75
76
|
partitions = [partitions];
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
if (!availableModules) {
|
|
80
|
+
super.loadModules();
|
|
81
|
+
} else {
|
|
82
|
+
assert(
|
|
83
|
+
`Available modules must be an object.`,
|
|
84
|
+
typeof availableModules === 'object',
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
this._availableModules = availableModules;
|
|
88
|
+
this._testModules = Object.keys(availableModules);
|
|
89
|
+
}
|
|
90
|
+
|
|
79
91
|
this.setupModuleMetadataHandler();
|
|
80
92
|
|
|
81
93
|
if (modulePath || filePath) {
|
|
@@ -93,6 +105,7 @@ export default class EmberExamTestLoader extends TestLoader {
|
|
|
93
105
|
split,
|
|
94
106
|
partitions,
|
|
95
107
|
);
|
|
108
|
+
|
|
96
109
|
this._testem.emit(
|
|
97
110
|
'testem:set-modules-queue',
|
|
98
111
|
this._testModules,
|
|
@@ -104,6 +117,15 @@ export default class EmberExamTestLoader extends TestLoader {
|
|
|
104
117
|
split,
|
|
105
118
|
partitions,
|
|
106
119
|
);
|
|
120
|
+
|
|
121
|
+
if (this._availableModules) {
|
|
122
|
+
await this.loadAvailableModules();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Legacy support
|
|
128
|
+
*/
|
|
107
129
|
this._testModules.forEach((moduleName) => {
|
|
108
130
|
super.require(moduleName);
|
|
109
131
|
super.unsee(moduleName);
|
|
@@ -111,18 +133,54 @@ export default class EmberExamTestLoader extends TestLoader {
|
|
|
111
133
|
}
|
|
112
134
|
}
|
|
113
135
|
|
|
136
|
+
/**
|
|
137
|
+
* availableModules are passed in from loadModules
|
|
138
|
+
* from loadEmberExam
|
|
139
|
+
* from start
|
|
140
|
+
*/
|
|
141
|
+
async loadAvailableModules() {
|
|
142
|
+
if (this._availableModules) {
|
|
143
|
+
await Promise.all(
|
|
144
|
+
this._testModules.map(async (moduleName) => {
|
|
145
|
+
let loader = this._availableModules[moduleName];
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* If it's not a function, it's already loaded
|
|
149
|
+
*/
|
|
150
|
+
if (typeof loader === 'function') {
|
|
151
|
+
await loader();
|
|
152
|
+
}
|
|
153
|
+
}),
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
114
158
|
/**
|
|
115
159
|
* Allow loading one module at a time.
|
|
116
160
|
*
|
|
117
161
|
* @method loadIndividualModule
|
|
118
162
|
* @param {string} moduleName
|
|
119
163
|
*/
|
|
120
|
-
loadIndividualModule(moduleName) {
|
|
164
|
+
async loadIndividualModule(moduleName) {
|
|
121
165
|
if (moduleName === undefined) {
|
|
122
166
|
throw new Error(
|
|
123
167
|
'Failed to load a test module. `moduleName` is undefined in `loadIndividualModule`.',
|
|
124
168
|
);
|
|
125
169
|
}
|
|
170
|
+
|
|
171
|
+
if (this._availableModules) {
|
|
172
|
+
let loader = this._availableModules[moduleName];
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* If it's not a function, it's already loaded
|
|
176
|
+
*/
|
|
177
|
+
if (typeof loader === 'function') {
|
|
178
|
+
await loader();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
126
184
|
super.require(moduleName);
|
|
127
185
|
super.unsee(moduleName);
|
|
128
186
|
}
|
|
@@ -168,10 +226,10 @@ export default class EmberExamTestLoader extends TestLoader {
|
|
|
168
226
|
|
|
169
227
|
return nextModuleAsyncIterator
|
|
170
228
|
.next()
|
|
171
|
-
.then((response) => {
|
|
229
|
+
.then(async (response) => {
|
|
172
230
|
if (!response.done) {
|
|
173
231
|
const moduleName = response.value;
|
|
174
|
-
this.loadIndividualModule(moduleName);
|
|
232
|
+
await this.loadIndividualModule(moduleName);
|
|
175
233
|
|
|
176
234
|
// if no tests were added, request the next module
|
|
177
235
|
if (this._qunit.config.queue.length === 0) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as start } from './start';
|
|
@@ -6,15 +6,16 @@ import { start as qunitStart } from 'ember-qunit';
|
|
|
6
6
|
*
|
|
7
7
|
* @function loadTests
|
|
8
8
|
* @param {*} testLoader
|
|
9
|
+
* @param {*} loaderOptions
|
|
9
10
|
*/
|
|
10
|
-
function loadTests(testLoader) {
|
|
11
|
+
async function loadTests(testLoader, loaderOptions = {}) {
|
|
11
12
|
if (testLoader === undefined) {
|
|
12
13
|
throw new Error(
|
|
13
14
|
'A testLoader instance has not been created. You must call `loadEmberExam()` before calling `loadTest()`.',
|
|
14
15
|
);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
testLoader.loadModules();
|
|
18
|
+
await testLoader.loadModules(loaderOptions);
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -24,11 +25,13 @@ function loadTests(testLoader) {
|
|
|
24
25
|
* @function start
|
|
25
26
|
* @param {*} qunitOptions
|
|
26
27
|
*/
|
|
27
|
-
export default function start(qunitOptions) {
|
|
28
|
-
const
|
|
28
|
+
export default async function start(qunitOptions = {}) {
|
|
29
|
+
const { availableModules, ...modifiedOptions } =
|
|
30
|
+
qunitOptions || Object.create(null);
|
|
31
|
+
|
|
29
32
|
modifiedOptions.loadTests = false;
|
|
30
33
|
|
|
31
34
|
const testLoader = loadEmberExam();
|
|
32
|
-
loadTests(testLoader);
|
|
35
|
+
await loadTests(testLoader, { availableModules });
|
|
33
36
|
qunitStart(modifiedOptions);
|
|
34
37
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { defineConfig } from 'vitepress'
|
|
2
|
+
|
|
3
|
+
// https://vitepress.dev/reference/site-config
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
title: "ember-exam",
|
|
6
|
+
description: "Run your tests with randomization, splitting, and parallelization for beautiful tests.",
|
|
7
|
+
base: '/ember-exam/',
|
|
8
|
+
markdown: {
|
|
9
|
+
// theme: {
|
|
10
|
+
// ...dark,
|
|
11
|
+
// settings: [
|
|
12
|
+
// {
|
|
13
|
+
// scope: 'comment',
|
|
14
|
+
// settings: {
|
|
15
|
+
// // 'foreground': 'rgb(200, 200, 200)'
|
|
16
|
+
// }
|
|
17
|
+
// },
|
|
18
|
+
// ]
|
|
19
|
+
// },
|
|
20
|
+
},
|
|
21
|
+
themeConfig: {
|
|
22
|
+
// https://vitepress.dev/reference/default-theme-config
|
|
23
|
+
nav: [
|
|
24
|
+
{ text: 'Home', link: '/' },
|
|
25
|
+
// { text: 'Examples', link: '/markdown-examples' }
|
|
26
|
+
],
|
|
27
|
+
|
|
28
|
+
sidebar: [
|
|
29
|
+
{
|
|
30
|
+
text: 'Options',
|
|
31
|
+
items: [
|
|
32
|
+
{ text: 'Randomization', link: '/randomization' },
|
|
33
|
+
{ text: 'Randomization Iterator', link: '/randomization-iterator' },
|
|
34
|
+
{ text: 'Generating Module Metadata For Test Execution', link: '/module-metadata' },
|
|
35
|
+
{ text: 'Splitting', link: '/splitting' },
|
|
36
|
+
{ text: 'Split Test Parallelization', link: '/split-parallel' },
|
|
37
|
+
{ text: 'Filtering', link: '/filtering' },
|
|
38
|
+
{ text: 'Test Load Balancing', link: '/load-balancing' },
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
text: 'Advanced Configuration',
|
|
43
|
+
items: [
|
|
44
|
+
{ text: 'Ember Try & CI Integration', link: '/ember-try-and-ci' },
|
|
45
|
+
{ text: 'Test Suite Segmentation', link: '/test-suite-segmentation' },
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
|
|
50
|
+
socialLinks: [
|
|
51
|
+
{ icon: 'github', link: 'https://github.com/ember-cli/ember-exam' }
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// https://vitepress.dev/guide/custom-theme
|
|
2
|
+
import { h } from 'vue'
|
|
3
|
+
import type { Theme } from 'vitepress'
|
|
4
|
+
import DefaultTheme from 'vitepress/theme'
|
|
5
|
+
import './style.css'
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
extends: DefaultTheme,
|
|
9
|
+
Layout: () => {
|
|
10
|
+
return h(DefaultTheme.Layout, null, {
|
|
11
|
+
// https://vitepress.dev/guide/extending-default-theme#layout-slots
|
|
12
|
+
})
|
|
13
|
+
},
|
|
14
|
+
enhanceApp({ app, router, siteData }) {
|
|
15
|
+
// ...
|
|
16
|
+
}
|
|
17
|
+
} satisfies Theme
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Customize default theme styling by overriding CSS variables:
|
|
3
|
+
* https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Colors
|
|
8
|
+
*
|
|
9
|
+
* Each colors have exact same color scale system with 3 levels of solid
|
|
10
|
+
* colors with different brightness, and 1 soft color.
|
|
11
|
+
*
|
|
12
|
+
* - `XXX-1`: The most solid color used mainly for colored text. It must
|
|
13
|
+
* satisfy the contrast ratio against when used on top of `XXX-soft`.
|
|
14
|
+
*
|
|
15
|
+
* - `XXX-2`: The color used mainly for hover state of the button.
|
|
16
|
+
*
|
|
17
|
+
* - `XXX-3`: The color for solid background, such as bg color of the button.
|
|
18
|
+
* It must satisfy the contrast ratio with pure white (#ffffff) text on
|
|
19
|
+
* top of it.
|
|
20
|
+
*
|
|
21
|
+
* - `XXX-soft`: The color used for subtle background such as custom container
|
|
22
|
+
* or badges. It must satisfy the contrast ratio when putting `XXX-1` colors
|
|
23
|
+
* on top of it.
|
|
24
|
+
*
|
|
25
|
+
* The soft color must be semi transparent alpha channel. This is crucial
|
|
26
|
+
* because it allows adding multiple "soft" colors on top of each other
|
|
27
|
+
* to create a accent, such as when having inline code block inside
|
|
28
|
+
* custom containers.
|
|
29
|
+
*
|
|
30
|
+
* - `default`: The color used purely for subtle indication without any
|
|
31
|
+
* special meanings attached to it such as bg color for menu hover state.
|
|
32
|
+
*
|
|
33
|
+
* - `brand`: Used for primary brand colors, such as link text, button with
|
|
34
|
+
* brand theme, etc.
|
|
35
|
+
*
|
|
36
|
+
* - `tip`: Used to indicate useful information. The default theme uses the
|
|
37
|
+
* brand color for this by default.
|
|
38
|
+
*
|
|
39
|
+
* - `warning`: Used to indicate warning to the users. Used in custom
|
|
40
|
+
* container, badges, etc.
|
|
41
|
+
*
|
|
42
|
+
* - `danger`: Used to show error, or dangerous message to the users. Used
|
|
43
|
+
* in custom container, badges, etc.
|
|
44
|
+
* -------------------------------------------------------------------------- */
|
|
45
|
+
|
|
46
|
+
:root {
|
|
47
|
+
--vp-c-default-1: var(--vp-c-gray-1);
|
|
48
|
+
--vp-c-default-2: var(--vp-c-gray-2);
|
|
49
|
+
--vp-c-default-3: var(--vp-c-gray-3);
|
|
50
|
+
--vp-c-default-soft: var(--vp-c-gray-soft);
|
|
51
|
+
|
|
52
|
+
--vp-c-brand-1: var(--vp-c-indigo-1);
|
|
53
|
+
--vp-c-brand-2: var(--vp-c-indigo-2);
|
|
54
|
+
--vp-c-brand-3: var(--vp-c-indigo-3);
|
|
55
|
+
--vp-c-brand-soft: var(--vp-c-indigo-soft);
|
|
56
|
+
|
|
57
|
+
--vp-c-tip-1: var(--vp-c-brand-1);
|
|
58
|
+
--vp-c-tip-2: var(--vp-c-brand-2);
|
|
59
|
+
--vp-c-tip-3: var(--vp-c-brand-3);
|
|
60
|
+
--vp-c-tip-soft: var(--vp-c-brand-soft);
|
|
61
|
+
|
|
62
|
+
--vp-c-warning-1: var(--vp-c-yellow-1);
|
|
63
|
+
--vp-c-warning-2: var(--vp-c-yellow-2);
|
|
64
|
+
--vp-c-warning-3: var(--vp-c-yellow-3);
|
|
65
|
+
--vp-c-warning-soft: var(--vp-c-yellow-soft);
|
|
66
|
+
|
|
67
|
+
--vp-c-danger-1: var(--vp-c-red-1);
|
|
68
|
+
--vp-c-danger-2: var(--vp-c-red-2);
|
|
69
|
+
--vp-c-danger-3: var(--vp-c-red-3);
|
|
70
|
+
--vp-c-danger-soft: var(--vp-c-red-soft);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Component: Button
|
|
75
|
+
* -------------------------------------------------------------------------- */
|
|
76
|
+
|
|
77
|
+
:root {
|
|
78
|
+
--vp-button-brand-border: transparent;
|
|
79
|
+
--vp-button-brand-text: var(--vp-c-white);
|
|
80
|
+
--vp-button-brand-bg: var(--vp-c-brand-3);
|
|
81
|
+
--vp-button-brand-hover-border: transparent;
|
|
82
|
+
--vp-button-brand-hover-text: var(--vp-c-white);
|
|
83
|
+
--vp-button-brand-hover-bg: var(--vp-c-brand-2);
|
|
84
|
+
--vp-button-brand-active-border: transparent;
|
|
85
|
+
--vp-button-brand-active-text: var(--vp-c-white);
|
|
86
|
+
--vp-button-brand-active-bg: var(--vp-c-brand-1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Component: Home
|
|
91
|
+
* -------------------------------------------------------------------------- */
|
|
92
|
+
|
|
93
|
+
:root {
|
|
94
|
+
--vp-home-hero-name-color: transparent;
|
|
95
|
+
--vp-home-hero-name-background: -webkit-linear-gradient(
|
|
96
|
+
120deg,
|
|
97
|
+
#bd34fe 30%,
|
|
98
|
+
#41d1ff
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
--vp-home-hero-image-background-image: linear-gradient(
|
|
102
|
+
-45deg,
|
|
103
|
+
#bd34fe 50%,
|
|
104
|
+
#47caff 50%
|
|
105
|
+
);
|
|
106
|
+
--vp-home-hero-image-filter: blur(44px);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@media (min-width: 640px) {
|
|
110
|
+
:root {
|
|
111
|
+
--vp-home-hero-image-filter: blur(56px);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@media (min-width: 960px) {
|
|
116
|
+
:root {
|
|
117
|
+
--vp-home-hero-image-filter: blur(68px);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Component: Custom Block
|
|
123
|
+
* -------------------------------------------------------------------------- */
|
|
124
|
+
|
|
125
|
+
:root {
|
|
126
|
+
--vp-custom-block-tip-border: transparent;
|
|
127
|
+
--vp-custom-block-tip-text: var(--vp-c-text-1);
|
|
128
|
+
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
|
|
129
|
+
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Component: Algolia
|
|
134
|
+
* -------------------------------------------------------------------------- */
|
|
135
|
+
|
|
136
|
+
.DocSearch {
|
|
137
|
+
--docsearch-primary-color: var(--vp-c-brand-1) !important;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
.badges {
|
|
143
|
+
> p {
|
|
144
|
+
display: flex;
|
|
145
|
+
gap: 1rem;
|
|
146
|
+
justify-content: center;
|
|
147
|
+
align-items: center;
|
|
148
|
+
}
|
|
149
|
+
img, a {
|
|
150
|
+
display: inline-flex;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Contrast fixes
|
|
157
|
+
*/
|
|
158
|
+
html {
|
|
159
|
+
--vp-c-text-2: rgb(40, 40, 40);
|
|
160
|
+
}
|
|
161
|
+
html.dark {
|
|
162
|
+
--vp-c-text-2: rgb(200, 200, 200);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
html [class*='language-'] > span.lang {
|
|
166
|
+
--vp-code-lang-color: rgb(40,40,40);
|
|
167
|
+
}
|
|
168
|
+
html.dark [class*='language-'] > span.lang {
|
|
169
|
+
--vp-code-lang-color: rgb(200,200,200);
|
|
170
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
### Ember Try & CI Integration
|
|
2
|
+
|
|
3
|
+
Integrating ember-exam with [ember-try](https://github.com/ember-cli/ember-try) is remarkably easy. Define a [`command` in your `ember-try.js` config](https://github.com/ember-cli/ember-try#configuration-files) that leverages the `exam` command:
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
// config/ember-try.js
|
|
7
|
+
module.exports = {
|
|
8
|
+
command: 'ember exam --split 3 --parallel',
|
|
9
|
+
// ...
|
|
10
|
+
};
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Using [environmental variables](https://nodejs.org/api/process.html#process_process_env) gives you flexibility in how you run your tests. For instance, you could distribute your tests across processes instead of parallelizing them by specifying a `PARTITION` variable in your process environment and then consuming it like so:
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
module.exports = {
|
|
17
|
+
command: 'ember exam --split 20 --partition ' + process.env.PARTITION,
|
|
18
|
+
// ...
|
|
19
|
+
};
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If you are working with [Travis CI](https://travis-ci.org/) then you can also easily set up seeded-random runs based on PR numbers. Similar to the following:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
const command = ['ember', 'exam', '--random'];
|
|
26
|
+
const pr = process.env.TRAVIS_PULL_REQUEST;
|
|
27
|
+
|
|
28
|
+
if (pr) {
|
|
29
|
+
command.push(pr);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
command: command.join(' '),
|
|
34
|
+
// ...
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
You can refer to [Travis' default environment variables](https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables) to see what else you could possibly leverage for your test setup.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
### Filtering
|
|
2
|
+
|
|
3
|
+
Ember Exam provides options to filter test suites by two types - module path and test file path.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
$ ember exam --module-path=<module-path>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
#### For Vite Apps
|
|
10
|
+
|
|
11
|
+
The `file-path` option allows you to filter modules by the given relative path that is generated from `import.meta.glob(...)` in your `tests/index.html`.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# This will run tests that are defined in `/my-application/tests/unit/my-test.js`
|
|
15
|
+
$ ember exam --file-path='/my-application/tests/unit/my-test.js'
|
|
16
|
+
|
|
17
|
+
# This will run all test files that are under `/my-application/tests/unit/`
|
|
18
|
+
$ ember exam --file-path='/my-application/tests/unit/*.js'
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
#### For non-Vite Apps
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
The `module-path` option allows you to filter module paths by a given value. Module paths are mapped by test files and they are generated during `ember build`. After the build, `tests.js` file is created and it resides under [build-directory]/assets.
|
|
26
|
+
|
|
27
|
+
The file is combined of all tests in an application and it has a form of `define("<module-path>", others..`.
|
|
28
|
+
|
|
29
|
+
The value for `module-path` can have either string or regular expression, for instance:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# When module path value is string. This will run all modules which match with the passed value
|
|
33
|
+
$ ember exam --module-path='dummy/tests/helpers/module-for-acceptance'
|
|
34
|
+
|
|
35
|
+
# When module path value is regex. This will run all modules which have `dummy` in it
|
|
36
|
+
$ ember exam --module-path='!/dummy/'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The `file-path` option is to filter tests by *test file path*. The test file path is a location of the test file in a file system. You can specify `file-path` to a location of specific test file path or you can use wildcards in paths to target multiple test files.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# This will run tests that are defined in `/my-application/tests/unit/my-test.js`
|
|
43
|
+
$ ember exam --file-path='/my-application/tests/unit/my-test.js'
|
|
44
|
+
|
|
45
|
+
# This will run all test files that are under `/my-application/tests/unit/`
|
|
46
|
+
$ ember exam --file-path='/my-application/tests/unit/*.js'
|
|
47
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
# https://vitepress.dev/reference/default-theme-home-page
|
|
3
|
+
layout: home
|
|
4
|
+
|
|
5
|
+
hero:
|
|
6
|
+
name: "ember-exam"
|
|
7
|
+
# text: "Run your tests with randomization, splitting, and parallelization for beautiful tests."
|
|
8
|
+
tagline: "Run your tests with randomization, splitting, and parallelization for beautiful tests."
|
|
9
|
+
actions:
|
|
10
|
+
- theme: brand
|
|
11
|
+
text: Quickstart
|
|
12
|
+
link: /quickstart
|
|
13
|
+
# - theme: alt
|
|
14
|
+
# text: API Examples
|
|
15
|
+
# link: /api-examples
|
|
16
|
+
|
|
17
|
+
features:
|
|
18
|
+
- title: Partitioning
|
|
19
|
+
details: Specify the number of parallel browser instances to use to speed up your test suite.
|
|
20
|
+
- title: Load Balancing
|
|
21
|
+
details: Balance tests to maximize the effectivess of parallel browsers that would otherwise completely quickly due to happenstance of being given quickly running tests.
|
|
22
|
+
- title: Randomization
|
|
23
|
+
details: Find and eliminate brittle tests by changing the order of tests within the test suite.
|
|
24
|
+
- title: Replay
|
|
25
|
+
details: Record and replay test execution order for reliably reproducing potentially flaky behaviors.
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
<span class="badges">
|
|
30
|
+
|
|
31
|
+

|
|
32
|
+
[][npm]
|
|
33
|
+
[][score]
|
|
34
|
+
|
|
35
|
+
</span>
|
|
36
|
+
|
|
37
|
+
[npm]: https://npmjs.com/package/ember-exam
|
|
38
|
+
[score]: https://emberobserver.com/addons/ember-exam
|
|
39
|
+
|
|
40
|
+
Ember Exam is an addon to allow you more control over how you run your tests when used in conjunction with [ember-qunit](https://github.com/emberjs/ember-qunit). It provides the ability to randomize, split, parallelize, and load-balance your test suite by adding a more robust CLI command.
|
|
41
|
+
|
|
42
|
+
It started as a way to help reduce flaky tests and encourage healthy test driven development.
|
|
43
|
+
|
|
44
|
+
[](https://embermap.com/video/ember-exam)
|
|
45
|
+
|
|
46
|
+
|