@evertondgn/solid-tooling 0.2.0 → 0.3.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/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # @evertondgn/solid-tooling
2
2
 
3
- Lint preset, formatter config and TypeScript base for SolidJS 2 applications
4
- built with [Vite+](https://viteplus.dev/guide/).
3
+ Lint preset, formatter config, TypeScript configs and test configs for SolidJS 2
4
+ applications built with [Vite+](https://viteplus.dev/guide/).
5
5
 
6
- The package contains the lint, format and TypeScript setup of
6
+ The package contains the lint, format, TypeScript and test setup of
7
7
  [boilerplate_solidjs](https://github.com/everton-dgn/boilerplate_solidjs), a
8
8
  SolidJS application template. Applications created from it install the package
9
9
  instead of copying the files, so a rule change reaches them through a version
@@ -27,6 +27,13 @@ with the version in its `devDependencies`.
27
27
  `eslint-plugin-solid` comes with the package, so the application does not
28
28
  declare it.
29
29
 
30
+ The test entries need the test tools the application already runs:
31
+
32
+ | Entry | The application installs |
33
+ | -------------- | ------------------------------------------------------------------------------ |
34
+ | `./vitest` | `@vitest/browser-playwright`, `@vitest/coverage-v8`, `happy-dom`, `playwright` |
35
+ | `./playwright` | `@playwright/test`, an optional peer dependency pinned like the others |
36
+
30
37
  ## Install
31
38
 
32
39
  `vp` is the Vite+ CLI. An application built with Vite+ already has `vite-plus`
@@ -68,6 +75,63 @@ export default defineConfig({ fmt, lint })
68
75
 
69
76
  `vp check`, `vp lint` and `vp fmt` read both configs from `vite.config.ts`.
70
77
 
78
+ ## Tests
79
+
80
+ `solidTest` returns the `test` block of `vite.config.ts`, with three Vitest
81
+ projects:
82
+
83
+ | Project | Files | Environment |
84
+ | --------- | -------------------------------- | ------------------------------------------------ |
85
+ | `node` | `src/**/*.node.test.{ts,tsx}` | Node, with stand-ins for the build-only modules |
86
+ | `dom` | `src/**/*.dom.test.{ts,tsx}` | happy-dom at `http://localhost/en` |
87
+ | `browser` | `src/**/*.browser.test.{ts,tsx}` | Chromium through Playwright, with the CSS loaded |
88
+
89
+ ```ts
90
+ // vite.config.ts
91
+ import { solidTest } from '@evertondgn/solid-tooling/vitest'
92
+
93
+ export default defineConfig({
94
+ test: solidTest({ root: import.meta.dirname, plugins: componentPlugins })
95
+ })
96
+ ```
97
+
98
+ `plugins` is a function that returns the Vite plugins the `dom` and `browser`
99
+ projects need to compile components: Solid, routes, icons and i18n. The preset
100
+ calls it once per project, because each project starts its own Vite server and a
101
+ plugin instance keeps the state of one server. The preset also sets the coverage
102
+ thresholds, the reporters and the workers on CI, passes `BASE_URL_TEST`, `HOST`
103
+ and `PORT` to the tests when they are set, and resets the Paraglide locale
104
+ before each browser test.
105
+
106
+ The `node` project does not load the Solid and routing plugins, so a plugin of
107
+ the preset serves `server-only`, `virtual:file-routes` and
108
+ `virtual:solid-server-function-handler`. Knip does not know `server-only`, a
109
+ virtual module of `@solidjs/vite-plugin`: list it in `ignoreDependencies`.
110
+
111
+ `definePlaywrightConfig` builds the Playwright config from the application root:
112
+
113
+ ```ts
114
+ // playwright.config.ts
115
+ import { definePlaywrightConfig } from '@evertondgn/solid-tooling/playwright'
116
+
117
+ export default definePlaywrightConfig({ root: import.meta.dirname })
118
+ ```
119
+
120
+ It reads `BASE_URL_TEST` from `.env.test`, builds the application (`e2e` mode
121
+ for the fixture routes, `production` with `TEST_PRODUCTION_ROUTES=true`), starts
122
+ the preview, and checks the server log for private markers when the suite ends.
123
+ `TEST_PREBUILT=true` reuses an existing production build.
124
+
125
+ | Option | Default | Use |
126
+ | ---------------- | ----------------- | ---------------------------------------------------------------------- |
127
+ | `testDir` | `src/tests/pages` | Folder of the `*.e2e.test.ts` files |
128
+ | `fixtureServers` | none | Extra servers for the fixture routes, as `{ command, url }` |
129
+ | `suites` | none | Globs of serial suites: `serverLogs`, `markdown` and `publicationLoad` |
130
+
131
+ Each serial suite gets its own project: `markdown` runs with one worker,
132
+ `serverLogs` runs last as the teardown of the others, and `publicationLoad` runs
133
+ alone, against two servers, with `TEST_PUBLICATION_LOAD=true`.
134
+
71
135
  ## Project layout the preset expects
72
136
 
73
137
  The rules match file paths relative to the folder where lint runs, so run it
@@ -205,20 +269,26 @@ overrides: [
205
269
 
206
270
  ## Entry points
207
271
 
208
- | Entry | Content |
209
- | ----------------------- | ------------------------------------------------------------------------- |
210
- | `./lint` | `lint`: the lint preset, with the plugins below registered |
211
- | `./fmt` | `fmt`: the formatter config |
212
- | `./tsconfig.base.json` | Compiler options, without application paths |
213
- | `./project-plugin` | The `project` rules |
214
- | `./backend-plugin` | The `backend` rules |
215
- | `./architecture-plugin` | The `architecture` rule |
216
- | `./solid-plugin` | Re-export of `eslint-plugin-solid` |
217
- | `./css-filename` | `cssFilenameError(path)`, the CSS naming check, for a script outside lint |
218
-
219
- An application only imports `./lint`, `./fmt` and `./tsconfig.base.json`. The
220
- plugin entries exist because Oxlint loads plugins by specifier, from the
221
- application.
272
+ | Entry | Content |
273
+ | ------------------------ | ------------------------------------------------------------------------- |
274
+ | `./lint` | `lint`: the lint preset, with the plugins below registered |
275
+ | `./fmt` | `fmt`: the formatter config |
276
+ | `./tsconfig.base.json` | Compiler options, without application paths |
277
+ | `./tsconfig.app.json` | The base plus the `types` and `include` of the boilerplate layout |
278
+ | `./vitest` | `solidTest(options)`, the `test` block of `vite.config.ts` |
279
+ | `./playwright` | `definePlaywrightConfig(options)`, the Playwright config |
280
+ | `./vitest-setup/browser` | Setup file of the browser project, loaded by `./vitest` |
281
+ | `./playwright-teardown` | Server log check, loaded by `./playwright` |
282
+ | `./project-plugin` | The `project` rules |
283
+ | `./backend-plugin` | The `backend` rules |
284
+ | `./architecture-plugin` | The `architecture` rule |
285
+ | `./solid-plugin` | Re-export of `eslint-plugin-solid` |
286
+ | `./css-filename` | `cssFilenameError(path)`, the CSS naming check, for a script outside lint |
287
+
288
+ An application imports `./lint`, `./fmt`, `./vitest`, `./playwright` and one of
289
+ the TypeScript configs. The plugin entries exist because Oxlint loads plugins by
290
+ specifier, from the application; the setup and teardown entries are loaded by
291
+ the test presets.
222
292
 
223
293
  ## Formatter
224
294
 
@@ -230,8 +300,36 @@ generated route types, SVG and lock files.
230
300
 
231
301
  `tsconfig.base.json` targets ES2024 with bundler resolution, keeps JSX for the
232
302
  Solid compiler (`jsxImportSource: @solidjs/web`), emits nothing and turns on the
233
- unused code and unchecked index checks. It has no `paths`, `include` or `types`:
234
- those depend on the application and stay in its `tsconfig.json`.
303
+ unused code and unchecked index checks. It has no `paths`, `include` or `types`.
304
+
305
+ `tsconfig.app.json` extends the base with the `types` of a boilerplate
306
+ application and an `include` resolved from the application folder with
307
+ `${configDir}`, which needs TypeScript 5.5 or later. Each entry of `types` comes
308
+ from a package the application installs:
309
+
310
+ | Entry of `types` | Package |
311
+ | --------------------------------------- | --------------------------- |
312
+ | `node` | `@types/node` |
313
+ | `vite/client` | `vite` |
314
+ | `vite-plus/test/globals` | `vite-plus` |
315
+ | `@testing-library/jest-dom/vitest` | `@testing-library/jest-dom` |
316
+ | `@solidjs/vite-plugin/boundary-modules` | `@solidjs/vite-plugin` |
317
+ | `@solidjs/vite-plugin/virtual-modules` | `@solidjs/vite-plugin` |
318
+
319
+ The application still declares its `paths`:
320
+
321
+ ```json
322
+ {
323
+ "extends": "@evertondgn/solid-tooling/tsconfig.app.json",
324
+ "compilerOptions": {
325
+ "paths": { "@/*": ["./src/*"], "@paraglide/*": ["./paraglide/*"] }
326
+ }
327
+ }
328
+ ```
329
+
330
+ Playwright reads the `tsconfig.json` of the test files with its own loader,
331
+ which does not expand `${configDir}`, so paths declared in the package would
332
+ break the `@/` imports of the end-to-end tests.
235
333
 
236
334
  ## Known limits
237
335
 
@@ -246,6 +344,10 @@ those depend on the application and stay in its `tsconfig.json`.
246
344
  installed even in an application without translations.
247
345
  - Some rule messages point to `docs/architecture.md` and `AGENTS.md`. Those
248
346
  files belong to the application created from boilerplate_solidjs.
347
+ - The test presets expect the boilerplate layout: tests named by suffix
348
+ (`.node.test`, `.dom.test`, `.browser.test`, `.e2e.test`), page tests in
349
+ `src/tests/pages/`, Paraglide output in `paraglide/` and `.env.test` at the
350
+ root.
249
351
 
250
352
  ## Versions
251
353
 
@@ -0,0 +1 @@
1
+ export default function checkServerLog(): Promise<void>;
@@ -0,0 +1,23 @@
1
+ import { env } from "node:process";
2
+ import { readFile } from "node:fs/promises";
3
+ import { stripVTControlCharacters } from "node:util";
4
+ // src/playwright/teardown.ts
5
+ const PRIVATE_MARKER = /PRIVATE_[A-Z0-9_]+/u;
6
+ async function checkLog({ file, baseUrl }) {
7
+ if (!file || !baseUrl) throw new Error("Server log file is not configured");
8
+ const log = stripVTControlCharacters(await readFile(file, "utf8"));
9
+ const { host } = new URL(baseUrl);
10
+ if (!log.includes(host)) throw new Error(`Server log does not show the preview startup: ${file}`);
11
+ if (PRIVATE_MARKER.test(log)) throw new Error(`Server log contains a private marker: ${file}`);
12
+ }
13
+ async function checkServerLog() {
14
+ await checkLog({
15
+ file: env.SERVER_LOG_FILE,
16
+ baseUrl: env.BASE_URL_TEST
17
+ });
18
+ if (env.TEST_PUBLICATION_LOAD === "true") await checkLog({
19
+ file: env.SERVER_LOG_SECONDARY,
20
+ baseUrl: env.PUBLICATION_SECONDARY_URL
21
+ });
22
+ }
23
+ export { checkServerLog as default };
@@ -0,0 +1,18 @@
1
+ import { PlaywrightTestConfig } from "@playwright/test";
2
+ type FixtureServer = {
3
+ command: string;
4
+ url: string;
5
+ };
6
+ type SerialSuites = {
7
+ serverLogs?: string;
8
+ markdown?: string;
9
+ publicationLoad?: string;
10
+ };
11
+ type PlaywrightOptions = {
12
+ root: string;
13
+ testDir?: string;
14
+ fixtureServers?: FixtureServer[];
15
+ suites?: SerialSuites;
16
+ };
17
+ export declare function definePlaywrightConfig({ root, testDir, fixtureServers, suites }: PlaywrightOptions): PlaywrightTestConfig;
18
+ export {};
@@ -0,0 +1,158 @@
1
+ import path from "node:path";
2
+ import { env, loadEnvFile } from "node:process";
3
+ import { fileURLToPath } from "node:url";
4
+ import { defineConfig, devices } from "@playwright/test";
5
+ import { loadEnv } from "vite-plus";
6
+ // src/playwright/index.ts
7
+ const STARTUP_TIMEOUT = 12e4;
8
+ const SECONDARY_PORT_OFFSET = 2;
9
+ const MAX_PORT = 65535;
10
+ const CI_WORKERS = 2;
11
+ const SECONDARY_LOG = "test-results/server-publication-secondary.log";
12
+ const PREBUILT_GUARD = "if [ -e .vercel/output/static/.vite ]; then echo 'TEST_PREBUILT found an e2e build; run vp run build first' >&2; exit 1; fi && ";
13
+ function readRunMode(suites) {
14
+ const mode = {
15
+ isProduction: env.TEST_PRODUCTION_ROUTES === "true",
16
+ isPublicationLoad: env.TEST_PUBLICATION_LOAD === "true",
17
+ shouldBuild: env.TEST_PREBUILT !== "true"
18
+ };
19
+ if (mode.isPublicationLoad && mode.isProduction) throw new Error("TEST_PUBLICATION_LOAD requires fixture routes");
20
+ if (mode.isPublicationLoad && !suites.publicationLoad) throw new Error("TEST_PUBLICATION_LOAD requires a publicationLoad suite");
21
+ if (!mode.shouldBuild && !mode.isProduction) throw new Error("TEST_PREBUILT requires production routes");
22
+ return mode;
23
+ }
24
+ function readBaseUrl(mode) {
25
+ if (!env.BASE_URL_TEST) throw new Error(".env.test must define BASE_URL_TEST");
26
+ const baseUrl = new URL(env.BASE_URL_TEST);
27
+ if (!baseUrl.port) throw new Error("BASE_URL_TEST must include an explicit port");
28
+ if (mode.isPublicationLoad && Number(baseUrl.port) + SECONDARY_PORT_OFFSET > MAX_PORT) throw new Error("BASE_URL_TEST leaves no port for the secondary server");
29
+ return env.BASE_URL_TEST;
30
+ }
31
+ function readWorkers(mode) {
32
+ if (mode.isPublicationLoad) return 1;
33
+ return env.CI ? CI_WORKERS : void 0;
34
+ }
35
+ function secondaryUrl(baseUrl) {
36
+ const url = new URL(baseUrl);
37
+ url.port = String(Number(url.port) + SECONDARY_PORT_OFFSET);
38
+ return url;
39
+ }
40
+ function buildProjects({ mode, suites }) {
41
+ if (mode.isPublicationLoad) return [{
42
+ name: "publication-load",
43
+ testMatch: suites.publicationLoad
44
+ }];
45
+ if (mode.isProduction) return [{ name: "chromium" }];
46
+ const teardown = suites.serverLogs ? { teardown: "server-logs" } : {};
47
+ const projects = [{
48
+ name: "chromium",
49
+ testIgnore: ["**/*.production.e2e.test.ts", ...[
50
+ suites.serverLogs,
51
+ suites.publicationLoad,
52
+ suites.markdown
53
+ ].filter((suite) => suite !== void 0)],
54
+ ...teardown
55
+ }];
56
+ if (suites.markdown) projects.push({
57
+ name: "markdown",
58
+ testMatch: suites.markdown,
59
+ fullyParallel: false,
60
+ workers: 1,
61
+ ...teardown
62
+ });
63
+ if (suites.serverLogs) projects.push({
64
+ name: "server-logs",
65
+ testMatch: suites.serverLogs,
66
+ fullyParallel: false
67
+ });
68
+ return projects;
69
+ }
70
+ function buildServers({ root, mode, fixtureServers, baseUrl, serverLog }) {
71
+ const buildMode = mode.isProduction ? "production" : "e2e";
72
+ const build = mode.shouldBuild ? `vp run build --mode ${buildMode} && ` : PREBUILT_GUARD;
73
+ const shared = {
74
+ cwd: root,
75
+ reuseExistingServer: false
76
+ };
77
+ const server = {
78
+ ...shared,
79
+ timeout: STARTUP_TIMEOUT
80
+ };
81
+ const fixtures = mode.isProduction ? [] : fixtureServers.map((fixture) => ({
82
+ ...fixture,
83
+ ...shared
84
+ }));
85
+ const { hostname, port } = new URL(baseUrl);
86
+ const secondary = secondaryUrl(baseUrl);
87
+ return [
88
+ ...fixtures,
89
+ {
90
+ ...server,
91
+ command: `${build}mkdir -p test-results && vp run start --strictPort > ${serverLog} 2>&1`,
92
+ env: {
93
+ HOST: hostname,
94
+ PORT: port,
95
+ NODE_ENV: "production"
96
+ },
97
+ url: baseUrl
98
+ },
99
+ ...mode.isPublicationLoad ? [{
100
+ ...server,
101
+ command: `vp run start --strictPort > ${SECONDARY_LOG} 2>&1`,
102
+ env: {
103
+ HOST: hostname,
104
+ PORT: secondary.port,
105
+ NODE_ENV: "production"
106
+ },
107
+ url: secondary.href
108
+ }] : []
109
+ ];
110
+ }
111
+ function definePlaywrightConfig({ root, testDir = "src/tests/pages", fixtureServers = [], suites = {} }) {
112
+ loadEnvFile(path.join(root, ".env.test"));
113
+ const mode = readRunMode(suites);
114
+ const buildMode = mode.isProduction ? "production" : "e2e";
115
+ Object.assign(env, loadEnv(buildMode, root, "VITE_"));
116
+ const baseUrl = readBaseUrl(mode);
117
+ const serverLog = `test-results/server-${buildMode}.log`;
118
+ env.SERVER_LOG_FILE = path.join(root, serverLog);
119
+ if (mode.isPublicationLoad) {
120
+ env.PUBLICATION_SECONDARY_URL = secondaryUrl(baseUrl).href;
121
+ env.SERVER_LOG_SECONDARY = path.join(root, SECONDARY_LOG);
122
+ }
123
+ const reportFolder = mode.isProduction ? "production" : "e2e";
124
+ return defineConfig({
125
+ testDir: path.join(root, testDir),
126
+ testMatch: mode.isProduction ? "**/*.production.e2e.test.ts" : "**/*.e2e.test.ts",
127
+ outputDir: path.join(root, mode.isProduction ? "test-results/e2e-production" : "test-results/e2e"),
128
+ globalTeardown: fileURLToPath(new URL("playwright-teardown.mjs", import.meta.url)),
129
+ fullyParallel: !mode.isPublicationLoad,
130
+ forbidOnly: true,
131
+ workers: readWorkers(mode),
132
+ reporter: [["list"], ["html", {
133
+ outputFolder: path.join(root, "playwright-report", reportFolder),
134
+ open: "never",
135
+ onlyFailures: Boolean(env.CI)
136
+ }]],
137
+ use: {
138
+ ...devices["Desktop Chrome"],
139
+ channel: env.CI ? "chrome" : void 0,
140
+ baseURL: baseUrl,
141
+ locale: "en-US",
142
+ screenshot: "only-on-failure",
143
+ trace: "retain-on-failure"
144
+ },
145
+ projects: buildProjects({
146
+ mode,
147
+ suites
148
+ }),
149
+ webServer: buildServers({
150
+ root,
151
+ mode,
152
+ fixtureServers,
153
+ baseUrl,
154
+ serverLog
155
+ })
156
+ });
157
+ }
158
+ export { definePlaywrightConfig };
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,5 @@
1
+ import { baseLocale, setLocale } from "@paraglide/runtime.js";
2
+ import { beforeEach } from "vite-plus/test";
3
+ // src/vitest/setup/browser.ts
4
+ beforeEach(() => setLocale(baseLocale, { reload: false }));
5
+ export {};
@@ -0,0 +1,7 @@
1
+ import { TestUserConfig, ViteUserConfig } from "vite-plus";
2
+ type SolidTestOptions = {
3
+ root: string;
4
+ plugins: () => ViteUserConfig['plugins'];
5
+ };
6
+ export declare function solidTest({ root, plugins }: SolidTestOptions): TestUserConfig;
7
+ export {};
@@ -0,0 +1,129 @@
1
+ import path from "node:path";
2
+ import { env } from "node:process";
3
+ import { fileURLToPath } from "node:url";
4
+ import { playwright } from "vite-plus/test/browser-playwright";
5
+ // src/vitest/index.ts
6
+ const CI_WORKERS = 2;
7
+ const STUB_PREFIX = "\0solid-tooling-stub:";
8
+ const NODE_STUBS = /* @__PURE__ */ new Map([
9
+ ["server-only", "export default undefined"],
10
+ ["virtual:file-routes", "export const pageRoutes = []\nexport default []"],
11
+ ["virtual:solid-server-function-handler", "export const endpoint = '/_server'"]
12
+ ]);
13
+ const TEST_ENV_KEYS = [
14
+ "BASE_URL_TEST",
15
+ "HOST",
16
+ "PORT"
17
+ ];
18
+ function packageFile(name) {
19
+ return fileURLToPath(new URL(name, import.meta.url));
20
+ }
21
+ function nodeStubs() {
22
+ return {
23
+ name: "solid-tooling:node-stubs",
24
+ enforce: "pre",
25
+ resolveId: (id) => NODE_STUBS.has(id) ? `${STUB_PREFIX}${id}` : void 0,
26
+ load: (id) => id.startsWith(STUB_PREFIX) ? NODE_STUBS.get(id.slice(20)) : void 0
27
+ };
28
+ }
29
+ function readTestEnv() {
30
+ return Object.fromEntries(TEST_ENV_KEYS.flatMap((key) => {
31
+ const value = env[key];
32
+ return value === void 0 ? [] : [[key, value]];
33
+ }));
34
+ }
35
+ function solidTest({ root, plugins }) {
36
+ return {
37
+ pool: "threads",
38
+ maxWorkers: env.CI ? CI_WORKERS : void 0,
39
+ css: false,
40
+ globals: true,
41
+ restoreMocks: true,
42
+ unstubGlobals: true,
43
+ unstubEnvs: true,
44
+ expect: {
45
+ requireAssertions: true,
46
+ poll: { interval: 10 }
47
+ },
48
+ env: readTestEnv(),
49
+ coverage: {
50
+ provider: "v8",
51
+ reporter: ["text", "html"],
52
+ thresholds: {
53
+ lines: 80,
54
+ functions: 80,
55
+ branches: 75,
56
+ statements: 80
57
+ },
58
+ include: ["src/**/*.{ts,tsx}"],
59
+ exclude: [
60
+ "src/**/*.d.ts",
61
+ "src/**/{constants,types,@types}/**",
62
+ "src/**/{constants,types}.{ts,tsx}",
63
+ "src/**/__tests__/**",
64
+ "src/tests/**",
65
+ "src/App.tsx",
66
+ "src/Document.tsx",
67
+ "src/entry-server.tsx",
68
+ "src/entry-client.tsx",
69
+ "src/router.ts"
70
+ ]
71
+ },
72
+ reporters: env.GITHUB_ACTIONS ? ["default", "github-actions"] : ["verbose"],
73
+ projects: [
74
+ {
75
+ plugins: [nodeStubs()],
76
+ test: {
77
+ name: {
78
+ label: "node",
79
+ color: "cyan"
80
+ },
81
+ environment: "node",
82
+ include: ["src/**/*.node.test.{ts,tsx}"]
83
+ }
84
+ },
85
+ {
86
+ plugins: plugins(),
87
+ test: {
88
+ name: {
89
+ label: "dom",
90
+ color: "magenta"
91
+ },
92
+ environment: "happy-dom",
93
+ environmentOptions: { happyDOM: { url: "http://localhost/en" } },
94
+ include: ["src/**/*.dom.test.{ts,tsx}"]
95
+ }
96
+ },
97
+ {
98
+ plugins: plugins(),
99
+ resolve: { alias: [{
100
+ find: /^@paraglide\//u,
101
+ replacement: `${path.join(root, "paraglide")}/`
102
+ }] },
103
+ test: {
104
+ css: true,
105
+ name: {
106
+ label: "browser",
107
+ color: "yellow"
108
+ },
109
+ setupFiles: [packageFile("vitest-setup/browser.mjs")],
110
+ include: ["src/**/*.browser.test.{ts,tsx}"],
111
+ browser: {
112
+ enabled: true,
113
+ headless: true,
114
+ trace: {
115
+ mode: "retain-on-failure",
116
+ tracesDir: path.join(root, "test-results/browser-traces")
117
+ },
118
+ provider: playwright({
119
+ contextOptions: { locale: "en-US" },
120
+ launchOptions: env.CI ? { channel: "chrome" } : {}
121
+ }),
122
+ instances: [{ browser: "chromium" }]
123
+ }
124
+ }
125
+ }
126
+ ]
127
+ };
128
+ }
129
+ export { solidTest };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@evertondgn/solid-tooling",
3
- "version": "0.2.0",
4
- "description": "Lint, formatter and TypeScript presets for SolidJS applications built with Vite+.",
3
+ "version": "0.3.0",
4
+ "description": "Lint, formatter, TypeScript and test presets for SolidJS applications built with Vite+.",
5
5
  "author": "Éverton Toffanetto",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -19,7 +19,8 @@
19
19
  "type": "module",
20
20
  "files": [
21
21
  "dist",
22
- "tsconfig.base.json"
22
+ "tsconfig.base.json",
23
+ "tsconfig.app.json"
23
24
  ],
24
25
  "exports": {
25
26
  "./architecture-plugin": "./dist/architecture-plugin.mjs",
@@ -27,10 +28,15 @@
27
28
  "./css-filename": "./dist/css-filename.mjs",
28
29
  "./fmt": "./dist/fmt.mjs",
29
30
  "./lint": "./dist/lint.mjs",
31
+ "./playwright": "./dist/playwright.mjs",
32
+ "./playwright-teardown": "./dist/playwright-teardown.mjs",
30
33
  "./project-plugin": "./dist/project-plugin.mjs",
31
34
  "./solid-plugin": "./dist/solid-plugin.mjs",
35
+ "./vitest": "./dist/vitest.mjs",
36
+ "./vitest-setup/browser": "./dist/vitest-setup/browser.mjs",
32
37
  "./package.json": "./package.json",
33
- "./tsconfig.base.json": "./tsconfig.base.json"
38
+ "./tsconfig.base.json": "./tsconfig.base.json",
39
+ "./tsconfig.app.json": "./tsconfig.app.json"
34
40
  },
35
41
  "publishConfig": {
36
42
  "access": "public"
@@ -46,13 +52,20 @@
46
52
  },
47
53
  "peerDependencies": {
48
54
  "@inlang/paraglide-js": "3.2.2",
49
- "vite-plus": "1.6.0"
55
+ "vite-plus": "1.6.0",
56
+ "@playwright/test": "1.65.0"
50
57
  },
51
58
  "devDependencies": {
52
59
  "@inlang/paraglide-js": "3.2.2",
53
60
  "@types/node": "24.19.2",
54
61
  "typescript": "7.0.2",
55
62
  "valibot": "1.5.0",
56
- "vite-plus": "1.6.0"
63
+ "vite-plus": "1.6.0",
64
+ "@playwright/test": "1.65.0"
65
+ },
66
+ "peerDependenciesMeta": {
67
+ "@playwright/test": {
68
+ "optional": true
69
+ }
57
70
  }
58
71
  }
@@ -0,0 +1,21 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "types": [
5
+ "node",
6
+ "vite/client",
7
+ "vite-plus/test/globals",
8
+ "@testing-library/jest-dom/vitest",
9
+ "@solidjs/vite-plugin/boundary-modules",
10
+ "@solidjs/vite-plugin/virtual-modules"
11
+ ]
12
+ },
13
+ "include": [
14
+ "${configDir}/src",
15
+ "${configDir}/env.ts",
16
+ "${configDir}/solid-env.d.ts",
17
+ "${configDir}/vite.config.ts",
18
+ "${configDir}/playwright.config.ts",
19
+ "${configDir}/tooling/**/*.ts"
20
+ ]
21
+ }