Skip to content

Conversation

anikdhabal
Copy link
Contributor

@anikdhabal anikdhabal commented Aug 8, 2025

fix: prevent makeBodyVisible timeout from running after test teardown

Summary

Fixed a frequently failing unit test in CI that was throwing ReferenceError: document is not defined due to a recursive timeout from the makeBodyVisible function continuing to run after test environment teardown.

Root cause: The makeBodyVisible function uses runAsap() (a 50ms setTimeout wrapper) to recursively call itself, ensuring the document body stays visible. In tests, this recursive timeout would sometimes continue running after the test environment was cleaned up, causing the "document is not defined" error when it tried to access document.body.

Solution: Added vi.clearAllTimers() to the test teardown (afterEach block) to ensure all pending timers are cleared before switching back to real timers. This prevents the recursive timeout from executing after the test environment is destroyed.

Key decision: Initially implemented a comprehensive solution that tracked timeout IDs in the makeBodyVisible function, but based on code review feedback from @hariombalhara, simplified to use only vi.clearAllTimers() which proved sufficient and much cleaner.

Review & Testing Checklist for Human

  • Verify CI stability: Run the embed iframe tests multiple times in CI to confirm the intermittent "document is not defined" error is eliminated (this was the original failing behavior)
  • Validate timer cleanup: Confirm that vi.clearAllTimers() effectively clears the recursive timeout created by makeBodyVisiblerunAsapsetTimeout chain
  • Check for test isolation: Ensure the additional timer cleanup in afterEach doesn't negatively impact other tests in the same file or test suite

Recommended test plan: Monitor the specific test file packages/embeds/embed-core/src/__tests__/embed-iframe.test.ts in CI over several runs to confirm stable behavior, particularly watching for the original "Unhandled Errors" section that contained the ReferenceError: document is not defined.


Diagram

%%{ init : { "theme" : "default" }}%%
graph TD
    TestFile["packages/embeds/embed-core/src/<br/>__tests__/embed-iframe.test.ts"]:::major-edit
    EmbedIframe["packages/embeds/embed-core/src/<br/>embed-iframe.ts"]:::context  
    UtilsFile["packages/embeds/embed-core/src/<br/>embed-iframe/lib/utils.ts"]:::context
    
    TestFile -->|"calls functions that trigger"| EmbedIframe
    EmbedIframe -->|"makeBodyVisible() uses"| UtilsFile
    UtilsFile -->|"runAsap() creates setTimeout"| Timeout["Recursive setTimeout<br/>(50ms intervals)"]:::context
    Timeout -->|"continues after test teardown<br/>causing ReferenceError"| Error["document is not defined<br/>CI failure"]:::context
    
    TestFile -->|"vi.clearAllTimers() in afterEach<br/>now prevents"| Error
    
    subgraph Legend
        L1["Major Edit"]:::major-edit
        L2["Minor Edit"]:::minor-edit  
        L3["Context/No Edit"]:::context
    end
    
    classDef major-edit fill:#90EE90
    classDef minor-edit fill:#87CEEB  
    classDef context fill:#FFFFFF
Loading

Notes

  • Testing confidence: Locally verified with 3 consecutive test runs (15/15 tests passed each time) and type checking, but the original issue was intermittent in CI so real validation requires CI monitoring
  • Code review driven: This simplified approach was suggested by @hariombalhara who correctly identified that vi.clearAllTimers() alone would be sufficient
  • Session details: Requested by @anikdhabal via Slack. Full session available at: https://app.devin.ai/sessions/0104416bd4804c76b56becb1854ae678

- Add timeout tracking to makeBodyVisible function to enable cleanup
- Add vi.clearAllTimers() to test teardown to clear recursive timeouts
- Prevents 'ReferenceError: document is not defined' in CI tests

Fixes intermittent test failures where makeBodyVisible recursive timeout
continues running after test environment is torn down.

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Contributor

coderabbitai bot commented Aug 8, 2025

Walkthrough

The afterEach hook in the embed-iframe.test.ts test file was modified to add a call to vi.clearAllTimers(). This supplements the existing cleanup steps, which already included clearing mocks, resetting modules, and restoring real timers. No changes were made to any exported or public entities.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3ea73e7 and 12eee13.

📒 Files selected for processing (1)
  • packages/embeds/embed-core/src/__tests__/embed-iframe.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/embeds/embed-core/src/__tests__/embed-iframe.test.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/embeds/embed-core/src/__tests__/embed-iframe.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1754641449-fix-embed-iframe-test-timeout

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

Support

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

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 generate unit tests to generate unit tests for 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.

@keithwillcode keithwillcode added the core area: core, team members only label Aug 8, 2025
Copy link

vercel bot commented Aug 8, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
cal ⬜️ Ignored (Inspect) Aug 8, 2025 8:53am
cal-eu ⬜️ Ignored (Inspect) Aug 8, 2025 8:53am

Copy link
Contributor

The makeBodyVisible function is called from two locations in the same file:

  1. showPageAsNonEmbed() (line 308) - called when the embed is opened in the top window instead of an iframe
  2. tryInformingLinkReady() (line 410) - called within the parentKnowsIframeReady method after the link is ready

Both callers don't use the return value, so changing the function signature from void to () => void (cleanup function) is backward compatible. The cleanup function is primarily intended for test environments to prevent the recursive timeout from continuing after test teardown.

Copy link
Contributor

Good question! Both changes are actually needed for a complete fix:

Why alone isn't sufficient:

  • only clears timers that were created while fake timers were active
  • The recursive timeout might be created after is called in the teardown
  • Real timers created after switching back to real timers won't be cleared by

Why the timeout tracking is necessary:

  • The global ensures we can cancel the specific recursive timeout regardless of when it was created
  • It provides a deterministic cleanup mechanism that works in both test and production environments
  • Without it, there's a race condition where the timeout could fire after test teardown

The combination ensures robust cleanup: handles fake timers, and the timeout tracking handles any real timers that might slip through.

Based on code review feedback, test if vi.clearAllTimers() alone
is sufficient without modifying makeBodyVisible function.

- Reverted makeBodyVisible function changes
- Kept only vi.clearAllTimers() in test teardown
- Verified with multiple test runs and type checking

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
Copy link
Contributor

Investigation Results: You were absolutely right!

I tested the simplified approach (using only vi.clearAllTimers() without modifying makeBodyVisible) and it works perfectly:

Testing performed:

  • ✅ Reverted all makeBodyVisible function changes
  • ✅ Kept only vi.clearAllTimers() in test teardown
  • ✅ Ran tests 3 consecutive times - all passed (15/15 tests each time)
  • ✅ Verified type checking passes with yarn type-check:ci

Why vi.clearAllTimers() alone is sufficient:

  • It clears all pending timers created during the test, including the recursive timeout from makeBodyVisible
  • The timing doesn't matter - vi.clearAllTimers() works regardless of when the timeout was created
  • Much simpler solution with minimal code changes

Updated the PR to use only the simplified approach. Thanks for the excellent suggestion - this is definitely the better solution! 🎯

@devin-ai-integration devin-ai-integration bot force-pushed the devin/1754641449-fix-embed-iframe-test-timeout branch from 27c8cae to 12eee13 Compare August 8, 2025 08:53
@anikdhabal anikdhabal marked this pull request as ready for review August 8, 2025 08:55
@anikdhabal anikdhabal requested a review from a team as a code owner August 8, 2025 08:55
@anikdhabal anikdhabal enabled auto-merge (squash) August 8, 2025 08:55
@graphite-app graphite-app bot requested a review from a team August 8, 2025 08:55
@dosubot dosubot bot added the 🐛 bug Something isn't working label Aug 8, 2025
Copy link

graphite-app bot commented Aug 8, 2025

Graphite Automations

"Add consumer team as reviewer" took an action on this PR • (08/08/25)

1 reviewer was added to this PR based on Keith Williams's automation.

Copy link
Contributor

github-actions bot commented Aug 8, 2025

E2E results are ready!

@anikdhabal anikdhabal merged commit 6af473a into main Aug 8, 2025
82 of 85 checks passed
@anikdhabal anikdhabal deleted the devin/1754641449-fix-embed-iframe-test-timeout branch August 8, 2025 11:07
Pallava-Joshi pushed a commit to Pallava-Joshi/cal.com that referenced this pull request Aug 8, 2025
…calcom#22972)

* fix: prevent makeBodyVisible timeout from running after test teardown

- Add timeout tracking to makeBodyVisible function to enable cleanup
- Add vi.clearAllTimers() to test teardown to clear recursive timeouts
- Prevents 'ReferenceError: document is not defined' in CI tests

Fixes intermittent test failures where makeBodyVisible recursive timeout
continues running after test environment is torn down.

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* simplify: use only vi.clearAllTimers() to fix timeout issue

Based on code review feedback, test if vi.clearAllTimers() alone
is sufficient without modifying makeBodyVisible function.

- Reverted makeBodyVisible function changes
- Kept only vi.clearAllTimers() in test teardown
- Verified with multiple test runs and type checking

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Something isn't working core area: core, team members only ready-for-e2e
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants