Skip to content

feat(e2e): Introduce JS exception catcher to whole test suite #16788

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

Vere-Grey
Copy link
Contributor

@Vere-Grey Vere-Grey commented Feb 3, 2025

Description

Introduces a JS exception catcher that fails the test in a teardown if there was any JS exception in the page during test run.

Screenshots:

Here you can see a at the top a failed test because of the JS catcher detect a JS exception during test run (I have sabotaged it). Then I commented out the JS catcher and run the tests again. You can see the test passed even tho there were JS exception thrown in the page.
Screenshot from 2025-02-03 21-39-52

@Vere-Grey Vere-Grey self-assigned this Feb 3, 2025
Copy link

coderabbitai bot commented Feb 3, 2025

Walkthrough

The changes introduce a new asynchronous property named exceptionLogger to the Fixtures type within the test framework. This property captures JavaScript errors that occur during test execution by listening for the pageerror event and storing the errors in an array. After test completion, if any errors were captured, the function throws a new error that includes the messages and stack traces of the recorded errors. Additionally, a new asynchronous function called skipFixture is added, allowing for the overriding of automatic fixtures in specific tests. The test configurations in various test files are updated to utilize skipFixture for exception logging, enhancing the error handling mechanism across the test suite.

Tip

🌐 Web search-backed reviews and chat
  • We have enabled web search-based reviews and chat for all users. This feature allows CodeRabbit to access the latest documentation and information on the web.
  • You can disable this feature by setting web_search: false in the knowledge_base settings.
  • Please share any feedback in the Discord discussion.
✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 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. (Beta)
  • @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.

);
}
},
{ auto: true },
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This means fixture is automatically used even if not imported to a test.

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)
packages/suite-desktop-core/e2e/support/fixtures.ts (2)

63-63: Use a more appropriate type for the exceptionLogger property.

The void type is confusing outside a return type. Since this property is used for auto-running setup code, consider using a more appropriate type.

Apply this diff to improve type clarity:

-    exceptionLogger: void;
+    exceptionLogger: undefined;
🧰 Tools
🪛 Biome (1.9.4)

[error] 63-63: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


221-238: Enhance error handling and reporting.

The implementation effectively captures JavaScript errors, but could be improved in several ways:

Consider these enhancements:

 exceptionLogger: [
     async ({ page }, use) => {
-        const errors: Error[] = [];
+        const errors = new Map<string, Error>(); // Use Map for deduplication
+        const knownErrors = new Set(['Expected error message']); // Add known/expected errors
+
         page.on('pageerror', error => {
-            errors.push(error);
+            // Skip known/expected errors
+            if (knownErrors.has(error.message)) return;
+            
+            // Deduplicate errors by message
+            if (!errors.has(error.message)) {
+                errors.set(error.message, error);
+            }
         });

         await use();

-        if (errors.length > 0) {
+        if (errors.size > 0) {
+            const errorsByType = new Map<string, Error[]>();
+            
+            // Categorize errors
+            for (const error of errors.values()) {
+                const type = error.name || 'Unknown';
+                if (!errorsByType.has(type)) {
+                    errorsByType.set(type, []);
+                }
+                errorsByType.get(type)!.push(error);
+            }
+            
+            // Format error message with categories
             throw new Error(
-                `There was a JS exception during test run.
-                \n${errors.map(error => `${error.message}\n${error.stack}`).join('\n-----\n')}`,
+                `JavaScript exceptions occurred during test run:\n\n${
+                    Array.from(errorsByType.entries())
+                        .map(([type, typeErrors]) => 
+                            `${type} Errors:\n${
+                                typeErrors
+                                    .map(error => `  - ${error.message}\n    ${error.stack}`)
+                                    .join('\n\n')
+                            }`
+                        )
+                        .join('\n\n')
+                }`
             );
         }
     },
     { auto: true },
 ],

These improvements:

  1. Deduplicate errors to avoid noise from repeated issues
  2. Filter out known/expected errors
  3. Categorize errors by type for better organization
  4. Enhance error message formatting for improved readability
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 683cc27 and 6cd87f6.

📒 Files selected for processing (1)
  • packages/suite-desktop-core/e2e/support/fixtures.ts (2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
packages/suite-desktop-core/e2e/support/fixtures.ts

[error] 63-63: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: run-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: run-desktop-tests (@group=device-management, trezor-user-env-unix)
  • GitHub Check: build-web
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: run-desktop-tests (@group=suite, trezor-user-env-unix)

@Vere-Grey Vere-Grey marked this pull request as draft February 3, 2025 21:22
@Vere-Grey
Copy link
Contributor Author

This is the only JS exception we caught so far. And it happens on not supported browser:

1) [web] › browser/safari.test.ts:20:9 › Safari › Suite does not support Safari @group=other @webOnly @snapshot 

    Error: There was a JS exception during test run.
                        
    /127.0.0.1:21325/ due to access control checks.
    Fetch API cannot load http://127.0.0.1:21325/ due to access control checks.
        at unknown (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/12524.e19d3a0f.js:2:2704856)
        at unknown (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:357236)
        at core_bridgeApiCall (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:357963)
        at unknown (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:363877)
        at post (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:365248)
        at unknown (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:361046)
        at unknown (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:361298)
        at unknown (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:216954)
        at W (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:47:3250)
        at e (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:47:5447)
        at unknown (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:216946)
        at u (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:217021)
        at unknown (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:217681)
        at unknown (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:217637)
        at z (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:47:3099)
        at E (https://dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:47:1125)
        at unknown (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/12524.e19d3a0f.js:2:2704856)
        at unknown (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:357236)
        at core_bridgeApiCall (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:357963)
        at unknown (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:363877)
        at post (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:365248)
        at unknown (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:361046)
        at unknown (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:51:361298)
        at unknown (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:216954)
        at W (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:47:3250)
        at e (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:47:5447)
        at unknown (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:216946)
        at u (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:217021)
        at unknown (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:217681)
        at unknown (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:1:[217](https://github.com/trezor/trezor-suite/actions/runs/13122616459/job/36612099007?pr=16788#step:6:218)637)
        at z (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:47:3099)
        at E (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/https:/dev.suite.sldev.cz/suite-web/feat/suite-desktop-core/e2e-catch-javascript-exceptions/web/js/core.js:47:1125)
        at Object.exports.test._test.test.extend.exceptionLogger.auto (/home/runner/work/trezor-suite/trezor-suite/packages/suite-desktop-core/e2e/support/fixtures.ts:231:23)

@Vere-Grey Vere-Grey force-pushed the feat/suite-desktop-core/e2e-catch-javascript-exceptions branch from ffd73f8 to 826ffee Compare February 4, 2025 09:06
@Vere-Grey Vere-Grey marked this pull request as ready for review February 4, 2025 09:22
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 (1)
packages/suite-desktop-core/e2e/support/common.ts (1)

175-180: Add JSDoc to clarify the fixture override pattern.

The implementation looks good and follows Playwright's fixture pattern. However, consider adding JSDoc to better document the purpose and usage of this function.

Add JSDoc to explain the empty object pattern and usage:

+/**
+ * Helper function to skip automatic fixtures in specific tests.
+ * The empty object pattern is intentional as it follows Playwright's fixture override pattern.
+ * @example
+ * test.use({ exceptionLogger: skipFixture });
+ */
/* eslint-disable no-empty-pattern, react-hooks/rules-of-hooks */
export async function skipFixture({}, use: (r: void) => Promise<void>) {
    await use();
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 177-177: Unexpected empty object pattern.

(lint/correctness/noEmptyPattern)


[error] 177-177: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6cd87f6 and 826ffee.

📒 Files selected for processing (5)
  • packages/suite-desktop-core/e2e/support/common.ts (1 hunks)
  • packages/suite-desktop-core/e2e/tests/bridge-tor/spawn-bridge-daemon.test.ts (1 hunks)
  • packages/suite-desktop-core/e2e/tests/bridge-tor/spawn-bridge.test.ts (1 hunks)
  • packages/suite-desktop-core/e2e/tests/bridge-tor/spawn-tor.test.ts (1 hunks)
  • packages/suite-desktop-core/e2e/tests/browser/safari.test.ts (2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
packages/suite-desktop-core/e2e/support/common.ts

[error] 177-177: Unexpected empty object pattern.

(lint/correctness/noEmptyPattern)


[error] 177-177: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

🔇 Additional comments (4)
packages/suite-desktop-core/e2e/tests/browser/safari.test.ts (1)

3-3: LGTM! Exception logging properly configured for Safari tests.

The integration of the exception logger is correctly implemented, ensuring that any JavaScript exceptions during Safari compatibility testing will be caught and reported.

Also applies to: 19-24

packages/suite-desktop-core/e2e/tests/bridge-tor/spawn-bridge-daemon.test.ts (1)

6-6: LGTM! Exception logging properly configured for bridge daemon tests.

The exception logger integration will help catch any JavaScript errors during bridge daemon operations. Consider adding specific error scenarios to verify the exception logger's effectiveness.

To verify the exception logger's effectiveness with bridge daemon operations, consider adding a test that deliberately triggers a JavaScript error:

test('Exception logger catches JS errors in bridge daemon', async ({ request }) => {
    // Trigger a JavaScript error
    await expect(async () => {
        // @ts-ignore - Deliberately cause an error
        await undefined.someMethod();
    }).toThrow();
});

Also applies to: 9-9

packages/suite-desktop-core/e2e/tests/bridge-tor/spawn-bridge.test.ts (1)

7-7: LGTM! Exception logging properly configured for bridge spawning tests.

The exception logger integration will help catch JavaScript errors during bridge operations. Consider adding specific error scenarios to validate the exception catching mechanism.

To verify the exception logger's effectiveness with bridge operations, consider adding error scenarios:

test('Exception logger catches JS errors during bridge operations', async ({ request }) => {
    // Test error during bridge version check
    await expect(async () => {
        // @ts-ignore - Deliberately cause an error
        const version = await (undefined).getBridgeVersion();
    }).toThrow();
});

Also applies to: 13-13

✅ Verification successful

LGTM! Exception logger integration is correctly set up in the spawn-bridge tests.

  • The file now imports skipFixture along with the existing functions.
  • Exception logging is properly configured to catch potential JS errors during bridge operations.
  • As a future enhancement, consider adding tests for error scenarios (e.g., simulating a failure during a bridge version check as shown) to validate that exceptions are caught as expected. This suggestion applies similarly to the configurations on line 13.
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts or web queries found

packages/suite-desktop-core/e2e/tests/bridge-tor/spawn-tor.test.ts (1)

3-3: LGTM! Exception logging properly configured for Tor tests.

The exception logger integration will help catch JavaScript errors during Tor operations. Given the long-running nature of Tor tests (5-minute timeout), ensure the exception logger can handle delayed errors.

To verify the exception logger's effectiveness with long-running Tor operations:

test('Exception logger handles delayed errors in Tor operations', async () => {
    // Test delayed error scenario
    await expect(async () => {
        await new Promise(resolve => setTimeout(resolve, 1000));
        // @ts-ignore - Deliberately cause an error
        await undefined.torMethod();
    }).toThrow();
});

Also applies to: 7-8

✅ Verification successful

LGTM! Exception logging is correctly integrated for the Tor tests.

  • The added skipFixture import and exception logger configuration follow the expected pattern.
  • The test’s 5-minute timeout is noted; ensure that the exception logger is monitored for any delayed errors during extended operations.
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts or web queries found

@HajekOndrej HajekOndrej merged commit 0ce9d7b into develop Feb 4, 2025
25 checks passed
@HajekOndrej HajekOndrej deleted the feat/suite-desktop-core/e2e-catch-javascript-exceptions branch February 4, 2025 12:58
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