import { tap, expect } from '@push.rocks/tapbundle'; import { AsyncContext } from '../ts/logcontext.classes.asynccontext.js'; import { AsyncStore } from '../ts/logcontext.classes.asyncstore.js'; process.env.DEBUG = 'true'; /** * This test file demonstrates how to use the AsyncContext and ensures * that runScoped() properly creates child AsyncStore contexts and merges parent data. */ const asyncContext = new AsyncContext(); tap.test('should run a scoped function and add data to a child store', async () => { // add some default data to the parent store asyncContext.store.add('parentKey', 'parentValue'); expect(asyncContext.store.get('parentKey')).toEqual('parentValue'); // now run a child scope, add some data, and check that parent's data is still accessible await asyncContext.runScoped(async () => { asyncContext.store.add('childKey', 'childValue'); // child should see its own data expect(asyncContext.store.get('childKey')).toEqual('childValue'); // child should also see parent data expect(asyncContext.store.get('parentKey')).toEqual('parentValue'); }); }); tap.test('should not contaminate the parent store with child-only data', async () => { // create a new child scope await asyncContext.runScoped(async () => { asyncContext.store.add('temporaryKey', 'temporaryValue'); expect(asyncContext.store.get('temporaryKey')).toEqual('temporaryValue'); }); // after the child scope finishes, 'temporaryKey' should not exist in the parent expect(asyncContext.store.get('temporaryKey')).toBeUndefined(); }); tap.test('should allow adding data in multiple scopes independently', async (toolsArg) => { const done = toolsArg.cumulativeDefer(); // add data in first scope asyncContext.runScoped(async () => { const subDone = done.subDefer(); asyncContext.store.add('childKey1', 'childValue1-v1'); await toolsArg.delayFor(2000); expect(asyncContext.store.get('childKey1')).toEqual('childValue1-v1'); subDone.resolve(); }); asyncContext.runScoped(async () => { const subDone = done.subDefer(); asyncContext.store.add('childKey1', 'childValue1-v2'); await toolsArg.delayFor(1000); expect(asyncContext.store.get('childKey1')).toEqual('childValue1-v2'); subDone.resolve(); }); // add data in second scope asyncContext.runScoped(async () => { asyncContext.store.add('childKey2', 'childValue2'); expect(asyncContext.store.get('childKey2')).toEqual('childValue2'); }); // neither childKey1 nor childKey2 should exist in the parent store expect(asyncContext.store.get('childKey1')).toBeUndefined(); expect(asyncContext.store.get('childKey2')).toBeUndefined(); await done.promise; }); tap.test( 'should allow deleting data in a child store without removing it from the parent store', async (toolsArg) => { // ensure parent has some data asyncContext.store.add('deletableKey', 'iShouldStayInParent'); await asyncContext.runScoped(async () => { // child sees the parent's data expect(asyncContext.store.get('deletableKey')).toEqual('iShouldStayInParent'); // attempt to delete it in the child asyncContext.store.delete('deletableKey'); // child no longer sees it expect(asyncContext.store.get('deletableKey')).toBeUndefined(); // but parent still has it }); expect(asyncContext.store.get('deletableKey')).toEqual('iShouldStayInParent'); } ); tap.test('should allow multiple child scopes to share the same parent store data', async () => { // add a key to the parent store asyncContext.store.add('sharedKey', 'sharedValue'); expect(asyncContext.store.get('sharedKey')).toEqual('sharedValue'); // first child scope await asyncContext.runScoped(async () => { expect(asyncContext.store.get('sharedKey')).toEqual('sharedValue'); }); // second child scope await asyncContext.runScoped(async () => { expect(asyncContext.store.get('sharedKey')).toEqual('sharedValue'); }); }); export default tap.start();