Skip to content

Openfn compile for unit tests#1443

Draft
mtuchi wants to merge 5 commits into
mainfrom
1424-unit-tests
Draft

Openfn compile for unit tests#1443
mtuchi wants to merge 5 commits into
mainfrom
1424-unit-tests

Conversation

@mtuchi
Copy link
Copy Markdown
Contributor

@mtuchi mtuchi commented Jun 4, 2026

Short Description

Adds openfn compile --test for unit testing job code. Compiles job expressions to standard JavaScript, writing output to tests/ by default.

Fixes #1424

Implementation Details

  • --test flag (packages/cli): writes output to tests/ by default; override with -o <dir> or dirs.tests in openfn.yaml. Supports single-file and project-wide compilation.
  • Strip mode (default with --test): tree-shakes the AST in top-level-operations transformer — only export const/export function declarations and their transitive dependencies are kept. Operation calls, non-exported helpers, export default [], and the injected _defer import are all removed.
  • --no-strip: opt-out flag to keep the full compiled output including operations in export default [...].
  • --watch flag: uses chokidar to watch source files and recompile on change.
  • Skip empty files: In strip mode, steps with no exportable code are skipped — no file is written and a log message is emitted.
  • Stale file cleanup: after each project-wide strip run, step files that were skipped are automatically deleted from tests/ if they exist from a previous run. Only exact step paths (tests/<workflow-id>/<step-id>.js) are touched — user-added files at other paths are never removed.
  • Compiler changes (packages/compiler): top-level-operations transformer extended with collectRefs, buildDeclMap, and collectDeps helpers for the tree-shaking logic.

QA Notes

  # Single file — should write to tests/my-workflow/step.js
  openfnx compile workflows/my-workflow/step.js --test

  # Should print to stdout (unchanged behaviour)
  openfnx compile workflows/my-workflow/step.js

  # Project-wide — writes tests/<workflow>/<step>.js, skips steps with no exports
  openfnx compile --test

  # No-strip — writes full compiled output including operations
  openfnx compile --test --no-strip

  # Watch mode — recompiles on file change, Ctrl+C to stop
  openfnx compile --test --watch

  # Stale cleanup — run with --no-strip first, then without; files with no
  # exports should be removed from tests/ on the second run
  openfnx compile --test --no-strip
  openfnx compile --test 

Verify openfnx compile --help shows --test, --no-strip, and --watch with correct descriptions and examples.

AI Usage

Please disclose whether you've used AI anywhere in this PR (it's cool, we just
want to know!):

  • I have used Claude Code
  • I have used another model
  • I have not used AI

You can read more details in our
Responsible AI Policy

Release branch checklist

Delete this section if this is not a release PR.

If this IS a release branch:

  • Run pnpm changeset version from root to bump versions
  • Run pnpm install
  • Commit the new version numbers
  • Run pnpm changeset tag to generate tags
  • Push tags git push --tags

Tags may need updating if commits come in after the tags are first generated.

mtuchi and others added 5 commits June 4, 2026 18:01
- Add --test flag: compiles job expressions for unit testing, writing
  output to tests/ by default (reads dirs.tests from openfn.yaml)
- Add --strip (default on with --test): tree-shakes compiled output,
  keeping only export const/function declarations and their transitive
  dependencies; use --no-strip to keep all compiled code
- Add --watch flag: watches source files and recompiles on change
  (uses chokidar)
- Strip mode removes injected _defer import when operations are stripped
- Skip writing files with no exportable code after stripping; log when
  skipping
- Auto-clean stale step files in tests/ that were skipped in the current
  run without touching user-added files at other paths
- Fix --test --no-strip skipping pure-operation jobs (hasExportableCode
  guard now only applies when strip is active)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- remove export default [] from strip mode output (not needed for unit testing)
- add --no-strip flag to keep full compiled output including operations
- remove --strip standalone flag (stripping is always on with --test by default)
- auto-derive output path for single-file --test using tests/ dir
- skip writing files with no exportable code in strip mode
- auto-clean stale step files in tests/ after project-wide strip runs
- fix --test --no-strip skipping pure-operation jobs
- update help examples and option descriptions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-project-automation github-project-automation Bot moved this to New Issues in Core Jun 4, 2026
@josephjclark
Copy link
Copy Markdown
Collaborator

@mtuchi I'm not liking the --tests argument. What we really want here is just to easily compile some or all of a project to disk. Stripping the operations is an optional step. As mentioned in the issue I'd call that compile --exports-only.

When you do openfn compile workflow.json today, it'll compile that workflow and print the result to stdout.

When you do openfn compile my-workflow, what will happen? It should lookup the workflow called my-workflow in the project, compile that, and print it to stdout. It doesn't, but that would be consistent.

When you do openfn compile it should compile the whole project. It can't print that to stdout because it'll compiling multiple files. But it can compile to dist and write all the files there. That is what I expect the default behaviour to be.

I'd also suggest that openfn compile my-workflow should compile to disk by default (the user can pass -O to write to stdout). That's a little inconsistent with openfn compile workflow.yaml but it IS consistent with compiling through the project. So I'm OK with it. Maybe later, in CLI 2.0, we'll always compile to disk for consistency. But since this stuff is very rarely used I wouldn't worry too much.

So drop the --tests flag please and just make openfn compile compile a project to a folder on disk.

wrap: boolean; // TODO
wrap?: boolean; // TODO
// Strip operations instead of moving them into the export array (for test compilation)
strip?: boolean;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sold that this is the correct implementation

This transformer's one job is to identify operations in the code.

What we need to add here is a different transformer which strips all non-exported lines from code. It's a totally unrelated thing really (OK, as it goes, all operations would be removed - but that's fine). The compiler is simply looking for export statements and removing everything else. The logic would be a lot simpler.

So this would be new transformer which runs probably before all the others

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New Issues

Development

Successfully merging this pull request may close these issues.

Compile a project for unit tests

3 participants