ember-vitest 0.3.0 → 0.3.2

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,6 @@
1
1
  # ember-vitest
2
2
 
3
- Ember<->Vitest integration
3
+ ember <-> vitest integration
4
4
 
5
5
  - browser testing is first class
6
6
  - pause test execution for UI debugging purposes (and without pausing JS execution)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-vitest",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "integration for testing Ember with Vitest",
5
5
  "keywords": [
6
6
  "ember",
@@ -36,6 +36,7 @@
36
36
  "files": [
37
37
  "ember-addon-main.cjs",
38
38
  "dist",
39
+ "src",
39
40
  "declarations"
40
41
  ],
41
42
  "dependencies": {
@@ -46,7 +47,7 @@
46
47
  "@babel/plugin-syntax-explicit-resource-management": "^7.27.1",
47
48
  "@babel/plugin-transform-runtime": "^7.28.3",
48
49
  "@babel/plugin-transform-typescript": "^7.28.5",
49
- "@ember/library-tsconfig": "^1.1.3",
50
+ "@ember/library-tsconfig": "^2.0.0",
50
51
  "@ember/test-helpers": "^5.4.0",
51
52
  "@embroider/addon-dev": "^8.1.2",
52
53
  "@embroider/core": "^4.2.0",
@@ -0,0 +1,21 @@
1
+ import Application from "ember-strict-application-resolver";
2
+ import type EmberApplication from "@ember/application";
3
+
4
+ class App extends Application {
5
+ modules = {};
6
+ }
7
+
8
+ export function createApp(element: HTMLElement) {
9
+ return App.create({ autoboot: false, rootElement: element });
10
+ }
11
+
12
+ export function create(
13
+ app: typeof EmberApplication | undefined,
14
+ element: HTMLElement,
15
+ ) {
16
+ if (app) {
17
+ return app.create({ autoboot: false, rootElement: element });
18
+ }
19
+
20
+ return createApp(element);
21
+ }
@@ -0,0 +1,149 @@
1
+ import {
2
+ setApplication,
3
+ resumeTest,
4
+ pauseTest,
5
+ type TestContext,
6
+ } from "@ember/test-helpers";
7
+
8
+ // https://vitest.dev/guide/test-context.html#extend-test-context
9
+ import { test as baseTest } from "vitest";
10
+ import {
11
+ setupContext,
12
+ teardownContext,
13
+ setupRenderingContext,
14
+ setupApplicationContext,
15
+ } from "@ember/test-helpers";
16
+
17
+ import Application from "ember-strict-application-resolver";
18
+
19
+ import type EmberApplication from "@ember/application";
20
+ import type { Owner } from "@ember/test-helpers/build-owner";
21
+
22
+ globalThis.resumeTest = resumeTest;
23
+
24
+ class App extends Application {
25
+ modules = {};
26
+ }
27
+
28
+ const waitForSettled = true;
29
+ const teardownContextOptions = { waitForSettled };
30
+
31
+ type ExtendedTestContext = {
32
+ app: typeof EmberApplication;
33
+ element: HTMLElement;
34
+ context: TestContext;
35
+ env: {
36
+ owner: Owner;
37
+ element: HTMLElement;
38
+ pauseTest: () => Promise<void>;
39
+ };
40
+ };
41
+
42
+ export const test = baseTest.extend<ExtendedTestContext>({
43
+ app: ({}, use) => use(App),
44
+ element: ({}, use) => use(document.createElement("div")),
45
+ context: ({}, use) => use({} as TestContext),
46
+ env: [
47
+ async (
48
+ {
49
+ app,
50
+ element,
51
+ context,
52
+ }: {
53
+ app: typeof EmberApplication;
54
+ element: HTMLElement;
55
+ context: TestContext;
56
+ },
57
+ use,
58
+ ) => {
59
+ document.body.append(element);
60
+
61
+ setApplication(app.create({ autoboot: false, rootElement: element }));
62
+ await setupContext(context);
63
+
64
+ await use({
65
+ owner: context.owner,
66
+ element,
67
+ pauseTest,
68
+ });
69
+
70
+ await teardownContext(context, teardownContextOptions);
71
+ element.remove();
72
+ },
73
+ { auto: true },
74
+ ],
75
+ });
76
+
77
+ export const renderingTest = baseTest.extend<ExtendedTestContext>({
78
+ app: ({}, use) => use(App),
79
+ element: ({}, use) => use(document.createElement("div")),
80
+ context: ({}, use) => use({} as TestContext),
81
+ env: [
82
+ async (
83
+ {
84
+ app,
85
+ element,
86
+ context,
87
+ }: {
88
+ app: typeof EmberApplication;
89
+ element: HTMLElement;
90
+ context: TestContext;
91
+ },
92
+ use,
93
+ ) => {
94
+ document.body.append(element);
95
+
96
+ setApplication(app.create({ autoboot: false, rootElement: element }));
97
+ await setupContext(context);
98
+ await setupRenderingContext(context);
99
+
100
+ await use({
101
+ owner: context.owner,
102
+ element,
103
+ pauseTest,
104
+ });
105
+
106
+ await teardownContext(context, teardownContextOptions);
107
+ element.remove();
108
+ },
109
+ { auto: true },
110
+ ],
111
+ });
112
+
113
+ export const applicationTest = baseTest.extend<ExtendedTestContext>({
114
+ app: ({}, use) => use(App),
115
+ element: ({}, use) => use(document.createElement("div")),
116
+ context: ({}, use) => use({} as TestContext),
117
+ env: [
118
+ async (
119
+ {
120
+ app,
121
+ element,
122
+ context,
123
+ }: {
124
+ app: typeof EmberApplication;
125
+ element: HTMLElement;
126
+ context: TestContext;
127
+ },
128
+ use,
129
+ ) => {
130
+ document.body.append(element);
131
+
132
+ console.log(app);
133
+
134
+ setApplication(app.create({ autoboot: false, rootElement: element }));
135
+ await setupContext(context);
136
+ await setupApplicationContext(context);
137
+
138
+ await use({
139
+ owner: context.owner,
140
+ element,
141
+ pauseTest,
142
+ });
143
+
144
+ await teardownContext(context, teardownContextOptions);
145
+ element.remove();
146
+ },
147
+ { auto: true },
148
+ ],
149
+ });
package/src/global.ts ADDED
@@ -0,0 +1,6 @@
1
+ declare global {
2
+ var resumeTest: typeof import("@ember/test-helpers").resumeTest;
3
+ var pauseTest: typeof import("@ember/test-helpers").pauseTest;
4
+ }
5
+
6
+ export {};
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export {
2
+ test,
3
+ renderingTest,
4
+ applicationTest,
5
+ } from "./extended-test-context.ts";
6
+
7
+ export { setupContext, setupRenderingContext } from "./manual.ts";
package/src/manual.ts ADDED
@@ -0,0 +1,112 @@
1
+ import { getOwner } from "@ember/owner";
2
+ import { settled, click, type TestContext } from "@ember/test-helpers";
3
+ import {
4
+ setupContext as emberSetupContext,
5
+ teardownContext,
6
+ setApplication,
7
+ type Target,
8
+ } from "@ember/test-helpers";
9
+ import { renderComponent } from "@ember/renderer";
10
+ import { create, createApp } from "./create-app.ts";
11
+
12
+ import type EmberApplication from "@ember/application";
13
+ import type Component from "@glimmer/component";
14
+ import type TOC from "@ember/component/template-only";
15
+
16
+ export function setupContext() {
17
+ let element = document.createElement("div");
18
+ document.body.append(element);
19
+ const app = createApp(element);
20
+
21
+ return {
22
+ element,
23
+ get owner() {
24
+ return getOwner(app);
25
+ },
26
+ async [Symbol.asyncDispose]() {
27
+ app.destroy();
28
+ await settled();
29
+ element.remove();
30
+ },
31
+ };
32
+ }
33
+
34
+ export async function setupRenderingContext(app: typeof EmberApplication) {
35
+ let element = document.createElement("div");
36
+ document.body.append(element);
37
+
38
+ let renders: Array<ReturnType<typeof renderComponent>> = [];
39
+ let ctx = {} as TestContext;
40
+ let created = create(app, element);
41
+
42
+ setApplication(created);
43
+
44
+ await emberSetupContext(ctx);
45
+
46
+ // Overloads that match Element.querySelector:
47
+ function find<K extends keyof (HTMLElementTagNameMap | SVGElementTagNameMap)>(
48
+ selector: K,
49
+ ): HTMLElementTagNameMap[K] | SVGElementTagNameMap[K] | null;
50
+ function find<K extends keyof HTMLElementTagNameMap>(
51
+ selector: K,
52
+ ): HTMLElementTagNameMap[K] | null;
53
+ function find<K extends keyof SVGElementTagNameMap>(
54
+ selector: K,
55
+ ): SVGElementTagNameMap[K] | null;
56
+ function find<E extends Element = Element>(selector: string): E | null;
57
+ function find(selector: string) {
58
+ return element.querySelector(selector);
59
+ }
60
+
61
+ // Overloads that match Element.querySelectorAll:
62
+ function findAll<K extends keyof HTMLElementTagNameMap>(
63
+ selector: K,
64
+ ): NodeListOf<HTMLElementTagNameMap[K]>;
65
+ function findAll<K extends keyof SVGElementTagNameMap>(
66
+ selector: K,
67
+ ): NodeListOf<SVGElementTagNameMap[K]>;
68
+ function findAll<K extends keyof HTMLElementDeprecatedTagNameMap>(
69
+ selector: K,
70
+ ): NodeListOf<HTMLElementDeprecatedTagNameMap[K]>;
71
+ function findAll<E extends Element = Element>(
72
+ selector: string,
73
+ ): NodeListOf<E>;
74
+ function findAll(selector: string) {
75
+ return element.querySelectorAll(selector);
76
+ }
77
+
78
+ return {
79
+ element,
80
+ get owner() {
81
+ return ctx.owner;
82
+ },
83
+ find,
84
+ findAll,
85
+ click(target: Parameters<typeof click>[0]) {
86
+ return click(target);
87
+ },
88
+ async render(
89
+ component: (new (...args: unknown[]) => Component) | typeof TOC,
90
+ ) {
91
+ let result = renderComponent(component, {
92
+ into: element,
93
+ owner: ctx.owner,
94
+ });
95
+
96
+ renders.push(result);
97
+ await settled();
98
+ },
99
+ async [Symbol.dispose]() {
100
+ renders.forEach((r) => r.destroy());
101
+ await teardownContext(ctx);
102
+ element.remove();
103
+ },
104
+ async [Symbol.asyncDispose]() {
105
+ renders.forEach((r) => r.destroy());
106
+ await settled();
107
+ await teardownContext(ctx);
108
+ await settled();
109
+ element.remove();
110
+ },
111
+ };
112
+ }