Move this.stopper guard to top of run() before resetting isAborted.
This ensures an in-flight execution's abort flag cannot be accidentally
cleared if run() is invoked while the interpreter is already active.
Move isAborted flag reset from cleanup() to run() so that in-flight
crawl loops see the abort flag during teardown and exit cleanly,
preventing CPU/RAM leaks from timed-out runs.
Previously, cleanup() reset isAborted = false during teardown, which
accidentally un-aborted active async crawl loops. The loops would then
continue running against a closed Playwright browser context, consuming
CPU/RAM and flooding server logs with errors.
Now, isAborted is only reset at the start of a new run() call, which is
the only time it should be cleared. This covers all three timeout
triggers: task-runner, scheduler, and API record handler.
Refs: #1183
Per maintainer review (RohitR311 on #1138): the repo has no existing
test infra or CI to run tests, so introducing jest here is out of
scope. Removes jest configs, test files, tsconfig.test.json, the
test:server script, and jest/ts-jest/@types/jest/jest-environment-jsdom
dependencies from both maxun-core and server.
output-validation.ts stays - it's a real production module (not test
code) extracted to fix the duplicated isPartial bug CodeRabbit flagged;
only its test file is dropped.
Discovered while actually building maxun-core to verify the fix end-to-end:
running `npm run build` compiled with type errors (test files pulled into
the production tsconfig with no jest types, plus a pre-existing implicit-any
in concurrency.ts) and still silently emitted output anyway. Exclude
src/__tests__ from the shipped build and fix the implicit-any so `npm run
build` is actually clean, not just non-fatal.
maxun-core had no test infra at all (jest was declared in package.json
but never installed, no config, no test files). Add jest/ts-jest and a
jsdom-backed mock Page, and drive the real Interpreter through crawl
and search-scrape workflows to prove serializableCallback fires once
per page with a strictly growing snapshot - not once at the end - and
that a mid-run failure or abort still leaves prior pages recorded.
The crawl and search-scrape actions accumulated every visited page into
a local array and only handed it to the persistence callback once,
after the whole page-by-page loop finished. If the run was killed,
timed out, or errored mid-loop, everything scraped so far was lost
even though it had already been extracted.
Persist the running snapshot after every page (success or failure),
matching the pattern scrapeList pagination already uses. Also stop the
search scrape loop promptly on abort, matching crawl's existing check.
- validate formats in PUT /runs/:id before persisting, so a malformed
value can't reach the interpreter and break formats.includes(...)
- re-throw on failed search-result navigation so it records an error
entry instead of scraping/screenshotting the stale page (matches the
crawl loop's behavior)
- correct stale getNavigationWaitStrategy JSDoc (networkidle is driven
by visualRenderRequired, not screenshot formats)
- fix duplicated phrase in processRobotOutputFormats JSDoc