Skip to content

Conversation

@HankYuLinksys
Copy link
Collaborator

@HankYuLinksys HankYuLinksys commented Jan 15, 2026

User description

Summary

  • Extract device info data into dedicated deviceInfoProvider
  • Extract ethernet ports data into ethernetPortsProvider
  • Extract router time data into routerTimeProvider
  • Extract system stats data into systemStatsProvider
  • Extract WiFi radios data into wifiRadiosProvider
  • Add polling_helpers.dart for shared polling data extraction utilities
  • Rename DashboardManagerProvider to SessionProvider for session operations
  • Rename DashboardManagerService to SessionService for clarity
  • Update all consumers to use new focused providers
  • Add comprehensive unit tests for all new providers
  • Remove obsolete DashboardManagerState and related files

Changes

New Providers (Read-only, derived from polling data):

  • deviceInfoProvider - Extracts NodeDeviceInfo and SKU model number
  • ethernetPortsProvider - Extracts WAN/LAN connection status
  • routerTimeProvider - Extracts router local time with system fallback
  • systemStatsProvider - Extracts CPU, memory, and temperature stats
  • wifiRadiosProvider - Extracts WiFi radio information

Refactored Session Management:

  • SessionProvider (formerly DashboardManagerProvider) - Handles session operations
  • SessionService (formerly DashboardManagerService) - JNAP communication for session

Test Coverage:

  • Added unit tests for all 5 new providers
  • Added unit tests for SessionProvider and SessionService
  • Updated existing tests to use new provider structure

Impact

This refactoring improves:

  • Single Responsibility: Each provider has a focused purpose
  • Testability: Easier to mock and test individual components
  • Maintainability: Clear separation between data extraction and session management
  • Reusability: Polling data providers can be reused across the application

PR Type

Enhancement, Refactoring, Tests


Description

  • Extract focused providers from DashboardManagerProvider: Created dedicated providers (deviceInfoProvider, ethernetPortsProvider, routerTimeProvider, systemStatsProvider, wifiRadiosProvider) for specific polling data with improved single responsibility principle

  • Rename session management classes: Renamed DashboardManagerProvider to SessionProvider and DashboardManagerService to SessionService for clarity

  • Refactor views to use new providers: Updated InstantVerifyView and InternetSettingsView to consume focused providers instead of monolithic dashboard manager provider

  • Improve test infrastructure: Introduced TestHelper utility class for consistent test setup across multiple test files (AppsAndGamingViewTest, WiFiMainViewTest, InternetSettingsViewTest)

  • Add golden file testing: Integrated visual regression testing with golden files in view tests for better test coverage

  • Refactor WiFiItem model: Removed RouterRadio conversion and added null-safety checks with sensible defaults

  • Add IPv6 WAN form factory: Implemented factory pattern for creating appropriate IPv6 WAN form widgets based on connection type

  • UI framework updates: Migrated from StyledAppPageView to UiKitPageView and updated button components to new AppButton API

  • Code quality improvements: Fixed whitespace formatting in JNAPRetryOptions and added DDNS models barrel export file


Diagram Walkthrough

flowchart LR
  DMP["DashboardManagerProvider<br/>(monolithic)"]
  SP["SessionProvider<br/>(session ops)"]
  DIP["deviceInfoProvider"]
  EPP["ethernetPortsProvider"]
  RTP["routerTimeProvider"]
  SSP["systemStatsProvider"]
  WRP["wifiRadiosProvider"]
  IVV["InstantVerifyView"]
  ISV["InternetSettingsView"]
  
  DMP -->|refactor| SP
  DMP -->|extract| DIP
  DMP -->|extract| EPP
  DMP -->|extract| RTP
  DMP -->|extract| SSP
  DMP -->|extract| WRP
  
  DIP -->|consume| IVV
  RTP -->|consume| IVV
  SSP -->|consume| IVV
  
  ISV -->|consume| ISV
Loading

File Walkthrough

Relevant files
Tests
3 files
apps_and_gaming_view_test.dart
Refactor apps and gaming view tests with TestHelper and golden files

test/page/advanced_settings/apps_and_gaming/views/localizations/apps_and_gaming_view_test.dart

  • Refactored test setup to use new TestHelper class instead of manual
    mock registration and dependency injection
  • Replaced individual mock notifiers with centralized testHelper mock
    management
  • Updated test cases to use testHelper.pumpView() for widget setup
    instead of testableSingleRoute()
  • Added comprehensive test documentation with View ID APPGAM and
    detailed test case mapping table
  • Simplified tab switching logic with new switchToTab() helper function
  • Updated widget finders to use new key-based approach (e.g.,
    appDataTable_addButton, applicationNameTextField)
  • Added golden file references for visual regression testing with
    standardized naming convention
  • Replaced deprecated widget types (AppDropdownButtonAppDropdown,
    AppTabBarTabBar)
+728/-1301
wifi_main_view_test.dart
Refactor WiFi main view tests with golden files                   

test/page/wifi_settings/views/localizations/wifi_main_view_test.dart

  • Restructured test file from 862 lines to 426 lines with clearer test
    organization and documentation
  • Replaced individual mock setup with TestHelper utility class for
    consistent test infrastructure
  • Added comprehensive test ID comments (WIFIS-ADV_VIEW, WIFIS-MLO_WARN,
    etc.) mapping to specific UI scenarios
  • Converted tests to use golden file screenshots with descriptive
    filenames for visual regression testing
  • Added new helper function getWifiBundleTestState() to generate test
    state with dirty state support
+319/-755
internet_settings_view_test.dart
Refactor internet settings tests with TestHelper utility 

test/page/advanced_settings/internet_settings/views/localizations/internet_settings_view_test.dart

  • Replaced manual mock setup with TestHelper utility class for cleaner
    test infrastructure
  • Updated test structure to use testHelper.pumpView() instead of
    testableSingleRoute() for widget mounting
  • Added comprehensive test documentation with View ID comments and
    detailed scenario descriptions for each test case
  • Updated widget finders to use ValueKey and Key instead of icon-based
    lookups for better test stability
  • Added golden filename parameters to all test cases for screenshot
    testing
+534/-380
Refactoring
3 files
wifi_item.dart
Remove RouterRadio conversion and add null-safety to WiFiItem

lib/page/wifi_settings/providers/wifi_item.dart

  • Removed fromRadio() factory constructor that converted RouterRadio
    objects to WiFiItem
  • Updated fromMap() factory to add null-safety checks for all map fields
    with sensible defaults
  • Changed import from radio_info.dart to wifi_enums.dart and added
    re-export
  • Added default values for missing fields: WifiRadioBand.radio_24, empty
    strings, WifiSecurityType.open, etc.
+36/-226
internet_settings_view.dart
Refactor internet settings view to use focused providers 

lib/page/advanced_settings/internet_settings/views/internet_settings_view.dart

  • Refactored view to use new focused providers
    (internetSettingsIPv4FormValidityProvider,
    internetSettingsIPv6FormValidityProvider,
    optionalSettingsFormValidityProvider) instead of managing form state
    locally
  • Extracted IPv4, IPv6, and release/renew views into separate widget
    files (Ipv4ConnectionView, Ipv6ConnectionView, ReleaseAndRenewView)
  • Simplified state management by removing 20+ TextEditingControllers and
    replacing with form validity providers
  • Updated UI framework from StyledAppPageView to UiKitPageView and
    button components to use new AppButton API
  • Removed complex local state tracking (isIpv4Editing, isIpv6Editing,
    originalState) in favor of provider-based state management
+128/-1825
instant_verify_view.dart
Refactor instant verify view with new focused providers   

lib/page/instant_verify/views/instant_verify_view.dart

  • Refactored imports to use new focused providers (deviceInfoProvider,
    routerTimeProvider, systemStatsProvider) instead of
    dashboardManagerProvider
  • Reorganized UI components with new topology visualization using
    AppTopology widget and TopologyMenuHelper
  • Extracted PDF generation logic into dedicated InstantVerifyPdfService
    class
  • Refactored connectivity and WiFi status widgets with improved visual
    hierarchy and layout structure
  • Migrated from StyledAppPageView to UiKitPageView and updated
    icon/spacing constants to new design system
+740/-912
Enhancement
1 files
ipv6_wan_form_factory.dart
Add IPv6 WAN form factory for connection type handling     

lib/page/advanced_settings/internet_settings/widgets/wan_forms/ipv6/ipv6_wan_form_factory.dart

  • New factory class IPv6WanFormFactory to create appropriate IPv6 WAN
    form widgets based on connection type
  • Implements factory pattern with create() method supporting WanIPv6Type
    enum
  • Currently supports automatic type with AutomaticIPv6Form
  • Provides fallback _UnsupportedIPv6Form for unsupported IPv6 connection
    types
  • Validates IPv6 type against supported WAN combinations and displays
    appropriate error messages
