Skip to content

test: add unit tests for baked-in template discovery and filtering#1943

Open
miantalha45 wants to merge 3 commits intoasyncapi:masterfrom
miantalha45:test/add-baked-in-templates-tests
Open

test: add unit tests for baked-in template discovery and filtering#1943
miantalha45 wants to merge 3 commits intoasyncapi:masterfrom
miantalha45:test/add-baked-in-templates-tests

Conversation

@miantalha45
Copy link

@miantalha45 miantalha45 commented Feb 7, 2026

Description

Adds comprehensive unit tests for the baked-in template discovery and filtering functionality in lib/templates/bakedInTemplates.js. This addresses the gap where core template discovery functions had no dedicated test coverage.

What's Changed

  • Added test/bakedInTemplates.test.js with 31 test cases covering:
    • listBakedInTemplates: 16 tests covering no filter, single filters (type, stack, protocol, target), combined filters, and edge cases
    • isCoreTemplate: 7 tests covering existing/non-existing templates and edge cases (null, undefined, empty string, case sensitivity)
    • getTemplate: 8 tests covering path resolution, fallback behavior, and error handling

Testing

All 31 tests pass:

  • No filter scenarios
  • Single filter scenarios (type, stack, protocol, target)
  • Combined filter scenarios
  • Edge cases and error handling
  • Path resolution and fallback logic

Related Issue

Fixes #1850

Checklist

  • Tests added/updated
  • All tests pass
  • Code follows project style guidelines
  • No linting errors

Summary by CodeRabbit

  • Tests
    • Added comprehensive test coverage for baked-in templates: listing with varied filters (type, protocol, stack, target), core-template checks, and retrieval behaviors including explicit and fallback paths.
  • Bug Fixes
    • Hardened template retrieval: invalid or missing names now return no result, and path resolution reliably prefers explicit template paths when available.

@changeset-bot
Copy link

changeset-bot bot commented Feb 7, 2026

⚠️ No Changeset found

Latest commit: 3475654

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@asyncapi-bot
Copy link
Contributor

What reviewer looks at during PR review

The following are ideal points maintainers look for during review. Reviewing these points yourself beforehand can help streamline the review process and reduce time to merge.

  1. PR Title: Use a concise title that follows our Conventional Commits guidelines and clearly summarizes the change using imperative mood (it means spoken or written as if giving a command or instruction, like "add new helper for listing operations")

    Note - In Generator, prepend feat: or fix: in PR title only when PATCH/MINOR release must be triggered.

  2. PR Description: Clearly explain the issue being solved, summarize the changes made, and mention the related issue.

    Note - In Generator, we use Maintainers Work board to track progress. Ensure the PR Description includes Resolves #<issue-number> or Fixes #<issue-number> this will automatically close the linked issue when the PR is merged and helps automate the maintainers workflow.

  3. Documentation: Update the relevant Generator documentation to accurately reflect the changes introduced in the PR, ensuring users and contributors have up-to-date guidance.

  4. Comments and JSDoc: Write clear and consistent JSDoc comments for functions, including parameter types, return values, and error conditions, so others can easily understand and use the code.

  5. DRY Code: Ensure the code follows the Don't Repeat Yourself principle. Look out for duplicate logic that can be reused.

  6. Test Coverage: Ensure the new code is well-tested with meaningful test cases that pass consistently and cover all relevant edge cases.

  7. Commit History: Contributors should avoid force-pushing as much as possible. It makes it harder to track incremental changes and review the latest updates.

  8. Template Design Principles Alignment: While reviewing template-related changes in the packages/ directory, ensure they align with the Assumptions and Principles. If any principle feels outdated or no longer applicable, start a discussion these principles are meant to evolve with the project.

  9. Reduce Scope When Needed: If an issue or PR feels too large or complex, consider splitting it and creating follow-up issues. Smaller, focused PRs are easier to review and merge.

  10. Bot Comments: As reviewers, check that contributors have appropriately addressed comments or suggestions made by automated bots. If there are bot comments the reviewer disagrees with, react to them or mark them as resolved, so the review history remains clear and accurate.

@coderabbitai
Copy link

coderabbitai bot commented Feb 7, 2026

📝 Walkthrough

Walkthrough

Adds a Jest test suite and a fixture for baked‑in template helpers; updates getTemplate to validate inputs and return undefined for invalid or missing templates, and to prefer an explicit template.path with a fallback resolution.

Changes

Cohort / File(s) Summary
Baked-in Templates Tests
apps/generator/test/bakedInTemplates.test.js
New Jest test suite covering listBakedInTemplates (no filters, single and combined filters, empty/missing cases), isCoreTemplate (exists, missing, case/edge cases), and getTemplate (explicit path vs fallback, invalid inputs).
Template resolver
apps/generator/lib/templates/bakedInTemplates.js
Added input validation in getTemplate to return undefined for null/undefined/non-string/whitespace inputs; returns undefined when no match found; resolves path using template.path or a fallback path based on template.name.
Test fixture
apps/generator/test/fixtures/bakedInTemplatesFixture.json
New JSON fixture with three template descriptors (varying name, type, protocol, target, optional stack and one with explicit path) used by the new tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title follows Conventional Commits with 'test:' prefix and uses imperative mood to clearly describe adding unit tests for baked-in template discovery and filtering.
Linked Issues check ✅ Passed All three main coding requirements from issue #1850 are met: listBakedInTemplates tests (16 tests covering no filter, single filters, combined filters), isCoreTemplate tests (7 tests including edge cases), and getTemplate tests (8 tests with path resolution and fallback behavior).
Out of Scope Changes check ✅ Passed The PR includes one minor out-of-scope change: input validation in getTemplate (checking for null/undefined/non-string/whitespace) that extends beyond the test coverage objective, though it supports better error handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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.

Copy link

@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: 1

🤖 Fix all issues with AI agents
In `@apps/generator/test/bakedInTemplates.test.js`:
- Around line 201-219: The tests currently rely on incidental TypeErrors; add
explicit validation in getTemplate to check the input (e.g.,
null/undefined/empty string) and throw a clear, intentional error (for example
throw new Error('Invalid template name') ) and then update the tests in
bakedInTemplates.test.js to assert that specific error/message (use await
expect(getTemplate(...)).rejects.toThrow('Invalid template name')) so the
contract is explicit and resilient to implementation changes.
🧹 Nitpick comments (3)
apps/generator/test/bakedInTemplates.test.js (3)

112-119: Conditional guard causes this test to silently pass without asserting anything.

If no templates lack a stack property, the if block is skipped and the test passes vacuously. This is a common testing anti-pattern — a green check mark with zero coverage.

Consider either: (a) removing the guard and asserting unconditionally (skip the test if the precondition isn't met), or (b) using a mock/fixture to guarantee the precondition.

Option A: Skip when precondition is unmet (preferred)
     it('handles templates without optional stack property', () => {
       const templatesWithoutStack = templates.filter(t => !t.stack);
-      if (templatesWithoutStack.length > 0) {
-        const result = listBakedInTemplates({ stack: 'quarkus' });
-        // Should not include templates without stack property
-        expect(result.every(t => t.stack === 'quarkus')).toBe(true);
-      }
+      // Ensure precondition is met so the test is meaningful
+      expect(templatesWithoutStack.length).toBeGreaterThan(0);
+      const result = listBakedInTemplates({ stack: 'quarkus' });
+      // Filtered results must not include templates without a stack property
+      expect(result.every(t => t.stack === 'quarkus')).toBe(true);
+      // None of the stack-less templates should appear
+      templatesWithoutStack.forEach(t => {
+        expect(result.find(r => r.name === t.name)).toBeUndefined();
+      });
     });

150-156: Same silent-pass issue with the if guard on case-sensitivity test.

If templates[0].name is already all-uppercase, the if is skipped and nothing is asserted. This test should guarantee its precondition or use a known fixture.

Proposed fix
     it('is case-sensitive', () => {
       const existingTemplate = templates[0];
       const caseVariation = existingTemplate.name.toUpperCase();
-      if (caseVariation !== existingTemplate.name) {
-        expect(isCoreTemplate(caseVariation)).toBe(false);
-      }
+      // Ensure the precondition holds so the test is meaningful
+      expect(caseVariation).not.toBe(existingTemplate.name);
+      expect(isCoreTemplate(caseVariation)).toBe(false);
     });

170-189: Two more if-guarded tests that can silently pass.

Both "uses template path when available" (Line 172) and "falls back to bakedInTemplates directory" (Line 180) are fully wrapped in conditionals. If the JSON data doesn't contain the expected shape, these tests contribute nothing. Apply the same fix: assert the precondition up front or use controlled fixtures.

Comment on lines 201 to 219
it('throws error for non-existing template', async () => {
// Current implementation throws when template.name is accessed on undefined
await expect(getTemplate('nonexistent-template')).rejects.toThrow();
});

it('throws error for empty string template name', async () => {
// Current implementation will throw when template is not found
await expect(getTemplate('')).rejects.toThrow();
});

it('throws error for null template name', async () => {
// Current implementation will throw when template is not found
await expect(getTemplate(null)).rejects.toThrow();
});

it('throws error for undefined template name', async () => {
// Current implementation will throw when template is not found
await expect(getTemplate(undefined)).rejects.toThrow();
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Error tests rely on incidental TypeError rather than intentional error handling.

The comments on Lines 202, 207, 212 acknowledge these tests depend on the implementation accidentally throwing (e.g., accessing .name on undefined). This is brittle — if the implementation changes to return undefined or null instead of throwing, these tests break or become misleading.

Consider verifying the actual error type/message to document the expected contract, or filing an issue to add explicit validation in getTemplate.

#!/bin/bash
# Check if getTemplate has explicit validation/error handling for invalid input
ast-grep --pattern $'function getTemplate($_) {
  $$$
}'

# Also check as arrow/async function or module.exports
rg -n -A 15 'getTemplate' --glob '**/bakedInTemplates.js'
🤖 Prompt for AI Agents
In `@apps/generator/test/bakedInTemplates.test.js` around lines 201 - 219, The
tests currently rely on incidental TypeErrors; add explicit validation in
getTemplate to check the input (e.g., null/undefined/empty string) and throw a
clear, intentional error (for example throw new Error('Invalid template name') )
and then update the tests in bakedInTemplates.test.js to assert that specific
error/message (use await expect(getTemplate(...)).rejects.toThrow('Invalid
template name')) so the contract is explicit and resilient to implementation
changes.

@miantalha45 miantalha45 force-pushed the test/add-baked-in-templates-tests branch from dcd5b05 to ba7e988 Compare February 8, 2026 06:02
Copy link

@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: 1

🤖 Fix all issues with AI agents
In `@apps/generator/lib/templates/bakedInTemplates.js`:
- Line 43: Update the JSDoc on the function in
apps/generator/lib/templates/bakedInTemplates.js that currently has "@returns
{Promise<{name: string, path: string}|undefined>}" to remove the "|undefined"
since the function never returns undefined, and add one or more "@throws" tags
documenting the error conditions the function can raise (e.g., invalid
input/argument validation errors and "template not found" errors) so callers
know what exceptions to handle; keep the existing `@returns` describing
Promise<{name: string, path: string}> and ensure the `@throws` messages reference
the actual thrown error types/messages used by that function.
🧹 Nitpick comments (1)
apps/generator/lib/templates/bakedInTemplates.js (1)

53-53: Redundant __dirname in path.resolveBAKED_IN_TEMPLATES_DIR is already absolute.

BAKED_IN_TEMPLATES_DIR (Line 4) is resolved to an absolute path via path.resolve(__dirname, 'bakedInTemplates'). When path.resolve encounters an absolute segment, it discards all preceding segments, so __dirname here is silently ignored. The code works but is misleading.

Suggested fix
-  const templatePath = template.path || path.resolve(__dirname, BAKED_IN_TEMPLATES_DIR, template.name);
+  const templatePath = template.path || path.resolve(BAKED_IN_TEMPLATES_DIR, template.name);

@@ -43,9 +43,14 @@ module.exports.isCoreTemplate = (templateName) => {
* @returns {Promise<{name: string, path: string}|undefined>} An object containing the template's name and path, or undefined if not found.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

JSDoc @returns is now inaccurate — the function never returns undefined.

Since both invalid input and missing templates now throw, the |undefined in the return type is misleading. Also, the @throws conditions should be documented per the coding guidelines.

Proposed fix
- * `@returns` {Promise<{name: string, path: string}|undefined>} An object containing the template's name and path, or undefined if not found.
+ * `@returns` {Promise<{name: string, path: string}>} An object containing the template's name and resolved path.
+ * `@throws` {Error} If templateName is not a non-empty string or does not match any core template.

As per coding guidelines: **/*.{js,ts,jsx,tsx}: Write clear and consistent JSDoc comments for functions, including parameter types, return values, and error conditions.

📝 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
* @returns {Promise<{name: string, path: string}|undefined>} An object containing the template's name and path, or undefined if not found.
* `@returns` {Promise<{name: string, path: string}>} An object containing the template's name and resolved path.
* `@throws` {Error} If templateName is not a non-empty string or does not match any core template.
🤖 Prompt for AI Agents
In `@apps/generator/lib/templates/bakedInTemplates.js` at line 43, Update the
JSDoc on the function in apps/generator/lib/templates/bakedInTemplates.js that
currently has "@returns {Promise<{name: string, path: string}|undefined>}" to
remove the "|undefined" since the function never returns undefined, and add one
or more "@throws" tags documenting the error conditions the function can raise
(e.g., invalid input/argument validation errors and "template not found" errors)
so callers know what exceptions to handle; keep the existing `@returns` describing
Promise<{name: string, path: string}> and ensure the `@throws` messages reference
the actual thrown error types/messages used by that function.

Copy link
Member

Choose a reason for hiding this comment

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

@miantalha45 please look at CodeRabbit, it rarely makes mistakes

*/
const path = require('path');
const { listBakedInTemplates, isCoreTemplate, getTemplate } = require('../lib/templates/bakedInTemplates');
const templates = require('../lib/templates/BakedInTemplatesList.json');
Copy link
Member

Choose a reason for hiding this comment

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

you cannot test using production data because any changes in the list of templates can cause false/positive errors in tests - you need to create a dummy fixture that will be used only in tests

@@ -43,9 +43,14 @@ module.exports.isCoreTemplate = (templateName) => {
* @returns {Promise<{name: string, path: string}|undefined>} An object containing the template's name and path, or undefined if not found.
*/
module.exports.getTemplate = async (templateName) => {
Copy link
Member

Choose a reason for hiding this comment

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

I'm not fan of throwing errors but rather gracefully going forward if possible. So if template name is invalid, it should work like the template name is not on the list, and return empty array, not throw error

@sonarqubecloud
Copy link

Copy link

@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.

🧹 Nitpick comments (1)
apps/generator/lib/templates/bakedInTemplates.js (1)

54-54: Redundant __dirname in path.resolve — the first argument is silently ignored.

BAKED_IN_TEMPLATES_DIR (line 4) is already an absolute path produced by path.resolve(__dirname, 'bakedInTemplates'). When path.resolve encounters an absolute segment, it discards everything before it, so the leading __dirname here is dead code and misleading to future readers.

Proposed fix
-  const templatePath = template.path || path.resolve(__dirname, BAKED_IN_TEMPLATES_DIR, template.name);
+  const templatePath = template.path || path.resolve(BAKED_IN_TEMPLATES_DIR, template.name);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/generator/lib/templates/bakedInTemplates.js` at line 54, The call
constructing templatePath uses path.resolve(__dirname, BAKED_IN_TEMPLATES_DIR,
template.name) but BAKED_IN_TEMPLATES_DIR is already an absolute path so the
leading __dirname is redundant; update the expression that sets templatePath
(where template.path || path.resolve(...)) to remove __dirname and call
path.resolve(BAKED_IN_TEMPLATES_DIR, template.name) (keeping the fallback to
template.path unchanged), ensuring references to templatePath,
BAKED_IN_TEMPLATES_DIR, template.name, and path.resolve are adjusted
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/generator/lib/templates/bakedInTemplates.js`:
- Line 54: The call constructing templatePath uses path.resolve(__dirname,
BAKED_IN_TEMPLATES_DIR, template.name) but BAKED_IN_TEMPLATES_DIR is already an
absolute path so the leading __dirname is redundant; update the expression that
sets templatePath (where template.path || path.resolve(...)) to remove __dirname
and call path.resolve(BAKED_IN_TEMPLATES_DIR, template.name) (keeping the
fallback to template.path unchanged), ensuring references to templatePath,
BAKED_IN_TEMPLATES_DIR, template.name, and path.resolve are adjusted
accordingly.

@miantalha45 miantalha45 requested a review from derberg February 17, 2026 09:34
@derberg derberg moved this to In Progress in Maintainers work Feb 18, 2026
@derberg derberg self-assigned this Feb 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

Add unit tests for baked‑in template discovery/filtering

3 participants

Comments