All files / core/blong-gogo/src chain.ts

93.93% Statements 93/99
80% Branches 8/10
66.66% Functions 2/3
93.93% Lines 93/99

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 1001x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 182x 182x 39x 39x 39x 39x 39x 39x 39x 39x 39x       39x 39x 39x 39x 39x 39x 174x 165x 165x 174x 39x       39x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 13x 13x 13x 13x 13x 39x 13x  
import {TestExecutor, type ITestLogger} from '@feasibleone/blong-chain';
import {withProgress} from '@feasibleone/blong-lib';
import assert from 'node:assert';
 
type Step = (a: typeof assert, results: object) => object | Promise<object>;
type Steps = (Promise<(Step | Step[]) & {name: string}>[] | Step[]) & {
    name: string;
    autoSnapshot?: boolean;
    mask?: string[];
};
interface ITestContext {
    test: (name: string, fn: (t: unknown) => void | Promise<void>) => unknown;
}
 
const runSteps =
    (
        steps: Steps,
        log?: ITestLogger,
        results = {$meta: {}},
    ): ((t: ITestContext) => Promise<void>) =>
    async (t: ITestContext) => {
        // Use new parallel TestExecutor for improved performance
        const executor = new TestExecutor({
            concurrency: 10,
            log,
            autoSnapshot: (steps as Steps).autoSnapshot,
            mask: (steps as Steps).mask,
        });
 
        // Resolve any promises in steps array
        const resolvedSteps: (Step | Step[])[] = [];
        for (const stepPromise of steps) {
            resolvedSteps.push(await stepPromise);
        }
 
        // Execute with parallel executor, passing test context for nested output
        try {
            await withProgress(
                log,
                `run ${steps.name}`,
                executor.execute(resolvedSteps, results.$meta || {}, t),
                {
                    getProgress: () => {
                        const progress = executor.getProgress();
                        return {done: progress.completedSteps, total: progress.totalSteps};
                    },
                },
            );
 
            // Copy results from executor context to results object
            const progress = executor.getProgress();
            for (const [name, stepProgress] of progress.steps) {
                if (stepProgress.result !== undefined) {
                    (results as Record<string, unknown>)[name] = stepProgress.result;
                }
            }
        } catch (error) {
            // Preserve error with context
            throw error;
        }
    };
 
// const runStepsSerial =
//     (
//         steps: Steps,
//         results = {$meta: {}} as Record<string, unknown>,
//     ): ((t: ITestContext) => Promise<void>) =>
//     async (t: ITestContext) => {
//         for (const [index, stepPromise] of steps.entries()) {
//             const step = await stepPromise;
//             if (Array.isArray(step))
//                 t.test(
//                     step.name || `step ${index + 1}`,
//                     runStepsSerial(step, results) as (t: unknown) => void | Promise<void>,
//                 );
//             else if (typeof step === 'function') {
//                 const name = step.name;
//                 if (name) {
//                     await t.test(name, async () => {
//                         const result = await step(assert, results);
//                         if (results) (results as Record<string, unknown>)[name] = result;
//                     });
//                 } else {
//                     await t.test(`step ${index + 1}`, async () => {
//                         await step(assert, results);
//                     });
//                 }
//             }
//         }
//     };
 
export default async (
    test: ITestContext,
    log?: ITestLogger,
): Promise<(steps: Steps) => unknown> => {
    const context = test || (await import('node:test')).default;
    return steps =>
        context.test(steps.name, runSteps(steps, log) as (t: unknown) => void | Promise<void>);
};