+86/-0   
Miscellaneous
1 files
_models.dart
Add DDNS models barrel export file                                             

lib/page/advanced_settings/apps_and_gaming/ddns/models/_models.dart

  • Created new barrel export file for DDNS UI models
  • Exports ddns_ui_models.dart for centralized model access
+1/-0     
Formatting
1 files
jnap_retry_options.dart
Fix whitespace formatting in JNAPRetryOptions                       

lib/core/jnap/command/http/jnap_retry_options.dart

  • Fixed whitespace formatting in constructor declaration (removed extra
    space after opening parenthesis)
  • Fixed whitespace formatting in copyWith method (removed extra space
    before retryDelays parameter)
+2/-2     
Additional files
101 files
review-screenshot-tests.md +142/-0 
speckit.analyze.md +184/-0 
speckit.checklist.md +294/-0 
speckit.clarify.md +181/-0 
speckit.constitution.md +82/-0   
speckit.implement.md +135/-0 
speckit.plan.md +89/-0   
speckit.specify.md +258/-0 
speckit.tasks.md +137/-0 
speckit.taskstoissues.md +30/-0   
settings.local.json +24/-0   
.fvmrc +3/-0     
ci.yml +156/-0 
deploy-demo.yml +84/-0   
.gitmodules +0/-3     
.metadata +30/-0   
constitution.md +1093/-0
check-prerequisites.sh +166/-0 
common.sh +156/-0 
create-new-feature.sh +297/-0 
setup-plan.sh +61/-0   
update-agent-context.sh +799/-0 
agent-file-template.md +28/-0   
checklist-template.md +40/-0   
plan-template.md +104/-0 
spec-template.md +115/-0 
tasks-template.md +251/-0 
launch.json +19/-85 
.windsurfrules +385/-0 
AGENTS.md +29/-0   
APPGAP_MAPPING.md +148/-0 
CLAUDE.md +169/-0 
README.md +116/-10
SCREENSHOT_TESTING.md +146/-0 
TEST_CASES.md +381/-0 
THEME.md +201/-0 
google-services.json +0/-46   
AndroidManifest.xml +0/-7     
AndroidManifest.xml +0/-73   
MainActivity.kt +0/-7     
launch_background.xml +0/-9     
launch_background.xml +0/-9     
launch_background.xml +0/-9     
launch_background.xml +0/-9     
ic_launcher.xml +0/-5     
ic_launcher_round.xml +0/-5     
styles.xml +0/-21   
styles.xml +0/-21   
styles.xml +0/-21   
styles.xml +0/-21   
network_security_config.xml +0/-7     
AndroidManifest.xml +0/-7     
gradle.properties +0/-3     
gradle-wrapper.properties +0/-6     
project.properties +0/-4     
env.template +5/-0     
demo_cache_data.json +2818/-0
build_android.sh +0/-61   
build_ios.sh +0/-53   
clear_goldens.sh +30/-0   
constitution.md +1093/-0
lcov.info +59460/-0
dart_test.yaml +2/-1     
devtools_options.yaml +3/-0     
FAQ_AGENT.md +279/-0 
router_ai_assistant.md +142/-0 
router_assistant_architecture.md +155/-0 
architecture_analysis_2026-01-05.md +727/-0 
MIGRATION_TEST_RESULTS.md +1103/-0
REMAINING_TESTS_SUMMARY.md +352/-0 
SCREENSHOT_TEST_COVERAGE.md +239/-0 
SCREEN_SIZE_VERIFICATION_STATUS.md +358/-0 
platform-conditional-exports-audit.md +287/-0 
service-decoupling-audit.md +259/-0 
dirty_guard_framework_guide.md +226/-0 
dirty_guard_framework_requirements.md +266/-0 
pnp-flow.md +144/-0 
pnp.md +58/-0   
responsive_page_view.md +574/-0 
routing.md +51/-0   
SCREENSHOT_TEST_ANALYSIS_REPORT.md +205/-0 
SCREENSHOT_TEST_MASTER_REPORT.md +248/-0 
TICKER_MODE_SUMMARY.md +235/-0 
screenshot_testing_fix_workflow.md +697/-0 
screenshot_testing_guideline.md +89/-0   
screenshot_testing_knowledge_base.md +1295/-0
screenshot_testing_ticker_mode_enhancement.md +454/-0 
speedtest.md +93/-0   
mock_generation_guide.md +221/-0 
COMMON_ACTIONS.md +17/-0   
MOCKING.md +83/-0   
TEST_PROMPT.md +63/-0   
adm_tests.yaml +78/-0   
advrt_tests.yaml +80/-0   
apps_tests.yaml +175/-0 
dashboard_tests.yaml +59/-0   
dhcp_tests.yaml +60/-0   
dmz_tests.yaml +36/-0   
fw_tests.yaml +118/-0 
instant_adm_tests.yaml +53/-0   
Additional files not shown

…ManagerProvider

- Extract device info data into dedicated `deviceInfoProvider`
- Extract ethernet ports data into `ethernetPortsProvider`
- Extract router time data into `routerTimeProvider`
- Extract system stats data into `systemStatsProvider`
- Extract WiFi radios data into `wifiRadiosProvider`
- Add `polling_helpers.dart` for shared polling data extraction utilities
- Rename `DashboardManagerProvider` to `SessionProvider` for session operations
- Rename `DashboardManagerService` to `SessionService` for clarity
- Update all consumers to use new focused providers
- Add comprehensive unit tests for all new providers
- Remove obsolete `DashboardManagerState` and related files
@HankYuLinksys HankYuLinksys changed the base branch from main to dev-2.0.0 January 15, 2026 05:51
@qodo-code-review
Copy link

qodo-code-review bot commented Jan 15, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Unhandled async failures: New async flows (e.g., QR generation/export) use chained .then(...) without visible error
handling, which can result in silent failures and unclear user behavior if QR
creation/export fails.

Referred Code
    createWiFiQRCode(WiFiCredential(
            ssid: wifiSSID,
            password: wifiPassword,
            type: SecurityType.wpa))
        .then((imageBytes) {
      printWiFiQRCode(
          context, imageBytes, wifiSSID, wifiPassword);
    });
  },
),
AppButton.text(
  label: loc(context).downloadQR,
  icon: AppIcon.font(AppFontIcons.download),
  onTap: () async {
    createWiFiQRCode(WiFiCredential(
            ssid: wifiSSID,
            password: wifiPassword,
            type: SecurityType.wpa))
        .then((imageBytes) {
      exportFileFromBytes(
          fileName: 'share_wifi_$wifiSSID)}.png',



 ... (clipped 3 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Error details exposed: A user-facing snackbar includes internal error details via ${pnpState.error}, which can
leak implementation/system information to end users.

Referred Code
ref.listen(pnpProvider.select((s) => s.status), (previous, next) {
  if (next == PnpFlowStatus.wizardConfiguring &&
      previous == PnpFlowStatus.wizardSaving) {
    // This handles the case for unconfigured routers where saving moves to the next step.
    _stepController?.stepContinue();
  }
  if (next == PnpFlowStatus.wizardSaveFailed) {
    showSimpleSnackBar(context, 'Unexcepted error! <${pnpState.error}>');
  }
});

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status:
Ambiguous boolean naming: Newly introduced boolean identifiers like isGuestWiFiSupport and isNightModeSupport are
slightly unclear and would be more self-documenting as
isGuestWiFiSupported/isNightModeSupported.

Referred Code
final isGuestWiFiSupport = capabilities?.isGuestWiFiSupported ?? false;
final isNightModeSupport = capabilities?.isNightModeSupported ?? false;

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Sensitive data risk: The snackbar and file-export path incorporate dynamic values (pnpState.error, wifiSSID)
that may contain sensitive or unsafe content, and it is unclear from the diff whether
these values are sanitized/redacted before being shown or used.

Referred Code
    showSimpleSnackBar(context, 'Unexcepted error! <${pnpState.error}>');
  }
});

// Listen for firmware update status changes.
ref.listen(firmwareUpdateProvider, (previous, next) {
  if (pnpState.status != PnpFlowStatus.wizardUpdatingFirmware) return;

  if (previous?.isUpdating == true && next.isUpdating == false) {
    logger.i(
        '[PnP]: Firmware update finished, proceeding to Wi-Fi Ready screen.');
    ref.read(pnpProvider.notifier).completeFwCheck();
  }
});

// Build steps only once or when necessary.
if (steps.isEmpty) {
  steps = _buildSteps(pnpState);
}

return UiKitPageView(



 ... (clipped 233 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Filename not sanitized: The exported QR filename is derived from wifiSSID without visible
sanitization/normalization, which could lead to invalid or unsafe filenames depending on
SSID content.

Referred Code
createWiFiQRCode(WiFiCredential(
        ssid: wifiSSID,
        password: wifiPassword,
        type: SecurityType.wpa))
    .then((imageBytes) {
  exportFileFromBytes(
      fileName: 'share_wifi_$wifiSSID)}.png',
      utf8Bytes: imageBytes);
});

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link

qodo-code-review bot commented Jan 15, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Separate the undocumented USP protocol implementation

The PR introduces a large, undocumented User Services Platform (USP) protocol
implementation using Protobuf. This major feature should be moved to a separate
PR to improve clarity and reviewability.

Examples:

packages/usp_protocol_common/lib/src/generated/usp_msg.pb.dart [1-6559]
// This is a generated file - do not edit.
//
// Generated from usp_msg.proto.

// @dart = 3.3

// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes

 ... (clipped 6549 lines)
packages/usp_protocol_common/lib/src/generated/usp_msg.pbjson.dart [1-2172]

Solution Walkthrough:

Before:

// PR Title: "Refactor: Extract focused providers from DashboardManager"
// PR Description: Details about refactoring providers...

// Changed Files in this PR:
// - packages/usp_protocol_common/lib/src/generated/usp_msg.pb.dart (new, 6000+ lines)
// - packages/usp_protocol_common/lib/src/generated/usp_msg.pbjson.dart (new, 2000+ lines)
// - lib/providers/session_provider.dart (refactored)
// - lib/providers/device_info_provider.dart (new, extracted)
// - ... other refactoring files
// - test/.../apps_and_gaming_view_test.dart (updated tests)

After:

// PR #1: Refactoring
// PR Title: "Refactor: Extract focused providers from DashboardManager"
// PR Description: Details about refactoring providers...
// Changed Files:
// - lib/providers/session_provider.dart (refactored)
// - lib/providers/device_info_provider.dart (new, extracted)
// - ... other refactoring files
// - test/.../apps_and_gaming_view_test.dart (updated tests)

// PR #2: New Feature
// PR Title: "Feature: Add USP protocol implementation"
// PR Description: Explains the purpose and impact of adding USP.
// Changed Files:
// - packages/usp_protocol_common/lib/src/generated/usp_msg.pb.dart (new, 6000+ lines)
// - packages/usp_protocol_common/lib/src/generated/usp_msg.pbjson.dart (new, 2000+ lines)
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a massive, undocumented feature (USP protocol implementation) bundled with a refactoring, which severely impacts the PR's reviewability and scope.

High
Possible issue
Use DefaultTabController for tab switching

Fix the switchToTab helper function by using DefaultTabController.of() to
correctly retrieve the TabController, as the current implementation fails to
switch tabs.

test/page/advanced_settings/apps_and_gaming/views/localizations/apps_and_gaming_view_test.dart [23-35]

 Future<void> switchToTab(WidgetTester tester, int index) async {
-  final tabBarFinder = find.byType(TabBar);
-  expect(tabBarFinder, findsOneWidget);
+  // Retrieve the TabController from the DefaultTabController
+  final element = find.byType(TabBar).evaluate().first;
+  final controller = DefaultTabController.of(element);
+  expect(controller, isNotNull, reason: 'No DefaultTabController found');
 
-  final tabBar = tester.widget<TabBar>(tabBarFinder);
-  final controller = tabBar.controller;
-  if (controller != null) {
-    controller.animateTo(index);
-    await tester.pump();
-    await tester.pump(const Duration(milliseconds: 300));
-    await tester.pumpAndSettle();
-  }
+  controller!.animateTo(index);
+  // A single pumpAndSettle is usually sufficient
+  await tester.pumpAndSettle();
 }
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical bug in the switchToTab helper function, which would cause all tests relying on it to fail to switch tabs and test the wrong view.

High
Refine mock to be more specific

Refine the mock for isPortConflict in the APPGAM-SPF_OVER_ERR_DESK test to use
the specific port value 22 instead of any for a more precise test case.

test/page/advanced_settings/apps_and_gaming/views/localizations/apps_and_gaming_view_test.dart [501-553]

 // Test ID: APPGAM-SPF_OVER_ERR_DESK
 testLocalizations(
   'Single port forwarding - edit overlap error',
   (tester, screen) async {
     when(testHelper.mockSinglePortForwardingListNotifier.build())
         .thenReturn(SinglePortForwardingListState.fromMap(
             singlePortForwardingListTestState));
     when(testHelper.mockSinglePortForwardingRuleNotifier
-            .isPortConflict(any, any))
+            .isPortConflict(22, any))
         .thenAnswer((invocation) => true);
     when(testHelper.mockSinglePortForwardingRuleNotifier.isRuleValid())
         .thenAnswer((invocation) => false);
 
     // Enable animations for tab switching - MUST be set before pumpView
     testHelper.disableAnimations = false;
 
     await testHelper.pumpView(
       tester,
       locale: screen.locale,
       child: const AppsGamingSettingsView(),
     );
     await tester.pumpAndSettle();
     await switchToTab(tester, 1);
 
     final addBtnFinder = find.byKey(const Key('appDataTable_addButton'));
     await tester.tap(addBtnFinder);
     await tester.pumpAndSettle();
 
     await tester.enterText(
         find.byKey(const Key('externalPortTextField')), '22');
     await tester.pumpAndSettle();
 
     await tester.tap(find.byType(SinglePortForwardingListView));
     await tester.pumpAndSettle();
 
     // Hover on error icon to trigger tooltip display for overlap error
     final errorIconFinder = find.byIcon(Icons.error_outline);
     if (tester.any(errorIconFinder)) {
       final gesture =
           await tester.createGesture(kind: PointerDeviceKind.mouse);
       addTearDown(gesture.removePointer);
       await gesture.addPointer(location: Offset.zero);
       await gesture.moveTo(tester.getCenter(errorIconFinder.first));
       await tester.pumpAndSettle();
     }
   },
   screens: [
     ...responsiveDesktopScreens
         .map((e) => e.copyWith(height: 1080))
         .toList()
   ],
   goldenFilename: 'APPGAM-SPF_OVER_ERR_DESK-01-overlap_error',
 );

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that the mock for isPortConflict is too broad, and refining it to a specific value makes the test more precise and robust.

Low
  • Update

- Add new `--collect` / `-p` flag to collect golden files after tests
- Implement `_copyGoldensToSnapshots()` function to copy all golden files from test directories to snapshots folder
- Fix issue where golden files were never collected when using the Dart tool (since it always passes `-f` to shell script)
@qodo-code-review
Copy link

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: 🛡️ Quality & Logic (PR)

Failed stage: 🔍 Flutter Analyze [❌]

Failed test name: ""

Failure summary:

The action failed during Flutter/Dart static analysis (flutter analyze) because there were
compile-time analyzer errors (undefined_identifier), which caused the analyzer to exit with code 1.

- lib/page/instant_verify/views/instant_verify_view.dart:726:29: Undefined name
dashboardManagerProvider
- lib/page/wifi_settings/providers/wifi_bundle_provider.dart:55:29:
Undefined name dashboardManagerState
-
lib/page/wifi_settings/providers/wifi_bundle_provider.dart:84:44: Undefined name
dashboardManagerProvider
Additional lint warnings/infos were reported, but the error-level undefined
identifiers are what made the job fail.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

458:  FLUTTER_ROOT: /opt/hostedtoolcache/flutter/stable-3.38.7-x64
459:  PUB_CACHE: /home/runner/.pub-cache
460:  SSH_AUTH_SOCK: /tmp/ssh-sHtRISiRi9Qz/agent.2363
461:  SSH_AGENT_PID: 2364
462:  ##[endgroup]
463:  Analyzing PrivacyGUI...                                         
464:  info • Don't use 'BuildContext's across async gaps • lib/page/advanced_settings/dmz/views/dmz_settings_view.dart:88:41 • use_build_context_synchronously
465:  info • Don't use 'BuildContext's across async gaps • lib/page/advanced_settings/dmz/views/dmz_settings_view.dart:88:54 • use_build_context_synchronously
466:  info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • lib/page/advanced_settings/firewall/views/firewall_view.dart:94:17 • use_build_context_synchronously
467:  info • Use a 'SizedBox' to add whitespace to a layout • lib/page/dashboard/views/components/widgets/port_and_speed.dart:180:12 • sized_box_for_whitespace
468:  warning • The declaration '_showLayoutSettingsDialog' isn't referenced • lib/page/dashboard/views/dashboard_menu_view.dart:152:8 • unused_element
469:  info • Don't use 'BuildContext's across async gaps • lib/page/instant_admin/views/manual_firmware_update_view.dart:112:49 • use_build_context_synchronously
470:  info • Don't use 'BuildContext's across async gaps • lib/page/instant_admin/views/manual_firmware_update_view.dart:127:49 • use_build_context_synchronously
471:  info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • lib/page/instant_admin/views/timezone_view.dart:57:17 • use_build_context_synchronously
472:  info • Don't use 'BuildContext's across async gaps • lib/page/instant_setup/pnp_setup_view.dart:355:31 • use_build_context_synchronously
473:  error • Undefined name 'dashboardManagerProvider' • lib/page/instant_verify/views/instant_verify_view.dart:726:29 • undefined_identifier
474:  error • Undefined name 'dashboardManagerState' • lib/page/wifi_settings/providers/wifi_bundle_provider.dart:55:29 • undefined_identifier
475:  error • Undefined name 'dashboardManagerProvider' • lib/page/wifi_settings/providers/wifi_bundle_provider.dart:84:44 • undefined_identifier
476:  info • Don't use 'BuildContext's across async gaps • lib/util/get_log_selector/get_log_mobile.dart:11:36 • use_build_context_synchronously
...

479:  info • The type of the right operand ('Provider<RouterRepository>') isn't a subtype or a supertype of the left operand ('ProviderListenable<T>') • test/common/unit_test_helper.dart:48:18 • unrelated_type_equality_checks
480:  info • The type of the right operand ('NotifierProviderImpl<DashboardHomeNotifier, DashboardHomeState>') isn't a subtype or a supertype of the left operand ('ProviderListenable<T>') • test/common/unit_test_helper.dart:51:18 • unrelated_type_equality_checks
481:  warning • The method doesn't override an inherited method • test/mocks/add_nodes_notifier_mocks.dart:138:30 • override_on_non_overriding_member
482:  warning • The method doesn't override an inherited method • test/mocks/add_nodes_notifier_mocks.dart:161:39 • override_on_non_overriding_member
483:  warning • The method doesn't override an inherited method • test/mocks/add_nodes_notifier_mocks.dart:176:42 • override_on_non_overriding_member
484:  warning • The method doesn't override an inherited method • test/mocks/add_nodes_notifier_mocks.dart:202:27 • override_on_non_overriding_member
485:  warning • The method doesn't override an inherited method • test/mocks/add_wired_nodes_notifier_mocks.dart:152:23 • override_on_non_overriding_member
486:  warning • The method doesn't override an inherited method • test/mocks/auto_parent_first_login_notifier_mocks.dart:129:20 • override_on_non_overriding_member
487:  warning • The method doesn't override an inherited method • test/mocks/auto_parent_first_login_notifier_mocks.dart:140:20 • override_on_non_overriding_member
488:  warning • The method doesn't override an inherited method • test/mocks/auto_parent_first_login_notifier_mocks.dart:150:20 • override_on_non_overriding_member
489:  warning • Unused import: 'package:privacy_gui/core/jnap/models/device.dart' • test/page/dashboard/providers/dashboard_home_provider_test.dart:9:8 • unused_import
490:  warning • Unused import: 'package:flutter_riverpod/flutter_riverpod.dart' • test/page/nodes/services/add_nodes_service_test.dart:3:8 • unused_import
491:  info • Use 'const' literals as arguments to constructors of '@immutable' classes • test/page/nodes/services/add_nodes_service_test.dart:191:72 • prefer_const_literals_to_create_immutables
492:  info • Use 'const' literals as arguments to constructors of '@immutable' classes • test/page/nodes/services/add_wired_nodes_service_test.dart:110:74 • prefer_const_literals_to_create_immutables
493:  29 issues found. (ran in 37.0s)
494:  ##[error]Process completed with exit code 1.
495:  Post job cleanup.
496:  Stopping SSH agent
497:  The "file" argument must be of type string. Received undefined
498:  Error stopping the SSH agent, proceeding anyway
499:  Post job cleanup.

@HankYuLinksys HankYuLinksys deleted the refactoring-dashboard-manager branch January 15, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants