Skip to content
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

feat: added 'forced' param to IpNetworkDetector.detect() #4001

Open
wants to merge 1 commit into
base: next
Choose a base branch
from

Conversation

marcin-bazyl
Copy link
Collaborator

@marcin-bazyl marcin-bazyl commented Nov 21, 2024

COMPLETES #SPARK-580033

This pull request addresses

When we do ip network version detection, we are not able to tell if we're on ipv4 or ipv6 network if the app hasn't acquired any local user media. Therefore, we need the app to trigger new ip network detection once the app has successfully acquired user media.

by making the following changes

Added force parameter to IpNetworkDetector.detect() method, so the app can use it when calling SDK after a stream is acquired. When force is false, SDK can decide if it's worth doing another detection or not - basically we only need to do it if previous one failed, because we only received mDNS candidates (so we couldn't detect ipv4/ipv6).

As the app now calls detect(), we also need to make sure to handle cases when detect() is called while detection is already in progress, so I had to add state and pendingDetection to IpNetworkDetector.

Initially I tried to just have a listener on mic/camera permissions in the SDK, but that doesn't work. In Firefox, even when we have the permissions, we don't get real candidates (ipv4 or ipv6) and we only get mDNS candidates until app acquires a user media stream (mic or camera).

related web app PR: https://sqbu-github.cisco.com/WebExSquared/webex-web-client/pull/7002

Change Type

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Tooling change
  • Internal code refactor

The following scenarios where tested

unit tests, manual test with the web app

I certified that

  • I have read and followed contributing guidelines

  • I discussed changes with code owners prior to submitting this pull request

  • I have not skipped any automated checks

  • All existing and new tests passed

  • I have updated the documentation accordingly


Make sure to have followed the contributing guidelines before submitting.

Summary by CodeRabbit

  • New Features

    • Enhanced state management for the network detection process with new properties and improved control flow.
    • The detection method now includes a force parameter for conditional execution.
    • Streamlined reachability checks by allowing IP version detection to run concurrently.
  • Bug Fixes

    • Improved error handling and queuing mechanism for concurrent detection calls.
  • Tests

    • Added new test cases to verify the behavior of the detection method with the force parameter and ensure proper state transitions.
    • Expanded reachability tests to cover various scenarios and configurations.

@marcin-bazyl marcin-bazyl requested review from a team as code owners November 21, 2024 22:02
Copy link

coderabbitai bot commented Nov 21, 2024

Walkthrough

The changes involve modifications to the IpNetworkDetector class in the ipNetworkDetector.ts file, where two new properties are introduced and the detect method is updated to accept a force parameter. This enhances state management and control flow during the detection process. The associated unit tests in ipNetworkDetector.js are also updated to reflect these changes, including new test cases that validate the behavior of the detect method under various conditions. Additionally, the Reachability class in index.ts is updated to allow non-blocking IP version detection, with corresponding test enhancements in index.ts.

Changes

File Path Change Summary
packages/@webex/internal-plugin-device/src/ipNetworkDetector.ts Added properties state: string and pendingDetection: object to IpNetworkDetector. Updated detect method to accept force: boolean. Changed return type to Promise<void>.
packages/@webex/internal-plugin-device/test/unit/spec/ipNetworkDetector.js Added utility function flushPromises. Updated tests for detect method to include force parameter. New test cases added for various detection scenarios and state management.
packages/@webex/plugin-meetings/src/reachability/index.ts Modified gatherReachability method to not await IP version detection, passing true as an argument to detect. Enhanced error logging in getClusters.
packages/@webex/plugin-meetings/test/unit/spec/reachability/index.ts Added assertions and test cases for isAnyPublicClusterReachable and isWebexMediaBackendUnreachable. Updated tests to validate detect method calls with boolean parameters.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant IpNetworkDetector

    Client->>IpNetworkDetector: detect(force)
    IpNetworkDetector->>IpNetworkDetector: Check current state
    alt State is 'in-progress'
        IpNetworkDetector->>IpNetworkDetector: Set pendingDetection with force
        IpNetworkDetector-->>Client: Return early
    else State is not 'initial' and force is false
        IpNetworkDetector-->>Client: Skip detection
    else
        IpNetworkDetector->>IpNetworkDetector: Set state to 'in-progress'
        IpNetworkDetector->>IpNetworkDetector: Execute detection logic
        IpNetworkDetector->>IpNetworkDetector: Set state to 'idle'
        alt Pending detection exists
            IpNetworkDetector->>IpNetworkDetector: Call detect(pendingDetection.force)
        end
        IpNetworkDetector-->>Client: Complete detection
    end
Loading

Possibly related PRs

  • fix: added config for backend ipv6 native support #3962: The changes in this PR involve modifications to the getIpVersion method, which now includes logic that depends on the backend's IPv6 support, similar to the state management enhancements in the IpNetworkDetector class in the main PR. Both PRs focus on improving network configuration handling.
  • fix: locus DTOs not handled if an earlier one causes an error #3982: This PR addresses error handling in the processing of Locus DTOs, which is relevant to the overall robustness of the SDK's network operations, akin to the improvements in state management and error handling in the IpNetworkDetector class from the main PR.

Suggested reviewers

  • chburket
  • edvujic
  • robstax

🐇 In the meadow, we hop and play,
New changes brightening our day!
With states and forces, we detect,
Our code now dances, what a perfect effect!
So let’s rejoice and cheer with glee,
For a smoother path, oh, can’t you see?
🌼

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 (1.23.1)

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.

warning eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
warning eslint > @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
warning eslint > @humanwhocodes/config-array > @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
warning eslint > file-entry-cache > flat-cache > rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
warning eslint > file-entry-cache > flat-cache > rimraf > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning eslint > file-entry-cache > flat-cache > rimraf > glob > inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
warning eslint-import-resolver-typescript > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning glob@7.2.3: Glob versions prior to v9 are no longer supported
warning intern > glob@7.1.7: Glob versions prior to v9 are no longer supported
warning intern > glob > inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
warning jasmine > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning jest > jest-cli > jest-config > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning jest > @jest/core > jest-runtime > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning jest > @jest/core > @jest/reporters > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning jest > @jest/core > @jest/transform > babel-plugin-istanbul > test-exclude > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning mocha > glob@7.2.0: Glob versions prior to v9 are no longer supported
warning mocha > glob > inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
warning sinon@9.2.4: 16.1.1
warning wd > request@2.88.0: request has been deprecated, see request/request#3142
warning wd > q@1.5.1: You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.

(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)
warning wd > archiver > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning wd > request > uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
warning wd > request > har-validator@5.1.5: this library is no longer supported
warning wd > archiver > archiver-utils > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning @babel/cli > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning @babel/plugin-proposal-async-generator-functions@7.20.7: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.
warning @babel/plugin-proposal-class-properties@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.
warning @babel/plugin-proposal-export-namespace-from@7.18.9: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead.
warning @babel/plugin-proposal-nullish-coalescing-operator@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.
warning @babel/plugin-proposal-object-rest-spread@7.20.7: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.
warning @babel/plugin-proposal-optional-chaining@7.21.0: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.
warning @babel/polyfill@7.12.1: 🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.
warning @babel/polyfill > core-js@2.6.12: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
warning @babel/runtime-corejs2 > core-js@2.6.12: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
warning babel-plugin-lodash > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > glob@7.2.3: Glob versions prior to v9 are no longer supported
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > sinon@9.2.4: 16.1.1
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > @babel/plugin-proposal-async-generator-functions@7.20.7: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > @babel/plugin-proposal-class-properties@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > @babel/plugin-proposal-export-namespace-from@7.18.9: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead.
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > @babel/plugin-proposal-nullish-coalescing-operator@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > @babel/plugin-proposal-object-rest-spread@7.20.7: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > @babel/plugin-proposal-optional-chaining@7.21.0: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.
warning workspace-aggregator-ead1a36f-57b1-48c5-b8bf-38abc58441a0 > @babel/polyfill@7.12.1: 🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.
error eslint-plugin-jsdoc@40.3.0: The engine "node" is incompatible with this module. Expected version "^14 || ^16 || ^17 || ^18 || ^19". Got "22.9.0"
error Found incompatible module.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

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

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

🧹 Outside diff range and nitpick comments (3)
packages/@webex/internal-plugin-device/src/ipNetworkDetector.ts (2)

20-21: Consider using constants or an enumeration for 'state' values

Using string literals like 'initial', 'in-progress', and 'idle' for the state property may lead to typos or inconsistencies. Defining these states as constants or an enumeration can improve maintainability and reduce errors.


189-194: Consider handling the Promise returned by 'detect' method

