@devvit/test 0.12.6-next-2025-12-08-21-42-15-9f008f8f0.0 → 0.12.6-next-2025-12-09-15-11-17-96a26acd9.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devvit/test",
3
- "version": "0.12.6-next-2025-12-08-21-42-15-9f008f8f0.0",
3
+ "version": "0.12.6-next-2025-12-09-15-11-17-96a26acd9.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-08-21-42-15-9f008f8f0.0",
39
- "@devvit/protos": "0.12.6-next-2025-12-08-21-42-15-9f008f8f0.0",
40
- "@devvit/redis": "0.12.6-next-2025-12-08-21-42-15-9f008f8f0.0",
41
- "@devvit/server": "0.12.6-next-2025-12-08-21-42-15-9f008f8f0.0",
42
- "@devvit/shared-types": "0.12.6-next-2025-12-08-21-42-15-9f008f8f0.0",
38
+ "@devvit/media": "0.12.6-next-2025-12-09-15-11-17-96a26acd9.0",
39
+ "@devvit/protos": "0.12.6-next-2025-12-09-15-11-17-96a26acd9.0",
40
+ "@devvit/redis": "0.12.6-next-2025-12-09-15-11-17-96a26acd9.0",
41
+ "@devvit/server": "0.12.6-next-2025-12-09-15-11-17-96a26acd9.0",
42
+ "@devvit/shared-types": "0.12.6-next-2025-12-09-15-11-17-96a26acd9.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-08-21-42-15-9f008f8f0.0",
51
- "@devvit/tsconfig": "0.12.6-next-2025-12-08-21-42-15-9f008f8f0.0",
50
+ "@devvit/repo-tools": "0.12.6-next-2025-12-09-15-11-17-96a26acd9.0",
51
+ "@devvit/tsconfig": "0.12.6-next-2025-12-09-15-11-17-96a26acd9.0",
52
52
  "eslint": "9.11.1",
53
53
  "typescript": "5.8.3",
54
54
  "vitest": "1.6.1"
55
55
  },
56
- "gitHead": "08c324a099f152eff57673696385bc9c00940172"
56
+ "gitHead": "0648a19e71928872d54b79a960ba797ae646f7a7"
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;AAG/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;AAOpD,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;KAClB,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;AAmIF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAQ,gBAAqB,KAAG,OAAO,CAAC,cAAc,CAEtF,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
- await fixtures.mocks.redis.clear();
31
- // Heuristic to detect Vitest TestContext
32
- // Standard test() calls receive a single TestContext object.
33
- // test.each() calls receive the parameters as arguments.
34
- const isTestContext = fnArgs.length === 1 &&
35
- fnArgs[0] &&
36
- (typeof fnArgs[0] === 'object' || typeof fnArgs[0] === 'function') &&
37
- 'task' in fnArgs[0] &&
38
- // Vitest context usually has these lifecycle methods
39
- 'onTestFailed' in fnArgs[0];
40
- if (isTestContext) {
41
- const mergedCtx = { ...fixtures, ...fnArgs[0] };
42
- return runWithContext(reqCtx, () => runWithTestContext(testContext, () => userFn(mergedCtx)));
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 } };