Skip to content

test(contact-point): simplifies container test#1400

Merged
ygrishajev merged 2 commits intomainfrom
feature/contact-point
May 30, 2025
Merged

test(contact-point): simplifies container test#1400
ygrishajev merged 2 commits intomainfrom
feature/contact-point

Conversation

@ygrishajev
Copy link
Contributor

@ygrishajev ygrishajev commented May 28, 2025

This is a draft attempting to simplify container testing via providing a simple object as a child which can be used to call container methods.

Summary by CodeRabbit

  • Refactor
    • Improved test suites for contact point containers by replacing DOM interactions with direct method invocation, resulting in more maintainable and efficient tests.
    • Exported internal type definitions to allow for better type sharing across modules.
  • Tests
    • Introduced a new utility for capturing and interacting with child components in tests, enhancing testing capabilities and reliability.
  • Chores
    • Updated environment configuration by removing unused variables and comments.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 28, 2025

Walkthrough

This update exports the ChildrenProps types from two container components and introduces a testing utility for capturing child render props. Related test suites are refactored to use this utility, shifting from DOM-driven event simulation to direct invocation of container child methods. An unused environment variable is also removed.

Changes

File(s) Change Summary
apps/api/env/.env Removed a TODO comment and the NOTIFICATIONS_API_BASE_URL variable.
apps/deploy-web/src/components/alerts/ContactPointCreateContainer/ContactPointCreateContainer.tsx Made ChildrenProps type exported.
apps/deploy-web/src/components/alerts/ContactPointsListContainer/ContactPointsListContainer.tsx Made ChildrenProps type exported.
apps/deploy-web/tests/unit/container-testing-child-capturer.tsx Added a new utility class and factory: ContainerTestingChildCapturer<T> and createContainerTestingChildCapturer.
apps/deploy-web/src/components/alerts/ContactPointCreateContainer/ContactPointFormContainer.spec.tsx Refactored tests to use the child capturer utility and direct method invocation.
apps/deploy-web/src/components/alerts/ContactPointsListContainer/ContactPointsListContainer.spec.tsx Refactored tests to use the child capturer utility and direct method invocation; made setup async.

Sequence Diagram(s)

sequenceDiagram
    participant TestSuite
    participant Container
    participant ChildCapturer

    TestSuite->>ChildCapturer: createContainerTestingChildCapturer()
    TestSuite->>Container: render with ChildCapturer.renderChild as child
    Container->>ChildCapturer: invoke renderChild(childProps)
    TestSuite->>ChildCapturer: awaitChild()
    ChildCapturer-->>TestSuite: childProps
    TestSuite->>childProps: call method (e.g., create, onRemove)
    Container->>TestSuite: update state/props as a result
Loading

Possibly related PRs

Poem

A bunny with code in its paws,
Refactors with barely a pause.
Now children are captured with ease,
And tests run as swift as the breeze.
With types exported, clean and bright—
This rabbit hops off with delight! 🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-05-30T09_34_44_659Z-debug-0.log

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @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 explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

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 generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

@codecov
Copy link

codecov bot commented May 28, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 36.50%. Comparing base (baeeb07) to head (b5a8c0b).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1400      +/-   ##
==========================================
+ Coverage   36.49%   36.50%   +0.01%     
==========================================
  Files         818      818              
  Lines       19678    19678              
  Branches     3630     3630              
==========================================
+ Hits         7181     7183       +2     
+ Misses      12172    12170       -2     
  Partials      325      325              
Flag Coverage Δ *Carryforward flag
api 66.62% <ø> (+0.03%) ⬆️
deploy-web 15.78% <ø> (ø)
notifications 88.48% <ø> (ø) Carriedforward from a9b9e43
provider-proxy 80.09% <ø> (ø) Carriedforward from a9b9e43

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
...intCreateContainer/ContactPointCreateContainer.tsx 100.00% <ø> (ø)
...PointsListContainer/ContactPointsListContainer.tsx 96.87% <ø> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ygrishajev ygrishajev force-pushed the feature/contact-point branch from ebb7478 to a9b9e43 Compare May 30, 2025 09:08
@ygrishajev ygrishajev marked this pull request as ready for review May 30, 2025 09:33
@ygrishajev ygrishajev requested a review from a team as a code owner May 30, 2025 09:33
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/deploy-web/tests/unit/container-testing-child-capturer.tsx (2)

3-8: Consider using arrow functions to eliminate constructor binding.

The manual binding in the constructor can be simplified by using arrow functions, which automatically bind this context.