When invoking this.detect(forceParam);, since detect is an async function, any unhandled exceptions might be missed. Consider adding error handling or at least acknowledging that this call is intentionally not awaited.

packages/@webex/internal-plugin-device/test/unit/spec/ipNetworkDetector.js (1)

6-7: Ensure setImmediate is compatible with all test environments

The use of setImmediate in flushPromises may not be universally supported across all JavaScript environments. For better compatibility, consider using Promise.resolve() or process.nextTick().

Suggested change:

-const flushPromises = () => new Promise(setImmediate);
+const flushPromises = () => Promise.resolve();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ea7c9b8 and ac8238d.

📒 Files selected for processing (2)
  • packages/@webex/internal-plugin-device/src/ipNetworkDetector.ts (2 hunks)
  • packages/@webex/internal-plugin-device/test/unit/spec/ipNetworkDetector.js (3 hunks)
🔇 Additional comments (3)
packages/@webex/internal-plugin-device/src/ipNetworkDetector.ts (1)

167-177: State management and pending detection logic look good

The implementation for handling concurrent calls to detect() and managing the state transitions is well-structured and should prevent race conditions.

packages/@webex/internal-plugin-device/test/unit/spec/ipNetworkDetector.js (2)

345-387: Test correctly validates queuing behavior of detect() calls

The added test case effectively verifies that calling detect() while a detection is already in progress queues the new detection and that the peer connection methods are invoked the expected number of times.


389-425: Verify compatibility of it.each with the testing framework

Ensure that the use of it.each for parameterized tests is supported by your testing framework. In Mocha, it.each is not available by default and may require additional libraries like mocha-each or mocha-param.

To confirm whether it.each is available, you can search for its definition in your dependencies:

✅ Verification successful

The test file is using Jest's test framework

The test file is using Jest's built-in it.each functionality, which is natively supported by Jest. This is confirmed by:

  1. The package.json shows Jest as the test runner: "test:unit": "webex-legacy-tools test --unit --runner jest"
  2. The package uses @webex/jest-config-legacy in its dependencies
  3. it.each is a standard feature in Jest for parameterized testing and doesn't require additional libraries
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if `it.each` is available in the test environment.

# Search for `it.each` in node_modules
rg 'it\.each' node_modules/

# Alternatively, check for installed packages that provide `it.each`
npm list --depth=0 mocha-each mocha-param

Length of output: 173


Script:

#!/bin/bash
# Let's check the package.json and test setup files for testing framework and dependencies
fd "package.json|karma.conf.js|test.*config.*" --type f --exec cat {}

# Also search for any it.each usage in the codebase
rg "it\.each" --type js

Length of output: 101503


Script:

#!/bin/bash
# Let's check the test framework setup and dependencies in the specific package
fd "package.json" --type f --base-directory packages/@webex/internal-plugin-device --exec cat {}

# Also check for any jest setup files in the package
fd "jest.*" --type f --base-directory packages/@webex/internal-plugin-device --exec cat {}

Length of output: 2106


Script:

#!/bin/bash
# Let's check the jest-config-legacy package for test configuration
fd "index.js|jest.config.js" --type f --base-directory packages/@webex/jest-config-legacy/static --exec cat {}

# Also check if jest-each is available in dependencies
rg "jest-each" packages/@webex/jest-config-legacy/package.json

Length of output: 369

Copy link

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-4001.d3m3l2kee0btzx.amplifyapp.com

@marcin-bazyl marcin-bazyl added the validated If the pull request is validated for automation. label Nov 22, 2024
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

🧹 Outside diff range and nitpick comments (10)
packages/@webex/internal-plugin-device/src/ipNetworkDetector.ts (4)

7-11: LGTM! Consider using TypeScript enums for better type safety.

The state management implementation looks good. For better type safety, consider using TypeScript enums instead of string constants.

-const STATE = {
-  INITIAL: 'initial',
-  IN_PROGRESS: 'in-progress',
-  IDLE: 'idle',
-};
+enum STATE {
+  INITIAL = 'initial',
+  IN_PROGRESS = 'in-progress',
+  IDLE = 'idle',
+}

 props: {
-  state: ['string', true, STATE.INITIAL],
+  state: [STATE, true, STATE.INITIAL],
   pendingDetection: ['object', false, undefined],
 }

Also applies to: 26-27


166-169: Enhance JSDoc documentation for clarity.

The JSDoc should be updated to reflect the method's complete behavior, including state transitions and the possibility of queued detections.

 /**
  * Detects if we are on IPv4 and/or IPv6 network. Once it resolves, read the
  * supportsIpV4 and supportsIpV6 props to find out the result.
+ *
  * @param {boolean} force - if false, the detection will only be done if we haven't managed to get any meaningful results yet
+ * @param {boolean} [force=false] - Whether to force a new detection regardless of previous results
+ * @returns {Promise<void>} Resolves when detection completes or queues detection if one is in progress
+ * @throws {Error} When RTCPeerConnection creation or offer setting fails
  */

185-192: Consider adding error logging for state transitions.

While the state transitions are handled correctly, adding debug logs would help with troubleshooting.

 try {
+  this.webex.logger.debug('IpNetworkDetector: Starting detection');
   this.state = STATE.IN_PROGRESS;

   pc = new RTCPeerConnection();
   results = await this.gatherLocalCandidates(pc);
 } finally {
   pc.close();
+  this.webex.logger.debug(`IpNetworkDetector: Detection completed, state: ${this.state}`);
   this.state = STATE.IDLE;
 }

195-200: Add type safety for pendingDetection.

The pendingDetection property would benefit from a proper TypeScript interface.

+interface PendingDetection {
+  force: boolean;
+}

 props: {
-  pendingDetection: ['object', false, undefined],
+  pendingDetection: [PendingDetection, false, undefined],
 }
packages/@webex/internal-plugin-device/test/unit/spec/ipNetworkDetector.js (3)

331-331: Consider adding test coverage for force=false scenario.

The test verifies reset behavior with force=true, but it would be valuable to also verify the behavior when force=false.

 // now call detect() again
-const promise2 = ipNetworkDetector.detect(true);
+const promise2 = ipNetworkDetector.detect(false);

 // everything should have been reset
 assert.equal(ipNetworkDetector.supportsIpV4, undefined);

345-387: Consider verifying state transitions during queued detection.

The test effectively verifies the queuing behavior, but it would be valuable to also assert the state transitions during the process.

Add assertions to verify state transitions:

 // now call detect() again
 ipNetworkDetector.detect(true);
+assert.equal(ipNetworkDetector.state, 'detecting');

 // simulate the end of the detection -> another one should be started
 simulateEndOfCandidateGathering(10);
+assert.equal(ipNetworkDetector.state, 'idle');

389-424: Enhance test readability and coverage.

The parametrized test effectively covers various scenarios, but consider these improvements:

  1. Use more descriptive test titles that explain the expected behavior.
  2. Verify state transitions during the detection process.
 it.each`
   force    | state        | receivedOnlyMDnsCandidates | expectedToRunDetection
   ${true}  | ${'initial'} | ${false}                   | ${true}
   ${true}  | ${'idle'}    | ${false}                   | ${true}
   ${true}  | ${'initial'} | ${true}                    | ${true}
   ${true}  | ${'idle'}    | ${true}                    | ${true}
   ${false} | ${'initial'} | ${false}                   | ${true}
   ${false} | ${'initial'} | ${true}                    | ${true}
   ${false} | ${'idle'}    | ${true}                    | ${true}
   ${false} | ${'idle'}    | ${false}                   | ${false}
 `(
-  'force=$force, state=$state, receivedOnlyMDnsCandidates=$receivedOnlyMDnsCandidates => expectedToRunDetection=$expectedToRunDetection',
+  '$state state with force=$force should ${expectedToRunDetection ? "" : "not "}run detection when ${receivedOnlyMDnsCandidates ? "only mDNS candidates were received" : "real candidates were received"}',
   async ({force, state, receivedOnlyMDnsCandidates, expectedToRunDetection}) => {
     ipNetworkDetector.state = state;
     sinon
       .stub(ipNetworkDetector, 'receivedOnlyMDnsCandidates')
       .returns(receivedOnlyMDnsCandidates);

     const result = ipNetworkDetector.detect(force);
+    assert.equal(ipNetworkDetector.state, expectedToRunDetection ? 'detecting' : state);

     if (expectedToRunDetection) {
       simulateEndOfCandidateGathering(10);
     }
     await result;

+    assert.equal(ipNetworkDetector.state, 'idle');
packages/@webex/plugin-meetings/src/reachability/index.ts (3)

157-160: LGTM! Non-blocking IP detection implementation looks good.

The implementation correctly addresses the PR objectives by:

  • Making IP detection non-blocking
  • Using the new force parameter
  • Gracefully handling potential failures

Consider adding a more detailed comment explaining why forcing IP detection here is necessary, e.g.:

-      // kick off ip version detection. We don't await it, as we don't want to waste time
-      // and if it fails, that's ok we can still carry on
+      // Force IP version detection to ensure accurate network information after user media acquisition.
+      // This is not awaited to avoid blocking the reachability checks, as they can proceed without
+      // the IP version information if the detection fails.

160-160: Consider improving type safety by removing @ts-ignore.

The @ts-ignore comment suggests incomplete type definitions for the webex internal API.

Consider adding proper type definitions for the webex internal API:

interface IpNetworkDetector {
  detect(force?: boolean): Promise<void>;
}

interface WebexInternalDevice {
  ipNetworkDetector: IpNetworkDetector;
}

interface WebexInternal {
  device: WebexInternalDevice;
}

interface Webex {
  internal: WebexInternal;
  // ... other properties
}

Line range hint 589-594: Consider consolidating type safety improvements in metrics collection.

The metrics collection accesses several IpNetworkDetector properties, all marked with @ts-ignore.

Consider extending the earlier suggested type definitions to include these properties:

interface IpNetworkDetector {
  detect(force?: boolean): Promise<void>;
  firstIpV4: boolean;
  firstIpV6: boolean;
  firstMdns: boolean;
  totalTime: number;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ac8238d and 7e7c3ec.

📒 Files selected for processing (4)
  • packages/@webex/internal-plugin-device/src/ipNetworkDetector.ts (3 hunks)
  • packages/@webex/internal-plugin-device/test/unit/spec/ipNetworkDetector.js (3 hunks)
  • packages/@webex/plugin-meetings/src/reachability/index.ts (1 hunks)
  • packages/@webex/plugin-meetings/test/unit/spec/reachability/index.ts (1 hunks)
🔇 Additional comments (5)
packages/@webex/plugin-meetings/test/unit/spec/reachability/index.ts (1)

1237-1237: LGTM!

The test correctly asserts that the detect method is called with the force parameter set to true, aligning with the changes introduced in the PR.

packages/@webex/internal-plugin-device/src/ipNetworkDetector.ts (2)

173-182: LGTM! State management logic is robust.

The state checks and early returns are well-implemented, preventing concurrent detections and unnecessary re-runs.


179-182: Verify behavior with mDNS-only candidates.

The PR objectives mention handling scenarios where only mDNS candidates are available. Let's verify this implementation.

✅ Verification successful

mDNS-only scenario is properly handled in the implementation

The implementation correctly handles mDNS-only scenarios:

  • The receivedOnlyMDnsCandidates() method specifically checks for mDNS-only cases
  • The condition !force && this.state !== STATE.INITIAL && !this.receivedOnlyMDnsCandidates() ensures re-detection when only mDNS candidates are received
  • Test coverage confirms the behavior: "works correctly when we get only mDNS candidates" verifies that supportsIpV4 and supportsIpV6 are set to undefined in mDNS-only cases
  • The implementation aligns with the PR objectives for handling mDNS-only scenarios
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for tests covering mDNS-only scenarios
rg -l "mDNS" --type ts --type js

# Search for related test cases
ast-grep --pattern 'describe($_, function() { 
  $$$
  it($_, function() {
    $$$
    firstMdns
    $$$
  })
  $$$
})'

Length of output: 293


Script:

#!/bin/bash
# Let's examine the test file content for mDNS scenarios
cat packages/@webex/internal-plugin-device/test/unit/spec/ipNetworkDetector.js

# Also check the implementation details
cat packages/@webex/internal-plugin-device/src/ipNetworkDetector.ts

Length of output: 22759

packages/@webex/internal-plugin-device/test/unit/spec/ipNetworkDetector.js (2)

6-7: LGTM! Well-implemented utility function.

The flushPromises utility function is correctly implemented using setImmediate to handle Promise microtasks in tests.


Line range hint 1-516: Overall test implementation is robust and comprehensive.

The test suite effectively covers the new functionality for IP network detection, including:

  • Handling of concurrent detect calls
  • State management
  • Force parameter behavior
  • Various network scenarios (IPv4, IPv6, mDNS)

The tests are well-structured, maintainable, and align with the PR objectives.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
validated If the pull request is validated for automation.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant