@sanity/cli-test 3.0.1 → 5.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/dist/index.d.ts +7 -4
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/mocks/cli-core/SanityCommand.d.ts +50 -0
- package/dist/mocks/cli-core/SanityCommand.js +75 -0
- package/dist/mocks/cli-core/SanityCommand.js.map +1 -0
- package/dist/mocks/cli-core/apiClient.d.ts +9 -0
- package/dist/mocks/cli-core/apiClient.js +5 -0
- package/dist/mocks/cli-core/apiClient.js.map +1 -0
- package/dist/mocks/cli-core/browser.d.ts +6 -0
- package/dist/mocks/cli-core/browser.js +4 -0
- package/dist/mocks/cli-core/browser.js.map +1 -0
- package/dist/mocks/cli-core/config.d.ts +66 -0
- package/dist/mocks/cli-core/config.js +30 -0
- package/dist/mocks/cli-core/config.js.map +1 -0
- package/dist/mocks/cli-core/package-manager.d.ts +30 -0
- package/dist/mocks/cli-core/package-manager.js +12 -0
- package/dist/mocks/cli-core/package-manager.js.map +1 -0
- package/dist/mocks/cli-core/request.d.ts +42 -0
- package/dist/mocks/cli-core/request.js +40 -0
- package/dist/mocks/cli-core/request.js.map +1 -0
- package/dist/mocks/cli-core/tasks.d.ts +12 -0
- package/dist/mocks/cli-core/tasks.js +6 -0
- package/dist/mocks/cli-core/tasks.js.map +1 -0
- package/dist/mocks/cli-core/telemetry.d.ts +31 -0
- package/dist/mocks/cli-core/telemetry.js +22 -0
- package/dist/mocks/cli-core/telemetry.js.map +1 -0
- package/dist/mocks/cli-core/ux.d.ts +77 -0
- package/dist/mocks/cli-core/ux.js +56 -0
- package/dist/mocks/cli-core/ux.js.map +1 -0
- package/dist/test/captureOutput.js +1 -1
- package/dist/test/captureOutput.js.map +1 -1
- package/dist/test/createMockSpinner.js +1 -0
- package/dist/test/createMockSpinner.js.map +1 -1
- package/dist/test/createTestClient.d.ts +57 -0
- package/dist/test/mockApi.d.ts +56 -0
- package/dist/test/mockSanityCommand.js.map +1 -1
- package/dist/test/mockTelemetry.js.map +1 -1
- package/dist/test/oclif.d.ts +179 -0
- package/dist/test/oclif.js +7 -0
- package/dist/test/oclif.js.map +1 -0
- package/dist/test/setupFixtures.d.ts +90 -0
- package/dist/test/setupFixtures.js +8 -10
- package/dist/test/setupFixtures.js.map +1 -1
- package/dist/test/util.d.ts +203 -0
- package/dist/test/util.js +11 -0
- package/dist/test/util.js.map +1 -0
- package/dist/utils/paths.d.ts +65 -0
- package/package.json +63 -4
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Mock } from "vitest";
|
|
2
|
+
|
|
3
|
+
/** @internal */
|
|
4
|
+
export declare const boxen: Mock;
|
|
5
|
+
|
|
6
|
+
/** @internal */
|
|
7
|
+
export declare const checkbox: Mock;
|
|
8
|
+
|
|
9
|
+
/** @internal */
|
|
10
|
+
export declare const colorizeJson: Mock;
|
|
11
|
+
|
|
12
|
+
/** @internal */
|
|
13
|
+
export declare const confirm: Mock;
|
|
14
|
+
|
|
15
|
+
/** @internal */
|
|
16
|
+
export declare const editor: Mock;
|
|
17
|
+
|
|
18
|
+
/** @internal */
|
|
19
|
+
export declare const expand: Mock;
|
|
20
|
+
|
|
21
|
+
/** @internal */
|
|
22
|
+
export declare const getTimer: Mock;
|
|
23
|
+
|
|
24
|
+
/** @internal */
|
|
25
|
+
export declare const input: Mock;
|
|
26
|
+
|
|
27
|
+
/** @internal */
|
|
28
|
+
export declare const logSymbols: {
|
|
29
|
+
error: string;
|
|
30
|
+
info: string;
|
|
31
|
+
success: string;
|
|
32
|
+
warning: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** @internal */
|
|
36
|
+
export declare const number: Mock;
|
|
37
|
+
|
|
38
|
+
/** @internal */
|
|
39
|
+
export declare const password: Mock;
|
|
40
|
+
|
|
41
|
+
/** @internal */
|
|
42
|
+
export declare const rawlist: Mock;
|
|
43
|
+
|
|
44
|
+
/** @internal */
|
|
45
|
+
export declare const search: Mock;
|
|
46
|
+
|
|
47
|
+
/** @internal */
|
|
48
|
+
export declare const select: Mock;
|
|
49
|
+
|
|
50
|
+
/** @internal */
|
|
51
|
+
export declare class Separator {}
|
|
52
|
+
|
|
53
|
+
/** @internal */
|
|
54
|
+
export declare const spinner: Mock;
|
|
55
|
+
|
|
56
|
+
/** @internal */
|
|
57
|
+
export declare const spinnerPromise: Mock;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Spy for asserting on spinner start.
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export declare const spinnerStart: Mock;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Spy for asserting on spinner succeed.
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
export declare const spinnerSucceed: Mock;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Spy for asserting on what text is assigned to a terminal spinner.
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
export declare const spinnerText: Mock;
|
|
76
|
+
|
|
77
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
/** @internal */ export const boxen = vi.fn((str)=>str);
|
|
3
|
+
/** @internal */ export const colorizeJson = vi.fn();
|
|
4
|
+
/** @internal */ export const logSymbols = {
|
|
5
|
+
error: 'e',
|
|
6
|
+
info: 'i',
|
|
7
|
+
success: 's',
|
|
8
|
+
warning: 'w'
|
|
9
|
+
};
|
|
10
|
+
/** @internal */ export const checkbox = vi.fn();
|
|
11
|
+
/** @internal */ export const confirm = vi.fn();
|
|
12
|
+
/** @internal */ export const editor = vi.fn();
|
|
13
|
+
/** @internal */ export const expand = vi.fn();
|
|
14
|
+
/** @internal */ export const input = vi.fn();
|
|
15
|
+
/** @internal */ export const number = vi.fn();
|
|
16
|
+
/** @internal */ export const password = vi.fn();
|
|
17
|
+
/** @internal */ export const rawlist = vi.fn();
|
|
18
|
+
/** @internal */ export const search = vi.fn();
|
|
19
|
+
/** @internal */ export const select = vi.fn();
|
|
20
|
+
/**
|
|
21
|
+
* Spy for asserting on what text is assigned to a terminal spinner.
|
|
22
|
+
* @internal
|
|
23
|
+
*/ export const spinnerText = vi.fn();
|
|
24
|
+
/**
|
|
25
|
+
* Spy for asserting on spinner start.
|
|
26
|
+
* @internal
|
|
27
|
+
*/ export const spinnerStart = vi.fn().mockReturnThis();
|
|
28
|
+
/**
|
|
29
|
+
* Spy for asserting on spinner succeed.
|
|
30
|
+
* @internal
|
|
31
|
+
*/ export const spinnerSucceed = vi.fn();
|
|
32
|
+
/** @internal */ export const spinner = vi.fn(()=>{
|
|
33
|
+
const mockSpin = {
|
|
34
|
+
clear: vi.fn(),
|
|
35
|
+
fail: vi.fn(),
|
|
36
|
+
info: vi.fn(),
|
|
37
|
+
render: vi.fn(),
|
|
38
|
+
start: spinnerStart,
|
|
39
|
+
stop: vi.fn(),
|
|
40
|
+
succeed: spinnerSucceed
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(mockSpin, 'text', {
|
|
43
|
+
configurable: true,
|
|
44
|
+
set: spinnerText
|
|
45
|
+
});
|
|
46
|
+
return mockSpin;
|
|
47
|
+
});
|
|
48
|
+
/** @internal */ export const spinnerPromise = vi.fn();
|
|
49
|
+
/** @internal */ export const getTimer = vi.fn().mockReturnValue({
|
|
50
|
+
end: vi.fn().mockReturnValue(0),
|
|
51
|
+
start: vi.fn()
|
|
52
|
+
});
|
|
53
|
+
/** @internal */ export class Separator {
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=ux.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/mocks/cli-core/ux.ts"],"sourcesContent":["import {type Mock, vi} from 'vitest'\n/** @internal */\nexport const boxen: Mock = vi.fn((str: string) => str)\n/** @internal */\nexport const colorizeJson: Mock = vi.fn()\n/** @internal */\nexport const logSymbols = {error: 'e', info: 'i', success: 's', warning: 'w'}\n/** @internal */\nexport const checkbox: Mock = vi.fn()\n/** @internal */\nexport const confirm: Mock = vi.fn()\n/** @internal */\nexport const editor: Mock = vi.fn()\n/** @internal */\nexport const expand: Mock = vi.fn()\n/** @internal */\nexport const input: Mock = vi.fn()\n/** @internal */\nexport const number: Mock = vi.fn()\n/** @internal */\nexport const password: Mock = vi.fn()\n/** @internal */\nexport const rawlist: Mock = vi.fn()\n/** @internal */\nexport const search: Mock = vi.fn()\n/** @internal */\nexport const select: Mock = vi.fn()\n/**\n * Spy for asserting on what text is assigned to a terminal spinner.\n * @internal\n */\nexport const spinnerText: Mock = vi.fn()\n/**\n * Spy for asserting on spinner start.\n * @internal\n */\nexport const spinnerStart: Mock = vi.fn().mockReturnThis()\n/**\n * Spy for asserting on spinner succeed.\n * @internal\n */\nexport const spinnerSucceed: Mock = vi.fn()\n/** @internal */\nexport const spinner: Mock = vi.fn(() => {\n const mockSpin = {\n clear: vi.fn(),\n fail: vi.fn(),\n info: vi.fn(),\n render: vi.fn(),\n start: spinnerStart,\n stop: vi.fn(),\n succeed: spinnerSucceed,\n }\n Object.defineProperty(mockSpin, 'text', {\n configurable: true,\n set: spinnerText,\n })\n return mockSpin\n})\n/** @internal */\nexport const spinnerPromise: Mock = vi.fn()\n/** @internal */\nexport const getTimer: Mock = vi\n .fn()\n .mockReturnValue({end: vi.fn().mockReturnValue(0), start: vi.fn()})\n/** @internal */\nexport class Separator {}\n"],"names":["vi","boxen","fn","str","colorizeJson","logSymbols","error","info","success","warning","checkbox","confirm","editor","expand","input","number","password","rawlist","search","select","spinnerText","spinnerStart","mockReturnThis","spinnerSucceed","spinner","mockSpin","clear","fail","render","start","stop","succeed","Object","defineProperty","configurable","set","spinnerPromise","getTimer","mockReturnValue","end","Separator"],"mappings":"AAAA,SAAmBA,EAAE,QAAO,SAAQ;AACpC,cAAc,GACd,OAAO,MAAMC,QAAcD,GAAGE,EAAE,CAAC,CAACC,MAAgBA,KAAI;AACtD,cAAc,GACd,OAAO,MAAMC,eAAqBJ,GAAGE,EAAE,GAAE;AACzC,cAAc,GACd,OAAO,MAAMG,aAAa;IAACC,OAAO;IAAKC,MAAM;IAAKC,SAAS;IAAKC,SAAS;AAAG,EAAC;AAC7E,cAAc,GACd,OAAO,MAAMC,WAAiBV,GAAGE,EAAE,GAAE;AACrC,cAAc,GACd,OAAO,MAAMS,UAAgBX,GAAGE,EAAE,GAAE;AACpC,cAAc,GACd,OAAO,MAAMU,SAAeZ,GAAGE,EAAE,GAAE;AACnC,cAAc,GACd,OAAO,MAAMW,SAAeb,GAAGE,EAAE,GAAE;AACnC,cAAc,GACd,OAAO,MAAMY,QAAcd,GAAGE,EAAE,GAAE;AAClC,cAAc,GACd,OAAO,MAAMa,SAAef,GAAGE,EAAE,GAAE;AACnC,cAAc,GACd,OAAO,MAAMc,WAAiBhB,GAAGE,EAAE,GAAE;AACrC,cAAc,GACd,OAAO,MAAMe,UAAgBjB,GAAGE,EAAE,GAAE;AACpC,cAAc,GACd,OAAO,MAAMgB,SAAelB,GAAGE,EAAE,GAAE;AACnC,cAAc,GACd,OAAO,MAAMiB,SAAenB,GAAGE,EAAE,GAAE;AACnC;;;CAGC,GACD,OAAO,MAAMkB,cAAoBpB,GAAGE,EAAE,GAAE;AACxC;;;CAGC,GACD,OAAO,MAAMmB,eAAqBrB,GAAGE,EAAE,GAAGoB,cAAc,GAAE;AAC1D;;;CAGC,GACD,OAAO,MAAMC,iBAAuBvB,GAAGE,EAAE,GAAE;AAC3C,cAAc,GACd,OAAO,MAAMsB,UAAgBxB,GAAGE,EAAE,CAAC;IACjC,MAAMuB,WAAW;QACfC,OAAO1B,GAAGE,EAAE;QACZyB,MAAM3B,GAAGE,EAAE;QACXK,MAAMP,GAAGE,EAAE;QACX0B,QAAQ5B,GAAGE,EAAE;QACb2B,OAAOR;QACPS,MAAM9B,GAAGE,EAAE;QACX6B,SAASR;IACX;IACAS,OAAOC,cAAc,CAACR,UAAU,QAAQ;QACtCS,cAAc;QACdC,KAAKf;IACP;IACA,OAAOK;AACT,GAAE;AACF,cAAc,GACd,OAAO,MAAMW,iBAAuBpC,GAAGE,EAAE,GAAE;AAC3C,cAAc,GACd,OAAO,MAAMmC,WAAiBrC,GAC3BE,EAAE,GACFoC,eAAe,CAAC;IAACC,KAAKvC,GAAGE,EAAE,GAAGoC,eAAe,CAAC;IAAIT,OAAO7B,GAAGE,EAAE;AAAE,GAAE;AACrE,cAAc,GACd,OAAO,MAAMsC;AAAW"}
|
|
@@ -5,7 +5,7 @@ import ansis from 'ansis';
|
|
|
5
5
|
* @param fn - The function to capture the output of
|
|
6
6
|
* @param opts - The options for the capture
|
|
7
7
|
* @returns The result of the command
|
|
8
|
-
* @
|
|
8
|
+
* @public
|
|
9
9
|
*
|
|
10
10
|
* Credits to oclif for the original implementation:
|
|
11
11
|
* https://github.com/oclif/test/blob/2a5407e6fc80d388043d10f6b7b8eaa586483015/src/index.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/test/captureOutput.ts"],"sourcesContent":["import {type Errors} from '@oclif/core'\nimport ansis from 'ansis'\n\nexport interface CaptureOptions {\n /**\n * Whether to print the output to the console\n */\n print?: boolean\n /**\n * Whether to strip ANSI escape codes from the output\n */\n stripAnsi?: boolean\n testNodeEnv?: string\n}\n\nexport interface CaptureResult<T = unknown> {\n stderr: string\n stdout: string\n\n error?: Error & Partial<Errors.CLIError>\n result?: T\n}\n\n/**\n * Capture the output of a command and return the result\n *\n * @param fn - The function to capture the output of\n * @param opts - The options for the capture\n * @returns The result of the command\n * @
|
|
1
|
+
{"version":3,"sources":["../../src/test/captureOutput.ts"],"sourcesContent":["import {type Errors} from '@oclif/core'\nimport ansis from 'ansis'\n\n/** @public */\nexport interface CaptureOptions {\n /**\n * Whether to print the output to the console\n */\n print?: boolean\n /**\n * Whether to strip ANSI escape codes from the output\n */\n stripAnsi?: boolean\n testNodeEnv?: string\n}\n\n/** @public */\nexport interface CaptureResult<T = unknown> {\n stderr: string\n stdout: string\n\n error?: Error & Partial<Errors.CLIError>\n result?: T\n}\n\n/**\n * Capture the output of a command and return the result\n *\n * @param fn - The function to capture the output of\n * @param opts - The options for the capture\n * @returns The result of the command\n * @public\n *\n * Credits to oclif for the original implementation:\n * https://github.com/oclif/test/blob/2a5407e6fc80d388043d10f6b7b8eaa586483015/src/index.ts\n *\n * We are not using the library directly since it does not support mocking code inside of the command\n * possibly because the commands run in a different thread\n */\nexport async function captureOutput<T>(\n fn: () => Promise<T>,\n opts?: CaptureOptions,\n): Promise<CaptureResult<T>> {\n const print = opts?.print ?? false\n const stripAnsi = opts?.stripAnsi ?? true\n const testNodeEnv = opts?.testNodeEnv || 'test'\n\n const originals = {\n NODE_ENV: process.env.NODE_ENV,\n stderrWrite: process.stderr.write,\n stdoutWrite: process.stdout.write,\n }\n\n const output: Record<'stderr' | 'stdout', string[]> = {\n stderr: [],\n stdout: [],\n }\n\n const toString = (str: string | Uint8Array): string =>\n stripAnsi ? ansis.strip(str.toString()) : str.toString()\n\n const getStderr = (): string => output.stderr.map((b) => toString(b)).join('')\n const getStdout = (): string => output.stdout.map((b) => toString(b)).join('')\n\n const mockWrite =\n (std: 'stderr' | 'stdout'): typeof process.stderr.write =>\n (\n chunk: string | Uint8Array,\n encodingOrCb?: ((err?: Error | null) => void) | BufferEncoding,\n cb?: (err?: Error | null) => void,\n ) => {\n output[std].push(chunk.toString())\n\n if (print) {\n let callback: ((err?: Error | null) => void) | undefined = cb\n let encoding: BufferEncoding | undefined\n if (typeof encodingOrCb === 'function') {\n callback = encodingOrCb\n } else {\n encoding = encodingOrCb\n }\n originals[`${std}Write`].apply(process[std], [chunk, encoding, callback])\n } else if (typeof cb === 'function') {\n cb()\n } else if (typeof encodingOrCb === 'function') {\n encodingOrCb()\n }\n return true\n }\n\n process.stdout.write = mockWrite('stdout')\n process.stderr.write = mockWrite('stderr')\n process.env.NODE_ENV = testNodeEnv\n\n try {\n const result = await fn()\n return {\n result,\n stderr: getStderr(),\n stdout: getStdout(),\n }\n } catch (error) {\n // Check if it's an oclif CLIError or a regular error\n const processedError =\n error instanceof Error // Check if it's an Error (this includes CLIError)\n ? Object.assign(error, {message: toString(error.message)}) // If so, process its message\n : new Error(toString(String(error))) // Otherwise, create a new Error from string representation\n\n return {\n error: processedError,\n stderr: getStderr(),\n stdout: getStdout(),\n }\n } finally {\n process.stdout.write = originals.stdoutWrite\n process.stderr.write = originals.stderrWrite\n process.env.NODE_ENV = originals.NODE_ENV\n }\n}\n"],"names":["ansis","captureOutput","fn","opts","print","stripAnsi","testNodeEnv","originals","NODE_ENV","process","env","stderrWrite","stderr","write","stdoutWrite","stdout","output","toString","str","strip","getStderr","map","b","join","getStdout","mockWrite","std","chunk","encodingOrCb","cb","push","callback","encoding","apply","result","error","processedError","Error","Object","assign","message","String"],"mappings":"AACA,OAAOA,WAAW,QAAO;AAwBzB;;;;;;;;;;;;;CAaC,GACD,OAAO,eAAeC,cACpBC,EAAoB,EACpBC,IAAqB;IAErB,MAAMC,QAAQD,MAAMC,SAAS;IAC7B,MAAMC,YAAYF,MAAME,aAAa;IACrC,MAAMC,cAAcH,MAAMG,eAAe;IAEzC,MAAMC,YAAY;QAChBC,UAAUC,QAAQC,GAAG,CAACF,QAAQ;QAC9BG,aAAaF,QAAQG,MAAM,CAACC,KAAK;QACjCC,aAAaL,QAAQM,MAAM,CAACF,KAAK;IACnC;IAEA,MAAMG,SAAgD;QACpDJ,QAAQ,EAAE;QACVG,QAAQ,EAAE;IACZ;IAEA,MAAME,WAAW,CAACC,MAChBb,YAAYL,MAAMmB,KAAK,CAACD,IAAID,QAAQ,MAAMC,IAAID,QAAQ;IAExD,MAAMG,YAAY,IAAcJ,OAAOJ,MAAM,CAACS,GAAG,CAAC,CAACC,IAAML,SAASK,IAAIC,IAAI,CAAC;IAC3E,MAAMC,YAAY,IAAcR,OAAOD,MAAM,CAACM,GAAG,CAAC,CAACC,IAAML,SAASK,IAAIC,IAAI,CAAC;IAE3E,MAAME,YACJ,CAACC,MACD,CACEC,OACAC,cACAC;YAEAb,MAAM,CAACU,IAAI,CAACI,IAAI,CAACH,MAAMV,QAAQ;YAE/B,IAAIb,OAAO;gBACT,IAAI2B,WAAuDF;gBAC3D,IAAIG;gBACJ,IAAI,OAAOJ,iBAAiB,YAAY;oBACtCG,WAAWH;gBACb,OAAO;oBACLI,WAAWJ;gBACb;gBACArB,SAAS,CAAC,GAAGmB,IAAI,KAAK,CAAC,CAAC,CAACO,KAAK,CAACxB,OAAO,CAACiB,IAAI,EAAE;oBAACC;oBAAOK;oBAAUD;iBAAS;YAC1E,OAAO,IAAI,OAAOF,OAAO,YAAY;gBACnCA;YACF,OAAO,IAAI,OAAOD,iBAAiB,YAAY;gBAC7CA;YACF;YACA,OAAO;QACT;IAEFnB,QAAQM,MAAM,CAACF,KAAK,GAAGY,UAAU;IACjChB,QAAQG,MAAM,CAACC,KAAK,GAAGY,UAAU;IACjChB,QAAQC,GAAG,CAACF,QAAQ,GAAGF;IAEvB,IAAI;QACF,MAAM4B,SAAS,MAAMhC;QACrB,OAAO;YACLgC;YACAtB,QAAQQ;YACRL,QAAQS;QACV;IACF,EAAE,OAAOW,OAAO;QACd,qDAAqD;QACrD,MAAMC,iBACJD,iBAAiBE,MAAM,kDAAkD;WACrEC,OAAOC,MAAM,CAACJ,OAAO;YAACK,SAASvB,SAASkB,MAAMK,OAAO;QAAC,GAAG,6BAA6B;WACtF,IAAIH,MAAMpB,SAASwB,OAAON,SAAS,2DAA2D;;QAEpG,OAAO;YACLA,OAAOC;YACPxB,QAAQQ;YACRL,QAAQS;QACV;IACF,SAAU;QACRf,QAAQM,MAAM,CAACF,KAAK,GAAGN,UAAUO,WAAW;QAC5CL,QAAQG,MAAM,CAACC,KAAK,GAAGN,UAAUI,WAAW;QAC5CF,QAAQC,GAAG,CAACF,QAAQ,GAAGD,UAAUC,QAAQ;IAC3C;AACF"}
|
|
@@ -3,6 +3,7 @@ import { vi } from 'vitest';
|
|
|
3
3
|
* Creates a mock spinner function to avoid writing output to stdout.
|
|
4
4
|
* @param overrides - Pass any mocks or stubs for test expectations
|
|
5
5
|
* @internal
|
|
6
|
+
* @deprecated Use mocks/cli-core/ux/spinner instead
|
|
6
7
|
*/ export function createMockSpinner(overrides) {
|
|
7
8
|
return vi.fn(()=>{
|
|
8
9
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/test/createMockSpinner.ts"],"sourcesContent":["import {type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/test/createMockSpinner.ts"],"sourcesContent":["import {type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {Mock, vi} from 'vitest'\n\n/**\n * Creates a mock spinner function to avoid writing output to stdout.\n * @param overrides - Pass any mocks or stubs for test expectations\n * @internal\n * @deprecated Use mocks/cli-core/ux/spinner instead\n */\nexport function createMockSpinner(\n overrides?: Partial<SpinnerInstance>,\n): Mock<(options: string) => SpinnerInstance> {\n return vi.fn(() => {\n return {\n clear: function (): SpinnerInstance {\n throw new Error('Function not implemented.')\n },\n color: false,\n fail: function (_text?: string): SpinnerInstance {\n throw new Error('Function not implemented.')\n },\n frame: function (): string {\n throw new Error('Function not implemented.')\n },\n indent: 0,\n info: function (_text?: string): SpinnerInstance {\n throw new Error('Function not implemented.')\n },\n interval: 0,\n isSpinning: false,\n prefixText: '',\n render: function (): SpinnerInstance {\n throw new Error('Function not implemented.')\n },\n spinner: {\n frames: [],\n interval: undefined,\n },\n start: function (_text?: string): SpinnerInstance {\n throw new Error('Function not implemented.')\n },\n stop: function (): SpinnerInstance {\n throw new Error('Function not implemented.')\n },\n stopAndPersist: function (_options?: any): SpinnerInstance {\n throw new Error('Function not implemented.')\n },\n succeed: function (_text?: string): SpinnerInstance {\n throw new Error('Function not implemented.')\n },\n suffixText: '',\n text: '',\n warn: function (_text?: string): SpinnerInstance {\n throw new Error('Function not implemented.')\n },\n ...overrides,\n }\n })\n}\n"],"names":["vi","createMockSpinner","overrides","fn","clear","Error","color","fail","_text","frame","indent","info","interval","isSpinning","prefixText","render","spinner","frames","undefined","start","stop","stopAndPersist","_options","succeed","suffixText","text","warn"],"mappings":"AACA,SAAcA,EAAE,QAAO,SAAQ;AAE/B;;;;;CAKC,GACD,OAAO,SAASC,kBACdC,SAAoC;IAEpC,OAAOF,GAAGG,EAAE,CAAC;QACX,OAAO;YACLC,OAAO;gBACL,MAAM,IAAIC,MAAM;YAClB;YACAC,OAAO;YACPC,MAAM,SAAUC,KAAc;gBAC5B,MAAM,IAAIH,MAAM;YAClB;YACAI,OAAO;gBACL,MAAM,IAAIJ,MAAM;YAClB;YACAK,QAAQ;YACRC,MAAM,SAAUH,KAAc;gBAC5B,MAAM,IAAIH,MAAM;YAClB;YACAO,UAAU;YACVC,YAAY;YACZC,YAAY;YACZC,QAAQ;gBACN,MAAM,IAAIV,MAAM;YAClB;YACAW,SAAS;gBACPC,QAAQ,EAAE;gBACVL,UAAUM;YACZ;YACAC,OAAO,SAAUX,KAAc;gBAC7B,MAAM,IAAIH,MAAM;YAClB;YACAe,MAAM;gBACJ,MAAM,IAAIf,MAAM;YAClB;YACAgB,gBAAgB,SAAUC,QAAc;gBACtC,MAAM,IAAIjB,MAAM;YAClB;YACAkB,SAAS,SAAUf,KAAc;gBAC/B,MAAM,IAAIH,MAAM;YAClB;YACAmB,YAAY;YACZC,MAAM;YACNC,MAAM,SAAUlB,KAAc;gBAC5B,MAAM,IAAIH,MAAM;YAClB;YACA,GAAGH,SAAS;QACd;IACF;AACF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ClientConfig } from "@sanity/client";
|
|
2
|
+
import { SanityClient } from "@sanity/client";
|
|
3
|
+
import { vi } from "vitest";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a real Sanity client instance for testing that makes actual HTTP requests.
|
|
7
|
+
* Use with mockApi() to intercept and mock the HTTP calls.
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* // Mock getGlobalCliClient to return a test client
|
|
14
|
+
* vi.mock('@sanity/cli-core', async (importOriginal) => {
|
|
15
|
+
* const actual = await importOriginal<typeof import('@sanity/cli-core')>()
|
|
16
|
+
* const {createTestClient} = await import('@sanity/cli-test')
|
|
17
|
+
*
|
|
18
|
+
* return {
|
|
19
|
+
* ...actual,
|
|
20
|
+
* getGlobalCliClient: vi.fn().mockImplementation((opts) => {
|
|
21
|
+
* return Promise.resolve(createTestClient({
|
|
22
|
+
* apiVersion: opts.apiVersion,
|
|
23
|
+
* }))
|
|
24
|
+
* }),
|
|
25
|
+
* }
|
|
26
|
+
* })
|
|
27
|
+
*
|
|
28
|
+
* // Then use mockApi to intercept requests
|
|
29
|
+
* mockApi({
|
|
30
|
+
* apiVersion: 'v2025-02-19',
|
|
31
|
+
* method: 'get',
|
|
32
|
+
* uri: '/media-libraries',
|
|
33
|
+
* }).reply(200, {data: [...]})
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function createTestClient(options: CreateTestClientOptions): {
|
|
37
|
+
client: SanityClient;
|
|
38
|
+
request: ReturnType<typeof vi.fn>;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Options for createTestClient
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export declare interface CreateTestClientOptions extends ClientConfig {
|
|
47
|
+
/**
|
|
48
|
+
* API version for the client
|
|
49
|
+
*/
|
|
50
|
+
apiVersion: string;
|
|
51
|
+
/**
|
|
52
|
+
* Authentication token
|
|
53
|
+
*/
|
|
54
|
+
token?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import nock from "nock";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mocks the API calls, add some defaults so it doesn't cause too much friction
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export declare function mockApi({
|
|
9
|
+
apiHost,
|
|
10
|
+
apiVersion,
|
|
11
|
+
includeQueryTag,
|
|
12
|
+
method,
|
|
13
|
+
projectId,
|
|
14
|
+
query,
|
|
15
|
+
uri,
|
|
16
|
+
}: MockApiOptions): nock.Interceptor;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export declare interface MockApiOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Uri to mock
|
|
24
|
+
*/
|
|
25
|
+
uri: string;
|
|
26
|
+
/**
|
|
27
|
+
* Api host to mock, defaults to `https://api.sanity.io`
|
|
28
|
+
*/
|
|
29
|
+
apiHost?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Api version to mock, defaults to `v2025-05-14`
|
|
32
|
+
*/
|
|
33
|
+
apiVersion?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Whether to include `tag: 'sanity.cli'` in query parameters.
|
|
36
|
+
* Defaults to `true`. Set to `false` for endpoints that don't use CLI tagging.
|
|
37
|
+
*/
|
|
38
|
+
includeQueryTag?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* HTTP method to mock
|
|
41
|
+
*
|
|
42
|
+
* Defaults to 'get'
|
|
43
|
+
*/
|
|
44
|
+
method?: "delete" | "get" | "patch" | "post" | "put";
|
|
45
|
+
/**
|
|
46
|
+
* Project ID to mock. When provided, constructs apiHost as `https://{projectId}.api.sanity.io`
|
|
47
|
+
* Takes precedence over apiHost if both are provided.
|
|
48
|
+
*/
|
|
49
|
+
projectId?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Query parameters to mock
|
|
52
|
+
*/
|
|
53
|
+
query?: Record<string, string>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/test/mockSanityCommand.ts"],"sourcesContent":["import {type Command} from '@oclif/core'\nimport {type CliConfig, type ProjectRootResult
|
|
1
|
+
{"version":3,"sources":["../../src/test/mockSanityCommand.ts"],"sourcesContent":["import {type Command} from '@oclif/core'\nimport {SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {type CliConfig, type ProjectRootResult} from '@sanity/cli-core/types'\n\nimport {convertToSystemPath} from '../utils/paths.js'\nimport {createTestToken} from './createTestToken.js'\n\n/**\n * @public\n */\nexport interface MockSanityCommandOptions {\n /**\n * Mock CLI config (required if command uses getCliConfig or getProjectId)\n */\n cliConfig?: CliConfig\n /**\n * When provided, getCliConfig() will throw this error instead of returning a config.\n * Useful for simulating running outside a project directory.\n */\n cliConfigError?: Error\n /**\n * Mock whether the terminal is interactive (used by isUnattended)\n */\n isInteractive?: boolean\n /**\n * Mock project root result (required if command uses getProjectRoot)\n */\n projectRoot?: ProjectRootResult\n /**\n * Mock authentication token (passed to API clients, bypasses getCliToken)\n */\n token?: string\n}\n\n/**\n * Creates a testable subclass of a command with mocked SanityCommand dependencies.\n *\n * @public\n *\n * @example\n * ```ts\n * // Basic config mocking\n * const TestAdd = mockSanityCommand(Add, {\n * cliConfig: { api: { projectId: 'test-project' } }\n * })\n *\n * // With mock API client\n * const mockClient = {\n * getDocument: vi.fn().mockResolvedValue({ _id: 'doc1', title: 'Test' }),\n * fetch: vi.fn().mockResolvedValue([]),\n * }\n * const TestGet = mockSanityCommand(GetDocumentCommand, {\n * cliConfig: { api: { projectId: 'test-project', dataset: 'production' } },\n * projectApiClient: mockClient,\n * })\n *\n * const {stdout} = await testCommand(TestGet, ['doc1'])\n * expect(mockClient.getDocument).toHaveBeenCalledWith('doc1')\n * ```\n */\nexport function mockSanityCommand<T extends typeof SanityCommand<typeof Command>>(\n CommandClass: T,\n options: MockSanityCommandOptions = {},\n): T {\n if (options.token) {\n createTestToken(options.token)\n }\n\n // Auto-convert paths in projectRoot to platform-appropriate format\n const projectRoot = options.projectRoot\n ? {\n ...options.projectRoot,\n directory: convertToSystemPath(options.projectRoot.directory),\n path: convertToSystemPath(options.projectRoot.path),\n }\n : undefined\n\n // Create a subclass that overrides methods when mocks are provided\n // Note: we use @ts-expect-error because TypeScript can't properly infer\n // the relationship between the generic CommandClass and SanityCommand\n // @ts-expect-error - TypeScript struggles with abstract class subclassing\n class MockedCommand extends CommandClass {\n protected getCliConfig(): Promise<CliConfig> {\n if (options.cliConfigError) {\n return Promise.reject(options.cliConfigError)\n }\n if (options.cliConfig) {\n return Promise.resolve(options.cliConfig)\n }\n return super.getCliConfig()\n }\n\n protected getProjectRoot(): Promise<ProjectRootResult> {\n if (\n options.cliConfigError &&\n 'name' in options.cliConfigError &&\n options.cliConfigError.name === 'ProjectRootNotFoundError'\n ) {\n return Promise.reject(options.cliConfigError)\n }\n if (projectRoot) {\n return Promise.resolve(projectRoot)\n }\n return super.getProjectRoot()\n }\n\n protected resolveIsInteractive(): boolean {\n if (options.isInteractive !== undefined) {\n return options.isInteractive\n }\n return super.resolveIsInteractive()\n }\n }\n\n return MockedCommand as T\n}\n"],"names":["convertToSystemPath","createTestToken","mockSanityCommand","CommandClass","options","token","projectRoot","directory","path","undefined","MockedCommand","getCliConfig","cliConfigError","Promise","reject","cliConfig","resolve","getProjectRoot","name","resolveIsInteractive","isInteractive"],"mappings":"AAIA,SAAQA,mBAAmB,QAAO,oBAAmB;AACrD,SAAQC,eAAe,QAAO,uBAAsB;AA6BpD;;;;;;;;;;;;;;;;;;;;;;;;;CAyBC,GACD,OAAO,SAASC,kBACdC,YAAe,EACfC,UAAoC,CAAC,CAAC;IAEtC,IAAIA,QAAQC,KAAK,EAAE;QACjBJ,gBAAgBG,QAAQC,KAAK;IAC/B;IAEA,mEAAmE;IACnE,MAAMC,cAAcF,QAAQE,WAAW,GACnC;QACE,GAAGF,QAAQE,WAAW;QACtBC,WAAWP,oBAAoBI,QAAQE,WAAW,CAACC,SAAS;QAC5DC,MAAMR,oBAAoBI,QAAQE,WAAW,CAACE,IAAI;IACpD,IACAC;IAEJ,mEAAmE;IACnE,wEAAwE;IACxE,sEAAsE;IACtE,0EAA0E;IAC1E,MAAMC,sBAAsBP;QAChBQ,eAAmC;YAC3C,IAAIP,QAAQQ,cAAc,EAAE;gBAC1B,OAAOC,QAAQC,MAAM,CAACV,QAAQQ,cAAc;YAC9C;YACA,IAAIR,QAAQW,SAAS,EAAE;gBACrB,OAAOF,QAAQG,OAAO,CAACZ,QAAQW,SAAS;YAC1C;YACA,OAAO,KAAK,CAACJ;QACf;QAEUM,iBAA6C;YACrD,IACEb,QAAQQ,cAAc,IACtB,UAAUR,QAAQQ,cAAc,IAChCR,QAAQQ,cAAc,CAACM,IAAI,KAAK,4BAChC;gBACA,OAAOL,QAAQC,MAAM,CAACV,QAAQQ,cAAc;YAC9C;YACA,IAAIN,aAAa;gBACf,OAAOO,QAAQG,OAAO,CAACV;YACzB;YACA,OAAO,KAAK,CAACW;QACf;QAEUE,uBAAgC;YACxC,IAAIf,QAAQgB,aAAa,KAAKX,WAAW;gBACvC,OAAOL,QAAQgB,aAAa;YAC9B;YACA,OAAO,KAAK,CAACD;QACf;IACF;IAEA,OAAOT;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/test/mockTelemetry.ts"],"sourcesContent":["import {type CLITelemetryStore} from '@sanity/cli-core'\nimport {vi} from 'vitest'\n\n/**\n * @public\n */\nexport interface MockTelemetryOptions {\n trace?: () => void\n updateUserProperties?: () => void\n}\n\n/**\n * @public\n * @param options - Options for mocking the telemetry store.\n * @returns The mocked telemetry store.\n */\nexport const mockTelemetry = (options: MockTelemetryOptions = {}): CLITelemetryStore => {\n const telemetry = {\n trace: vi.fn().mockReturnValue({\n complete: vi.fn(),\n error: vi.fn(),\n log: vi.fn(),\n newContext: vi.fn(),\n start: vi.fn(),\n }),\n updateUserProperties: vi.fn(),\n ...options,\n } as unknown as CLITelemetryStore\n\n // We are not using the export from @sanity/cli-core because\n // This can be used where `@sanity/cli-core` is mocked and vitest will run into issues.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(globalThis as any)[Symbol.for('sanity.cli.telemetry')] = {logger: telemetry}\n\n return telemetry\n}\n"],"names":["vi","mockTelemetry","options","telemetry","trace","fn","mockReturnValue","complete","error","log","newContext","start","updateUserProperties","globalThis","Symbol","for","logger"],"mappings":"AACA,SAAQA,EAAE,QAAO,SAAQ;AAUzB;;;;CAIC,GACD,OAAO,MAAMC,gBAAgB,CAACC,UAAgC,CAAC,CAAC;IAC9D,MAAMC,YAAY;QAChBC,OAAOJ,GAAGK,EAAE,GAAGC,eAAe,CAAC;YAC7BC,UAAUP,GAAGK,EAAE;YACfG,OAAOR,GAAGK,EAAE;YACZI,KAAKT,GAAGK,EAAE;YACVK,YAAYV,GAAGK,EAAE;YACjBM,OAAOX,GAAGK,EAAE;QACd;QACAO,sBAAsBZ,GAAGK,EAAE;QAC3B,GAAGH,OAAO;IACZ;IAKEW,UAAkB,CAACC,OAAOC,GAAG,CAAC,wBAAwB,GAAG;QAACC,QAAQb;IAAS;IAE7E,OAAOA;AACT,EAAC"}
|
|
1
|
+
{"version":3,"sources":["../../src/test/mockTelemetry.ts"],"sourcesContent":["import {type CLITelemetryStore} from '@sanity/cli-core/types'\nimport {vi} from 'vitest'\n\n/**\n * @public\n */\nexport interface MockTelemetryOptions {\n trace?: () => void\n updateUserProperties?: () => void\n}\n\n/**\n * @public\n * @param options - Options for mocking the telemetry store.\n * @returns The mocked telemetry store.\n */\nexport const mockTelemetry = (options: MockTelemetryOptions = {}): CLITelemetryStore => {\n const telemetry = {\n trace: vi.fn().mockReturnValue({\n complete: vi.fn(),\n error: vi.fn(),\n log: vi.fn(),\n newContext: vi.fn(),\n start: vi.fn(),\n }),\n updateUserProperties: vi.fn(),\n ...options,\n } as unknown as CLITelemetryStore\n\n // We are not using the export from @sanity/cli-core because\n // This can be used where `@sanity/cli-core` is mocked and vitest will run into issues.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(globalThis as any)[Symbol.for('sanity.cli.telemetry')] = {logger: telemetry}\n\n return telemetry\n}\n"],"names":["vi","mockTelemetry","options","telemetry","trace","fn","mockReturnValue","complete","error","log","newContext","start","updateUserProperties","globalThis","Symbol","for","logger"],"mappings":"AACA,SAAQA,EAAE,QAAO,SAAQ;AAUzB;;;;CAIC,GACD,OAAO,MAAMC,gBAAgB,CAACC,UAAgC,CAAC,CAAC;IAC9D,MAAMC,YAAY;QAChBC,OAAOJ,GAAGK,EAAE,GAAGC,eAAe,CAAC;YAC7BC,UAAUP,GAAGK,EAAE;YACfG,OAAOR,GAAGK,EAAE;YACZI,KAAKT,GAAGK,EAAE;YACVK,YAAYV,GAAGK,EAAE;YACjBM,OAAOX,GAAGK,EAAE;QACd;QACAO,sBAAsBZ,GAAGK,EAAE;QAC3B,GAAGH,OAAO;IACZ;IAKEW,UAAkB,CAACC,OAAOC,GAAG,CAAC,wBAAwB,GAAG;QAACC,QAAQb;IAAS;IAE7E,OAAOA;AACT,EAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { CliConfig } from "@sanity/cli-core/types";
|
|
2
|
+
import { Command } from "@oclif/core";
|
|
3
|
+
import { Config } from "@oclif/core";
|
|
4
|
+
import { Errors } from "@oclif/core";
|
|
5
|
+
import { Hook } from "@oclif/core/hooks";
|
|
6
|
+
import { Hooks } from "@oclif/core/hooks";
|
|
7
|
+
import { ProjectRootResult } from "@sanity/cli-core/types";
|
|
8
|
+
import { SanityCommand } from "@sanity/cli-core/SanityCommand";
|
|
9
|
+
|
|
10
|
+
/** @public */
|
|
11
|
+
export declare interface CaptureOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Whether to print the output to the console
|
|
14
|
+
*/
|
|
15
|
+
print?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Whether to strip ANSI escape codes from the output
|
|
18
|
+
*/
|
|
19
|
+
stripAnsi?: boolean;
|
|
20
|
+
testNodeEnv?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Capture the output of a command and return the result
|
|
25
|
+
*
|
|
26
|
+
* @param fn - The function to capture the output of
|
|
27
|
+
* @param opts - The options for the capture
|
|
28
|
+
* @returns The result of the command
|
|
29
|
+
* @public
|
|
30
|
+
*
|
|
31
|
+
* Credits to oclif for the original implementation:
|
|
32
|
+
* https://github.com/oclif/test/blob/2a5407e6fc80d388043d10f6b7b8eaa586483015/src/index.ts
|
|
33
|
+
*
|
|
34
|
+
* We are not using the library directly since it does not support mocking code inside of the command
|
|
35
|
+
* possibly because the commands run in a different thread
|
|
36
|
+
*/
|
|
37
|
+
export declare function captureOutput<T>(
|
|
38
|
+
fn: () => Promise<T>,
|
|
39
|
+
opts?: CaptureOptions,
|
|
40
|
+
): Promise<CaptureResult<T>>;
|
|
41
|
+
|
|
42
|
+
/** @public */
|
|
43
|
+
export declare interface CaptureResult<T = unknown> {
|
|
44
|
+
stderr: string;
|
|
45
|
+
stdout: string;
|
|
46
|
+
error?: Error & Partial<Errors.CLIError>;
|
|
47
|
+
result?: T;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
declare type CommandClass = (new (argv: string[], config: Config) => Command) &
|
|
51
|
+
typeof Command;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Creates a testable subclass of a command with mocked SanityCommand dependencies.
|
|
55
|
+
*
|
|
56
|
+
* @public
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* // Basic config mocking
|
|
61
|
+
* const TestAdd = mockSanityCommand(Add, {
|
|
62
|
+
* cliConfig: { api: { projectId: 'test-project' } }
|
|
63
|
+
* })
|
|
64
|
+
*
|
|
65
|
+
* // With mock API client
|
|
66
|
+
* const mockClient = {
|
|
67
|
+
* getDocument: vi.fn().mockResolvedValue({ _id: 'doc1', title: 'Test' }),
|
|
68
|
+
* fetch: vi.fn().mockResolvedValue([]),
|
|
69
|
+
* }
|
|
70
|
+
* const TestGet = mockSanityCommand(GetDocumentCommand, {
|
|
71
|
+
* cliConfig: { api: { projectId: 'test-project', dataset: 'production' } },
|
|
72
|
+
* projectApiClient: mockClient,
|
|
73
|
+
* })
|
|
74
|
+
*
|
|
75
|
+
* const {stdout} = await testCommand(TestGet, ['doc1'])
|
|
76
|
+
* expect(mockClient.getDocument).toHaveBeenCalledWith('doc1')
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function mockSanityCommand<
|
|
80
|
+
T extends typeof SanityCommand<typeof Command>,
|
|
81
|
+
>(CommandClass: T, options?: MockSanityCommandOptions): T;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @public
|
|
85
|
+
*/
|
|
86
|
+
export declare interface MockSanityCommandOptions {
|
|
87
|
+
/**
|
|
88
|
+
* Mock CLI config (required if command uses getCliConfig or getProjectId)
|
|
89
|
+
*/
|
|
90
|
+
cliConfig?: CliConfig;
|
|
91
|
+
/**
|
|
92
|
+
* When provided, getCliConfig() will throw this error instead of returning a config.
|
|
93
|
+
* Useful for simulating running outside a project directory.
|
|
94
|
+
*/
|
|
95
|
+
cliConfigError?: Error;
|
|
96
|
+
/**
|
|
97
|
+
* Mock whether the terminal is interactive (used by isUnattended)
|
|
98
|
+
*/
|
|
99
|
+
isInteractive?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Mock project root result (required if command uses getProjectRoot)
|
|
102
|
+
*/
|
|
103
|
+
projectRoot?: ProjectRootResult;
|
|
104
|
+
/**
|
|
105
|
+
* Mock authentication token (passed to API clients, bypasses getCliToken)
|
|
106
|
+
*/
|
|
107
|
+
token?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @public
|
|
112
|
+
*/
|
|
113
|
+
declare interface MockTelemetryOptions {
|
|
114
|
+
trace?: () => void;
|
|
115
|
+
updateUserProperties?: () => void;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
declare interface Options {
|
|
119
|
+
config: Config;
|
|
120
|
+
Command?: Command.Class;
|
|
121
|
+
context?: Hook.Context;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @public
|
|
126
|
+
*/
|
|
127
|
+
export declare function testCommand(
|
|
128
|
+
command: CommandClass,
|
|
129
|
+
args?: string[],
|
|
130
|
+
options?: TestCommandOptions,
|
|
131
|
+
): Promise<CaptureResult<unknown>>;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @public
|
|
135
|
+
*/
|
|
136
|
+
export declare interface TestCommandOptions {
|
|
137
|
+
/**
|
|
138
|
+
* Options for capturing output
|
|
139
|
+
*/
|
|
140
|
+
capture?: CaptureOptions;
|
|
141
|
+
/**
|
|
142
|
+
* Partial oclif config overrides
|
|
143
|
+
*/
|
|
144
|
+
config?: Partial<Config>;
|
|
145
|
+
/**
|
|
146
|
+
* Mock options for SanityCommand dependencies (config, project root, API clients).
|
|
147
|
+
* When provided, the command is automatically wrapped with mockSanityCommand.
|
|
148
|
+
*/
|
|
149
|
+
mocks?: MockSanityCommandOptions & MockTelemetryOptions;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Test an oclif hook
|
|
154
|
+
*
|
|
155
|
+
* @public
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* const result = await testHook(hook, {
|
|
160
|
+
* Command: Command.loadable,
|
|
161
|
+
* context: {
|
|
162
|
+
* config: Config.load({
|
|
163
|
+
* // CLI root is the directory of the package that contains the hook.
|
|
164
|
+
* root: path.resolve(fileURLToPath(import.meta.url), '../../../root'),
|
|
165
|
+
* }),
|
|
166
|
+
* },
|
|
167
|
+
* })
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @param hook - The hook to test
|
|
171
|
+
* @param options - The options for the hook
|
|
172
|
+
* @returns The result of the hook
|
|
173
|
+
*/
|
|
174
|
+
export declare function testHook<T extends keyof Hooks>(
|
|
175
|
+
hook: Hook<T>,
|
|
176
|
+
options: Options,
|
|
177
|
+
): Promise<CaptureResult<Hooks[T]["return"]>>;
|
|
178
|
+
|
|
179
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Heavy integration test tooling goes here. OCLIF is a transient dependency. Do not rely on this tooling - instead write unit tests!
|
|
2
|
+
export * from './captureOutput.js';
|
|
3
|
+
export * from './mockSanityCommand.js';
|
|
4
|
+
export * from './testCommand.js';
|
|
5
|
+
export * from './testHook.js';
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=oclif.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/test/oclif.ts"],"sourcesContent":["// Heavy integration test tooling goes here. OCLIF is a transient dependency. Do not rely on this tooling - instead write unit tests!\nexport * from './captureOutput.js'\nexport * from './mockSanityCommand.js'\nexport * from './testCommand.js'\nexport * from './testHook.js'\n"],"names":[],"mappings":"AAAA,qIAAqI;AACrI,cAAc,qBAAoB;AAClC,cAAc,yBAAwB;AACtC,cAAc,mBAAkB;AAChC,cAAc,gBAAe"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { TestProject } from "vitest/node";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Global setup function for initializing test fixtures.
|
|
5
|
+
*
|
|
6
|
+
* Copies fixtures from the bundled location to a temp directory
|
|
7
|
+
* and installs dependencies.
|
|
8
|
+
*
|
|
9
|
+
* Note: Fixtures are NOT built during setup. Tests that need built
|
|
10
|
+
* fixtures should build them as part of the test.
|
|
11
|
+
*
|
|
12
|
+
* This function is designed to be used with vitest globalSetup.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
*
|
|
16
|
+
* @param options - Configuration options
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // In vitest.config.ts
|
|
20
|
+
* export default defineConfig({
|
|
21
|
+
* test: {
|
|
22
|
+
* globalSetup: ['@sanity/cli-test/vitest']
|
|
23
|
+
* }
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function setup(
|
|
28
|
+
_: TestProject,
|
|
29
|
+
options?: SetupTestFixturesOptions,
|
|
30
|
+
): Promise<void>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Options for setupTestFixtures
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
export declare interface SetupTestFixturesOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Glob patterns for additional fixture directories to set up.
|
|
40
|
+
*
|
|
41
|
+
* Each pattern is matched against directories in the current working directory.
|
|
42
|
+
* Only directories containing a `package.json` file are included.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* ['fixtures/*', 'dev/*']
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
additionalFixtures?: string[];
|
|
50
|
+
/**
|
|
51
|
+
* When true, passes `--ignore-workspace` to pnpm install so fixtures get
|
|
52
|
+
* their own node_modules even when the temp directory is inside a pnpm
|
|
53
|
+
* workspace. Required for E2E tests that spawn the CLI binary against
|
|
54
|
+
* fixture directories.
|
|
55
|
+
*/
|
|
56
|
+
ignoreWorkspace?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Custom temp directory path. Defaults to process.cwd()/tmp
|
|
59
|
+
*/
|
|
60
|
+
tempDir?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Teardown function to clean up test fixtures.
|
|
65
|
+
*
|
|
66
|
+
* Removes the temp directory created by setupTestFixtures.
|
|
67
|
+
*
|
|
68
|
+
* This function is designed to be used with vitest globalSetup.
|
|
69
|
+
*
|
|
70
|
+
* @public
|
|
71
|
+
*
|
|
72
|
+
* @param options - Configuration options
|
|
73
|
+
*/
|
|
74
|
+
export declare function teardown(
|
|
75
|
+
options?: TeardownTestFixturesOptions,
|
|
76
|
+
): Promise<void>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Options for teardownTestFixtures
|
|
80
|
+
*
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
export declare interface TeardownTestFixturesOptions {
|
|
84
|
+
/**
|
|
85
|
+
* Custom temp directory path. Defaults to process.cwd()/tmp
|
|
86
|
+
*/
|
|
87
|
+
tempDir?: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export {};
|