Skip to content

Add a smoke test to generated fedify init apps - #990

Open
Palcimer wants to merge 4 commits into
fedify-dev:mainfrom
Palcimer:issue-898-add-a-smoke-test-to-fedify-init
Open

Add a smoke test to generated fedify init apps#990
Palcimer wants to merge 4 commits into
fedify-dev:mainfrom
Palcimer:issue-898-add-a-smoke-test-to-fedify-init

Conversation

@Palcimer

@Palcimer Palcimer commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

fedify init creates runnable apps, but a generated project has no standard way to check that it actually serves an actor object. Confirming it means starting the dev server by hand and looking an actor up separately, which is awkward for new users and gives contributors no quick way to validate scaffold changes.
This adds a test task to every scaffolded project. The task runs a generated scripts/smokeTest.ts that starts the app, reads the port the server actually bound from its output, waits for it to answer, and resolves the local actor with lookupObject(). On success, it prints the resolved actor. On failure, it prints the server's stdout and stderr output and exits the process with a failure code.

Assisted-by: Claude Code:claude-sonnet-5

Related issue

Changes

  • Added a required testFile property to the WebFrameworkInitializer interface, holding the path the smoke-test script is written to.
  • Added a template for the generated smoke-test script under templates/defaults, shared by every framework.
  • Added loadTest(), which reads that template and bakes in the dev command for the chosen package manager.
  • Added tsx as a dev dependency to generated apps whose package manager runs on Node.js, so that they can launch the smoke test.
  • Added a test task that starts the smoke test to the generated apps.
  • Updated the tests for patchFiles() to verify that fedify init writes the smoke-test script.

Benefits

  • Users can quickly verify that a newly generated app is running correctly and exposing an actor as expected.

Checklist

  • Did you add a changelog entry to the CHANGES.md?
  • [] Did you write some relevant docs about this change (if it's a new feature)?
  • [] Did you write a regression test to reproduce the bug (if it's a bug fix)?
  • Did you write some tests for this change (if it's a new feature)?
  • Did you run mise test on your machine?

Scaffolded projects had no quick way to confirm that their federation
setup actually serves an actor.  Verifying it meant starting the dev
server by hand and looking an actor up separately.

Added a smoke-test script that starts the dev server, reads the port,
waits for the server to answer, and looks an actor up with
`lookupObject()`.

fedify-dev#898

Assisted-by: Claude Code:claude-sonnet-5
Every framework now writes the smoke-test script and exposes it as a
`test` task, so a scaffolded project can be verified with one command.

The task runs the script with the runtime matching the package manager,
and Node.js projects gain `tsx` as a dev dependency to execute it.

fedify-dev#898

Assisted-by: Claude Code:claude-sonnet-5
Added a test covering that `patchFiles()` writes the script to the
initializer's `testFile` path with the dev command baked in, and filled
in `testFile` in the existing fixtures now that it is required.

fedify-dev#898

Assisted-by: Claude Code:claude-sonnet-5
@netlify

netlify Bot commented Aug 9, 2026

Copy link
Copy Markdown

Deploy Preview for fedify-json-schema canceled.

Name Link
🔨 Latest commit 27a7063
🔍 Latest deploy log https://app.netlify.com/projects/fedify-json-schema/deploys/6a786ed9c4d3560008f3f782

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

fedify init now generates a test task and scripts/smokeTest.ts. The script starts the app, waits for readiness, resolves the local actor, reports failures, and cleans up. Framework configurations provide runtime-specific commands and Node dependencies.

Changes

Generated smoke-test task

Layer / File(s) Summary
Framework task configuration
packages/init/src/types.ts, packages/init/src/webframeworks/*
Framework initializers now define scripts/smokeTest.ts, runtime-specific test tasks, and required Node test dependencies.
Smoke-test template generation
packages/init/src/action/templates.ts, packages/init/src/action/patch.ts
The initializer loads the smoke-test template, injects the package-manager-specific development command, generates the file, and checks for conflicts.
Smoke-test runtime flow
packages/init/src/templates/defaults/smokeTest.ts.tpl
The generated script starts the server, detects its port, polls readiness, validates the local actor, reports errors, and terminates the server.
Generation validation and documentation
packages/init/src/action/configs.test.ts, packages/init/src/action/patch.test.ts, CHANGES.md, changes.d/init/smoke-test.md
Tests verify smoke-test file generation and command substitution. Changelog entries document the new task and reference issue 898.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SmokeTest as Generated smokeTest.ts
  participant DevServer as Development server
  participant ActivityPub as ActivityPub endpoint
  participant Loader as Document loader
  SmokeTest->>DevServer: Spawn development command
  DevServer-->>SmokeTest: Emit listening URL
  SmokeTest->>ActivityPub: Poll readiness endpoint
  ActivityPub-->>SmokeTest: Return ActivityPub JSON
  SmokeTest->>Loader: Resolve configured actor
  Loader-->>SmokeTest: Return actor document
  SmokeTest->>DevServer: Terminate process group
Loading

Possibly related PRs

Suggested labels: component/cli, component/testing, component/tasks

Suggested reviewers: 2chanhaeng, dahlia

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: adding a smoke test to applications generated by fedify init.
Description check ✅ Passed The description explains the smoke-test workflow, generated files, task changes, dependencies, tests, and related issue.
Linked Issues check ✅ Passed The changes implement issue #898 by adding local actor smoke tests, package-manager-specific tasks, framework configuration, dependencies, and generation tests.
Out of Scope Changes check ✅ Passed The changes remain focused on generating and testing the smoke-test task for fedify init applications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/init/src/action/patch.test.ts`:
- Around line 95-105: Add coverage for the Deno branch of patchFiles by creating
init data with packageManager set to "deno", reading the generated smokeTest.ts,
and asserting it contains the expected Deno command substitution. Keep the
existing npm smoke-test coverage unchanged.

In `@packages/init/src/action/templates.ts`:
- Around line 60-70: Remove the JSDoc block immediately above the internal
loadTest helper in templates.ts, leaving the loadTest implementation unchanged.

In `@packages/init/src/templates/defaults/smokeTest.ts.tpl`:
- Around line 69-80: Update the onData handler to accumulate decoded server
output across chunks before applying portPatterns, so port values split between
chunks are matched correctly. Preserve the existing port parsing, timeout
cleanup, resolve behavior, and return once a match is found.
- Around line 115-118: Update checkActor to accept or obtain the startup abort
signal used by waitForServer, and pass that signal in the lookupObject options
so actor resolution is bounded by the same 1000ms timeout. Preserve the existing
documentLoader configuration.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7c0cfeac-c825-4dfd-bde1-4900b109e4d3

📥 Commits

Reviewing files that changed from the base of the PR and between 15ad151 and 27a7063.

📒 Files selected for processing (19)
  • CHANGES.md
  • changes.d/init/smoke-test.md
  • packages/init/src/action/configs.test.ts
  • packages/init/src/action/patch.test.ts
  • packages/init/src/action/patch.ts
  • packages/init/src/action/templates.ts
  • packages/init/src/templates/defaults/smokeTest.ts.tpl
  • packages/init/src/types.ts
  • packages/init/src/webframeworks/astro.ts
  • packages/init/src/webframeworks/bare-bones.ts
  • packages/init/src/webframeworks/elysia.ts
  • packages/init/src/webframeworks/express.ts
  • packages/init/src/webframeworks/hono.ts
  • packages/init/src/webframeworks/next.ts
  • packages/init/src/webframeworks/nitro.ts
  • packages/init/src/webframeworks/nuxt.ts
  • packages/init/src/webframeworks/solidstart.ts
  • packages/init/src/webframeworks/sveltekit.ts
  • packages/init/src/webframeworks/utils.ts

Comment on lines +95 to +105
test("patchFiles writes the smoke-test script", async () => {
await withTempDir(async (dir) => {
await patchFiles(createInitData(dir, false));

const testScript = await readFile(
join(dir, "scripts", "smokeTest.ts"),
"utf8",
);
assert.match(testScript, /\["npm","run","dev"\]/);
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Expect tests for Deno and Node.js or Bun smoke-test generation.
rg -n -C 4 \
  'smokeTest|packageManager: "(deno|bun|npm|pnpm|yarn)"|test task|run.*dev' \
  packages/init/src --glob '*.test.ts'

Repository: fedify-dev/fedify

Length of output: 15893


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Relevant patch.test.ts slices:"
sed -n '1,150p' packages/init/src/action/patch.test.ts

echo
echo "Tests mentioning smokeTest/runs/patchFiles/packageManager deno:"
rg -n -C 3 --glob '*.test.ts' \
  'smokeTest|patchFiles|packageManager:\s*"?deno"?"|packageManager:\s*"?bun"?"|packageManager:\s*"?npm"?"|run.*dev|test task|tasks:\s*' packages/init/src/action packages/init/src/action/patch.test.ts

Repository: fedify-dev/fedify

Length of output: 25321


Add smoke-test command coverage for Deno.

patchFiles has one smoke-test case that checks ["npm","run","dev"], but no case uses packageManager: "deno" or checks the Deno command. Add a Deno case, or ensure another patch test covers smokeTest.ts command substitution for Deno.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/init/src/action/patch.test.ts` around lines 95 - 105, Add coverage
for the Deno branch of patchFiles by creating init data with packageManager set
to "deno", reading the generated smokeTest.ts, and asserting it contains the
expected Deno command substitution. Keep the existing npm smoke-test coverage
unchanged.

Comment on lines +60 to +70
/**
* Loads the smoke-test script content for the initializer.
*
* Every framework shares the same *defaults/smokeTest.ts* template, so unlike
* {@link loadLogging} there is no per-framework template override. The
* template spawns the project's own dev server, so it needs the dev command
* for the chosen package manager baked in at generation time.
*
* @param param0 - {@link InitCommandData} containing `packageManager`
* @returns The complete smoke-test script content as a string
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the JSDoc from loadTest.

loadTest is an internal helper in the initializer action layer. Keep the implementation comment-free unless it becomes part of the package entry-point API.

Based on learnings, internal helpers that are not re-exported from a package entry point should not have JSDoc.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/init/src/action/templates.ts` around lines 60 - 70, Remove the JSDoc
block immediately above the internal loadTest helper in templates.ts, leaving
the loadTest implementation unchanged.

Source: Learnings

Comment on lines +69 to +80
const onData = (chunk: Buffer) => {
const text = chunk.toString("utf8");
for (const pattern of portPatterns) {
const match = text.match(pattern);
if (match && match[1]) {
const port = Number.parseInt(match[1], 10);
clearTimeout(timeout);
resolve(port);
return;
}
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Buffer server output before matching the port.

data chunks do not preserve line boundaries. If a server writes http://localhost:5173 across two chunks, none of these patterns match and the smoke test fails after 15 seconds although the server is ready.

Proposed fix
+    let portOutput = "";
     const onData = (chunk: Buffer) => {
-      const text = chunk.toString("utf8");
+      portOutput += chunk.toString("utf8");
       for (const pattern of portPatterns) {
-        const match = text.match(pattern);
+        const match = portOutput.match(pattern);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const onData = (chunk: Buffer) => {
const text = chunk.toString("utf8");
for (const pattern of portPatterns) {
const match = text.match(pattern);
if (match && match[1]) {
const port = Number.parseInt(match[1], 10);
clearTimeout(timeout);
resolve(port);
return;
}
}
};
let portOutput = "";
const onData = (chunk: Buffer) => {
portOutput += chunk.toString("utf8");
for (const pattern of portPatterns) {
const match = portOutput.match(pattern);
if (match && match[1]) {
const port = Number.parseInt(match[1], 10);
clearTimeout(timeout);
resolve(port);
return;
}
}
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/init/src/templates/defaults/smokeTest.ts.tpl` around lines 69 - 80,
Update the onData handler to accumulate decoded server output across chunks
before applying portPatterns, so port values split between chunks are matched
correctly. Preserve the existing port parsing, timeout cleanup, resolve
behavior, and return once a match is found.

Comment on lines +115 to +118
async function checkActor(url: string): Promise<Actor> {
const object = await lookupObject(url, {
documentLoader: getDocumentLoader({ allowPrivateAddress: true }),
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the local Fedify implementation for timeout or abort support.
rg -n -C 5 --glob '*.ts' \
  'lookupObject|function getDocumentLoader|const getDocumentLoader' .

Repository: fedify-dev/fedify

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== template excerpt =="
sed -n '80,140p' packages/init/src/templates/defaults/smokeTest.ts.tpl

echo
echo "== lookup API excerpt =="
sed -n '90,285p' packages/vocab/src/lookup.ts

echo
echo "== all lookupObject calls in smoke template =="
rg -n "lookupObject|signal|AbortController|setTimeout|checkActor|test\\(" packages/init/src/templates/defaults/smokeTest.ts.tpl

Repository: fedify-dev/fedify

Length of output: 8802


Apply the startup timeout to actor resolution.

waitForServer() uses AbortSignal.timeout(1000), but checkActor() calls lookupObject() without passing any signal. Actor retrieval can still hang after readiness succeeds; pass the same abortable request signal to lookupObject().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/init/src/templates/defaults/smokeTest.ts.tpl` around lines 115 -
118, Update checkActor to accept or obtain the startup abort signal used by
waitForServer, and pass that signal in the lookupObject options so actor
resolution is bounded by the same 1000ms timeout. Preserve the existing
documentLoader configuration.

@codecov

codecov Bot commented Aug 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.48485% with 2 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/init/src/webframeworks/sveltekit.ts 83.33% 1 Missing and 1 partial ⚠️
Files with missing lines Coverage Δ
packages/init/src/action/patch.ts 93.08% <100.00%> (+0.23%) ⬆️
packages/init/src/action/templates.ts 95.08% <100.00%> (+0.63%) ⬆️
packages/init/src/webframeworks/astro.ts 100.00% <100.00%> (ø)
packages/init/src/webframeworks/bare-bones.ts 100.00% <100.00%> (ø)
packages/init/src/webframeworks/elysia.ts 87.50% <100.00%> (+1.42%) ⬆️
packages/init/src/webframeworks/express.ts 97.26% <100.00%> (+0.38%) ⬆️
packages/init/src/webframeworks/hono.ts 87.91% <100.00%> (+1.32%) ⬆️
packages/init/src/webframeworks/next.ts 85.48% <100.00%> (+1.84%) ⬆️
packages/init/src/webframeworks/nitro.ts 86.66% <100.00%> (+1.48%) ⬆️
packages/init/src/webframeworks/nuxt.ts 85.52% <100.00%> (+1.46%) ⬆️
... and 3 more

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a smoke-test task to generated fedify init apps

1 participant