Skip to content

Supersede #910: entry shape test with lint unblock#919

Merged
justin808 merged 8 commits intomainfrom
codex/supersede-910-entry-shape-lint
Apr 23, 2026
Merged

Supersede #910: entry shape test with lint unblock#919
justin808 merged 8 commits intomainfrom
codex/supersede-910-entry-shape-lint

Conversation

@justin808
Copy link
Copy Markdown
Member

@justin808 justin808 commented Feb 15, 2026

Supersedes #910.

Includes:

Closes #792


Note

Low Risk
Adds a regression test around baseConfig.entry value types; no production code changes, so risk is limited to potential test brittleness across environments.

Overview
Adds a new Jest regression test in test/package/environments/base.test.js to ensure baseConfig.entry values remain consistently typed as either non-empty strings or arrays of strings, preserving stable shapes for TypeScript narrowing.

No runtime behavior is changed; this strictly tightens test coverage around entrypoint generation.

Reviewed by Cursor Bugbot for commit f00999e. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Tests
    • Added test coverage to ensure configuration type stability for improved reliability.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 15, 2026

Walkthrough

A new test case is added to test/package/environments/base.test.js that validates TypeScript type narrowing behavior for Entry configuration objects, asserting expected value shapes.

Changes

Cohort / File(s) Summary
Type Narrowing Validation Test
test/package/environments/base.test.js
Adds test assertions validating that baseConfig.entry.application is a string and baseConfig.entry.multi_entry is an array of strings, ensuring stable type narrowing in TypeScript.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Poem

🐰 TypeScript types, now we test with care,
Entry shapes held steady in the air,
Narrowing paths where booleans lead,
A rabbit's test to satisfy the need! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title references issue #910 and describes the main change (entry shape test with lint unblock), accurately reflecting the PR's primary objective.
Linked Issues check ✅ Passed The PR adds test coverage for Entry type shape validation and type narrowing behavior as required by issue #792, and includes lint-related fixes mentioned in the PR objectives.
Out of Scope Changes check ✅ Passed The changes are limited to test additions and prettierignore workflow updates, all directly aligned with the stated PR objectives for issue #792.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/supersede-910-entry-shape-lint

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 and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Feb 15, 2026

Greptile Summary

This PR adds a regression test for entry shape type narrowing and addresses unrelated lint failures by updating .prettierignore to temporarily exclude workflow files.

Key Changes:

  • Added test case to assert that entry values maintain stable shapes (string vs array) for TypeScript type narrowing
  • Fixed test matcher from toEqual to toStrictEqual for stricter assertion
  • Updated .prettierignore to exclude Claude workflow files that cannot be modified during PR validation

The test ensures that baseConfig.entry.application remains a string and baseConfig.entry.multi_entry remains an array, which is important for TypeScript consumers to properly narrow types.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The changes are straightforward and low-risk: adds a regression test with proper assertions and updates prettierignore to prevent unrelated lint failures. Both files have clear, focused changes that don't affect production code.
  • No files require special attention

Important Files Changed

Filename Overview
.prettierignore Added workflow files to prettierignore to prevent unrelated lint failures during PR validation
test/package/environments/base.test.js Added regression test for entry shape type narrowing and fixed matcher from toEqual to toStrictEqual

Last reviewed commit: aed85d8

@justin808 justin808 force-pushed the codex/supersede-910-entry-shape-lint branch from aed85d8 to 6011002 Compare February 15, 2026 22:16
@justin808 justin808 added codex Created by Codex next-release Targeting next release p3 Low: nice-to-haves, long-term roadmap, minor improvements defer Valid but deferred; not in current release scope enhancement javascript Pull requests that update Javascript code and removed next-release Targeting next release labels Feb 27, 2026
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Misleading assertion: duplicate asymmetric matchers match same element
    • Replaced the duplicate asymmetric matcher with a single expect.any(String) so the assertion no longer implies a two-element guarantee it does not enforce.

Create PR

Or push these changes by commenting:

@cursor push 2811bbf22c
Preview (2811bbf22c)
diff --git a/test/package/environments/base.test.js b/test/package/environments/base.test.js
--- a/test/package/environments/base.test.js
+++ b/test/package/environments/base.test.js
@@ -60,7 +60,7 @@
       expect(typeof baseConfig.entry.application).toBe("string")
       expect(Array.isArray(baseConfig.entry.multi_entry)).toBe(true)
       expect(baseConfig.entry.multi_entry).toStrictEqual(
-        expect.arrayContaining([expect.any(String), expect.any(String)])
+        expect.arrayContaining([expect.any(String)])
       )
     })

Comment thread test/package/environments/base.test.js
Comment thread test/package/environments/base.test.js Outdated
Comment thread test/package/environments/base.test.js Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 15, 2026

Review

The PR is low-risk (test-only change), but there are two issues worth addressing.

Bug: weak arrayContaining assertion (line 63-65)

expect.arrayContaining([expect.any(String), expect.any(String)]) does not verify the array has 2 elements. Jest matches each asymmetric matcher against any element in the received array without consuming it, so duplicate matchers like this are effectively de-duplicated. A single-element array ["a"] would pass this assertion, defeating the purpose of the test.

Redundancy

Both new type-shape assertions largely duplicate what the adjacent tests already verify more strictly. expect(typeof baseConfig.entry.application).toBe("string") — the test at line 32 already asserts the exact resolved path string via toStrictEqual, which implicitly confirms the type. Array.isArray(baseConfig.entry.multi_entry) — the test at line 52 already calls .sort() on multi_entry and asserts its exact sorted array contents.

Suggestion

If the intent is to explicitly document TypeScript-narrowing semantics (single-entry → string, multi-entry → string[]), that is a reasonable goal, but the test should be precise enough to actually fail when those shapes break. Consider tightening to check .length and .every((v) => typeof v === "string"). Or, since the existing tests already cover this ground more thoroughly, it may be simpler to drop the new test and add a comment in the existing one noting the TypeScript-narrowing rationale.

Comment thread test/package/environments/base.test.js Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 15, 2026

Review

Overall: Low-risk addition of a regression test. No production code changes. A couple of issues worth addressing.

Redundant assertions in stringEntries.forEach

See inline comment. The forEach loop that re-checks typeof entryValue === "string" is a no-op — those values were already selected by that exact predicate. It should be removed to keep signal-to-noise high.

Simplification opportunity

The test can be made more direct by iterating once instead of building two filtered arrays. This expresses the intent directly — every entry must be either a non-empty string[] or a string — without the intermediate filter step that makes redundant assertions possible.

.prettierignore workaround

The comment reads "Temporarily ignore workflow files that cannot be modified in PRs due to claude-review validation". If these files have formatting issues, silencing prettier permanently is the wrong resolution. The "temporarily" qualifier should come with a tracking issue or a follow-up TODO referencing when/how the underlying formatting will actually be fixed, otherwise this will quietly become permanent.

Comment thread test/package/environments/base.test.js
Comment thread test/package/environments/base.test.js Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 15, 2026

Review

Good addition — a regression test protecting entry-value shapes is a clear win for TypeScript consumers of the config.

Two issues worth addressing before merge:

1. forEach + expect silent-skip risk (inline comment on lines 71–76)
If arrayEntries is empty, the inner assertions never run and the test passes vacuously. Use expect.arrayContaining([expect.any(String)]) to express the constraint in one shot, or add an explicit length guard before the loop. See the inline for a concrete suggestion.

2. String entries are never validated (inline comment on lines 62–69)
stringEntries is only used in the sum assertion — there's no check that each string entry is non-empty. The array branch gets careful inner validation; the string branch deserves the same treatment.

Minor: PR description mentions a .prettierignore update, but no such file is in the diff. If that change was intentionally left out (already merged, landed in main, etc.) it would be good to update the description so reviewers aren't left wondering.

Otherwise the test structure and intent are clear.

Comment thread test/package/environments/base.test.js
Comment thread test/package/environments/base.test.js Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 15, 2026

Review: PR #919 — Entry shape test + prettierignore

Overall: Low-risk addition (test-only, no production changes). Two issues worth addressing before merge.

Issues

1. Poor failure diagnostics (.every(...).toBe(true) pattern)

The two .every() predicate checks (lines 73-74 and 78-81) will produce unhelpful failure messages like expected false to be true with no indication of which entry value failed. See inline comment for a forEach-based alternative that names the offending value.

2. Fragile fixture dependency

expect(stringEntries.length).toBeGreaterThan(0) and expect(arrayEntries.length).toBeGreaterThan(0) (lines 71-72) implicitly require the test fixtures to contain both a single-file entry and a multi-file entry at all times. The PR's own risk note acknowledges this. The adjacent tests at lines 32-35 and 52-56 already cover the concrete shapes of application and multi_entry specifically — this generic test adds little on top of that and introduces a hidden coupling to fixture layout.

.prettierignore change

Adding workflow files to .prettierignore is a workaround for a tooling constraint (claude-review blocks modification of those files), not a formatting problem in the files themselves. That is fine as a pragmatic unblock, but worth noting that if those files ever develop genuine formatting drift they will be silently ignored.

@justin808 justin808 force-pushed the codex/supersede-910-entry-shape-lint branch from 1b8a2b3 to 2b1222a Compare April 23, 2026 02:19
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 23, 2026

Code Review

Summary: Adds a regression test to assert that baseConfig.entry values are either non-empty strings or arrays of non-empty strings — a shape contract needed for TypeScript type narrowing downstream. Low risk; no runtime changes.


What works well

  • The intent is clear and well-scoped: guard against future changes that break the string | string[] entry shape contract.
  • The .prettierignore addition is a sensible unblock for the lint CI gate.
  • The test is placed logically alongside the existing entry-point tests.

Issues

1. Fixture dependency baked into assertions (main concern)

expect(stringEntries.length).toBeGreaterThan(0)
expect(arrayEntries.length).toBeGreaterThan(0)  // requires multi_entry fixture

The second assertion silently encodes a fact about the test fixture (that multi_entry exists with both .js and .css files) rather than a fact about the runtime logic. If someone renames or removes that fixture for an unrelated reason, this test fails with a misleading message. The useful invariant — "all entry values are strings or string[]" — doesn't depend on both types being present simultaneously.

Consider splitting into two tests: one that asserts the type-shape invariant for all entries (without requiring both shapes to appear), and keep the multi_entry array-shape assertion in the existing test that explicitly exercises multi_entry.

2. .every(...).toBe(true) gives opaque failure messages

When stringEntries.every(...) fails, Jest only reports expected false to be true with no indication of which value failed or what it contained. Per project convention, prefer per-element assertions:

stringEntries.forEach((v) => expect(typeof v).toBe("string"))
stringEntries.forEach((v) => expect(v.length).toBeGreaterThan(0))
flattenedArrayEntries.forEach((v) => expect(typeof v).toBe("string"))

3. flattenedArrayEntries.length > 0 is redundant

arrayEntries.length > 0 is already asserted on the line above. Since getEntryObject only pushes into an array when there are at least two paths for the same name (the array always has ≥ 2 elements), flattenedArrayEntries can never be empty when arrayEntries is non-empty. The assertion adds noise without safety.


Minor

  • toBeGreaterThan(0) vs not.toHaveLength(0) — either works; just noting the existing tests in this file lean on toStrictEqual / toBeUndefined rather than toBeGreaterThan. Not a blocking issue.

Comment thread test/package/environments/base.test.js Outdated
Comment thread test/package/environments/base.test.js Outdated
Comment thread test/package/environments/base.test.js Outdated
Comment thread test/package/environments/base.test.js Outdated
Address review feedback on PR #919:
- Convert .every(...).toBe(true) to forEach+expect for named failure
  messages when a string entry or array element is not the expected
  shape.
- Drop expect(arrayEntries.length).toBeGreaterThan(0) which coupled
  the test to the fixture containing a multi-file entry; the
  string+array sum check already guards the type-shape invariant.
- Drop expect(flattenedArrayEntries.length).toBeGreaterThan(0) which
  was redundant with the arrayEntries guard that was removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@justin808
Copy link
Copy Markdown
Member Author

Review round addressed in f00999e

Thanks for the review. All four actionable items from the 2026-04-23 round have been applied:

  1. stringEntries.every(...).toBe(true)forEach(expect(...)) — a failing string entry now names itself in the assertion error instead of the opaque expected false to be true.
  2. flattenedArrayEntries.every(...).toBe(true)forEach(expect(...)) — same diagnostic improvement for the array-element branch.
  3. Dropped expect(arrayEntries.length).toBeGreaterThan(0) — this was the fixture-coupled assertion that required the fixture to contain both single- and multi-file entries simultaneously. The type-shape invariant is still guarded by the stringEntries.length + arrayEntries.length === entryValues.length check above, and the concrete multi_entry array shape is covered by the adjacent test at line 52.
  4. Dropped expect(flattenedArrayEntries.length).toBeGreaterThan(0) — redundant with the removed arrayEntries.length guard.

The two earlier inline comments from 2026-03-15 were superseded by this later round and have been resolved with a pointer reply. The general-body review from 2026-04-23 is covered by the inline replies on items 1–4.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Array entry assertions pass vacuously without length guard
    • Added an explicit expect(arrayEntries.length).toBeGreaterThan(0) assertion so array-entry type checks cannot pass on an empty set.

Create PR

Or push these changes by commenting:

@cursor push c9d1901dfe
Preview (c9d1901dfe)
diff --git a/test/package/environments/base.test.js b/test/package/environments/base.test.js
--- a/test/package/environments/base.test.js
+++ b/test/package/environments/base.test.js
@@ -69,6 +69,7 @@
         entryValues.length
       )
       expect(stringEntries.length).toBeGreaterThan(0)
+      expect(arrayEntries.length).toBeGreaterThan(0)
       stringEntries.forEach((entryValue) =>
         expect(entryValue.length).toBeGreaterThan(0)
       )

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit f00999e. Configure here.

)
flattenedArrayEntries.forEach((entryValue) =>
expect(typeof entryValue).toBe("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.

Array entry assertions pass vacuously without length guard

Low Severity

The test checks stringEntries.length is greater than zero before iterating, but has no equivalent guard for arrayEntries. If entry shapes ever change so no array entries exist, the flattenedArrayEntries.forEach on line 75 silently iterates over an empty array, making the type assertion vacuously true. This means the test would pass without actually verifying that array-typed entry values contain strings, undermining the purpose of the entry-shape regression test.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f00999e. Configure here.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 23, 2026

Code Review

Overview

Adds a regression test to test/package/environments/base.test.js verifying that baseConfig.entry values are consistently typed as either non-empty strings or arrays of strings. This guards against type-shape regressions that would break TypeScript narrowing downstream. No production code changes; risk is low.

What works well

  • The core invariant being tested is real and meaningful — getEntryObject() in base.ts builds entries as either a plain string or string[], and a regression test for that is appropriate.
  • The assertion stringEntries.length + arrayEntries.length === entryValues.length is a clean way to assert exhaustive type coverage without enumerating all possible alternatives.
  • Consistent with surrounding test style (module-level baseConfig, no unnecessary re-requires).

Issues

1. Silent gap: array-element validation may never run

The flattenedArrayEntries.forEach loop only executes if at least one array entry exists. In the current test fixture (nested_entries == false), multi_entry does produce an array entry so this currently runs — but nothing asserts arrayEntries.length > 0. If the fixture changes or multi_entry is removed, the inner type checks become silently vacuous and the test keeps passing even if arrays contain non-strings.

Consider adding expect(arrayEntries.length).toBeGreaterThan(0) to make the structural assumption explicit.

2. Array elements checked for type but not non-emptiness

stringEntries validates entryValue.length > 0 (non-empty), but the parallel loop for array elements only checks typeof entryValue === 'string' — an empty string would pass. For consistency with the stated goal ("non-empty strings or arrays of strings"), consider adding the same length check on flattened array elements.

Minor

  • The test description mentions "TypeScript narrowing" in a plain-JS test file. This is accurate context but may be slightly surprising to future readers. A brief inline comment linking to base.ts would help.

Summary

The test is well-reasoned and closes a real coverage gap with minimal footprint. The two issues above are low-severity but worth fixing to make the assertions watertight.

Comment on lines +74 to +75
)
flattenedArrayEntries.forEach((entryValue) =>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This loop is only exercised when arrayEntries.length > 0. In the current test fixture, multi_entry happens to produce an array entry, but there is no assertion locking that in. If the fixture changes, these checks become silently vacuous.

Suggested change
)
flattenedArrayEntries.forEach((entryValue) =>
expect(arrayEntries.length).toBeGreaterThan(0)
flattenedArrayEntries.forEach((entryValue) =>
expect(entryValue.length).toBeGreaterThan(0)
)
flattenedArrayEntries.forEach((entryValue) =>
expect(typeof entryValue).toBe("string")

This also adds the missing non-emptiness check on array elements to mirror the stringEntries check above.

@justin808 justin808 merged commit 64c2938 into main Apr 23, 2026
48 checks passed
@justin808 justin808 deleted the codex/supersede-910-entry-shape-lint branch April 23, 2026 07:16
justin808 added a commit that referenced this pull request Apr 30, 2026
* origin/main: (22 commits)
  docs: add Dependabot configuration guide (#1094)
  Sync address-review prompt with upstream PR #16 (#1098)
  Supersede #910: entry shape test with lint unblock (#919)
  fix: align rspack v2 peer deps and installer defaults (#1091)
  docs: update README and guides for Shakapacker v10 (#1092)
  Release 10.0.0
  Update CHANGELOG.md for v10.0.0 (#1089)
  Release 10.0.0-rc.1
  Update CHANGELOG.md for v10.0.0-rc.1 (#1087)
  Supersede #961 by using pack-config-diff (#973)
  Add final summary output to rake release (#1041)
  Add bin/setup to install development deps (#1039)
  Release 10.0.0-rc.0
  Use npx release-it to avoid mise shim failures (#1040)
  Fix Nokogiri build failure on Ruby 3.4.6 (#1038)
  Update CHANGELOG.md for v10.0.0-rc.0 (#1037)
  Update rspack dev deps to 2.0.0-rc.0 (#1036)
  Fix stale and broken documentation across Shakapacker guides (#1023)
  Allow webpack-cli v7 in peer dependencies (#1021)
  refactor: simplify resolving js peer versions when installing (#1034)
  ...

# Conflicts:
#	package.json
justin808 added a commit that referenced this pull request Apr 30, 2026
* origin/main:
  docs: add Dependabot configuration guide (#1094)
  Sync address-review prompt with upstream PR #16 (#1098)
  Supersede #910: entry shape test with lint unblock (#919)
  fix: align rspack v2 peer deps and installer defaults (#1091)
  docs: update README and guides for Shakapacker v10 (#1092)
  Release 10.0.0
  Update CHANGELOG.md for v10.0.0 (#1089)
  Release 10.0.0-rc.1
  Update CHANGELOG.md for v10.0.0-rc.1 (#1087)
  Supersede #961 by using pack-config-diff (#973)

# Conflicts:
#	CHANGELOG.md
#	Rakefile
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex Created by Codex defer Valid but deferred; not in current release scope enhancement javascript Pull requests that update Javascript code p3 Low: nice-to-haves, long-term roadmap, minor improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validate type narrowing for Entry type in base.ts

1 participant