@@ -20,137 +20,6 @@ import AppService from './AppService';
2020
2121import { describe , expect , it } from 'vitest' ;
2222
23- /*
24- // CRITICAL: Mock BOTH Context modules (CommonJS and ESM) BEFORE any other imports
25- // CommonJS modules use '../../util/context', ESM modules use '../../util/esmcontext.js'
26- vi.mock('../../util/context', async () => {
27- const actual = await vi.importActual('../../util/context');
28- const { Context: OriginalContext } = actual;
29-
30- // Store original get method BEFORE patching
31- const originalGet = OriginalContext.get;
32-
33- // Store test values
34- let testContext = null;
35- let testActor = null;
36- let testUser = null;
37-
38- // Patch Context.get to use test values
39- OriginalContext.get = function(key, options) {
40- // Check test values FIRST
41- if (key === 'actor' && testActor) {
42- return testActor;
43- }
44- if (key === 'user' && testUser) {
45- return testUser;
46- }
47-
48- // Call original get method
49- return originalGet.call(this, key, options);
50- };
51-
52- // Export patched Context with setters for test values
53- return {
54- ...actual,
55- Context: OriginalContext,
56- __setTestValues: (ctx, actor, user) => {
57- testContext = ctx;
58- testActor = actor;
59- testUser = user;
60- },
61- __clearTestValues: () => {
62- testContext = null;
63- testActor = null;
64- testUser = null;
65- },
66- };
67- });
68-
69- vi.mock('../../util/esmcontext.js', async () => {
70- const actual = await vi.importActual('../../util/esmcontext.js');
71- const { Context: OriginalContext } = actual;
72-
73- // Store original get method BEFORE patching
74- const originalGet = OriginalContext.get;
75-
76- // Store test values
77- let testContext = null;
78- let testActor = null;
79- let testUser = null;
80-
81- // Patch Context.get to use test values
82- OriginalContext.get = function(key, options) {
83- // Check test values FIRST
84- if (key === 'actor' && testActor) {
85- return testActor;
86- }
87- if (key === 'user' && testUser) {
88- return testUser;
89- }
90-
91- // Call original get method
92- return originalGet.call(this, key, options);
93- };
94-
95- // Export patched Context with setters for test values
96- return {
97- ...actual,
98- Context: OriginalContext,
99- __setTestValues: (ctx, actor, user) => {
100- testContext = ctx;
101- testActor = actor;
102- testUser = user;
103- },
104- __clearTestValues: () => {
105- testContext = null;
106- testActor = null;
107- testUser = null;
108- },
109- };
110- });
111-
112- // Store test values globally - this is the most reliable approach
113- let globalTestActor = null;
114- let globalTestUser = null;
115-
116- // Patch Context.get directly (after imports) - this MUST work
117- // We patch it on the actual Context class that's imported
118- const originalContextGet = Context.get;
119- Context.get = function(key, options) {
120- // ALWAYS check global test values FIRST - this is the most reliable
121- if (key === 'actor' && globalTestActor) {
122- return globalTestActor;
123- }
124- if (key === 'user' && globalTestUser) {
125- return globalTestUser;
126- }
127- // Call original
128- return originalContextGet.call(this, key, options);
129- };
130-
131- // Also patch the Context class that CommonJS modules might have cached
132- // Intercept require() calls to context.js and ensure they get our patched version
133- const Module = require('module');
134- const originalRequire = Module.prototype.require;
135- Module.prototype.require = function(id) {
136- const result = originalRequire.call(this, id);
137- // If this is context.js, patch its Context.get
138- if (id.includes('util/context') && result && result.Context) {
139- const originalGet = result.Context.get;
140- result.Context.get = function(key, options) {
141- if (key === 'actor' && globalTestActor) {
142- return globalTestActor;
143- }
144- if (key === 'user' && globalTestUser) {
145- return globalTestUser;
146- }
147- return originalGet.call(this, key, options);
148- };
149- }
150- return result;
151- };
152- */
153-
15423const ES_APP_ARGS = {
15524 entity : 'app' ,
15625 upstream : ESBuilder . create ( [
@@ -182,16 +51,15 @@ const ES_APP_ARGS = {
18251 ] ) ,
18352} ;
18453
54+ // Fix: Manually initialize AsyncLocalStorage store for Vitest
55+ // Under Vitest, AsyncLocalStorage may not have a store initialized, causing Context.get() to fail.
56+ // This manually creates a store and sets the root context, ensuring Context operations work.
57+ // This may be a side-effect of OpenTelemetry's own use of AsyncLocalStorage.
18558const fixContextInitialization = async ( callback ) => {
186- process . stdout . write ( `contextAsyncLocalStorage:${ Context . contextAsyncLocalStorage } \n` ) ;
187- try {
188- return Context . contextAsyncLocalStorage . run ( Context . root , ( ) => {
189- Context . contextAsyncLocalStorage . getStore ( ) . set ( 'context' , Context . root ) ;
190- callback ( ) ;
191- } ) ;
192- } catch ( e ) {
193- process . stdout . write ( e . stack ) ;
194- }
59+ return await Context . contextAsyncLocalStorage . run ( Context . root , async ( ) => {
60+ Context . contextAsyncLocalStorage . getStore ( ) . set ( 'context' , Context . root ) ;
61+ return await callback ( ) ;
62+ } ) ;
19563} ;
19664
19765const testWithEachService = async ( fnToRunOnBoth ) => {
@@ -244,8 +112,6 @@ describe('AppService Regression Prevention Tests', () => {
244112 it ( 'should create the app' , async ( ) => {
245113 await fixContextInitialization ( async ( ) => {
246114 await testWithEachService ( async ( { kernel, key } ) => {
247- // Context initialization fix
248-
249115 // Create a test user and context
250116 const db = kernel . services . get ( 'database' ) . get ( 'write' , 'test' ) ;
251117 const userId = 1 ;
@@ -284,38 +150,15 @@ describe('AppService Regression Prevention Tests', () => {
284150
285151 await userContext . arun ( async ( ) => {
286152 Context . set ( 'actor' , actor ) ;
287- // Set test values in BOTH mocked Context modules AND globally
288- // globalTestActor = actor;
289- // globalTestUser = user;
290-
291- const contextCJS = require ( '../../util/context' ) ;
292- const contextESM = await import ( '../../util/esmcontext.js' ) ;
293- if ( contextCJS . __setTestValues ) contextCJS . __setTestValues ( userContext , actor , user ) ;
294- if ( contextESM . __setTestValues ) contextESM . __setTestValues ( userContext , actor , user ) ;
295-
296- process . stdout . write ( `actor: ${ actor } \n` ) ;
297- process . stdout . write ( `context root from test: ${ Context . get ( 'rootContextUUID' ) } \n` ) ;
298-
299- try {
300- const service = kernel . services . get ( key ) ;
301- const crudQ = service . constructor . IMPLEMENTS [ 'crud-q' ] ;
302- await crudQ . create . call ( service , {
303- object : {
304- name : 'test-app' ,
305- title : 'Test App' ,
306- index_url : 'https://example.com' ,
307- } ,
308- } ) ;
309- } finally {
310- // Clear after test
311- // globalTestActor = null;
312- // globalTestUser = null;
313-
314- const contextCJS = require ( '../../util/context' ) ;
315- const contextESM = await import ( '../../util/esmcontext.js' ) ;
316- if ( contextCJS . __clearTestValues ) contextCJS . __clearTestValues ( ) ;
317- if ( contextESM . __clearTestValues ) contextESM . __clearTestValues ( ) ;
318- }
153+ const service = kernel . services . get ( key ) ;
154+ const crudQ = service . constructor . IMPLEMENTS [ 'crud-q' ] ;
155+ await crudQ . create . call ( service , {
156+ object : {
157+ name : 'test-app' ,
158+ title : 'Test App' ,
159+ index_url : 'https://example.com' ,
160+ } ,
161+ } ) ;
319162 } ) ;
320163 } ) ;
321164 } ) ;
0 commit comments