@devvit/test 0.12.6-next-2025-12-08-21-42-15-9f008f8f0.0 → 0.12.6-next-2025-12-09-22-01-39-77cc3d62a.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/package.json +9 -9
- package/server/mocks/http/httpMock.d.ts +11 -0
- package/server/mocks/http/httpMock.d.ts.map +1 -0
- package/server/mocks/http/httpMock.js +11 -0
- package/server/vitest/devvitTest.d.ts +3 -0
- package/server/vitest/devvitTest.d.ts.map +1 -1
- package/server/vitest/devvitTest.http.test.d.ts.map +1 -0
- package/server/vitest/devvitTest.js +26 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devvit/test",
|
|
3
|
-
"version": "0.12.6-next-2025-12-
|
|
3
|
+
"version": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
"test:unit-with-coverage": "vitest run --coverage"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@devvit/media": "0.12.6-next-2025-12-
|
|
39
|
-
"@devvit/protos": "0.12.6-next-2025-12-
|
|
40
|
-
"@devvit/redis": "0.12.6-next-2025-12-
|
|
41
|
-
"@devvit/server": "0.12.6-next-2025-12-
|
|
42
|
-
"@devvit/shared-types": "0.12.6-next-2025-12-
|
|
38
|
+
"@devvit/media": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
|
|
39
|
+
"@devvit/protos": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
|
|
40
|
+
"@devvit/redis": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
|
|
41
|
+
"@devvit/server": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
|
|
42
|
+
"@devvit/shared-types": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
|
|
43
43
|
"ioredis": "5.7.0",
|
|
44
44
|
"redis-memory-server": "0.12.1"
|
|
45
45
|
},
|
|
@@ -47,11 +47,11 @@
|
|
|
47
47
|
"vitest": "*"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@devvit/repo-tools": "0.12.6-next-2025-12-
|
|
51
|
-
"@devvit/tsconfig": "0.12.6-next-2025-12-
|
|
50
|
+
"@devvit/repo-tools": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
|
|
51
|
+
"@devvit/tsconfig": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
|
|
52
52
|
"eslint": "9.11.1",
|
|
53
53
|
"typescript": "5.8.3",
|
|
54
54
|
"vitest": "1.6.1"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "8bfbd5035ccf97cdac44004ac41645c50cdd8a02"
|
|
57
57
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type HTTP, type Metadata } from '@devvit/protos';
|
|
2
|
+
import type { FetchRequest, FetchResponse } from '@devvit/protos/types/devvit/plugin/http/http.js';
|
|
3
|
+
/**
|
|
4
|
+
* Mock implementation of the HTTP plugin that throws an error when requests are made.
|
|
5
|
+
*
|
|
6
|
+
* Use this in tests to ensure that HTTP requests are not accidentally made.
|
|
7
|
+
*/
|
|
8
|
+
export declare class HTTPMock implements HTTP {
|
|
9
|
+
Fetch(_request: FetchRequest, _metadata?: Metadata): Promise<FetchResponse>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=httpMock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpMock.d.ts","sourceRoot":"","sources":["../../../../src/server/mocks/http/httpMock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iDAAiD,CAAC;AAEnG;;;;GAIG;AACH,qBAAa,QAAS,YAAW,IAAI;IAC7B,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;CAKlF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {} from '@devvit/protos';
|
|
2
|
+
/**
|
|
3
|
+
* Mock implementation of the HTTP plugin that throws an error when requests are made.
|
|
4
|
+
*
|
|
5
|
+
* Use this in tests to ensure that HTTP requests are not accidentally made.
|
|
6
|
+
*/
|
|
7
|
+
export class HTTPMock {
|
|
8
|
+
async Fetch(_request, _metadata) {
|
|
9
|
+
throw new Error(`HTTP requests are not allowed in tests by default. To mock HTTP requests, use vi.spyOn(globalThis, "fetch"). See https://developers.reddit.com/docs/guides/tools/devvit_test#http for details.`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import '@devvit/shared-types/polyfill/fetch.polyfill.js';
|
|
1
2
|
import { MediaMock } from '@devvit/media/test';
|
|
2
3
|
import { RedisMock } from '@devvit/redis/test';
|
|
3
4
|
import type { Config } from '@devvit/shared-types/Config.js';
|
|
@@ -5,6 +6,7 @@ import { Header } from '@devvit/shared-types/Header.js';
|
|
|
5
6
|
import type { AppConfig } from '@devvit/shared-types/schemas/config-file.v1.js';
|
|
6
7
|
import type { T2, T5 } from '@devvit/shared-types/tid.js';
|
|
7
8
|
import type { TestAPI } from 'vitest';
|
|
9
|
+
import { HTTPMock } from '../mocks/http/httpMock.js';
|
|
8
10
|
export type DevvitFixtures = {
|
|
9
11
|
/**
|
|
10
12
|
* The Devvit configuration object for the current test context.
|
|
@@ -50,6 +52,7 @@ export type DevvitFixtures = {
|
|
|
50
52
|
mocks: {
|
|
51
53
|
media: MediaMock;
|
|
52
54
|
redis: RedisMock;
|
|
55
|
+
http: HTTPMock;
|
|
53
56
|
};
|
|
54
57
|
};
|
|
55
58
|
export type DevvitTestConfig = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devvitTest.d.ts","sourceRoot":"","sources":["../../../src/server/vitest/devvitTest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"devvitTest.d.ts","sourceRoot":"","sources":["../../../src/server/vitest/devvitTest.ts"],"names":[],"mappings":"AAAA,OAAO,iDAAiD,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAI/C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gDAAgD,CAAC;AAMhF,OAAO,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,QAAQ,CAAC;AAGpD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAKrD,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE;SAAG,GAAG,IAAI,MAAM,CAAC,CAAC,EAAE,MAAM;KAAE,CAAC;IAEtC;;;OAGG;IACH,QAAQ,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAAA;KAAE,CAAC;IAE9E;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,MAAM,EAAE,EAAE,CAAC;IAEX;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,WAAW,EAAE,EAAE,CAAC;IAEhB;;;OAGG;IACH,KAAK,EAAE;QACL,KAAK,EAAE,SAAS,CAAC;QACjB,KAAK,EAAE,SAAS,CAAC;QACjB,IAAI,EAAE,QAAQ,CAAC;KAChB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,EAAE,CAAC;IAEZ;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,WAAW,CAAC,EAAE,EAAE,CAAC;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAAA;KAAE,CAAC;IAE/E;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AA0IF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAQ,gBAAqB,KAAG,OAAO,CAAC,cAAc,CAEtF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devvitTest.http.test.d.ts","sourceRoot":"","sources":["../../../src/server/vitest/devvitTest.http.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import '@devvit/shared-types/polyfill/fetch.polyfill.js';
|
|
1
2
|
import { MediaMock } from '@devvit/media/test';
|
|
3
|
+
import { HTTPDefinition } from '@devvit/protos';
|
|
2
4
|
import { MediaServiceDefinition } from '@devvit/protos/types//devvit/plugin/media/media.js';
|
|
3
5
|
import { RedisAPIDefinition } from '@devvit/protos/types/devvit/plugin/redis/redisapi.js';
|
|
4
6
|
import { RedisMock } from '@devvit/redis/test';
|
|
5
7
|
import { Context, runWithContext } from '@devvit/server';
|
|
6
8
|
import { Header } from '@devvit/shared-types/Header.js';
|
|
7
9
|
import { getDefaultAppConfig, makeConfig, MOCK_HEADERS as headersMock, } from '@devvit/shared-types/test/index.js';
|
|
8
|
-
import { test as baseTest } from 'vitest';
|
|
10
|
+
import { test as baseTest, vi } from 'vitest';
|
|
11
|
+
import { HTTPMock } from '../mocks/http/httpMock.js';
|
|
9
12
|
import { installDevvitInterceptors, runWithTestContext } from './context.js';
|
|
10
13
|
installDevvitInterceptors();
|
|
11
14
|
function createWrappedTestApi(target, setup) {
|
|
@@ -27,21 +30,26 @@ function createWrappedTestApi(target, setup) {
|
|
|
27
30
|
// Wrap the user's test function
|
|
28
31
|
args[lastFnIndex] = async (...fnArgs) => {
|
|
29
32
|
const { reqCtx, fixtures, testContext } = setup();
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
try {
|
|
34
|
+
// Heuristic to detect Vitest TestContext
|
|
35
|
+
// Standard test() calls receive a single TestContext object.
|
|
36
|
+
// test.each() calls receive the parameters as arguments.
|
|
37
|
+
const isTestContext = fnArgs.length === 1 &&
|
|
38
|
+
fnArgs[0] &&
|
|
39
|
+
(typeof fnArgs[0] === 'object' || typeof fnArgs[0] === 'function') &&
|
|
40
|
+
'task' in fnArgs[0] &&
|
|
41
|
+
// Vitest context usually has these lifecycle methods
|
|
42
|
+
'onTestFailed' in fnArgs[0];
|
|
43
|
+
if (isTestContext) {
|
|
44
|
+
const mergedCtx = { ...fixtures, ...fnArgs[0] };
|
|
45
|
+
return await runWithContext(reqCtx, () => runWithTestContext(testContext, () => userFn(mergedCtx)));
|
|
46
|
+
}
|
|
47
|
+
return await runWithContext(reqCtx, () => runWithTestContext(testContext, () => userFn(...fnArgs)));
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
vi.restoreAllMocks();
|
|
51
|
+
await fixtures.mocks.redis.clear();
|
|
43
52
|
}
|
|
44
|
-
return runWithContext(reqCtx, () => runWithTestContext(testContext, () => userFn(...fnArgs)));
|
|
45
53
|
};
|
|
46
54
|
}
|
|
47
55
|
const result = Reflect.apply(fn, thisArg, args);
|
|
@@ -80,10 +88,12 @@ const setup = (config) => {
|
|
|
80
88
|
};
|
|
81
89
|
const mediaMock = new MediaMock();
|
|
82
90
|
const redisMock = new RedisMock();
|
|
91
|
+
const httpMock = new HTTPMock();
|
|
83
92
|
const cfg = makeConfig({
|
|
84
93
|
plugins: {
|
|
85
94
|
[MediaServiceDefinition.fullName]: mediaMock,
|
|
86
95
|
[RedisAPIDefinition.fullName]: redisMock,
|
|
96
|
+
[HTTPDefinition.fullName]: httpMock,
|
|
87
97
|
},
|
|
88
98
|
});
|
|
89
99
|
const contextAppConfig = appConfig ?? getDefaultAppConfig();
|
|
@@ -99,6 +109,7 @@ const setup = (config) => {
|
|
|
99
109
|
mocks: {
|
|
100
110
|
media: mediaMock,
|
|
101
111
|
redis: redisMock,
|
|
112
|
+
http: httpMock,
|
|
102
113
|
},
|
|
103
114
|
};
|
|
104
115
|
return { reqCtx, fixtures, testContext: { config: cfg, appConfig: contextAppConfig } };
|