-
Notifications
You must be signed in to change notification settings - Fork 1
β¨ Add auto-mode detection and build lifecycle to Storybook plugin #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Code Review: Auto-Mode Detection & Build LifecycleExcellent work on this PR! The auto-mode detection is a significant UX improvement. Here's my detailed feedback: β Strengths1. Architecture & Design
2. Error Handling
3. Test Coverage
4. Developer Experience
π Issues & Concerns1. Critical: Test Code Duplication (src/index.js:72-91)The Issue: Recommendation: // In tests/concurrency.spec.js
import { mapWithConcurrency } from '../src/index.js'; // Import instead of redefineWhy it matters: If the implementation changes, tests won't catch regressions unless they're testing the actual production code. 2. Performance: Fetch Without Timeout (src/index.js:144-146)The health check fetch call has no timeout, which could hang indefinitely. Current code: let response = await fetch(`http://localhost:${serverInfo.port}/health`);
return response.ok;Recommendation: let controller = new AbortController();
let timeoutId = setTimeout(() => controller.abort(), 2000); // 2s timeout
try {
let response = await fetch(
`http://localhost:${serverInfo.port}/health`,
{ signal: controller.signal }
);
return response.ok;
} catch {
return false;
} finally {
clearTimeout(timeoutId);
}3. Resource Leak: Logger Mutation (src/plugin.js:21-22)Logger level is set to 'info' but never restored to original level. Current code: let originalLevel = logger.level; // Stored but never used
logger.level = 'info';Impact: This could affect subsequent commands in the same process. Recommendation: register(program, { config, logger, services }) {
let originalLevel = logger.level;
program
.command('storybook <path>')
// ... options ...
.action(async (path, options) => {
logger.level = 'info'; // Set before execution
try {
// ... existing code ...
} finally {
logger.level = originalLevel; // Restore in finally block
}
});
}4. Code Smell: Complex Git Detection Logic (src/index.js:222-241)The git utils import logic is overly complex with multiple fallback paths. Concerns:
Recommendation: async function loadGitUtils() {
// Try package first
try {
return await import('@vizzly-testing/cli/dist/utils/git.js');
} catch {}
// Try monorepo relative path
try {
return await import('../../../src/utils/git.js');
} catch {}
return null;
}5. Security: Environment Variable Mutation (src/index.js:284-286)The code mutates Current code: process.env.VIZZLY_SERVER_URL = `http://localhost:${runOptions.port}`;
process.env.VIZZLY_BUILD_ID = buildId;
process.env.VIZZLY_ENABLED = 'true';Concerns:
Recommendation: let envBackup = {
url: process.env.VIZZLY_SERVER_URL,
buildId: process.env.VIZZLY_BUILD_ID,
enabled: process.env.VIZZLY_ENABLED,
};
try {
process.env.VIZZLY_SERVER_URL = `http://localhost:${runOptions.port}`;
// ...
} finally {
// Restore original values
if (envBackup.url !== undefined) process.env.VIZZLY_SERVER_URL = envBackup.url;
else delete process.env.VIZZLY_SERVER_URL;
// ... restore others
}6. Race Condition: Build URL Event (src/index.js:215-220)The Current code: testRunner.once('build-created', buildInfo => {
// ...
});
buildId = await testRunner.createBuild(runOptions, false);Why it's a problem: If Recommendation: // Option 1: Register before calling
testRunner.once('build-created', buildInfo => { /* ... */ });
buildId = await testRunner.createBuild(runOptions, false);
// Option 2: Handle in response
let buildResult = await testRunner.createBuild(runOptions, false);
if (buildResult.url) {
buildUrl = buildResult.url;
logger.info(`π ${buildUrl}`);
}π‘ Minor Suggestions
π§ͺ Test Coverage Gaps
Recommended additions: describe('mode detection', () => {
it('should detect TDD mode when server.json exists', async () => { /* ... */ });
it('should detect Run mode when token is present', async () => { /* ... */ });
it('should warn when neither mode is available', async () => { /* ... */ });
});π Overall AssessmentRating: ββββ (4/5) This is a solid PR that significantly improves the developer experience. The architecture is sound and the feature implementation is mostly clean. However, there are some issues that should be addressed: Must Fix:
Should Fix:
Nice to Have:
π Next Steps
Great work overall! The auto-mode detection will make the Storybook plugin much more intuitive to use. π |
- Add automatic TDD/Run mode detection - Support direct `vizzly storybook` without wrapper command - Display mode indicator (TDD vs Cloud) and build URLs - Clean up log output for better DX - Add test coverage for concurrency control and hooks - Fix logger level override in plugin registration The plugin now automatically detects whether to use TDD server or cloud mode, eliminating the need to wrap commands with `vizzly run`. When VIZZLY_TOKEN is set, it creates builds, manages screenshot server lifecycle, and displays results URLs.
0f6584f to
5c268c9
Compare
## Summary - Add automatic TDD/Run mode detection to Storybook plugin - Enable direct `vizzly storybook` usage without `vizzly run` wrapper - Display mode indicators (π TDD / βοΈ Cloud) and build URLs - Clean up log output for better developer experience - Add comprehensive test coverage for concurrency control and hooks - Fix logger level override in plugin registration ## Changes ### Auto-Mode Detection The plugin now automatically detects whether to use TDD server or cloud mode: 1. **TDD mode** - If `.vizzly/server.json` exists and server responds to health check 2. **Run mode** - If `VIZZLY_TOKEN` environment variable is set 3. **Warning** - If neither is available ### Build Lifecycle Management When in Run mode, the plugin now: - Creates builds via test runner service - Starts screenshot server automatically - Listens for `build-created` event to display build URL - Finalizes builds with execution time and success/failure status - Properly cleans up server on completion or error ### Improved Logging - Override logger level from 'warn' to 'info' for progress visibility - Display mode indicator at start (π TDD / βοΈ Cloud) - Show build URL at start and end of process - Clean, minimal output with emojis for visual clarity - Remove verbose status messages ### Test Coverage Added 15 new tests across 2 test files: - `tests/concurrency.spec.js` - Concurrency control logic (4 tests) - `tests/hooks.spec.js` - Interaction hooks system (11 tests) Total: **67 tests passing** ## Test Plan - [x] Run `vizzly storybook` with TDD server running - shows TDD mode - [x] Run `VIZZLY_TOKEN=xxx vizzly storybook` - shows Run mode with build URL - [x] Run without TDD server or token - shows warning - [x] All 67 tests pass - [x] Build lifecycle completes successfully in Run mode - [x] Logger outputs progress messages correctly
Summary
vizzly storybookusage withoutvizzly runwrapperChanges
Auto-Mode Detection
The plugin now automatically detects whether to use TDD server or cloud mode:
.vizzly/server.jsonexists and server responds to health checkVIZZLY_TOKENenvironment variable is setBuild Lifecycle Management
When in Run mode, the plugin now:
build-createdevent to display build URLImproved Logging
Test Coverage
Added 15 new tests across 2 test files:
tests/concurrency.spec.js- Concurrency control logic (4 tests)tests/hooks.spec.js- Interaction hooks system (11 tests)Total: 67 tests passing
Test Plan
vizzly storybookwith TDD server running - shows TDD modeVIZZLY_TOKEN=xxx vizzly storybook- shows Run mode with build URL