Skip to content

Conversation

johnmasking
Copy link
Member

@johnmasking johnmasking commented Apr 5, 2025

Fixes #401

Changes proposed in this pull request:

  • create updateRecords in interface
  • create deleteRecords in interface
  • create updateRecords implementation in MongoDB
  • create updateRecords iimplementation in Memory
  • create deleteRecords implementation in MongoDB
  • create deleteRecords implementation in Memory
  • create tests

@MaskingTechnology/comify

Summary by CodeRabbit

  • New Features

    • Introduced bulk record update and deletion capabilities, allowing more efficient data management with improved filtering for precise record selection.
    • Added new methods for searching and finding records, improving data retrieval functionality.
    • Added a new query option to enhance filtering criteria in database queries.
    • Introduced new error classes for improved error handling related to record operations.
  • Bug Fixes

    • Enhanced error handling for record update and deletion operations to ensure better reliability.
  • Tests

    • Expanded test coverage to ensure the reliability and robustness of the new bulk operations, including new test suites for deleting and updating multiple records.
    • Added tests for limiting search results and verifying sorting functionality.

@johnmasking johnmasking linked an issue Apr 5, 2025 that may be closed by this pull request
@petermasking petermasking changed the title #401 (feat delete and update bulk requests in database interfaces feat: bulk updates and and deletes Apr 5, 2025
@petermasking petermasking changed the title feat: bulk updates and and deletes feat: bulk db operations Apr 5, 2025
@basmasking basmasking requested a review from Copilot April 5, 2025 20:37
Copy link

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

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

@basmasking basmasking self-requested a review April 5, 2025 20:38
Copy link

coderabbitai bot commented Apr 7, 2025

Walkthrough

The pull request introduces bulk operations to the database integration. Two new methods, updateRecords and deleteRecords, have been added to the core Database class and its underlying implementations in both the in-memory and MongoDB drivers. Corresponding changes were also made to the Driver interface definitions. Additionally, a new query filter and test suites have been added to verify the functionality of batch updates and deletions.

Changes

Files Change Summary
src/integrations/database/Database.ts
src/integrations/database/definitions/interfaces.ts
Added new methods updateRecords and deleteRecords to support bulk operations.
src/integrations/database/implementations/memory/Memory.ts
src/integrations/database/implementations/mongodb/MongoDb.ts
Implemented updateRecords and deleteRecords with bulk update and deletion logic, including error handling.
test/integrations/database/fixtures/queries.fixture.ts Added new query UPDATED with condition { size: { EQUALS: 40 } }.
test/integrations/database/implementation.spec.ts Added test suites for verifying the functionality of updateRecords and deleteRecords methods.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Database
    participant Driver
    Client->>Database: updateRecords(type, query, data)
    Database->>Driver: updateRecords(type, query, data)
    Driver-->>Database: Promise<void>
    Database-->>Client: Promise<void>
Loading
sequenceDiagram
    participant Client
    participant Database
    participant Driver
    Client->>Database: deleteRecords(type, query)
    Database->>Driver: deleteRecords(type, query)
    Driver-->>Database: Promise<void>
    Database-->>Client: Promise<void>
Loading

Assessment against linked issues

Objective Addressed Explanation
Bulk updates and deletes (#401)

Poem

Oh, I’m a bunny now, so spry and keen,
Hopping through code where bulk ops are seen.
Records update and vanish with speed,
Deletion's magic fulfills every need.
With whiskers twitching, I celebrate this scene! 🐰
Bursting with joy like a field of clover, so green!

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 077d96c and 1ada769.

📒 Files selected for processing (6)
  • src/integrations/database/Database.ts (1 hunks)
  • src/integrations/database/definitions/interfaces.ts (1 hunks)
  • src/integrations/database/implementations/memory/Memory.ts (1 hunks)
  • src/integrations/database/implementations/mongodb/MongoDb.ts (1 hunks)
  • test/integrations/database/fixtures/queries.fixture.ts (1 hunks)
  • test/integrations/database/implementation.spec.ts (3 hunks)
🧰 Additional context used
🧬 Code Definitions (4)
src/integrations/database/definitions/interfaces.ts (3)
src/integrations/database/implementations/memory/Memory.ts (4)
  • type (289-306)
  • query (206-213)
  • query (215-232)
  • data (308-324)
src/integrations/database/definitions/types.ts (3)
  • RecordType (6-6)
  • RecordQuery (20-20)
  • RecordData (11-11)
src/integrations/database/implementations/mongodb/MongoDb.ts (2)
  • query (209-250)
  • data (295-318)
src/integrations/database/Database.ts (3)
src/integrations/database/implementations/memory/Memory.ts (4)
  • type (289-306)
  • query (206-213)
  • query (215-232)
  • data (308-324)
src/integrations/database/definitions/types.ts (3)
  • RecordType (6-6)
  • RecordQuery (20-20)
  • RecordData (11-11)
src/integrations/database/implementations/mongodb/MongoDb.ts (2)
  • query (209-250)
  • data (295-318)
src/integrations/database/implementations/memory/Memory.ts (3)
src/integrations/database/definitions/types.ts (2)
  • QueryStatement (19-19)
  • RecordData (11-11)
src/integrations/database/errors/RecordNotUpdated.ts (1)
  • RecordNotUpdated (4-10)
src/integrations/database/errors/RecordNotFound.ts (1)
  • RecordNotFound (4-10)
test/integrations/database/implementation.spec.ts (2)
test/integrations/database/fixtures/queries.fixture.ts (1)
  • QUERIES (8-84)
src/integrations/database/definitions/types.ts (1)
  • RecordData (11-11)
🔇 Additional comments (3)
test/integrations/database/fixtures/queries.fixture.ts (1)

10-10: LGTM: The new query definition follows the existing pattern.

The new UPDATED query is well-structured and follows the existing pattern in this file, providing a clean way to test the new bulk update functionality.

src/integrations/database/definitions/interfaces.ts (1)

16-17: LGTM: Interface extensions align with the PR objectives.

The new method signatures for bulk operations follow the same pattern as the single-record operations and maintain consistency with the overall interface design.

src/integrations/database/Database.ts (1)

68-71: LGTM: The deleteRecords implementation is correct.

The implementation correctly delegates to the driver's deleteRecords method with the appropriate parameters.

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

🧹 Nitpick comments (1)
src/integrations/database/implementations/memory/Memory.ts (1)

135-144: Bulk updates mirror single updates.

Similar to .deleteRecords(), consider a single-pass approach for large data sets. Repeatedly calling .updateRecord() can degrade performance.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1ada769 and fc8e932.

📒 Files selected for processing (3)
  • src/integrations/database/Database.ts (2 hunks)
  • src/integrations/database/implementations/memory/Memory.ts (4 hunks)
  • test/integrations/database/implementation.spec.ts (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
test/integrations/database/implementation.spec.ts (6)
test/integrations/database/fixtures/records.fixture.ts (2)
  • RECORD_TYPES (4-8)
  • RECORDS (10-24)
test/integrations/database/fixtures/queries.fixture.ts (1)
  • QUERIES (8-84)
test/integrations/database/fixtures/values.fixture.ts (1)
  • VALUES (2-24)
src/integrations/database/errors/RecordNotFound.ts (1)
  • RecordNotFound (4-10)
src/integrations/database/errors/RecordNotUpdated.ts (1)
  • RecordNotUpdated (4-10)
src/integrations/database/definitions/types.ts (1)
  • RecordData (11-11)
src/integrations/database/implementations/memory/Memory.ts (3)
src/integrations/database/errors/RecordNotFound.ts (1)
  • RecordNotFound (4-10)
src/integrations/database/definitions/types.ts (2)
  • QueryStatement (19-19)
  • RecordData (11-11)
src/integrations/database/errors/RecordNotUpdated.ts (1)
  • RecordNotUpdated (4-10)
src/integrations/database/Database.ts (2)
src/integrations/database/definitions/types.ts (6)
  • RecordType (6-6)
  • RecordId (7-7)
  • RecordQuery (20-20)
  • RecordField (9-9)
  • RecordSort (23-23)
  • RecordData (11-11)
src/integrations/utilities/sanitize.ts (1)
  • sanitize (16-26)
🔇 Additional comments (20)
test/integrations/database/implementation.spec.ts (6)

4-4: Import usage looks proper.

No concerns regarding the newly introduced import of RecordData; it aligns with the test usage below.


36-54: Good test coverage for bulk deletion.

These tests cover both the successful bulk delete scenario and the no-match scenario, ensuring robust functionality.


71-86: Clear verification for limiting results.

The suite properly checks the limit and offset functionality, ensuring .limitNumberOfRecords behaves as intended.


88-114: Thorough coverage for record reading.

The tests validate reading a full record, partial fields, and handling of a non-existing record. Nicely done.


267-284: Comprehensive one-record update testing.

These tests correctly verify updating a record by ID and handling a non-existing record. Looks good.


286-307: Well-structured tests for batch updates.

The suite ensures all matching records are updated correctly and checks that no error is thrown when none match, providing meaningful coverage.

src/integrations/database/Database.ts (8)

18-21: Straightforward .clear() pass-through.

No issues; the method simply delegates to the driver and maintains consistency.


23-26: .connect() delegation is clear.

This direct pass-through ensures the driver determines the connection state.


35-38: Consistent .deleteRecord() method.

Delegating the call to the driver is appropriate. No concerns.


40-43: Bulk deletion logic is properly delegated.

Implementation aligns with the driver’s deleteRecords interface, keeping the method succinct.


45-48: Clean .disconnect() delegation.

Method is consistent with the driver-based disconnection approach.


55-59: Direct .readRecord() pass-through.

No issues; it cleanly calls this.#driver.readRecord(...).


65-71: Sanitization in .updateRecord() looks good.

Ensuring data is sanitized before delegating to the driver helps maintain consistency with single-record updates.


72-77: Bulk update method includes sanitization.

This addresses past concerns about missing data sanitization in updateRecords. Implementation is now consistent with .updateRecord().

src/integrations/database/implementations/memory/Memory.ts (6)

35-38: .clear() method is straightforward.

Clearing the in-memory store is well-handled.


40-43: .connect() implementation is simple.

No issues; flipping the #connected flag to true is sufficient for an in-memory driver.


58-69: Single-record deletion logic is correct.

Throwing RecordNotFound when no index is found ensures correctness. This is in line with the tests.


82-85: Simple disconnection approach.

Setting #connected = false is enough for an in-memory driver.


94-105: Reading a record by ID is well-implemented.

The logic checks for existence and throws RecordNotFound when absent, matching the test scenarios.


119-133: One-record update approach is sound.

Updates the desired fields and throws RecordNotUpdated for non-existing records. No concerns.

@basmasking basmasking requested review from petermasking and removed request for basmasking April 9, 2025 17:45
* Memory integration optimizations
* New bulk operation errors
* Code formatting and consistence improvements
@petermasking petermasking requested review from basmasking and removed request for petermasking April 11, 2025 08:21
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: 0

🧹 Nitpick comments (2)
src/integrations/database/Database.ts (2)

40-43: Consider adding JSDoc comments for better documentation.

The findRecord method is well-implemented but could benefit from JSDoc comments explaining its purpose, parameters, and return value for better maintainability and developer experience.

+/**
+ * Finds a single record matching the provided query.
+ * 
+ * @param type - The type of records to search in
+ * @param query - The query to filter records
+ * @param fields - Optional fields to include in the result
+ * @param sort - Optional sort criteria
+ * @returns A promise that resolves to the matching record or undefined if not found
+ */
findRecord(type: RecordType, query: RecordQuery, fields?: RecordField[], sort?: RecordSort): Promise<RecordData | undefined>
{
    return this.#driver.findRecord(type, query, fields, sort);
}

45-48: Consider adding JSDoc comments for better documentation.

Similar to the findRecord method, searchRecords could benefit from JSDoc comments explaining its purpose, parameters, and return value.

+/**
+ * Searches for records matching the provided query.
+ * 
+ * @param type - The type of records to search in
+ * @param query - The query to filter records
+ * @param fields - Optional fields to include in the result
+ * @param sort - Optional sort criteria
+ * @param limit - Optional maximum number of records to return
+ * @param offset - Optional number of records to skip
+ * @returns A promise that resolves to an array of matching records
+ */
searchRecords(type: RecordType, query: RecordQuery, fields?: RecordField[], sort?: RecordSort, limit?: number, offset?: number): Promise<RecordData[]>
{
    return this.#driver.searchRecords(type, query, fields, sort, limit, offset);
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 49a967c and 4913ef1.

📒 Files selected for processing (1)
  • src/integrations/database/Database.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/integrations/database/Database.ts (2)
src/integrations/database/definitions/types.ts (6)
  • RecordType (6-6)
  • RecordQuery (20-20)
  • RecordField (9-9)
  • RecordSort (23-23)
  • RecordData (11-11)
  • RecordId (7-7)
src/integrations/utilities/sanitize.ts (1)
  • sanitize (16-26)
🔇 Additional comments (3)
src/integrations/database/Database.ts (3)

57-62: Good job implementing data sanitization for bulk updates.

The updateRecords method properly sanitizes the data before passing it to the driver, maintaining consistency with the updateRecord method's approach to data handling.

It would be helpful to add JSDoc comments for better documentation:

+/**
+ * Updates multiple records matching the provided query.
+ * 
+ * @param type - The type of records to update
+ * @param query - The query to filter records for updating
+ * @param data - The data to update in the matching records
+ * @returns A promise that resolves when the update is complete
+ */
updateRecords(type: RecordType, query: RecordQuery, data: RecordData): Promise<void>
{
    const cleanData = sanitize(data);

    return this.#driver.updateRecords(type, query, cleanData);
}

64-67: Implementation looks good.

The deleteRecord method correctly delegates to the driver's implementation.

Consider adding JSDoc comments for better documentation:

+/**
+ * Deletes a single record by its ID.
+ * 
+ * @param type - The type of record to delete
+ * @param id - The ID of the record to delete
+ * @returns A promise that resolves when the deletion is complete
+ */
deleteRecord(type: RecordType, id: RecordId): Promise<void>
{
    return this.#driver.deleteRecord(type, id);
}

69-72: Implementation looks good.

The deleteRecords method correctly delegates to the driver's implementation for bulk deletion.

Consider adding JSDoc comments for better documentation:

+/**
+ * Deletes multiple records matching the provided query.
+ * 
+ * @param type - The type of records to delete
+ * @param query - The query to filter records for deletion
+ * @returns A promise that resolves when the deletion is complete
+ */
deleteRecords(type: RecordType, query: RecordQuery): Promise<void>
{
    return this.#driver.deleteRecords(type, query);
}

Copy link
Member

Choose a reason for hiding this comment

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

The tests are ordered in alphabetical order, but the order should be similar to the database defintion for easier maintenance.

Copy link
Member Author

Choose a reason for hiding this comment

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

order changed

{
it('should update all records matching the query', async () =>
{
const data: RecordData = { size: 40 };
Copy link
Member

Choose a reason for hiding this comment

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

In the values fixture we put the values we use in the tests. These hard coded numbers should be avoided in the test to make them easier to maintain.

Copy link
Member Author

Choose a reason for hiding this comment

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

data added to values.

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: 0

🧹 Nitpick comments (4)
test/integrations/database/implementation.spec.ts (4)

16-30: Consider testing multiple-match scenarios for .findRecord.

These tests effectively cover the “first match found” and “no match” cases. If multiple records can match, it may be beneficial to test ensuring the method indeed returns a single record (and specifically the first).


180-197: Tests for .updateRecord are thorough.

These tests verify both the successful update scenario and the error path for non-existent records. Consider adding a scenario for updating multiple fields at once, if applicable, to broaden coverage.


199-220: Good coverage for .updateRecords.

The tests confirm successful bulk updates and the no-match scenario. One optional enhancement: verify that records not covered by the query remain unchanged, ensuring updates are narrowly applied.


278-307: Extensive coverage for .sortRecords.

Tests verify ascending, descending, and multi-field variations. As an optional improvement, consider adding coverage for cases where some records might lack the sort field.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 99d07c4 and 58178ac.

📒 Files selected for processing (2)
  • test/integrations/database/fixtures/values.fixture.ts (1 hunks)
  • test/integrations/database/implementation.spec.ts (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/integrations/database/implementation.spec.ts (7)
test/integrations/database/fixtures/records.fixture.ts (2)
  • RECORD_TYPES (4-8)
  • RECORDS (10-24)
test/integrations/database/fixtures/queries.fixture.ts (1)
  • QUERIES (8-84)
src/integrations/database/errors/RecordNotUpdated.ts (1)
  • RecordNotUpdated (4-10)
src/integrations/database/definitions/types.ts (1)
  • RecordData (11-11)
src/integrations/database/errors/RecordNotFound.ts (1)
  • RecordNotFound (4-10)
test/integrations/database/fixtures/sorts.fixture.ts (1)
  • SORTS (5-11)
test/integrations/database/fixtures/results.fixture.ts (1)
  • RESULTS (8-33)
🔇 Additional comments (4)
test/integrations/database/fixtures/values.fixture.ts (1)

23-27: Good addition of a dedicated SIZE property.

Adding a new SIZE property in the fixtures helps keep test data consistent and centralized. This aligns well with previous feedback about avoiding hard-coded constants directly in the tests.

test/integrations/database/implementation.spec.ts (3)

4-4: Type import looks correct.

Importing RecordData as a type-only import is a clean approach, reducing overhead while improving clarity of the test logic.


222-239: Robust tests for .deleteRecord.

These tests correctly validate normal and error scenarios (record not found). Concurrency or partial-field checks are likely out of scope here, so this coverage suffices.


241-259: Comprehensive .deleteRecords testing.

Both the successful bulk-deletion and the empty-match scenario are properly verified, ensuring no accidental failures or unclear edge cases.

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

🧹 Nitpick comments (1)
test/integrations/database/implementation.spec.ts (1)

180-307: Consider reordering test suites to match database class structure.

The test suites appear to be in a somewhat random order. According to a previous review comment (line 1), the tests should be ordered similar to the database definition for easier maintenance.

Consider reordering the test suites to match the order of methods in the Database class:

  1. .readRecord
  2. .findRecord
  3. .searchRecords
  4. .limitNumberOfRecords
  5. .sortRecords
  6. .updateRecord
  7. .updateRecords
  8. .deleteRecord
  9. .deleteRecords
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 58178ac and 327ef4c.

📒 Files selected for processing (1)
  • test/integrations/database/implementation.spec.ts (5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/integrations/database/implementation.spec.ts (7)
test/integrations/database/fixtures/records.fixture.ts (2)
  • RECORD_TYPES (4-8)
  • RECORDS (10-24)
test/integrations/database/fixtures/queries.fixture.ts (1)
  • QUERIES (8-84)
test/integrations/database/fixtures/values.fixture.ts (1)
  • VALUES (2-29)
src/integrations/database/errors/RecordNotUpdated.ts (1)
  • RecordNotUpdated (4-10)
src/integrations/database/definitions/types.ts (1)
  • RecordData (11-11)
src/integrations/database/errors/RecordNotFound.ts (1)
  • RecordNotFound (4-10)
test/integrations/database/fixtures/sorts.fixture.ts (1)
  • SORTS (5-11)
🔇 Additional comments (5)
test/integrations/database/implementation.spec.ts (5)

4-4: LGTM: Added RecordData import.

The import of RecordData type is appropriate as it's used in the new test cases.


202-210: LGTM: Comprehensive test for updateRecords.

The test correctly verifies both the count and the actual values of the updated records, ensuring that the bulk update functionality works as expected. This addresses a previous review comment.


212-219: LGTM: Edge case handling for updateRecords.

Good test for ensuring that no errors are thrown when no records match the query. This aligns with the behavior we would expect and addresses a previous review comment.


243-249: LGTM: Comprehensive test for deleteRecords.

The test correctly verifies that all matching records are deleted by checking that a subsequent search returns no results.


251-258: LGTM: Edge case handling for deleteRecords.

Good test for ensuring that no errors are thrown when no records match the query, and that the database state remains unchanged. This addresses a previous review comment.

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

🧹 Nitpick comments (3)
test/integrations/database/implementation.spec.ts (3)

219-226: Enhance the .updateRecords test with proper value usage from fixtures.

The test is implementing the suggestions from previous reviews, which is good. However, you should use the value from the fixtures consistently.

-            const data: RecordData = VALUES.SIZE;
+            const data: RecordData = VALUES.SIZE;
             await database.updateRecords(RECORD_TYPES.PIZZAS, QUERIES.EQUALS, data);

             const records = await database.searchRecords(RECORD_TYPES.PIZZAS, QUERIES.UPDATED);
             expect(records).toHaveLength(2);
-            expect(records[0].size).toBe(40);
-            expect(records[1].size).toBe(40);
+            // Use the fixture value instead of hardcoding
+            expect(records[0].size).toBe(VALUES.SIZE.size);
+            expect(records[1].size).toBe(VALUES.SIZE.size);

230-234: Use fixture values for consistency in the second updateRecords test.

To maintain consistency with the rest of the tests and follow the feedback in previous reviews, use values from fixtures rather than hardcoded values.

-            const data: RecordData = { size: 99 };
+            // Add this value to VALUES.SIZE in the fixture, e.g., NO_MATCH_SIZE: { size: 99 }
+            const data: RecordData = VALUES.SIZE.NO_MATCH_SIZE;

             // This should not throw an error
             await expect(database.updateRecords(RECORD_TYPES.PIZZAS, QUERIES.NO_MATCH, data))
                 .resolves.toBeUndefined();

293-323: Maintain consistent indentation.

The indentation for the .sortRecords test suite appears to have changed. Ensure it matches the style of other test suites for consistency.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 327ef4c and dddcfbb.

📒 Files selected for processing (1)
  • test/integrations/database/implementation.spec.ts (5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/integrations/database/implementation.spec.ts (8)
test/integrations/database/fixtures/records.fixture.ts (2)
  • RECORD_TYPES (4-8)
  • RECORDS (10-24)
test/integrations/database/fixtures/queries.fixture.ts (1)
  • QUERIES (8-84)
test/integrations/database/fixtures/values.fixture.ts (1)
  • VALUES (2-29)
src/integrations/database/errors/RecordNotFound.ts (1)
  • RecordNotFound (4-10)
src/integrations/database/errors/RecordNotUpdated.ts (1)
  • RecordNotUpdated (4-10)
src/integrations/database/definitions/types.ts (1)
  • RecordData (11-11)
test/integrations/database/fixtures/sorts.fixture.ts (1)
  • SORTS (5-11)
test/integrations/database/fixtures/results.fixture.ts (1)
  • RESULTS (8-33)
🔇 Additional comments (2)
test/integrations/database/implementation.spec.ts (2)

196-255: Clarify intent regarding single-record operations.

The PR is introducing bulk operations with updateRecords and deleteRecords, but the test file still contains tests for the single-record operations updateRecord and deleteRecord. Please confirm if:

  1. Both single and bulk operations will coexist (preferred for backward compatibility)
  2. Or if the single operations are deprecated and these tests should be removed

If single operations are being maintained, consider adding a note in the tests explaining the relationship between the single and bulk operations.


267-274: LGTM - Properly implemented .deleteRecords test with verification.

The test correctly implements the suggested behavior from past review comments, including verification that the database state remains unchanged when no records match the query.

Comment on lines +40 to 59
describe('.findRecord', () =>
{
it('should delete a record by id', async () =>
{
const id = RECORDS.FRUITS.APPLE.id as string;

await database.deleteRecord(RECORD_TYPES.FRUITS, id);

const promise = database.readRecord(RECORD_TYPES.FRUITS, id);
await expect(promise).rejects.toStrictEqual(new RecordNotFound());
});

it('should throw an error when the record cannot be deleted', async () =>
it('should return the first matched record', async () =>
{
const promise = database.deleteRecord(RECORD_TYPES.PIZZAS, VALUES.IDS.NON_EXISTING);
await expect(promise).rejects.toStrictEqual(new RecordNotFound());
const result = await database.findRecord(RECORD_TYPES.PIZZAS, QUERIES.EMPTY);
expect(result).toMatchObject(RECORDS.PIZZAS.MARGHERITA);
});
});

describe('.updateRecord', () =>
{
it('should update a record by id', async () =>
it('should return undefined when no match found', async () =>
{
const id = RECORDS.FRUITS.PEAR.id as string;

await database.updateRecord(RECORD_TYPES.FRUITS, id, { country: VALUES.UPDATES.COUNTRY });

const result = await database.readRecord(RECORD_TYPES.FRUITS, id);
expect(result?.country).toBe(VALUES.UPDATES.COUNTRY);
const result = await database.findRecord(RECORD_TYPES.PIZZAS, QUERIES.NO_MATCH);
expect(result).toBe(undefined);
});

it('should throw an error when record cannot be updated', async () =>
it('should throw an error when a record is not found', async () =>
{
const promise = database.updateRecord(RECORD_TYPES.FRUITS, VALUES.IDS.NON_EXISTING, {});
await expect(promise).rejects.toStrictEqual(new RecordNotUpdated());
const promise = database.readRecord(RECORD_TYPES.PIZZAS, VALUES.IDS.NON_EXISTING);
await expect(promise).rejects.toStrictEqual(new RecordNotFound());
});
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix duplicate test suite for .findRecord.

There are two identical test suites for .findRecord which will result in the same tests being run twice. The first suite also includes a test case that belongs to .readRecord since it's testing database.readRecord() behavior.

Apply this fix:

// Keep the second suite at lines 61-74 and remove the first one at lines 40-59
-    describe('.findRecord', () =>
-    {
-        it('should return the first matched record', async () =>
-        {
-            const result = await database.findRecord(RECORD_TYPES.PIZZAS, QUERIES.EMPTY);
-            expect(result).toMatchObject(RECORDS.PIZZAS.MARGHERITA);
-        });
-
-        it('should return undefined when no match found', async () =>
-        {
-            const result = await database.findRecord(RECORD_TYPES.PIZZAS, QUERIES.NO_MATCH);
-            expect(result).toBe(undefined);
-        });
-
-        it('should throw an error when a record is not found', async () =>
-        {
-            const promise = database.readRecord(RECORD_TYPES.PIZZAS, VALUES.IDS.NON_EXISTING);
-            await expect(promise).rejects.toStrictEqual(new RecordNotFound());
-        });
-    });

Then, move the third test case to the .readRecord suite:

    describe('.readRecord', () =>
    {
        // Existing tests...
+
+        it('should throw an error when a record is not found', async () =>
+        {
+            const promise = database.readRecord(RECORD_TYPES.PIZZAS, VALUES.IDS.NON_EXISTING);
+            await expect(promise).rejects.toStrictEqual(new RecordNotFound());
+        });
    });

Also applies to: 61-74

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.

Actionable comments posted: 0

♻️ Duplicate comments (1)
test/integrations/database/implementation.spec.ts (1)

40-59: ⚠️ Potential issue

Fix duplicate test suite for .findRecord.

There are two identical test suites for .findRecord which will result in the same tests being run twice. The first suite also includes a test case that belongs to .readRecord since it's testing database.readRecord() behavior.

Apply this fix:

// Keep the second suite at lines 61-74 and remove the first one at lines 40-59
-    describe('.findRecord', () =>
-    {
-        it('should return the first matched record', async () =>
-        {
-            const result = await database.findRecord(RECORD_TYPES.PIZZAS, QUERIES.EMPTY);
-            expect(result).toMatchObject(RECORDS.PIZZAS.MARGHERITA);
-        });
-
-        it('should return undefined when no match found', async () =>
-        {
-            const result = await database.findRecord(RECORD_TYPES.PIZZAS, QUERIES.NO_MATCH);
-            expect(result).toBe(undefined);
-        });
-
-        it('should throw an error when a record is not found', async () =>
-        {
-            const promise = database.readRecord(RECORD_TYPES.PIZZAS, VALUES.IDS.NON_EXISTING);
-            await expect(promise).rejects.toStrictEqual(new RecordNotFound());
-        });
-    });

Then, move the third test case to the .readRecord suite:

    describe('.readRecord', () =>
    {
        // Existing tests...
+
+        it('should throw an error when a record is not found', async () =>
+        {
+            const promise = database.readRecord(RECORD_TYPES.PIZZAS, VALUES.IDS.NON_EXISTING);
+            await expect(promise).rejects.toStrictEqual(new RecordNotFound());
+        });
    });

Also applies to: 61-74

🧹 Nitpick comments (1)
test/integrations/database/implementation.spec.ts (1)

273-273: Consider using dynamic assertion for record count.

Rather than hardcoding the expected number of records (5), consider retrieving the count dynamically before running the delete operation or storing it in a constant in the test fixtures.

-            expect(records).toHaveLength(5);
+            const expectedCount = Object.keys(RECORDS.PIZZAS).length;
+            expect(records).toHaveLength(expectedCount);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between dddcfbb and 3622793.

📒 Files selected for processing (2)
  • test/integrations/database/fixtures/values.fixture.ts (1 hunks)
  • test/integrations/database/implementation.spec.ts (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/integrations/database/fixtures/values.fixture.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/integrations/database/implementation.spec.ts (7)
test/integrations/database/fixtures/records.fixture.ts (1)
  • RECORDS (10-24)
test/integrations/database/fixtures/queries.fixture.ts (1)
  • QUERIES (8-84)
test/integrations/database/fixtures/values.fixture.ts (1)
  • VALUES (2-34)
src/integrations/database/errors/RecordNotFound.ts (1)
  • RecordNotFound (4-10)
src/integrations/database/errors/RecordNotUpdated.ts (1)
  • RecordNotUpdated (4-10)
src/integrations/database/definitions/types.ts (1)
  • RecordData (11-11)
test/integrations/database/fixtures/sorts.fixture.ts (1)
  • SORTS (5-11)
🔇 Additional comments (5)
test/integrations/database/implementation.spec.ts (5)

4-4: Added RecordData import for bulk operations.

The RecordData import is properly added to support the new bulk operations test suites.


215-236: Well-structured updateRecords test suite.

Good implementation of the updateRecords test suite covering both successful updates and the case when no records match. The tests verify both the count of matching records and that the updated values are correct.


219-220: Good use of fixtures for test data.

Using VALUES.SIZE fixture instead of hardcoded values improves maintainability, following the project's convention as mentioned in past reviews.


257-274: Well-structured deleteRecords test suite.

The test suite for deleteRecords is well-designed, covering both successful deletions and the case when no records match. The verification that records are actually deleted and that the operation doesn't throw errors when nothing matches is comprehensive.


294-323: Unchanged sortRecords test suite.

The sortRecords test suite appears unchanged in functionality, with only line number changes due to the insertion of the new test suites.

@basmasking basmasking merged commit c054561 into main Apr 13, 2025
7 checks passed
@basmasking basmasking deleted the 401-bulk-updates-and-deletes branch April 13, 2025 18:38
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.

Bulk updates and deletes

3 participants