Skip to content

Conversation

@gtryus
Copy link
Contributor

@gtryus gtryus commented Dec 23, 2025

  • Added tests to verify navigation to /switch-teams when teamId is undefined, ensuring proper handling of localStorage.
  • Implemented logic in ProjectsScreen to call handleSwitchTeams if teamId is not set, enhancing user flow for team management.

These changes improve the navigation experience by ensuring users are directed to the appropriate screen based on their team selection.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the navigation logic in ProjectsScreen by ensuring users without a selected team are automatically redirected to the team selection screen. The implementation adds a check for undefined teamId and corresponding test coverage.

  • Added conditional navigation logic to redirect users to /switch-teams when teamId is not set
  • Implemented two test cases to verify the navigation behavior with and without a defined teamId

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/renderer/src/routes/ProjectsScreen.tsx Added check to call handleSwitchTeams() when teamId is undefined, redirecting users to team selection
src/renderer/src/routes/ProjectsScreen.cy.tsx Added two test cases verifying navigation occurs when teamId is undefined and doesn't occur when teamId is defined

Critical Issues Identified:

The implementation in ProjectsScreen.tsx has a critical bug that will cause an infinite render loop. The handleSwitchTeams() function is being called unconditionally in the component body (line 194), which will execute on every render. This creates an infinite loop: render → call handleSwitchTeams → navigate → re-render → call handleSwitchTeams again.

Additionally, the component continues to render its JSX after calling handleSwitchTeams, which can lead to errors since the component depends on teamId being present for computing derived values like thisTeam and projects.

The proper solution is to wrap this logic in a useEffect hook with appropriate dependencies, and return early (e.g., render null or a loading state) to prevent rendering the rest of the component when teamId is missing.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 266 to 303
const teamId = 'test-team-id';
const mockTeam = {
id: teamId,
type: 'organization',
attributes: { name: 'Test Team' },
};

cy.window().then((win) => {
win.localStorage.setItem(localUserKey(LocalKey.team), teamId);
});

mountProjectsScreen(createInitialState(), ['/projects'], {
isAdmin: () => false,
personalTeam: 'personal-team-id',
teams: [mockTeam],
});

cy.get('#ProjectsScreen').should('exist');
cy.get('header').should('exist'); // AppHead should render
});

it('should display "No projects yet." when there are no projects', () => {
mountProjectsScreen(createInitialState(), ['/projects']);
const teamId = 'test-team-id';
const mockTeam = {
id: teamId,
type: 'organization',
attributes: { name: 'Test Team' },
};

cy.window().then((win) => {
win.localStorage.setItem(localUserKey(LocalKey.team), teamId);
});

mountProjectsScreen(createInitialState(), ['/projects'], {
isAdmin: () => false,
personalTeam: 'personal-team-id',
teams: [mockTeam],
});
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

There's significant code duplication across multiple test cases where the same teamId setup, mockTeam creation, and localStorage initialization is repeated. Consider extracting this common setup into a helper function or beforeEach hook to improve maintainability and reduce duplication.

Copilot uses AI. Check for mistakes.
- Added tests to verify navigation to /switch-teams when teamId is undefined, ensuring proper handling of localStorage.
- Implemented logic in ProjectsScreen to call handleSwitchTeams if teamId is not set, enhancing user flow for team management.

These changes improve the navigation experience by ensuring users are directed to the appropriate screen based on their team selection.

Refactor ProjectsScreen to handle missing teamId with useEffect and prevent infinite render loops

Update src/renderer/src/routes/ProjectsScreen.tsx

Co-authored-by: Copilot <[email protected]>

Update src/renderer/src/routes/ProjectsScreen.tsx

Co-authored-by: Copilot <[email protected]>

Refactor ProjectsScreen to handle missing teamId with early return and useEffect for navigation
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +488 to +491
// Wait a bit to ensure navigation doesn't happen
cy.wait(200);

// Verify ProjectsScreen renders (navigation did not happen)
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The test relies on cy.wait() with hardcoded delays (200ms) to verify that navigation doesn't occur. This approach is brittle and can lead to flaky tests. The test should instead use Cypress's retry-ability by checking for the expected state directly without arbitrary waits.

Suggested change
// Wait a bit to ensure navigation doesn't happen
cy.wait(200);
// Verify ProjectsScreen renders (navigation did not happen)
// Verify ProjectsScreen renders (navigation did not happen)
// Cypress will automatically retry this assertion until it passes or times out.

Copilot uses AI. Check for mistakes.
Comment on lines +299 to +306
const mockTeam = createTestTeam(teamId);
setupTeamInLocalStorage(teamId);

mountProjectsScreen(initialState, initialEntries, {
isAdmin,
personalTeam,
teams: [mockTeam],
});
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The test uses cy.window().then() to set up localStorage asynchronously before mounting the component. However, Cypress commands are asynchronous and queued, while mountProjectsScreen is called synchronously. This creates a race condition where the component might mount before localStorage is properly set up. The setupTeamInLocalStorage call inside mountWithTeam should use cy.then() to ensure the mount happens after localStorage setup is complete, or the localStorage setup should happen before calling mountWithTeam.

Copilot uses AI. Check for mistakes.
// Wait for the navigation effect to occur
// The component calls handleSwitchTeams() in useEffect when teamId is undefined,
// which removes the plan from localStorage and navigates to /switch-teams
cy.wait(200).then(() => {
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The test relies on cy.wait() with hardcoded delays (200ms) to verify asynchronous behavior. This approach is brittle and can lead to flaky tests. The test should instead use Cypress's retry-ability by checking for the expected state changes directly, or use cy.waitUntil() or other deterministic approaches to verify the navigation occurred.

Copilot uses AI. Check for mistakes.
@gtryus gtryus merged commit c0ce2fb into develop Dec 23, 2025
7 checks passed
@gtryus gtryus deleted the TT-6998-switch-teams-initially branch December 23, 2025 19:37
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