@get-skipper/vitest 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Skipper Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # @get-skipper/vitest
2
+
3
+ Skipper plugin for [Vitest](https://vitest.dev/) — enable/disable tests from a Google Spreadsheet.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add -D @get-skipper/vitest
9
+ # or
10
+ npm install --save-dev @get-skipper/vitest
11
+ ```
12
+
13
+ ## Setup
14
+
15
+ Update `vitest.config.ts` — this is the **only change required**:
16
+
17
+ ```ts
18
+ import { defineConfig } from 'vitest/config';
19
+ import { createSkipperGlobalSetup, createSkipperGlobalTeardown, setupFile } from '@get-skipper/vitest';
20
+
21
+ const skipperConfig = {
22
+ spreadsheetId: process.env.SKIPPER_SPREADSHEET_ID!,
23
+ credentials: { credentialsBase64: process.env.GOOGLE_CREDS_B64! },
24
+ // Or for local dev:
25
+ // credentials: { credentialsFile: './service-account.json' },
26
+ };
27
+
28
+ export default defineConfig({
29
+ test: {
30
+ globalSetup: [createSkipperGlobalSetup(skipperConfig)],
31
+ globalTeardown: [createSkipperGlobalTeardown(skipperConfig)],
32
+ setupFiles: [setupFile],
33
+ // ... rest of your config
34
+ },
35
+ });
36
+ ```
37
+
38
+ No changes to test files are required. Tests with a future `disabledUntil` date are automatically skipped.
39
+
40
+ ## Test ID Format
41
+
42
+ ```
43
+ {relative file path} > {describe block(s)} > {test name}
44
+ ```
45
+
46
+ ## Modes
47
+
48
+ - **`read-only`** (default): reads the spreadsheet, skips disabled tests. No writes.
49
+ - **`sync`** (`SKIPPER_MODE=sync`): same as read-only + reconciles the spreadsheet after the run.
50
+
51
+ See the [root README](../../README.md) for full setup instructions.
52
+
53
+ ## License
54
+
55
+ MIT
@@ -0,0 +1,19 @@
1
+ import { SkipperConfig } from '@get-skipper/core';
2
+ export { SkipperConfig } from '@get-skipper/core';
3
+
4
+ declare function createSkipperGlobalSetup(config: SkipperConfig): () => Promise<void>;
5
+
6
+ declare function createSkipperGlobalTeardown(config: SkipperConfig): () => Promise<void>;
7
+
8
+ /**
9
+ * Absolute path to the setup file.
10
+ * Add to `setupFiles` in vitest.config.ts:
11
+ *
12
+ * ```ts
13
+ * import { setupFile } from '@get-skipper/vitest';
14
+ * export default defineConfig({ test: { setupFiles: [setupFile] } });
15
+ * ```
16
+ */
17
+ declare const setupFile: string;
18
+
19
+ export { createSkipperGlobalSetup, createSkipperGlobalTeardown, setupFile };
@@ -0,0 +1,19 @@
1
+ import { SkipperConfig } from '@get-skipper/core';
2
+ export { SkipperConfig } from '@get-skipper/core';
3
+
4
+ declare function createSkipperGlobalSetup(config: SkipperConfig): () => Promise<void>;
5
+
6
+ declare function createSkipperGlobalTeardown(config: SkipperConfig): () => Promise<void>;
7
+
8
+ /**
9
+ * Absolute path to the setup file.
10
+ * Add to `setupFiles` in vitest.config.ts:
11
+ *
12
+ * ```ts
13
+ * import { setupFile } from '@get-skipper/vitest';
14
+ * export default defineConfig({ test: { setupFiles: [setupFile] } });
15
+ * ```
16
+ */
17
+ declare const setupFile: string;
18
+
19
+ export { createSkipperGlobalSetup, createSkipperGlobalTeardown, setupFile };
package/dist/index.js ADDED
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ createSkipperGlobalSetup: () => createSkipperGlobalSetup,
34
+ createSkipperGlobalTeardown: () => createSkipperGlobalTeardown,
35
+ setupFile: () => setupFile
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+ var path2 = __toESM(require("path"));
39
+
40
+ // src/globalSetup.ts
41
+ var fs = __toESM(require("fs"));
42
+ var os = __toESM(require("os"));
43
+ var path = __toESM(require("path"));
44
+ var import_core = require("@get-skipper/core");
45
+ var SKIPPER_CACHE_PATH = path.join(os.tmpdir(), ".skipper-vitest-cache.json");
46
+ function createSkipperGlobalSetup(config) {
47
+ return async function skipperGlobalSetup() {
48
+ const resolver = new import_core.SkipperResolver(config);
49
+ await resolver.initialize();
50
+ fs.writeFileSync(SKIPPER_CACHE_PATH, JSON.stringify(resolver.toJSON()), "utf8");
51
+ (0, import_core.log)("[skipper] Spreadsheet loaded.");
52
+ };
53
+ }
54
+
55
+ // src/globalTeardown.ts
56
+ var import_core2 = require("@get-skipper/core");
57
+ function createSkipperGlobalTeardown(config) {
58
+ return async function skipperGlobalTeardown() {
59
+ if (process.env.SKIPPER_MODE !== "sync") return;
60
+ const raw = process.env.SKIPPER_DISCOVERED_TESTS;
61
+ if (!raw) {
62
+ (0, import_core2.warn)("[skipper] No discovered tests found \u2014 skipping spreadsheet sync.");
63
+ return;
64
+ }
65
+ let discoveredIds;
66
+ try {
67
+ discoveredIds = JSON.parse(raw);
68
+ } catch {
69
+ (0, import_core2.error)("[skipper] Failed to parse SKIPPER_DISCOVERED_TESTS \u2014 skipping sync.");
70
+ return;
71
+ }
72
+ (0, import_core2.log)(`[skipper] Syncing ${discoveredIds.length} test(s) to spreadsheet\u2026`);
73
+ const writer = new import_core2.SheetsWriter(config);
74
+ await writer.sync(discoveredIds);
75
+ };
76
+ }
77
+
78
+ // src/index.ts
79
+ var setupFile = path2.resolve(__dirname, "setup.js");
80
+ // Annotate the CommonJS export names for ESM import in node:
81
+ 0 && (module.exports = {
82
+ createSkipperGlobalSetup,
83
+ createSkipperGlobalTeardown,
84
+ setupFile
85
+ });
86
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/globalSetup.ts","../src/globalTeardown.ts"],"sourcesContent":["import * as path from 'path';\n\nexport { createSkipperGlobalSetup } from './globalSetup';\nexport { createSkipperGlobalTeardown } from './globalTeardown';\nexport type { SkipperConfig } from '@get-skipper/core';\n\n/**\n * Absolute path to the setup file.\n * Add to `setupFiles` in vitest.config.ts:\n *\n * ```ts\n * import { setupFile } from '@get-skipper/vitest';\n * export default defineConfig({ test: { setupFiles: [setupFile] } });\n * ```\n */\nexport const setupFile = path.resolve(__dirname, 'setup.js');\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { SkipperResolver, log } from '@get-skipper/core';\nimport type { SkipperConfig } from '@get-skipper/core';\n\nexport const SKIPPER_CACHE_PATH = path.join(os.tmpdir(), '.skipper-vitest-cache.json');\n\nexport function createSkipperGlobalSetup(config: SkipperConfig) {\n return async function skipperGlobalSetup(): Promise<void> {\n const resolver = new SkipperResolver(config);\n await resolver.initialize();\n // Write cache to a temp file instead of an env var to avoid OS env-var size\n // limits for large test suites. Vitest workers can read this shared file.\n fs.writeFileSync(SKIPPER_CACHE_PATH, JSON.stringify(resolver.toJSON()), 'utf8');\n log('[skipper] Spreadsheet loaded.');\n };\n}\n","import { SheetsWriter, log, warn, error } from '@get-skipper/core';\nimport type { SkipperConfig } from '@get-skipper/core';\n\nexport function createSkipperGlobalTeardown(config: SkipperConfig) {\n return async function skipperGlobalTeardown(): Promise<void> {\n if (process.env.SKIPPER_MODE !== 'sync') return;\n\n const raw = process.env.SKIPPER_DISCOVERED_TESTS;\n if (!raw) {\n warn('[skipper] No discovered tests found — skipping spreadsheet sync.');\n return;\n }\n\n let discoveredIds: string[];\n try {\n discoveredIds = JSON.parse(raw) as string[];\n } catch {\n error('[skipper] Failed to parse SKIPPER_DISCOVERED_TESTS — skipping sync.');\n return;\n }\n\n log(`[skipper] Syncing ${discoveredIds.length} test(s) to spreadsheet…`);\n const writer = new SheetsWriter(config);\n await writer.sync(discoveredIds);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,QAAsB;;;ACAtB,SAAoB;AACpB,SAAoB;AACpB,WAAsB;AACtB,kBAAqC;AAG9B,IAAM,qBAA0B,UAAQ,UAAO,GAAG,4BAA4B;AAE9E,SAAS,yBAAyB,QAAuB;AAC9D,SAAO,eAAe,qBAAoC;AACxD,UAAM,WAAW,IAAI,4BAAgB,MAAM;AAC3C,UAAM,SAAS,WAAW;AAG1B,IAAG,iBAAc,oBAAoB,KAAK,UAAU,SAAS,OAAO,CAAC,GAAG,MAAM;AAC9E,yBAAI,+BAA+B;AAAA,EACrC;AACF;;;ACjBA,IAAAC,eAA+C;AAGxC,SAAS,4BAA4B,QAAuB;AACjE,SAAO,eAAe,wBAAuC;AAC3D,QAAI,QAAQ,IAAI,iBAAiB,OAAQ;AAEzC,UAAM,MAAM,QAAQ,IAAI;AACxB,QAAI,CAAC,KAAK;AACR,6BAAK,uEAAkE;AACvE;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,sBAAgB,KAAK,MAAM,GAAG;AAAA,IAChC,QAAQ;AACN,8BAAM,0EAAqE;AAC3E;AAAA,IACF;AAEA,0BAAI,qBAAqB,cAAc,MAAM,+BAA0B;AACvE,UAAM,SAAS,IAAI,0BAAa,MAAM;AACtC,UAAM,OAAO,KAAK,aAAa;AAAA,EACjC;AACF;;;AFVO,IAAM,YAAiB,cAAQ,WAAW,UAAU;","names":["path","import_core"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,49 @@
1
+ // src/index.ts
2
+ import * as path2 from "path";
3
+
4
+ // src/globalSetup.ts
5
+ import * as fs from "fs";
6
+ import * as os from "os";
7
+ import * as path from "path";
8
+ import { SkipperResolver, log } from "@get-skipper/core";
9
+ var SKIPPER_CACHE_PATH = path.join(os.tmpdir(), ".skipper-vitest-cache.json");
10
+ function createSkipperGlobalSetup(config) {
11
+ return async function skipperGlobalSetup() {
12
+ const resolver = new SkipperResolver(config);
13
+ await resolver.initialize();
14
+ fs.writeFileSync(SKIPPER_CACHE_PATH, JSON.stringify(resolver.toJSON()), "utf8");
15
+ log("[skipper] Spreadsheet loaded.");
16
+ };
17
+ }
18
+
19
+ // src/globalTeardown.ts
20
+ import { SheetsWriter, log as log2, warn, error } from "@get-skipper/core";
21
+ function createSkipperGlobalTeardown(config) {
22
+ return async function skipperGlobalTeardown() {
23
+ if (process.env.SKIPPER_MODE !== "sync") return;
24
+ const raw = process.env.SKIPPER_DISCOVERED_TESTS;
25
+ if (!raw) {
26
+ warn("[skipper] No discovered tests found \u2014 skipping spreadsheet sync.");
27
+ return;
28
+ }
29
+ let discoveredIds;
30
+ try {
31
+ discoveredIds = JSON.parse(raw);
32
+ } catch {
33
+ error("[skipper] Failed to parse SKIPPER_DISCOVERED_TESTS \u2014 skipping sync.");
34
+ return;
35
+ }
36
+ log2(`[skipper] Syncing ${discoveredIds.length} test(s) to spreadsheet\u2026`);
37
+ const writer = new SheetsWriter(config);
38
+ await writer.sync(discoveredIds);
39
+ };
40
+ }
41
+
42
+ // src/index.ts
43
+ var setupFile = path2.resolve(__dirname, "setup.js");
44
+ export {
45
+ createSkipperGlobalSetup,
46
+ createSkipperGlobalTeardown,
47
+ setupFile
48
+ };
49
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/globalSetup.ts","../src/globalTeardown.ts"],"sourcesContent":["import * as path from 'path';\n\nexport { createSkipperGlobalSetup } from './globalSetup';\nexport { createSkipperGlobalTeardown } from './globalTeardown';\nexport type { SkipperConfig } from '@get-skipper/core';\n\n/**\n * Absolute path to the setup file.\n * Add to `setupFiles` in vitest.config.ts:\n *\n * ```ts\n * import { setupFile } from '@get-skipper/vitest';\n * export default defineConfig({ test: { setupFiles: [setupFile] } });\n * ```\n */\nexport const setupFile = path.resolve(__dirname, 'setup.js');\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { SkipperResolver, log } from '@get-skipper/core';\nimport type { SkipperConfig } from '@get-skipper/core';\n\nexport const SKIPPER_CACHE_PATH = path.join(os.tmpdir(), '.skipper-vitest-cache.json');\n\nexport function createSkipperGlobalSetup(config: SkipperConfig) {\n return async function skipperGlobalSetup(): Promise<void> {\n const resolver = new SkipperResolver(config);\n await resolver.initialize();\n // Write cache to a temp file instead of an env var to avoid OS env-var size\n // limits for large test suites. Vitest workers can read this shared file.\n fs.writeFileSync(SKIPPER_CACHE_PATH, JSON.stringify(resolver.toJSON()), 'utf8');\n log('[skipper] Spreadsheet loaded.');\n };\n}\n","import { SheetsWriter, log, warn, error } from '@get-skipper/core';\nimport type { SkipperConfig } from '@get-skipper/core';\n\nexport function createSkipperGlobalTeardown(config: SkipperConfig) {\n return async function skipperGlobalTeardown(): Promise<void> {\n if (process.env.SKIPPER_MODE !== 'sync') return;\n\n const raw = process.env.SKIPPER_DISCOVERED_TESTS;\n if (!raw) {\n warn('[skipper] No discovered tests found — skipping spreadsheet sync.');\n return;\n }\n\n let discoveredIds: string[];\n try {\n discoveredIds = JSON.parse(raw) as string[];\n } catch {\n error('[skipper] Failed to parse SKIPPER_DISCOVERED_TESTS — skipping sync.');\n return;\n }\n\n log(`[skipper] Syncing ${discoveredIds.length} test(s) to spreadsheet…`);\n const writer = new SheetsWriter(config);\n await writer.sync(discoveredIds);\n };\n}\n"],"mappings":";AAAA,YAAYA,WAAU;;;ACAtB,YAAY,QAAQ;AACpB,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,SAAS,iBAAiB,WAAW;AAG9B,IAAM,qBAA0B,UAAQ,UAAO,GAAG,4BAA4B;AAE9E,SAAS,yBAAyB,QAAuB;AAC9D,SAAO,eAAe,qBAAoC;AACxD,UAAM,WAAW,IAAI,gBAAgB,MAAM;AAC3C,UAAM,SAAS,WAAW;AAG1B,IAAG,iBAAc,oBAAoB,KAAK,UAAU,SAAS,OAAO,CAAC,GAAG,MAAM;AAC9E,QAAI,+BAA+B;AAAA,EACrC;AACF;;;ACjBA,SAAS,cAAc,OAAAC,MAAK,MAAM,aAAa;AAGxC,SAAS,4BAA4B,QAAuB;AACjE,SAAO,eAAe,wBAAuC;AAC3D,QAAI,QAAQ,IAAI,iBAAiB,OAAQ;AAEzC,UAAM,MAAM,QAAQ,IAAI;AACxB,QAAI,CAAC,KAAK;AACR,WAAK,uEAAkE;AACvE;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,sBAAgB,KAAK,MAAM,GAAG;AAAA,IAChC,QAAQ;AACN,YAAM,0EAAqE;AAC3E;AAAA,IACF;AAEA,IAAAA,KAAI,qBAAqB,cAAc,MAAM,+BAA0B;AACvE,UAAM,SAAS,IAAI,aAAa,MAAM;AACtC,UAAM,OAAO,KAAK,aAAa;AAAA,EACjC;AACF;;;AFVO,IAAM,YAAiB,cAAQ,WAAW,UAAU;","names":["path","log"]}
package/dist/setup.js ADDED
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/setup.ts
26
+ var fs = __toESM(require("fs"));
27
+ var import_core2 = require("@get-skipper/core");
28
+
29
+ // src/globalSetup.ts
30
+ var os = __toESM(require("os"));
31
+ var path = __toESM(require("path"));
32
+ var import_core = require("@get-skipper/core");
33
+ var SKIPPER_CACHE_PATH = path.join(os.tmpdir(), ".skipper-vitest-cache.json");
34
+
35
+ // src/setup.ts
36
+ var g = globalThis;
37
+ function getResolver() {
38
+ if (!fs.existsSync(SKIPPER_CACHE_PATH)) {
39
+ throw new Error(
40
+ "[skipper] Skipper cache file not found. Did you add createSkipperGlobalSetup() to globalSetup in vitest.config?"
41
+ );
42
+ }
43
+ const raw = fs.readFileSync(SKIPPER_CACHE_PATH, "utf8");
44
+ return import_core2.SkipperResolver.fromJSON(JSON.parse(raw));
45
+ }
46
+ var resolver = getResolver();
47
+ var describeStack = [];
48
+ function appendDiscovered(testId) {
49
+ const existing = process.env.SKIPPER_DISCOVERED_TESTS;
50
+ const arr = existing ? JSON.parse(existing) : [];
51
+ arr.push(testId);
52
+ process.env.SKIPPER_DISCOVERED_TESTS = JSON.stringify(arr);
53
+ }
54
+ var originalDescribe = g.describe;
55
+ if (originalDescribe) {
56
+ g.describe = Object.assign(
57
+ (name, fn) => {
58
+ describeStack.push(name);
59
+ originalDescribe(name, () => {
60
+ try {
61
+ fn();
62
+ } finally {
63
+ describeStack.pop();
64
+ }
65
+ });
66
+ },
67
+ originalDescribe
68
+ );
69
+ }
70
+ var originalTest = g.test;
71
+ if (originalTest) {
72
+ const wrapped = Object.assign(
73
+ (name, fn, timeout) => {
74
+ if (fn === void 0) return originalTest(name, fn, timeout);
75
+ const stack = new Error().stack ?? "";
76
+ const match = stack.match(/\((.+?):\d+:\d+\)/);
77
+ const filePath = match ? match[1] : "unknown";
78
+ const testId = (0, import_core2.buildTestId)(filePath, [...describeStack, name]);
79
+ appendDiscovered(testId);
80
+ return resolver.isTestEnabled(testId) ? originalTest(name, fn, timeout) : originalTest.skip(name, fn, timeout);
81
+ },
82
+ originalTest
83
+ );
84
+ g.test = wrapped;
85
+ g.it = wrapped;
86
+ }
87
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/setup.ts","../src/globalSetup.ts"],"sourcesContent":["/**\n * Vitest setup file — add to `setupFiles` in vitest.config.ts.\n *\n * This file:\n * 1. Rehydrates the SkipperResolver from the cache file written by globalSetup\n * 2. Overrides globalThis.test / globalThis.it to auto-skip disabled tests\n * 3. Collects all discovered test IDs into SKIPPER_DISCOVERED_TESTS for sync mode\n */\nimport * as fs from 'fs';\nimport { SkipperResolver, buildTestId } from '@get-skipper/core';\nimport { SKIPPER_CACHE_PATH } from './globalSetup';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst g = globalThis as any;\n\nfunction getResolver(): SkipperResolver {\n if (!fs.existsSync(SKIPPER_CACHE_PATH)) {\n throw new Error(\n '[skipper] Skipper cache file not found. ' +\n 'Did you add createSkipperGlobalSetup() to globalSetup in vitest.config?',\n );\n }\n const raw = fs.readFileSync(SKIPPER_CACHE_PATH, 'utf8');\n return SkipperResolver.fromJSON(JSON.parse(raw) as Record<string, string | null>);\n}\n\nconst resolver = getResolver();\n\n// Stack tracking current describe blocks\nconst describeStack: string[] = [];\n\nfunction appendDiscovered(testId: string): void {\n const existing = process.env.SKIPPER_DISCOVERED_TESTS;\n const arr: string[] = existing ? JSON.parse(existing) : [];\n arr.push(testId);\n process.env.SKIPPER_DISCOVERED_TESTS = JSON.stringify(arr);\n}\n\n// Override describe to maintain the stack\nconst originalDescribe = g.describe as ((name: string, fn: () => void) => void) | undefined;\nif (originalDescribe) {\n g.describe = Object.assign(\n (name: string, fn: () => void) => {\n describeStack.push(name);\n originalDescribe(name, () => {\n try {\n fn();\n } finally {\n describeStack.pop();\n }\n });\n },\n originalDescribe,\n );\n}\n\n// Override test / it\ntype TestLike = ((name: string, fn?: () => void | Promise<void>, timeout?: number) => void) & {\n skip: (name: string, fn?: () => void | Promise<void>, timeout?: number) => void;\n [key: string]: unknown;\n};\n\nconst originalTest = g.test as TestLike | undefined;\nif (originalTest) {\n const wrapped = Object.assign(\n (name: string, fn?: () => void | Promise<void>, timeout?: number) => {\n if (fn === undefined) return originalTest(name, fn, timeout);\n\n // Derive file path from Error stack\n const stack = new Error().stack ?? '';\n const match = stack.match(/\\((.+?):\\d+:\\d+\\)/);\n const filePath = match ? match[1] : 'unknown';\n\n const testId = buildTestId(filePath, [...describeStack, name]);\n appendDiscovered(testId);\n\n return resolver.isTestEnabled(testId)\n ? originalTest(name, fn, timeout)\n : originalTest.skip(name, fn, timeout);\n },\n originalTest,\n );\n\n g.test = wrapped;\n g.it = wrapped;\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { SkipperResolver, log } from '@get-skipper/core';\nimport type { SkipperConfig } from '@get-skipper/core';\n\nexport const SKIPPER_CACHE_PATH = path.join(os.tmpdir(), '.skipper-vitest-cache.json');\n\nexport function createSkipperGlobalSetup(config: SkipperConfig) {\n return async function skipperGlobalSetup(): Promise<void> {\n const resolver = new SkipperResolver(config);\n await resolver.initialize();\n // Write cache to a temp file instead of an env var to avoid OS env-var size\n // limits for large test suites. Vitest workers can read this shared file.\n fs.writeFileSync(SKIPPER_CACHE_PATH, JSON.stringify(resolver.toJSON()), 'utf8');\n log('[skipper] Spreadsheet loaded.');\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAQA,SAAoB;AACpB,IAAAA,eAA6C;;;ACR7C,SAAoB;AACpB,WAAsB;AACtB,kBAAqC;AAG9B,IAAM,qBAA0B,UAAQ,UAAO,GAAG,4BAA4B;;;ADOrF,IAAM,IAAI;AAEV,SAAS,cAA+B;AACtC,MAAI,CAAI,cAAW,kBAAkB,GAAG;AACtC,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,QAAM,MAAS,gBAAa,oBAAoB,MAAM;AACtD,SAAO,6BAAgB,SAAS,KAAK,MAAM,GAAG,CAAkC;AAClF;AAEA,IAAM,WAAW,YAAY;AAG7B,IAAM,gBAA0B,CAAC;AAEjC,SAAS,iBAAiB,QAAsB;AAC9C,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,MAAgB,WAAW,KAAK,MAAM,QAAQ,IAAI,CAAC;AACzD,MAAI,KAAK,MAAM;AACf,UAAQ,IAAI,2BAA2B,KAAK,UAAU,GAAG;AAC3D;AAGA,IAAM,mBAAmB,EAAE;AAC3B,IAAI,kBAAkB;AACpB,IAAE,WAAW,OAAO;AAAA,IAClB,CAAC,MAAc,OAAmB;AAChC,oBAAc,KAAK,IAAI;AACvB,uBAAiB,MAAM,MAAM;AAC3B,YAAI;AACF,aAAG;AAAA,QACL,UAAE;AACA,wBAAc,IAAI;AAAA,QACpB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA;AAAA,EACF;AACF;AAQA,IAAM,eAAe,EAAE;AACvB,IAAI,cAAc;AAChB,QAAM,UAAU,OAAO;AAAA,IACrB,CAAC,MAAc,IAAiC,YAAqB;AACnE,UAAI,OAAO,OAAW,QAAO,aAAa,MAAM,IAAI,OAAO;AAG3D,YAAM,QAAQ,IAAI,MAAM,EAAE,SAAS;AACnC,YAAM,QAAQ,MAAM,MAAM,mBAAmB;AAC7C,YAAM,WAAW,QAAQ,MAAM,CAAC,IAAI;AAEpC,YAAM,aAAS,0BAAY,UAAU,CAAC,GAAG,eAAe,IAAI,CAAC;AAC7D,uBAAiB,MAAM;AAEvB,aAAO,SAAS,cAAc,MAAM,IAChC,aAAa,MAAM,IAAI,OAAO,IAC9B,aAAa,KAAK,MAAM,IAAI,OAAO;AAAA,IACzC;AAAA,IACA;AAAA,EACF;AAEA,IAAE,OAAO;AACT,IAAE,KAAK;AACT;","names":["import_core"]}
package/dist/setup.mjs ADDED
@@ -0,0 +1,63 @@
1
+ // src/setup.ts
2
+ import * as fs from "fs";
3
+ import { SkipperResolver as SkipperResolver2, buildTestId } from "@get-skipper/core";
4
+
5
+ // src/globalSetup.ts
6
+ import * as os from "os";
7
+ import * as path from "path";
8
+ import { SkipperResolver, log } from "@get-skipper/core";
9
+ var SKIPPER_CACHE_PATH = path.join(os.tmpdir(), ".skipper-vitest-cache.json");
10
+
11
+ // src/setup.ts
12
+ var g = globalThis;
13
+ function getResolver() {
14
+ if (!fs.existsSync(SKIPPER_CACHE_PATH)) {
15
+ throw new Error(
16
+ "[skipper] Skipper cache file not found. Did you add createSkipperGlobalSetup() to globalSetup in vitest.config?"
17
+ );
18
+ }
19
+ const raw = fs.readFileSync(SKIPPER_CACHE_PATH, "utf8");
20
+ return SkipperResolver2.fromJSON(JSON.parse(raw));
21
+ }
22
+ var resolver = getResolver();
23
+ var describeStack = [];
24
+ function appendDiscovered(testId) {
25
+ const existing = process.env.SKIPPER_DISCOVERED_TESTS;
26
+ const arr = existing ? JSON.parse(existing) : [];
27
+ arr.push(testId);
28
+ process.env.SKIPPER_DISCOVERED_TESTS = JSON.stringify(arr);
29
+ }
30
+ var originalDescribe = g.describe;
31
+ if (originalDescribe) {
32
+ g.describe = Object.assign(
33
+ (name, fn) => {
34
+ describeStack.push(name);
35
+ originalDescribe(name, () => {
36
+ try {
37
+ fn();
38
+ } finally {
39
+ describeStack.pop();
40
+ }
41
+ });
42
+ },
43
+ originalDescribe
44
+ );
45
+ }
46
+ var originalTest = g.test;
47
+ if (originalTest) {
48
+ const wrapped = Object.assign(
49
+ (name, fn, timeout) => {
50
+ if (fn === void 0) return originalTest(name, fn, timeout);
51
+ const stack = new Error().stack ?? "";
52
+ const match = stack.match(/\((.+?):\d+:\d+\)/);
53
+ const filePath = match ? match[1] : "unknown";
54
+ const testId = buildTestId(filePath, [...describeStack, name]);
55
+ appendDiscovered(testId);
56
+ return resolver.isTestEnabled(testId) ? originalTest(name, fn, timeout) : originalTest.skip(name, fn, timeout);
57
+ },
58
+ originalTest
59
+ );
60
+ g.test = wrapped;
61
+ g.it = wrapped;
62
+ }
63
+ //# sourceMappingURL=setup.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/setup.ts","../src/globalSetup.ts"],"sourcesContent":["/**\n * Vitest setup file — add to `setupFiles` in vitest.config.ts.\n *\n * This file:\n * 1. Rehydrates the SkipperResolver from the cache file written by globalSetup\n * 2. Overrides globalThis.test / globalThis.it to auto-skip disabled tests\n * 3. Collects all discovered test IDs into SKIPPER_DISCOVERED_TESTS for sync mode\n */\nimport * as fs from 'fs';\nimport { SkipperResolver, buildTestId } from '@get-skipper/core';\nimport { SKIPPER_CACHE_PATH } from './globalSetup';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst g = globalThis as any;\n\nfunction getResolver(): SkipperResolver {\n if (!fs.existsSync(SKIPPER_CACHE_PATH)) {\n throw new Error(\n '[skipper] Skipper cache file not found. ' +\n 'Did you add createSkipperGlobalSetup() to globalSetup in vitest.config?',\n );\n }\n const raw = fs.readFileSync(SKIPPER_CACHE_PATH, 'utf8');\n return SkipperResolver.fromJSON(JSON.parse(raw) as Record<string, string | null>);\n}\n\nconst resolver = getResolver();\n\n// Stack tracking current describe blocks\nconst describeStack: string[] = [];\n\nfunction appendDiscovered(testId: string): void {\n const existing = process.env.SKIPPER_DISCOVERED_TESTS;\n const arr: string[] = existing ? JSON.parse(existing) : [];\n arr.push(testId);\n process.env.SKIPPER_DISCOVERED_TESTS = JSON.stringify(arr);\n}\n\n// Override describe to maintain the stack\nconst originalDescribe = g.describe as ((name: string, fn: () => void) => void) | undefined;\nif (originalDescribe) {\n g.describe = Object.assign(\n (name: string, fn: () => void) => {\n describeStack.push(name);\n originalDescribe(name, () => {\n try {\n fn();\n } finally {\n describeStack.pop();\n }\n });\n },\n originalDescribe,\n );\n}\n\n// Override test / it\ntype TestLike = ((name: string, fn?: () => void | Promise<void>, timeout?: number) => void) & {\n skip: (name: string, fn?: () => void | Promise<void>, timeout?: number) => void;\n [key: string]: unknown;\n};\n\nconst originalTest = g.test as TestLike | undefined;\nif (originalTest) {\n const wrapped = Object.assign(\n (name: string, fn?: () => void | Promise<void>, timeout?: number) => {\n if (fn === undefined) return originalTest(name, fn, timeout);\n\n // Derive file path from Error stack\n const stack = new Error().stack ?? '';\n const match = stack.match(/\\((.+?):\\d+:\\d+\\)/);\n const filePath = match ? match[1] : 'unknown';\n\n const testId = buildTestId(filePath, [...describeStack, name]);\n appendDiscovered(testId);\n\n return resolver.isTestEnabled(testId)\n ? originalTest(name, fn, timeout)\n : originalTest.skip(name, fn, timeout);\n },\n originalTest,\n );\n\n g.test = wrapped;\n g.it = wrapped;\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { SkipperResolver, log } from '@get-skipper/core';\nimport type { SkipperConfig } from '@get-skipper/core';\n\nexport const SKIPPER_CACHE_PATH = path.join(os.tmpdir(), '.skipper-vitest-cache.json');\n\nexport function createSkipperGlobalSetup(config: SkipperConfig) {\n return async function skipperGlobalSetup(): Promise<void> {\n const resolver = new SkipperResolver(config);\n await resolver.initialize();\n // Write cache to a temp file instead of an env var to avoid OS env-var size\n // limits for large test suites. Vitest workers can read this shared file.\n fs.writeFileSync(SKIPPER_CACHE_PATH, JSON.stringify(resolver.toJSON()), 'utf8');\n log('[skipper] Spreadsheet loaded.');\n };\n}\n"],"mappings":";AAQA,YAAY,QAAQ;AACpB,SAAS,mBAAAA,kBAAiB,mBAAmB;;;ACR7C,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,SAAS,iBAAiB,WAAW;AAG9B,IAAM,qBAA0B,UAAQ,UAAO,GAAG,4BAA4B;;;ADOrF,IAAM,IAAI;AAEV,SAAS,cAA+B;AACtC,MAAI,CAAI,cAAW,kBAAkB,GAAG;AACtC,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,QAAM,MAAS,gBAAa,oBAAoB,MAAM;AACtD,SAAOC,iBAAgB,SAAS,KAAK,MAAM,GAAG,CAAkC;AAClF;AAEA,IAAM,WAAW,YAAY;AAG7B,IAAM,gBAA0B,CAAC;AAEjC,SAAS,iBAAiB,QAAsB;AAC9C,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,MAAgB,WAAW,KAAK,MAAM,QAAQ,IAAI,CAAC;AACzD,MAAI,KAAK,MAAM;AACf,UAAQ,IAAI,2BAA2B,KAAK,UAAU,GAAG;AAC3D;AAGA,IAAM,mBAAmB,EAAE;AAC3B,IAAI,kBAAkB;AACpB,IAAE,WAAW,OAAO;AAAA,IAClB,CAAC,MAAc,OAAmB;AAChC,oBAAc,KAAK,IAAI;AACvB,uBAAiB,MAAM,MAAM;AAC3B,YAAI;AACF,aAAG;AAAA,QACL,UAAE;AACA,wBAAc,IAAI;AAAA,QACpB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA;AAAA,EACF;AACF;AAQA,IAAM,eAAe,EAAE;AACvB,IAAI,cAAc;AAChB,QAAM,UAAU,OAAO;AAAA,IACrB,CAAC,MAAc,IAAiC,YAAqB;AACnE,UAAI,OAAO,OAAW,QAAO,aAAa,MAAM,IAAI,OAAO;AAG3D,YAAM,QAAQ,IAAI,MAAM,EAAE,SAAS;AACnC,YAAM,QAAQ,MAAM,MAAM,mBAAmB;AAC7C,YAAM,WAAW,QAAQ,MAAM,CAAC,IAAI;AAEpC,YAAM,SAAS,YAAY,UAAU,CAAC,GAAG,eAAe,IAAI,CAAC;AAC7D,uBAAiB,MAAM;AAEvB,aAAO,SAAS,cAAc,MAAM,IAChC,aAAa,MAAM,IAAI,OAAO,IAC9B,aAAa,KAAK,MAAM,IAAI,OAAO;AAAA,IACzC;AAAA,IACA;AAAA,EACF;AAEA,IAAE,OAAO;AACT,IAAE,KAAK;AACT;","names":["SkipperResolver","SkipperResolver"]}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@get-skipper/vitest",
3
+ "version": "1.0.0",
4
+ "description": "Skipper plugin for Vitest — enable/disable tests from a Google Spreadsheet",
5
+ "keywords": [
6
+ "skipper",
7
+ "vitest",
8
+ "testing",
9
+ "google-sheets",
10
+ "test-gating"
11
+ ],
12
+ "license": "MIT",
13
+ "main": "dist/index.js",
14
+ "module": "dist/index.mjs",
15
+ "types": "dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.mjs",
20
+ "require": "./dist/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "dependencies": {
29
+ "@get-skipper/core": "1.0.0"
30
+ },
31
+ "peerDependencies": {
32
+ "vitest": ">=1.0.0"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "scripts": {
38
+ "build": "tsup",
39
+ "dev": "tsup --watch",
40
+ "typecheck": "tsc --noEmit",
41
+ "test": "jest --config ../../jest.config.js --testPathPattern=packages/vitest/"
42
+ }
43
+ }