Skip to content

Conversation

@charliecreates
Copy link
Contributor

@charliecreates charliecreates bot commented Dec 9, 2025

Component / Package Name:

jsx-email

This PR contains:

  • bugfix
  • feature
  • refactor
  • documentation
  • other

Are tests included?

  • yes (bugfixes and features will not be merged without tests)
  • no

Breaking Changes?

  • yes (breaking changes will not be merged unless absolutely necessary)
  • no

If yes, please include "BREAKING CHANGES:" in the first commit message body, followed by a description of what is breaking.

List any relevant issue numbers:

resolves #371

Description

On next/v3, email check had placeholder/debug output in formatNotes() and was missing --use-preview-props parity.

This PR:

  • Removes the placeholder/debug strings and makes Notes formatting deterministic.
  • Adds --use-preview-props to email check and passes it through to buildTemplates().
  • Adds focused unit coverage to ensure Notes/issue grouping output is stable and the flag is forwarded.

Verification

pnpm install

# Build deps used by tests
pnpm moon run jsx-email:build
rm -rf packages/create-mail/dist
pnpm moon run create-mail:build
pnpm moon run :build --query "project~plugin-*"

# Unit/snapshot tests
FORCE_COLOR=1 pnpm moon run jsx-email:test

# TypeScript
pnpm moon run jsx-email:tsc

# CLI suite
pnpm moon run test-cli:test.run

Self-review notes

  • reviewChanges flagged a set of warnings about pnpm-workspace.yaml, shared/tsconfig.*, scripts/ci-preview-setup.sh, and pnpm-lock.yaml. None of those files are changed in this PR; those warnings appear to be based on next/v3 branch divergence rather than this PR's diff.

- Remove placeholder/debug output from check Notes formatting
- Add --use-preview-props support for email check
- Add unit coverage for formatting + flag pass-through
Copy link
Contributor Author

@charliecreates charliecreates bot left a comment

Choose a reason for hiding this comment

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

The CLI changes look correct and the new formatting is deterministic, but the new tests have reliability/cleanup issues: temp directories may be left behind when a test fails, and one test writes under process.cwd() rather than the OS temp directory. Additionally, heavy use of any in mocks/assertions weakens the regression protection for the new usePreviewProps plumbing.

Additional notes (2)
  • Maintainability | packages/jsx-email/test/cli/check.test.ts:16-30
    This mock uses any for buildOptions/params and the test suite also relies on as any for formatIssue() and command() inputs. The compiler passing is assumed, but the any usage here reduces the value of the tests: they won’t catch accidental option shape regressions (the exact thing this PR is adding).

Given you're already importing command and buildTemplates, it's feasible to type the mock args without much overhead.

  • Compatibility | packages/jsx-email/src/cli/commands/check.ts:16-16
    The command’s options schema accepts usePreviewProps, but there’s no obvious wiring here that actually parses --use-preview-props into argv.usePreviewProps (it may be handled elsewhere, but within this file the only guarantee is assert(CheckOptionsStruct, argv)). If the argument parsing layer doesn’t auto-map kebab-case to camelCase, the flag will be documented but ineffective.

At minimum, this file should either:

  • Explicitly document the expected argv key (usePreviewProps) and/or
  • Add a small compatibility shim (argv.usePreviewProps ??= argv['use-preview-props']) if your parser provides raw keys.
Summary of changes

What changed

email check CLI enhancements

  • Added --use-preview-props to email check help output and option parsing via valibot (optional(boolean())).
  • Plumbed argv.usePreviewProps through to buildTemplates() via buildOptions.usePreviewProps.

Deterministic notes formatting

  • Replaced placeholder/debug output in formatNotes() with stable, indented, dimmed note rendering.
  • Exported formatNotes and formatIssue for direct unit testing.

Tests & snapshots

  • Added packages/jsx-email/test/cli/check.test.ts to cover:
    • help text includes --use-preview-props
    • no debug output / no placeholder strings in formatting
    • forwarding of usePreviewProps to buildTemplates
    • integration-ish check that build() respects preview props when enabled
  • Updated several config-related snapshots to reflect normalized (non-ANSI) log template output.

Comment on lines +72 to +119
test('passes --use-preview-props through to buildTemplates', async () => {
const dir = await mkdtemp(join(os.tmpdir(), 'jsx-email-check-'));
const templatePath = join(dir, 'template.tsx');
await writeFile(templatePath, 'export const Template = () => null;', 'utf8');

const { buildTemplates } = await import('../../src/cli/commands/build.js');

await command({ usePreviewProps: true } as any, [templatePath]);

expect(buildTemplates).toHaveBeenCalledWith({
buildOptions: { showStats: false, usePreviewProps: true, writeToFile: false },
targetPath: templatePath
});
});

test('build uses previewProps when usePreviewProps is enabled', async () => {
const dir = await mkdtemp(join(process.cwd(), '.tmp-jsx-email-preview-props-'));
const out = join(dir, 'out');
const modulePath = join(dir, 'template.mjs');

await writeFile(
modulePath,
[
"import React from 'react';",
"export const previewProps = { name: 'Bruce' };",
"export const Template = (props) => React.createElement('p', null, props.name ?? 'missing');",
''
].join('\n'),
'utf8'
);

const withPreviewProps = await build({
argv: { out, usePreviewProps: true, writeToFile: false } as any,
path: modulePath,
sourceFile: modulePath
});

const withoutPreviewProps = await build({
argv: { out, props: '{"name":"Clark"}', writeToFile: false } as any,
path: modulePath,
sourceFile: modulePath
});

expect(withPreviewProps.html).toContain('Bruce');
expect(withoutPreviewProps.html).toContain('Clark');

await rm(dir, { force: true, recursive: true });
});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The new test suite creates temp directories, but cleanup is not guaranteed if an assertion fails (or if build() throws). This can leave .tmp-jsx-email-preview-props-* directories behind in local runs/CI workspaces.

Also, this test mixes os.tmpdir() (good) and process.cwd() (riskier) for temp dirs; prefer one consistent approach (ideally os.tmpdir()).

Suggestion

Wrap temp-dir lifecycle in try/finally (or use afterEach) and use os.tmpdir() consistently.

test('build uses previewProps when usePreviewProps is enabled', async () => {
  const dir = await mkdtemp(join(os.tmpdir(), 'jsx-email-preview-props-'));
  try {
    const out = join(dir, 'out');
    const modulePath = join(dir, 'template.mjs');

    await writeFile(
      modulePath,
      [
        "import React from 'react';",
        "export const previewProps = { name: 'Bruce' };",
        "export const Template = (props) => React.createElement('p', null, props.name ?? 'missing');",
        ''
      ].join('\n'),
      'utf8'
    );

    const withPreviewProps = await build({
      argv: { out, usePreviewProps: true, writeToFile: false } as any,
      path: modulePath,
      sourceFile: modulePath
    });

    const withoutPreviewProps = await build({
      argv: { out, props: '{"name":"Clark"}', writeToFile: false } as any,
      path: modulePath,
      sourceFile: modulePath
    });

    expect(withPreviewProps.html).toContain('Bruce');
    expect(withoutPreviewProps.html).toContain('Clark');
  } finally {
    await rm(dir, { force: true, recursive: true });
  }
});

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this change.

@charliecreates charliecreates bot removed the request for review from CharlieHelps December 9, 2025 22:50
@shellscape shellscape closed this Dec 9, 2025
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.

3 participants