Skip to content

Conversation

@colinaaa
Copy link
Collaborator

@colinaaa colinaaa commented Aug 10, 2025

Summary by CodeRabbit

  • New Features

    • Introduced multiple new test suites to verify plugin behavior under various scenarios, including internal resolution errors, missing exports, and unexpected module syntax.
    • Added new example packages with different module and type declaration configurations for comprehensive testing.
    • Provided sample modules exporting functions and constants for use in tests.
  • Tests

    • Added extensive automated tests to ensure correct plugin responses, error handling, and logging across different build configurations.
    • Included snapshot and assertion checks for log outputs and file creation.
  • Chores

    • Added new package metadata files to support the new test scenarios and sample modules.
    • Updated coverage thresholds in testing configuration to higher standards.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 10, 2025

Walkthrough

This change introduces comprehensive test suites and supporting package files for the pluginAreTheTypesWrong plugin, targeting scenarios involving internal resolution errors, missing export equals, unexpected module syntax, build tools integration, exports handling, wildcard exports, and CJS to ESM resolution. Each suite includes tests for plugin error handling, configuration-based behavior, and ensures no unintended package files are generated. Supporting source, type, and package metadata files are also added for each scenario. Additionally, the Vitest coverage thresholds have been increased.

Changes

Cohort / File(s) Change Summary
Internal Resolution Error Tests and Fixtures
test/internal-resolution-error/index.test.ts, test/internal-resolution-error/package.json, test/internal-resolution-error/src/index.d.cts, test/internal-resolution-error/src/index.d.ts, test/internal-resolution-error/src/index.js, test/internal-resolution-error/src/types.d.ts
Adds a new test suite for internal resolution errors, including multiple test cases for plugin behavior under different configurations. Adds package metadata, source, and type declaration files for the test fixture.
Missing Export Equals Tests and Fixtures
test/missing-export-equals/index.test.ts, test/missing-export-equals/package.json, test/missing-export-equals/src/index.d.ts, test/missing-export-equals/src/index.js
Adds a new test suite for missing export equals scenarios, testing plugin behavior and configuration. Includes supporting package metadata, type declaration, and source files for the test fixture.
Unexpected Module Syntax Tests and Fixtures
test/unexpected-module-syntax/index.test.ts, test/unexpected-module-syntax/package.json, test/unexpected-module-syntax/src/index.d.ts, test/unexpected-module-syntax/src/index.js
Adds a new test suite for unexpected module syntax scenarios, with tests for plugin error handling and configuration. Adds corresponding package metadata, type declaration, and source files for the test fixture.
Build Tools Integration Tests and Fixtures
test/build-tools/index.test.ts, test/build-tools/package.json, test/build-tools/src/index.d.ts, test/build-tools/src/index.js
Adds tests for running the plugin with the rsbuild build tool under different option configurations. Adds supporting package metadata, source, and type declaration files.
Exports Handling Tests and Fixtures
test/exports/index.test.ts, test/exports/package.json, test/exports/src/bar.cjs, test/exports/src/bar.d.cts, test/exports/src/bar.d.ts, test/exports/src/bar.js, test/exports/src/foo.cjs, test/exports/src/foo.d.cts, test/exports/src/foo.d.ts, test/exports/src/foo.js
Adds tests for plugin behavior with various export styles, including ES modules and CommonJS. Provides multiple source and type declaration files for foo and bar exports, plus package metadata.
Wildcard Exports Tests and Fixtures
test/wildcard/index.test.ts, test/wildcard/package.json, test/wildcard/src/bar.cjs, test/wildcard/src/bar.d.cts, test/wildcard/src/bar.d.ts, test/wildcard/src/bar.js, test/wildcard/src/foo.cjs, test/wildcard/src/foo.d.cts, test/wildcard/src/foo.d.ts, test/wildcard/src/foo.js
Adds tests for plugin behavior with wildcard exports, covering multiple file types and configurations. Adds package metadata and source/type declaration files for foo and bar.
CJS Resolves to ESM Test Modification
test/cjs-resolves-to-esm/index.test.ts
Modifies an existing test to instantiate the plugin with an options object disabling emoji output. No other logic changes.
Vitest Configuration Update
vitest.config.ts
Increases the minimum coverage thresholds for lines, functions, branches, and statements in the Vitest configuration. No other changes made.

Sequence Diagram(s)

sequenceDiagram
    participant TestRunner as Test Suite
    participant Rsbuild as Rsbuild Build System
    participant Plugin as pluginAreTheTypesWrong
    participant Logger as Logger
    participant FS as File System

    TestRunner->>Rsbuild: Initialize build with plugin and options
    Rsbuild->>Plugin: Invoke plugin during build lifecycle
    Plugin->>Logger: Log error or success messages based on scenario and config
    Plugin->>FS: Attempt to create package file (conditional)
    FS-->>Plugin: Confirm presence or absence of package file
    Plugin-->>Rsbuild: Return build result or throw error
    Rsbuild-->>TestRunner: Build result or error
    TestRunner->>Logger: Spy/assert on logged messages
    TestRunner->>FS: Assert package file not created
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • feat: fail the build on type error #4: Adds utility and modifies plugin to fail build on type errors; related at the plugin functionality level as both PRs focus on error handling and plugin behavior.

Poem

In the warren of tests, the rabbits did hop,
Checking plugins for errors that bubble and pop.
With syntax and exports, and types to explore,
They nibbled at configs, then checked logs for more.
No stray files were found, all bunnies agree—
The tests are now thorough, as neat as can be! 🐇

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch colin/0810/test-1

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (10)
test/unexpected-module-syntax/src/index.js (1)

1-1: Intentional ESM-in-CJS: annotate and ensure linters don’t block this test

With "type": "commonjs" in the package, export is invalid at runtime—presumably intentional for the “UnexpectedModuleSyntax” test. Biome flagged a parse error; CI may fail unless ignored.

  • Add an explanatory comment at the top to prevent “fixes” later.
  • Ignore this file in Biome (parse errors can’t be suppressed inline).

Proposed header comment:

+// Intentionally uses ESM syntax in a CJS package to trigger the "UnexpectedModuleSyntax" rule in tests.
 export const hello = 'world';

Biome ignore (biome.json):

{
  "$schema": "https://biomejs.dev/schemas/1.8.0/schema.json",
  "files": {
    "ignore": ["test/unexpected-module-syntax/src/index.js"]
  }
}
test/missing-export-equals/src/index.js (1)

1-2: module.exports.default is overwritten on the next line

module.exports = foo replaces the entire exports object, discarding module.exports.default set just before it. If the goal is to mimic a CJS module that only exposes module.exports (to trigger “MissingExportEquals”), either:

  • Remove the first line for clarity, or
  • Add a comment explaining that the overwrite is intentional.

Option A (clarify by removal):

-module.exports.default = foo;
 module.exports = foo;

Option B (document the intention):

-module.exports.default = foo;
+// Intentionally set then overwrite to simulate a default type without a runtime default export.
 module.exports = foo;
test/internal-resolution-error/src/index.js (1)

1-5: Inline the default export for clarity

Equivalent behavior, avoids pre-declaration reference, and improves readability.

-export default foo;
-
-function foo() {
-  return 42;
-}
+export default function foo() {
+  return 42;
+}
test/missing-export-equals/package.json (1)

8-13: Be explicit about CJS resolution in exports

To make CJS intent unambiguous, add the require condition alongside default. This is a nice-to-have for clarity and parity with Node’s condition resolution.

   "exports": {
     ".": {
-      "types": "./src/index.d.ts",
-      "default": "./src/index.js"
+      "types": "./src/index.d.ts",
+      "require": "./src/index.js",
+      "default": "./src/index.js"
     }
   }
test/missing-export-equals/index.test.ts (2)

33-66: Document why this test is skipped (or convert to runtime conditional)

Add a reason/TODO to the skip so future maintainers know when to enable it, or gate it conditionally (e.g., only run when local env supports node16 resolutions).

-test.skip("should be able to ignore resolution node16-*", async () => {
+// TODO(colinaaa): Enable when ATTW supports ignoring node16-* resolutions in this scenario.
+test.skip("should be able to ignore resolution node16-*", async () => {

112-120: Optionally assert no error logs when enable: false

Not mandatory, but it makes the intent explicit.

-  const success = vi.spyOn(logger, "success");
+  const success = vi.spyOn(logger, "success");
+  const error = vi.spyOn(logger, "error");
@@
   expect(success).not.toBeCalled();
+  expect(error).not.toBeCalled();
test/unexpected-module-syntax/index.test.ts (2)

10-16: Nit: tighten test description

Minor grammar fix for readability.

-test("should throw when have unexpected module syntax", async () => {
+test("should throw on unexpected module syntax", async () => {

112-120: Optionally assert no error logs when disabled

Complements the existing assertion.

-  const success = vi.spyOn(logger, "success");
+  const success = vi.spyOn(logger, "success");
+  const error = vi.spyOn(logger, "error");
@@
   expect(success).not.toBeCalled();
+  expect(error).not.toBeCalled();
test/internal-resolution-error/index.test.ts (2)

10-16: Nit: tighten test description

Improve readability.

-test("should throw when have internal resolution error", async () => {
+test("should throw on internal resolution error", async () => {

112-120: Optionally also assert no error logs when disabled

Makes the disabled-path expectations explicit.

-  const success = vi.spyOn(logger, "success");
+  const success = vi.spyOn(logger, "success");
+  const error = vi.spyOn(logger, "error");
@@
   expect(success).not.toBeCalled();
+  expect(error).not.toBeCalled();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 927a3aa and 8bd0908.

⛔ Files ignored due to path filters (3)
  • test/internal-resolution-error/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • test/missing-export-equals/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • test/unexpected-module-syntax/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (14)
  • test/internal-resolution-error/index.test.ts (1 hunks)
  • test/internal-resolution-error/package.json (1 hunks)
  • test/internal-resolution-error/src/index.d.cts (1 hunks)
  • test/internal-resolution-error/src/index.d.ts (1 hunks)
  • test/internal-resolution-error/src/index.js (1 hunks)
  • test/internal-resolution-error/src/types.d.ts (1 hunks)
  • test/missing-export-equals/index.test.ts (1 hunks)
  • test/missing-export-equals/package.json (1 hunks)
  • test/missing-export-equals/src/index.d.ts (1 hunks)
  • test/missing-export-equals/src/index.js (1 hunks)
  • test/unexpected-module-syntax/index.test.ts (1 hunks)
  • test/unexpected-module-syntax/package.json (1 hunks)
  • test/unexpected-module-syntax/src/index.d.ts (1 hunks)
  • test/unexpected-module-syntax/src/index.js (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-10T13:56:09.286Z
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:10-31
Timestamp: 2025-08-10T13:56:09.286Z
Learning: The `rsbuild` instance created by `createRsbuild()` from `rsbuild/core` does not have a `close()` method. In test files, it's acceptable to not perform cleanup when the build fails with an error, as cleanup is not required in error cases.

Applied to files:

  • test/missing-export-equals/index.test.ts
  • test/unexpected-module-syntax/index.test.ts
  • test/internal-resolution-error/index.test.ts
📚 Learning: 2025-08-10T09:28:46.764Z
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#3
File: src/index.ts:49-51
Timestamp: 2025-08-10T09:28:46.764Z
Learning: In the rsbuild-plugin-arethetypeswrong project, Rslib is used to bundle the plugin, which means all imported dependencies (including `arethetypeswrong/core`) are bundled into the final output. Therefore, these dependencies can be placed in `devDependencies` rather than `dependencies` since they are only needed at build time, not at runtime for end users.

Applied to files:

  • test/missing-export-equals/index.test.ts
  • test/unexpected-module-syntax/index.test.ts
  • test/internal-resolution-error/index.test.ts
🧬 Code Graph Analysis (2)
test/unexpected-module-syntax/src/index.d.ts (1)
test/unexpected-module-syntax/src/index.js (2)
  • hello (1-1)
  • hello (1-1)
test/unexpected-module-syntax/index.test.ts (1)
src/index.ts (4)
  • pluginAreTheTypesWrong (18-78)
  • options (21-60)
  • setup (26-59)
  • PluginAreTheTypesWrongOptions (11-19)
🪛 Biome (2.1.2)
test/unexpected-module-syntax/src/index.js

[error] 1-1: Illegal use of an export declaration outside of a module

not allowed inside scripts

(parse)

🔇 Additional comments (6)
test/unexpected-module-syntax/package.json (1)

5-12: Config aligns with test intent (CJS + explicit export map)

This shape (CJS + exports with default and types) is good for exercising the rule. Note: when exports is present, Node ignores main; fine for the test package.

test/internal-resolution-error/package.json (1)

6-16: No require runtime export when exports is present (Node will ignore main)

Because exports exists, Node ignores main. There’s no "require" condition for runtime, so require('...') will fail—likely by design to trigger “InternalResolutionError”.

Please confirm this is intentional and tests don’t rely on CommonJS consumption. If not intentional, add:

       ".": {
         "types": {
           "import": "./src/index.d.ts",
           "require": "./src/index.d.cts"
         },
-        "import": "./src/index.js"
+        "import": "./src/index.js",
+        "require": "./src/index.js"
       }
test/unexpected-module-syntax/src/index.d.ts (1)

1-1: LGTM

Declaration matches the JS export and is syntactically correct.

test/missing-export-equals/index.test.ts (1)

6-6: Restore spies between tests

Restore all spies after each test to avoid cross-test leakage.

-import { expect, test, vi } from "vitest";
+import { afterEach, expect, test, vi } from "vitest";

Add after the imports:

+afterEach(() => {
+  vi.restoreAllMocks();
+});
⛔ Skipped due to learnings
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:6-7
Timestamp: 2025-08-10T13:57:06.293Z
Learning: In Vitest test files, when spies are created using `vi.spyOn()` within individual test function scopes (not at module level), they don't need to be restored between tests since each test creates its own isolated spy instance that goes out of scope when the test completes.
test/unexpected-module-syntax/index.test.ts (1)

6-6: Restore spies between tests

Same rationale as other suites: prevent cross-test leakage.

-import { expect, test, vi } from "vitest";
+import { afterEach, expect, test, vi } from "vitest";
+
+afterEach(() => {
+  vi.restoreAllMocks();
+});
⛔ Skipped due to learnings
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:6-7
Timestamp: 2025-08-10T13:57:06.293Z
Learning: In Vitest test files, when spies are created using `vi.spyOn()` within individual test function scopes (not at module level), they don't need to be restored between tests since each test creates its own isolated spy instance that goes out of scope when the test completes.
test/internal-resolution-error/index.test.ts (1)

6-6: Restore spies between tests

Avoid cross-test interference.

-import { expect, test, vi } from "vitest";
+import { afterEach, expect, test, vi } from "vitest";
+
+afterEach(() => {
+  vi.restoreAllMocks();
+});
⛔ Skipped due to learnings
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:6-7
Timestamp: 2025-08-10T13:57:06.293Z
Learning: In Vitest test files, when spies are created using `vi.spyOn()` within individual test function scopes (not at module level), they don't need to be restored between tests since each test creates its own isolated spy instance that goes out of scope when the test completes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (4)
test/build-tools/index.test.ts (1)

10-33: Reduce duplication by extracting a small helper

Three tests repeat the same build/spy/assert flow. Factor into a helper to keep tests concise and easier to maintain.

Example helper (place near the top of the file):

type Options = Parameters<typeof pluginAreTheTypesWrong>[0] | undefined;

async function runATTWTest(options?: Options) {
  const rsbuild = await createRsbuild({
    cwd: import.meta.dirname,
    rsbuildConfig: { plugins: [pluginAreTheTypesWrong(options)] },
  });

  const success = vi.spyOn(logger, "success");
  const { close } = await rsbuild.build();

  const messages = success.mock.calls
    .flatMap(call => call
      .filter(message => typeof message === "string" && message.includes("[arethetypeswrong]"))
      .map(stripVTControlCharacters));

  expect(messages).toMatchSnapshot();
  expect(existsSync(expectedTarball)).toBeFalsy();

  await close();
}

Then the tests become:

test("should run arethetypeswrong as expected", async () => {
  await runATTWTest();
});

test("should run arethetypeswrong without emoji", async () => {
  await runATTWTest({ areTheTypesWrongOptions: { emoji: false } });
});

test("should run arethetypeswrong without summary", async () => {
  await runATTWTest({ areTheTypesWrongOptions: { emoji: false, summary: false } });
});

Also applies to: 35-63, 64-92

test/exports/index.test.ts (2)

22-28: Make the spy output extraction simpler

The current nested flatMap + filter + map works but is verbose. Flatten arguments first, then filter.

-  expect(
-    success.mock.calls.flatMap(call =>
-      call
-        .filter(message => typeof message === "string" && message.includes("[arethetypeswrong]"))
-        .map(stripVTControlCharacters)
-    ),
-  ).toMatchSnapshot();
+  expect(
+    success.mock.calls
+      .flat()
+      .filter((message): message is string => typeof message === "string" && message.includes("[arethetypeswrong]"))
+      .map(stripVTControlCharacters),
+  ).toMatchSnapshot();

Also applies to: 51-57, 81-87


10-16: Optional: deduplicate repeated test setup via a helper

All three tests share the same structure; consider extracting a small run helper to reduce duplication and ease future changes.

Example helper (add near top of file):

async function run(options?: Parameters<typeof pluginAreTheTypesWrong>[0]) {
  const rsbuild = await createRsbuild({
    cwd: import.meta.dirname,
    rsbuildConfig: { plugins: [pluginAreTheTypesWrong(options)] },
  });

  const success = vi.spyOn(logger, "success");
  const error = vi.spyOn(logger, "error");
  const result = await rsbuild.build();

  try {
    const messages = success.mock.calls
      .flat()
      .filter((m): m is string => typeof m === "string" && m.includes("[arethetypeswrong]"))
      .map(stripVTControlCharacters);

    expect(messages).toMatchSnapshot();
    expect(error).not.toHaveBeenCalled();
    expect(existsSync(path.join(import.meta.dirname, "test-exports-0.0.0.tgz"))).toBe(false);
  } finally {
    await result.close();
    vi.restoreAllMocks();
  }
}

Then:

test("should run arethetypeswrong as expected", async () => run());
test("should run arethetypeswrong without emoji", async () => run({ areTheTypesWrongOptions: { emoji: false } }));
test("should run arethetypeswrong without summary", async () => run({ areTheTypesWrongOptions: { emoji: false, summary: false } }));

Also applies to: 35-45, 64-75

test/wildcard/index.test.ts (1)

10-33: Test structure is solid but consider reducing duplication.

The test correctly validates plugin behavior with default configuration. The use of snapshot testing for logger output and file existence checks is appropriate.

Consider extracting the common test logic into a helper function to reduce duplication:

async function runPluginTest(options?: Parameters<typeof pluginAreTheTypesWrong>[0]) {
  const rsbuild = await createRsbuild({
    cwd: import.meta.dirname,
    rsbuildConfig: {
      plugins: [pluginAreTheTypesWrong(options)],
    },
  });

  const success = vi.spyOn(logger, "success");
  const { close } = await rsbuild.build();
  
  const logMessages = success.mock.calls.flatMap(call =>
    call
      .filter(message => typeof message === "string" && message.includes("[arethetypeswrong]"))
      .map(stripVTControlCharacters)
  );

  return { logMessages, close };
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8bd0908 and 1b7b872.

⛔ Files ignored due to path filters (7)
  • test/build-tools/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • test/cjs-resolves-to-esm/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • test/exports/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • test/internal-resolution-error/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • test/missing-export-equals/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • test/unexpected-module-syntax/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • test/wildcard/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (39)
  • test/build-tools/index.test.ts (1 hunks)
  • test/build-tools/package.json (1 hunks)
  • test/build-tools/src/index.d.ts (1 hunks)
  • test/build-tools/src/index.js (1 hunks)
  • test/cjs-resolves-to-esm/index.test.ts (1 hunks)
  • test/exports/index.test.ts (1 hunks)
  • test/exports/package.json (1 hunks)
  • test/exports/src/bar.cjs (1 hunks)
  • test/exports/src/bar.d.cts (1 hunks)
  • test/exports/src/bar.d.ts (1 hunks)
  • test/exports/src/bar.js (1 hunks)
  • test/exports/src/foo.cjs (1 hunks)
  • test/exports/src/foo.d.cts (1 hunks)
  • test/exports/src/foo.d.ts (1 hunks)
  • test/exports/src/foo.js (1 hunks)
  • test/internal-resolution-error/index.test.ts (1 hunks)
  • test/internal-resolution-error/package.json (1 hunks)
  • test/internal-resolution-error/src/index.d.cts (1 hunks)
  • test/internal-resolution-error/src/index.d.ts (1 hunks)
  • test/internal-resolution-error/src/index.js (1 hunks)
  • test/internal-resolution-error/src/types.d.ts (1 hunks)
  • test/missing-export-equals/index.test.ts (1 hunks)
  • test/missing-export-equals/package.json (1 hunks)
  • test/missing-export-equals/src/index.d.ts (1 hunks)
  • test/missing-export-equals/src/index.js (1 hunks)
  • test/unexpected-module-syntax/index.test.ts (1 hunks)
  • test/unexpected-module-syntax/package.json (1 hunks)
  • test/unexpected-module-syntax/src/index.d.ts (1 hunks)
  • test/unexpected-module-syntax/src/index.js (1 hunks)
  • test/wildcard/index.test.ts (1 hunks)
  • test/wildcard/package.json (1 hunks)
  • test/wildcard/src/bar.cjs (1 hunks)
  • test/wildcard/src/bar.d.cts (1 hunks)
  • test/wildcard/src/bar.d.ts (1 hunks)
  • test/wildcard/src/bar.js (1 hunks)
  • test/wildcard/src/foo.cjs (1 hunks)
  • test/wildcard/src/foo.d.cts (1 hunks)
  • test/wildcard/src/foo.d.ts (1 hunks)
  • test/wildcard/src/foo.js (1 hunks)
✅ Files skipped from review due to trivial changes (11)
  • test/exports/src/bar.cjs
  • test/exports/src/bar.js
  • test/exports/src/foo.d.ts
  • test/wildcard/src/bar.d.ts
  • test/wildcard/src/foo.cjs
  • test/cjs-resolves-to-esm/index.test.ts
  • test/build-tools/package.json
  • test/exports/src/foo.cjs
  • test/wildcard/src/bar.cjs
  • test/exports/package.json
  • test/wildcard/package.json
🚧 Files skipped from review as they are similar to previous changes (13)
  • test/unexpected-module-syntax/src/index.d.ts
  • test/internal-resolution-error/src/types.d.ts
  • test/unexpected-module-syntax/package.json
  • test/missing-export-equals/src/index.d.ts
  • test/internal-resolution-error/src/index.d.cts
  • test/internal-resolution-error/src/index.d.ts
  • test/internal-resolution-error/package.json
  • test/internal-resolution-error/src/index.js
  • test/missing-export-equals/src/index.js
  • test/missing-export-equals/package.json
  • test/missing-export-equals/index.test.ts
  • test/unexpected-module-syntax/index.test.ts
  • test/internal-resolution-error/index.test.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-10T09:28:46.764Z
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#3
File: src/index.ts:49-51
Timestamp: 2025-08-10T09:28:46.764Z
Learning: In the rsbuild-plugin-arethetypeswrong project, Rslib is used to bundle the plugin, which means all imported dependencies (including `arethetypeswrong/core`) are bundled into the final output. Therefore, these dependencies can be placed in `devDependencies` rather than `dependencies` since they are only needed at build time, not at runtime for end users.

Applied to files:

  • test/build-tools/index.test.ts
  • test/exports/index.test.ts
  • test/wildcard/index.test.ts
🧬 Code Graph Analysis (9)
test/wildcard/src/foo.d.cts (1)
test/wildcard/src/foo.js (1)
  • foo (1-3)
test/build-tools/src/index.js (3)
test/exports/src/foo.js (1)
  • foo (1-3)
test/wildcard/src/foo.js (1)
  • foo (1-3)
test/named-exports/index.test.ts (2)
  • rsbuild (33-64)
  • message (89-89)
test/exports/src/bar.d.cts (1)
test/exports/src/bar.js (1)
  • bar (1-3)
test/build-tools/src/index.d.ts (1)
test/build-tools/src/index.js (1)
  • foo (1-3)
test/wildcard/src/bar.d.cts (2)
test/exports/src/bar.js (1)
  • bar (1-3)
test/wildcard/src/bar.js (1)
  • bar (1-3)
test/wildcard/src/foo.d.ts (1)
test/wildcard/src/foo.js (1)
  • foo (1-3)
test/exports/src/foo.d.cts (1)
test/exports/src/foo.js (1)
  • foo (1-3)
test/wildcard/src/foo.js (12)
test/build-tools/src/index.js (1)
  • foo (1-3)
test/exports/src/foo.js (1)
  • foo (1-3)
test/untyped-resolution/src/index.cjs (1)
  • foo (1-3)
test/untyped-resolution/src/index.mjs (1)
  • foo (1-3)
test/basic/src/index.js (1)
  • foo (1-3)
test/false-esm/src/index.mjs (1)
  • foo (1-3)
test/no-resolution/src/index.js (1)
  • foo (1-3)
test/untyped/src/index.js (1)
  • foo (1-3)
test/false-esm/src/index.cjs (1)
  • foo (1-3)
test/with-scope/src/index.js (1)
  • foo (1-3)
test/named-exports/index.test.ts (1)
  • message (89-89)
test/false-cjs/src/index.mjs (1)
  • main (1-3)
test/exports/index.test.ts (8)
src/index.ts (1)
  • pluginAreTheTypesWrong (18-78)
test/basic/index.test.ts (2)
  • rsbuild (64-92)
  • rsbuild (35-62)
test/named-exports/index.test.ts (1)
  • rsbuild (66-97)
test/with-scope/index.test.ts (2)
  • rsbuild (64-92)
  • rsbuild (35-62)
test/cjs-only-exports-default/index.test.ts (1)
  • rsbuild (33-65)
test/untyped-resolution/index.test.ts (1)
  • rsbuild (98-131)
test/false-cjs/index.test.ts (1)
  • rsbuild (33-64)
test/false-export-default/index.test.ts (1)
  • rsbuild (33-67)
🪛 Biome (2.1.2)
test/unexpected-module-syntax/src/index.js

[error] 1-1: Illegal use of an export declaration outside of a module

not allowed inside scripts

(parse)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test (windows-latest)
🔇 Additional comments (15)
test/build-tools/src/index.js (1)

1-3: LGTM: simple named export matches usage

Implementation is minimal and correct.

test/build-tools/src/index.d.ts (1)

1-1: LGTM: declaration matches implementation

foo returns a number and aligns with src/index.js.

test/build-tools/index.test.ts (1)

6-9: Restore mocks between tests to avoid spy-on conflicts and cross-test leakage

Without restoration, multiple vi.spyOn(logger, "success") calls across tests can collide or leak calls. Add a global afterEach to restore all mocks.

Apply this diff:

-import { expect, test, vi } from "vitest";
+import { expect, test, vi, afterEach } from "vitest";
@@
 import { pluginAreTheTypesWrong } from "../../src";
 
+afterEach(() => {
+  vi.restoreAllMocks();
+});
⛔ Skipped due to learnings
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:6-7
Timestamp: 2025-08-10T13:57:06.293Z
Learning: In Vitest test files, when spies are created using `vi.spyOn()` within individual test function scopes (not at module level), they don't need to be restored between tests since each test creates its own isolated spy instance that goes out of scope when the test completes.
test/exports/src/foo.d.cts (1)

1-1: Validate TypeScript version for .d.cts named exports

This pattern (export function foo(): number; in a .d.cts file) has been supported since TypeScript 4.7. Please ensure your project is using TS 4.7 or later so that this named‐export declaration correctly maps to exports.foo at runtime.

• File to check:

  • test/exports/src/foo.d.cts – no changes needed if TS ≥ 4.7.

• If you must support older TS versions, switch to a CommonJS‐style default export:

declare function foo(): number;
export = foo;
test/exports/src/bar.d.ts (1)

1-1: LGTM — declaration matches implementation intent

The bar function declaration is straightforward and consistent with the fixture’s JS implementation.

test/exports/src/bar.d.cts (1)

1-1: .d.cts declaration for bar verified

The test/exports/package.json correctly maps the CJS type entry for bar:

  • "types.require": "./src/bar.d.cts"

As long as you’re on TypeScript ≥ 4.7 with a Node-16 or bundler-style module resolution, named exports in .d.cts files work as expected. No further changes needed.

test/exports/src/foo.js (1)

1-3: LGTM — simple ESM export with deterministic return

Function is minimal, deterministic, and fits the test fixture purpose.

test/exports/index.test.ts (3)

18-33: Prevent spy leakage and ensure cleanup with try/finally

Spies are not restored between tests; this can cause cumulative mock.calls and flaky snapshots. Also prefer deterministic boolean assertions.

Apply:

-  const success = vi.spyOn(logger, "success");
-
-  const { close } = await rsbuild.build();
-
-  expect(
+  const success = vi.spyOn(logger, "success");
+  const error = vi.spyOn(logger, "error");
+  const result = await rsbuild.build();
+  try {
+    expect(
       success.mock.calls.flatMap(call =>
         call
           .filter(message => typeof message === "string" && message.includes("[arethetypeswrong]"))
           .map(stripVTControlCharacters)
       ),
-  ).toMatchSnapshot();
-
-  expect(existsSync(path.join(import.meta.dirname, "test-exports-0.0.0.tgz"))).toBeFalsy();
-
-  await close();
+    ).toMatchSnapshot();
+    expect(error).not.toHaveBeenCalled();
+    expect(existsSync(path.join(import.meta.dirname, "test-exports-0.0.0.tgz"))).toBe(false);
+  } finally {
+    await result.close();
+    vi.restoreAllMocks();
+  }
⛔ Skipped due to learnings
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:6-7
Timestamp: 2025-08-10T13:57:06.293Z
Learning: In Vitest test files, when spies are created using `vi.spyOn()` within individual test function scopes (not at module level), they don't need to be restored between tests since each test creates its own isolated spy instance that goes out of scope when the test completes.
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:10-31
Timestamp: 2025-08-10T13:56:09.286Z
Learning: The `rsbuild` instance created by `createRsbuild()` from `rsbuild/core` does not have a `close()` method. In test files, it's acceptable to not perform cleanup when the build fails with an error, as cleanup is not required in error cases.
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#10
File: test/pnpm/index.test.ts:20-33
Timestamp: 2025-08-10T15:53:16.194Z
Learning: In the rsbuild-plugin-arethetypeswrong project's test files, it's not necessary to ensure that Rsbuild instances are closed using try/finally blocks or other cleanup patterns. The `close()` function returned from `rsbuild.build()` doesn't need to be guaranteed to run even when test assertions fail.

77-92: Repeat cleanup fix in test 3 and assert no errors logged

Same isolation concerns apply; add error assertion and deterministic boolean check.

-  const success = vi.spyOn(logger, "success");
-
-  const { close } = await rsbuild.build();
-
-  expect(
+  const success = vi.spyOn(logger, "success");
+  const error = vi.spyOn(logger, "error");
+  const result = await rsbuild.build();
+  try {
+    expect(
       success.mock.calls.flatMap(call =>
         call
           .filter(message => typeof message === "string" && message.includes("[arethetypeswrong]"))
           .map(stripVTControlCharacters)
       ),
-  ).toMatchSnapshot();
-
-  expect(existsSync(path.join(import.meta.dirname, "test-exports-0.0.0.tgz"))).toBeFalsy();
-
-  await close();
+    ).toMatchSnapshot();
+    expect(error).not.toHaveBeenCalled();
+    expect(existsSync(path.join(import.meta.dirname, "test-exports-0.0.0.tgz"))).toBe(false);
+  } finally {
+    await result.close();
+    vi.restoreAllMocks();
+  }
⛔ Skipped due to learnings
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:10-31
Timestamp: 2025-08-10T13:56:09.286Z
Learning: The `rsbuild` instance created by `createRsbuild()` from `rsbuild/core` does not have a `close()` method. In test files, it's acceptable to not perform cleanup when the build fails with an error, as cleanup is not required in error cases.
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#10
File: test/pnpm/index.test.ts:20-33
Timestamp: 2025-08-10T15:53:16.194Z
Learning: In the rsbuild-plugin-arethetypeswrong project's test files, it's not necessary to ensure that Rsbuild instances are closed using try/finally blocks or other cleanup patterns. The `close()` function returned from `rsbuild.build()` doesn't need to be guaranteed to run even when test assertions fail.

47-62: Repeat cleanup fix in test 2 to isolate spies and results

Mirror the try/finally cleanup and add an error spy to assert no failures are logged.

-  const success = vi.spyOn(logger, "success");
-
-  const { close } = await rsbuild.build();
-
-  expect(
+  const success = vi.spyOn(logger, "success");
+  const error = vi.spyOn(logger, "error");
+  const result = await rsbuild.build();
+  try {
+    expect(
       success.mock.calls.flatMap(call =>
         call
           .filter(message => typeof message === "string" && message.includes("[arethetypeswrong]"))
           .map(stripVTControlCharacters)
       ),
-  ).toMatchSnapshot();
-
-  expect(existsSync(path.join(import.meta.dirname, "test-exports-0.0.0.tgz"))).toBeFalsy();
-
-  await close();
+    ).toMatchSnapshot();
+    expect(error).not.toHaveBeenCalled();
+    expect(existsSync(path.join(import.meta.dirname, "test-exports-0.0.0.tgz"))).toBe(false);
+  } finally {
+    await result.close();
+    vi.restoreAllMocks();
+  }
⛔ Skipped due to learnings
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:10-31
Timestamp: 2025-08-10T13:56:09.286Z
Learning: The `rsbuild` instance created by `createRsbuild()` from `rsbuild/core` does not have a `close()` method. In test files, it's acceptable to not perform cleanup when the build fails with an error, as cleanup is not required in error cases.
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#6
File: test/cjs-resolves-to-esm/index.test.ts:6-7
Timestamp: 2025-08-10T13:57:06.293Z
Learning: In Vitest test files, when spies are created using `vi.spyOn()` within individual test function scopes (not at module level), they don't need to be restored between tests since each test creates its own isolated spy instance that goes out of scope when the test completes.
Learnt from: colinaaa
PR: colinaaa/rsbuild-plugin-arethetypeswrong#10
File: test/pnpm/index.test.ts:20-33
Timestamp: 2025-08-10T15:53:16.194Z
Learning: In the rsbuild-plugin-arethetypeswrong project's test files, it's not necessary to ensure that Rsbuild instances are closed using try/finally blocks or other cleanup patterns. The `close()` function returned from `rsbuild.build()` doesn't need to be guaranteed to run even when test assertions fail.
test/wildcard/src/foo.js (1)

1-3: LGTM: Simple ESM named export matches expected usage

Named export foo returning 42 is consistent with similar fixtures and the associated type decls.

test/wildcard/src/bar.js (1)

1-3: LGTM: Consistent ESM named export

bar returns 42 and mirrors the pattern used across tests and declarations.

test/wildcard/src/foo.d.ts (1)

1-1: LGTM: Declaration aligns with implementation

export function foo(): number; matches the JS ESM export and is appropriate for ESM type consumers.

test/wildcard/src/foo.d.cts (1)

1-1: LGTM: CJS declaration mirrors ESM signature

export function foo(): number; is appropriate for a CJS-typed module when using named exports and complements the .d.ts.

test/wildcard/index.test.ts (1)

1-8: LGTM!

The import statements are well-organized and include all necessary dependencies for the test scenarios.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
test/unexpected-module-syntax/src/index.js (1)

1-1: Clarify fixture intent; exclude from Biome or mark as ESM to avoid parse error

Biome parses this as CJS/script and errors on export. If the invalid ESM-in-CJS is intentional to trigger “unexpected-module-syntax”, keep it—but exclude this fixture from Biome to avoid CI failures. If not intentional, make it ESM by adding "type": "module" to the fixture package.json or renaming to .mjs.

  • Exclude in Biome (preferred for this negative test):
# biome.json / biome.jsonc
{
+ "files": {
+   "ignore": [
+     "test/unexpected-module-syntax/**"
+   ]
+ }
}
  • Or make it a valid ESM module (only if you don’t want this as a negative fixture):
# test/unexpected-module-syntax/package.json
 {
   "name": "test-unexpected-module-syntax",
-  "type": "commonjs"
+  "type": "module"
 }

Run to verify current setup:

#!/bin/bash
set -e

echo "Fixture package.json type (expect commonjs if negative test):"
if [ -f test/unexpected-module-syntax/package.json ]; then
  jq -r '.type // "(absent)"' test/unexpected-module-syntax/package.json || cat test/unexpected-module-syntax/package.json
else
  echo "No test/unexpected-module-syntax/package.json"
fi

echo
echo "Biome configs and ignore entries (ensure test/unexpected-module-syntax/** is ignored):"
fd -HI -a "biome.json" "biome.jsonc" || true
for f in $(fd -HI "biome.json" "biome.jsonc"); do
  echo "---- $f ----"
  sed -n '1,160p' "$f"
  echo
  echo "Ignore contains test/unexpected-module-syntax?:"
  jq -e '.files.ignore[]? | test("test/unexpected-module-syntax/")' "$f" >/dev/null 2>&1 && echo "Yes" || echo "No"
  echo
done

echo
echo "Fixture files present:"
fd -a "test/unexpected-module-syntax" --extension js --extension d.ts || true
🧹 Nitpick comments (1)
vitest.config.ts (1)

21-24: Reduce flakiness risk from tight thresholds (esp. 100% functions)

Coverage can vary slightly across Node/V8 versions and remapping. Consider a small buffer to avoid CI flakes while keeping ambition high.

Apply this diff:

-        lines: 96.74,
-        functions: 100,
-        branches: 94.62,
-        statements: 96.92,
+        lines: 96.5,
+        functions: 99.5,
+        branches: 94.5,
+        statements: 96.5,

Optionally, if you want thresholds to apply to all source files (not only those touched by tests), add this outside the selected lines:

// inside coverage:
all: true,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b7b872 and 6cca2f6.

📒 Files selected for processing (14)
  • test/build-tools/package.json (1 hunks)
  • test/internal-resolution-error/index.test.ts (1 hunks)
  • test/internal-resolution-error/package.json (1 hunks)
  • test/internal-resolution-error/src/index.d.cts (1 hunks)
  • test/internal-resolution-error/src/index.d.ts (1 hunks)
  • test/internal-resolution-error/src/types.d.ts (1 hunks)
  • test/missing-export-equals/index.test.ts (1 hunks)
  • test/missing-export-equals/package.json (1 hunks)
  • test/missing-export-equals/src/index.d.ts (1 hunks)
  • test/unexpected-module-syntax/index.test.ts (1 hunks)
  • test/unexpected-module-syntax/package.json (1 hunks)
  • test/unexpected-module-syntax/src/index.d.ts (1 hunks)
  • test/unexpected-module-syntax/src/index.js (1 hunks)
  • vitest.config.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • test/unexpected-module-syntax/package.json
🚧 Files skipped from review as they are similar to previous changes (11)
  • test/internal-resolution-error/src/index.d.cts
  • test/missing-export-equals/src/index.d.ts
  • test/internal-resolution-error/src/index.d.ts
  • test/internal-resolution-error/src/types.d.ts
  • test/unexpected-module-syntax/src/index.d.ts
  • test/missing-export-equals/package.json
  • test/build-tools/package.json
  • test/internal-resolution-error/package.json
  • test/missing-export-equals/index.test.ts
  • test/unexpected-module-syntax/index.test.ts
  • test/internal-resolution-error/index.test.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/unexpected-module-syntax/src/index.js (3)
test/unexpected-module-syntax/src/index.d.ts (1)
  • hello (1-1)
test/named-exports/index.test.ts (1)
  • message (89-89)
test/cjs-only-exports-default/index.test.ts (4)
  • message (90-90)
  • rsbuild (33-65)
  • rsbuild (67-98)
  • rsbuild (10-31)
🪛 Biome (2.1.2)
test/unexpected-module-syntax/src/index.js

[error] 1-1: Illegal use of an export declaration outside of a module

not allowed inside scripts

(parse)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test (windows-latest)
🔇 Additional comments (1)
vitest.config.ts (1)

21-24: LGTM: higher coverage thresholds match the expanded test suites

Raising thresholds here is consistent with the new tests and signals strong confidence in coverage.

@colinaaa colinaaa merged commit 8c272c7 into main Aug 10, 2025
5 checks passed
@colinaaa colinaaa deleted the colin/0810/test-1 branch August 10, 2025 16:00
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.

2 participants