-class ContainerTestingChildCapturer<T> {
-  private child?: T;
-
-  constructor() {
-    this.renderChild = this.renderChild.bind(this);
-  }
+class ContainerTestingChildCapturer<T> {
+  private child?: T;

And update the method to an arrow function:

-  renderChild(props: T) {
+  renderChild = (props: T) => {
    this.child = props;
    return null;
-  }
+  };

15-22: Improve error message specificity.

The current error message "Child not rendered yet" doesn't distinguish between the child not being set vs the condition not being met, making debugging more difficult.

  async awaitChild(condition: (child: T) => boolean = () => true): Promise<T> {
    return await waitFor(() => {
-      if (!this.child || !condition(this.child)) {
-        throw new Error("Child not rendered yet");
+      if (!this.child) {
+        throw new Error("Child component has not been rendered yet");
+      }
+      if (!condition(this.child)) {
+        throw new Error("Child component condition not met");
      }
      return this.child as T;
    });
  }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 88a3f61 and a9b9e43.

📒 Files selected for processing (6)
  • apps/api/env/.env (0 hunks)
  • apps/deploy-web/src/components/alerts/ContactPointCreateContainer/ContactPointCreateContainer.tsx (1 hunks)
  • apps/deploy-web/src/components/alerts/ContactPointCreateContainer/ContactPointFormContainer.spec.tsx (4 hunks)
  • apps/deploy-web/src/components/alerts/ContactPointsListContainer/ContactPointsListContainer.spec.tsx (5 hunks)
  • apps/deploy-web/src/components/alerts/ContactPointsListContainer/ContactPointsListContainer.tsx (1 hunks)
  • apps/deploy-web/tests/unit/container-testing-child-capturer.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/api/env/.env
🧰 Additional context used
🧬 Code Graph Analysis (2)
apps/deploy-web/src/components/alerts/ContactPointsListContainer/ContactPointsListContainer.tsx (1)
apps/deploy-web/src/components/alerts/ContactPointCreateContainer/ContactPointCreateContainer.tsx (1)
  • ChildrenProps (17-20)
apps/deploy-web/src/components/alerts/ContactPointCreateContainer/ContactPointCreateContainer.tsx (1)
apps/deploy-web/src/components/alerts/ContactPointsListContainer/ContactPointsListContainer.tsx (1)
  • ChildrenProps (15-23)
🔇 Additional comments (16)
apps/deploy-web/tests/unit/container-testing-child-capturer.tsx (1)

25-27: Well-designed factory function.

The factory function provides a clean API for creating instances while maintaining type safety through generics.

apps/deploy-web/src/components/alerts/ContactPointsListContainer/ContactPointsListContainer.tsx (1)

15-15: Exporting internal types for testing is acceptable.

Exporting the ChildrenProps type enables type-safe testing with the new testing utility. While this slightly breaks encapsulation, it's a reasonable trade-off for improved test quality and type safety.

apps/deploy-web/src/components/alerts/ContactPointCreateContainer/ContactPointCreateContainer.tsx (1)

17-17: Consistent pattern for enabling testability.

Exporting the ChildrenProps type follows the same pattern as ContactPointsListContainer, maintaining consistency across container components. This enables type-safe interaction with the child render prop in tests.

apps/deploy-web/src/components/alerts/ContactPointCreateContainer/ContactPointFormContainer.spec.tsx (7)

10-10: Good use of exported type for type safety.

Importing the ChildrenProps type enables type-safe interaction with the container's child render prop, improving test reliability and developer experience.


15-16: Clean import organization.

The imports are well-organized, removing unused fireEvent and adding the necessary testing utility. The testing utility import follows a logical path structure.


20-22: Improved testing approach with direct method invocation.

The refactor from DOM event simulation to direct method calls makes the test more focused on the container's logic rather than UI interactions. This is generally better for unit testing container components.


75-75: Appropriate async setup function.

Making the setup function async is necessary to await the child capturer, ensuring the child render prop is available before tests proceed.


101-101: Good use of type parameter for type safety.

The generic type parameter <ChildrenProps> ensures type safety when capturing and using the child render prop methods.


107-107: Clean integration of testing utility.

Passing childCapturer.renderChild as the children function cleanly integrates the testing utility with the container component.


113-113: Proper async handling in setup.

The setup function correctly awaits the child capturer and returns the captured child along with other test dependencies, enabling clean test execution.

apps/deploy-web/src/components/alerts/ContactPointsListContainer/ContactPointsListContainer.spec.tsx (6)

10-10: LGTM! Import changes align with the new testing approach.

The import modifications correctly reflect the shift from DOM-driven to prop-driven testing:

  • Added ContactPointsListViewProps type for proper typing
  • Removed fireEvent as DOM events are no longer simulated
  • Added the child capturer utility for the new testing pattern

Also applies to: 14-14, 16-16


20-21: LGTM! Direct prop assertion is more reliable.

The change from DOM text assertions to direct data prop comparison is an improvement:

  • More deterministic than DOM content checking
  • Tests the actual data flow rather than rendered output
  • Eliminates potential flakiness from DOM rendering timing

25-26: LGTM! Direct method invocation improves test reliability.

The shift from fireEvent.click() to direct child.onRemove() invocation provides several benefits:

  • Tests the actual callback behavior without DOM interaction complexity
  • More focused unit testing of container logic
  • Eliminates potential timing issues with DOM events
  • Maintains the same test coverage for success and error scenarios

Also applies to: 38-40


52-53: LGTM! Pagination testing is well-implemented.

The direct invocation of child.onPaginationChange() with calculated pagination parameters is correct and maintains test coverage for pagination logic.


70-70: LGTM! Async setup function is necessary for the new testing pattern.

Converting the setup function to async is required to properly await the child capturer initialization and data loading.


95-95: LGTM! Child capturer implementation follows the expected pattern.

The implementation correctly:

  • Creates a typed capturer for ContactPointsListViewProps
  • Passes the capturer's render function to the container
  • Awaits child initialization with a proper condition (({ data }) => !!data.length)
  • Returns the captured child for test usage

This pattern provides a clean way to test container logic without DOM complexity.

Also applies to: 101-101, 107-109

@ygrishajev ygrishajev merged commit 8785461 into main May 30, 2025
8 checks passed
@ygrishajev ygrishajev deleted the feature/contact-point branch May 30, 2025 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments