Skip to content

Conversation

@ryoppippi
Copy link
Member

@ryoppippi ryoppippi commented Dec 29, 2025

Summary

  • Add @fast-check/vitest for native vitest integration with property-based testing
  • Add PBT to tfidf-index.ts: score range validation, sorting, case-insensitivity, determinism
  • Add PBT to array.ts: replace all example-based tests with comprehensive property tests
  • Add PBT to requestBuilder.ts: parameter key validation, header management, value serialization, depth limits, body type handling
  • Remove redundant example-based tests that are now covered by PBT
  • Add documentation comments to PBT explaining what tests were replaced with concrete examples

Test plan

  • All tests pass (pnpm test)
  • Coverage maintained: 92.45% statements, 93.47% lines
  • Branch coverage improved from 83.98% to 84.43%
  • Linting passes (pnpm lint)

- Add @fast-check/vitest ^0.2.0 to dev catalog
- Enables native vitest integration for PBT
- Verify scores are always within [0, 1] range
- Verify results are sorted by score in descending order
- Verify search returns at most k results
- Verify case-insensitive search produces consistent results
- Verify empty corpus always returns empty results
- Verify result IDs are from the indexed corpus
- Verify search is deterministic
- Verify array input returns same reference
- Verify non-array non-nullish input wraps in single-element array
- Verify null/undefined returns empty array
- Verify result is always an array

Property-based tests cover all original cases and more edge cases.
- Test parameter key validation (valid/invalid characters)
- Test header management (accumulation, User-Agent, immutability)
- Test value serialization (strings, integers, booleans, arrays)
- Test deep object nesting within depth limits
- Test body type handling for all supported types

PBT improves coverage of boundary conditions and error paths.
- Remove depth limit test from requestBuilder (covered by PBT)
- Remove invalid key validation test (covered by PBT)
- Remove array serialization test (covered by PBT)
- Clean up tfidf-index tests: remove Score Validation, Edge Cases,
  Case Sensitivity, and Search Limits sections (all covered by PBT)

Coverage maintained at 92.45% statements, 93.47% lines.
Branch coverage improved from 83.98% to 84.43%.
Copilot AI review requested due to automatic review settings December 29, 2025 09:10
@ryoppippi ryoppippi requested a review from a team as a code owner December 29, 2025 09:10
@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 29, 2025

Open in StackBlitz

npm i https://pkg.pr.new/StackOneHQ/stackone-ai-node/@stackone/ai@266

commit: 690d052

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 6 files

- Add JSDoc comments explaining what example-based tests were replaced
- Add inline comments with concrete examples for each property test
- Restore 'should handle arrays correctly within objects' test for clarity
- Keep concrete examples as documentation alongside PBT
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds property-based testing (PBT) support using @fast-check/vitest to enhance test coverage and replace many example-based tests with generative property tests. The changes focus on three core modules: TF-IDF indexing, array utilities, and request building.

Key Changes

  • Integration of @fast-check/vitest v0.2.4 for property-based testing
  • Replacement of 100+ lines of example-based tests with ~200 lines of property-based tests
  • Property tests now validate invariants across TF-IDF scoring, array conversions, and HTTP request building

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
pnpm-workspace.yaml Adds @fast-check/vitest v0.2.0 to dev catalog
pnpm-lock.yaml Resolves @fast-check/vitest v0.2.4 with dependencies
package.json Includes @fast-check/vitest in devDependencies
src/utils/tfidf-index.test.ts Replaces 13 example-based tests with 7 property-based tests covering score ranges, sorting, case-insensitivity, and determinism
src/utils/array.test.ts Converts example-based tests to 4 property tests validating array conversion behavior
src/requestBuilder.test.ts Replaces 3 example-based tests with property tests for parameter validation, header management, serialization, nesting limits, and body types
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* These tests verify invariants that must hold for ANY valid input,
* replacing the following example-based tests:
*
* - Score Validation: scores like 0.7071, 0.5, 1.0 are always in [0, 1]
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The removed test "handles single document corpus" is not adequately covered. While corpusArbitrary allows for single-element arrays (minLength: 1), the property-based tests don't explicitly verify the behavior with a single document, which is an important edge case. The original test verified that a search returns exactly 1 result with a positive score for a single-document corpus.

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +94
* - Case Sensitivity: "Alpha" and "ALPHA" and "alpha" return same results
* - Search Limits: search("term", 5) returns at most 5 results
*/
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The removed test "returns no matches when query shares no terms with the corpus" is not covered by property-based tests. The queryArbitrary generates valid words that might or might not match corpus content, but there's no explicit test ensuring the system correctly returns empty results when there are no matching terms. This is an important edge case that should be tested.

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +94
* - Case Sensitivity: "Alpha" and "ALPHA" and "alpha" return same results
* - Search Limits: search("term", 5) returns at most 5 results
*/
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The removed test "handles query with only stopwords" is not covered by property-based tests. This is a meaningful edge case that tests the system's stopword filtering behavior. The queryArbitrary only generates alphanumeric words without considering stopwords, so this scenario is no longer tested.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +10
* Property-Based Tests for toArray utility
*
* These tests verify the function's behavior for ANY valid input,
* replacing example-based tests like:
*
* - toArray([1, 2, 3]) === [1, 2, 3] (same reference)
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The property-based test expects toArray to return the same array reference for array inputs, but the original example-based tests showed that empty arrays return empty arrays (e.g., [] => []). The test should verify both the reference equality AND that the behavior is correct. Consider testing that the returned array contains the same elements, not just reference equality, to ensure the function doesn't mutate the input.

Copilot uses AI. Check for mistakes.
Comment on lines +678 to +686
const result = await builder.execute(params, { dryRun: true });
const url = new URL(result.url as string);

expect(url.searchParams.get('filter[key]')).toBe(String(bool));
},
);

// Example: { filter: { key: [1, 2, 3] } } => ?filter[key]=[1,2,3]
// Example: { filter: { key: ["a", "b"] } } => ?filter[key]=["a","b"]
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The test description says "all valid body types produce valid fetch options" but the assertion expects options.body to be defined. However, for a GET request with bodyParams, this behavior may not align with HTTP standards. GET requests typically shouldn't have a body. This test should verify the correct behavior for the combination of method and bodyType, or the test description should be updated to reflect what's actually being tested.

Copilot uses AI. Check for mistakes.
Comment on lines +616 to +629

// Example: const h = getHeaders(); h["X"] = "Y"; getHeaders()["X"] is still undefined
fcTest.prop([headerArbitrary], { numRuns: 50 })(
'getHeaders returns a copy, not the original',
(headers) => {
const builder = new RequestBuilder(baseConfig, headers);
const retrieved = builder.getHeaders();

// Mutating the returned object should not affect internal state
retrieved['Mutated-Header'] = 'mutated';

expect(builder.getHeaders()['Mutated-Header']).toBeUndefined();
},
);
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The removed test "should handle arrays correctly within objects" tested an important serialization behavior where arrays are converted to JSON strings in query parameters. While the new property test for arrays exists (line 621), it only tests top-level arrays in the filter object, not nested arrays within other objects. The specific nested array serialization behavior is no longer explicitly tested.

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +94
* - Case Sensitivity: "Alpha" and "ALPHA" and "alpha" return same results
* - Search Limits: search("term", 5) returns at most 5 results
*/
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The removed test "handles empty query" is not covered by the property-based tests. The queryArbitrary generator only produces non-empty strings (minLength: 1), so the edge case of searching with an empty string is no longer tested. Consider adding a specific test for empty query handling.

Copilot uses AI. Check for mistakes.
Comment on lines +85 to +90
* Property-Based Tests for TfidfIndex
*
* These tests verify invariants that must hold for ANY valid input,
* replacing the following example-based tests:
*
* - Score Validation: scores like 0.7071, 0.5, 1.0 are always in [0, 1]
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The documentArbitrary does not ensure unique document IDs. Multiple documents in the generated corpus could have the same ID, which would not test realistic scenarios and could mask potential bugs. Consider using fc.uniqueArray or adding a constraint to ensure unique IDs within the corpus.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@glebedel glebedel left a comment

Choose a reason for hiding this comment

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

LGTM

@ryoppippi ryoppippi merged commit 5d82f23 into main Dec 29, 2025
20 checks passed
@ryoppippi ryoppippi deleted the feat/property-based-testing branch December 29, 2025 11:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants