(data: TT.Tutorial, callbacks: Callbacks)
| 26 | } |
| 27 | |
| 28 | const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks): ((params: any) => Promise<void>) => { |
| 29 | const testRunnerConfig = data.config.testRunner |
| 30 | const testRunnerFilterArg = testRunnerConfig.args?.filter |
| 31 | return async ({ position, onSuccess }: TestRunnerParams): Promise<any> => { |
| 32 | const startTime = throttle() |
| 33 | // throttle time early |
| 34 | if (!startTime) { |
| 35 | return |
| 36 | } |
| 37 | |
| 38 | logger('------------------- RUN TEST -------------------') |
| 39 | |
| 40 | // calculate level & step from position |
| 41 | const level: TT.Level | null = data.levels.find((l) => l.id === position.levelId) || null |
| 42 | if (!level) { |
| 43 | logger(`Error: Level "${position.levelId}" not found`) |
| 44 | return |
| 45 | } |
| 46 | const step: TT.Step | null = level.steps.find((s) => s.id === position.stepId) || null |
| 47 | if (!step) { |
| 48 | logger(`Error: Step "${position.stepId}" not found`) |
| 49 | return |
| 50 | } |
| 51 | |
| 52 | callbacks.onRun(position) |
| 53 | |
| 54 | let result: { stdout: string | undefined; stderr: string | undefined } |
| 55 | try { |
| 56 | let command = testRunnerConfig.args |
| 57 | ? `${testRunnerConfig.command} ${testRunnerConfig?.args.tap}` |
| 58 | : testRunnerConfig.command // TODO: enforce TAP |
| 59 | |
| 60 | // filter tests if requested |
| 61 | if (testRunnerFilterArg) { |
| 62 | // get tutorial step from position |
| 63 | // check the step actions for specific command |
| 64 | // NOTE: cannot just pass in step actions as the test can be called by: |
| 65 | // - onEditorSave, onWatcher, onSolution, runTest, onSubTask |
| 66 | const levels = data.levels |
| 67 | const level = levels.find((l) => l.id === position.levelId) |
| 68 | const step = level?.steps.find((s) => s.id === position.stepId) |
| 69 | const testFilter = step?.setup?.filter |
| 70 | if (testFilter) { |
| 71 | // append filter commands |
| 72 | command = [command, testRunnerFilterArg, testFilter].join(' ') |
| 73 | } |
| 74 | } |
| 75 | logger(`COMMAND: ${command}`) |
| 76 | result = await exec({ command, dir: testRunnerConfig.directory }) |
| 77 | } catch (err: any) { |
| 78 | result = { stdout: err.stdout, stderr: err.stack } |
| 79 | } |
| 80 | |
| 81 | // ignore output if not latest process |
| 82 | // this is a crappy version of debounce |
| 83 | if (!debounce(startTime)) { |
| 84 | return |
| 85 | } |
no test coverage detected