Ensure myTeam.id is not undefined (#8375)
This commit is contained in:
parent
50a7b14b6a
commit
7123c7f3c0
2 changed files with 250 additions and 27 deletions
243
app/components/team_sidebar/team_list/index.test.tsx
Normal file
243
app/components/team_sidebar/team_list/index.test.tsx
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {render, waitFor} from '@testing-library/react-native';
|
||||
import React from 'react';
|
||||
import {of as of$} from 'rxjs';
|
||||
|
||||
import TeamList from './team_list';
|
||||
|
||||
import TeamListWrapper from './';
|
||||
|
||||
// Mock database queries
|
||||
jest.mock('@queries/servers/team', () => {
|
||||
const {of} = require('rxjs');
|
||||
return {
|
||||
queryMyTeams: jest.fn(() => of([])),
|
||||
queryJoinedTeams: jest.fn(() => ({
|
||||
observe: jest.fn(() => of([])),
|
||||
})),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@queries/servers/preference', () => {
|
||||
const {of} = require('rxjs');
|
||||
return {
|
||||
queryPreferencesByCategoryAndName: jest.fn(() => ({
|
||||
observe: jest.fn(() => of([])),
|
||||
observeWithColumns: jest.fn(() => of([])),
|
||||
})),
|
||||
};
|
||||
});
|
||||
|
||||
const {queryPreferencesByCategoryAndName} = require('@queries/servers/preference');
|
||||
const {queryMyTeams, queryJoinedTeams} = require('@queries/servers/team');
|
||||
|
||||
// Mock WatermelonDB HOCs
|
||||
jest.mock('@nozbe/watermelondb/react', () => ({
|
||||
withDatabase: jest.fn((Component) => Component),
|
||||
withObservables: jest.fn((_, observableMapper) => {
|
||||
// eslint-disable-next-line react/display-name
|
||||
return (Component: any) => (props: any) => {
|
||||
const observables = observableMapper(props);
|
||||
const mockedProps: Record<string, any> = {};
|
||||
// eslint-disable-next-line guard-for-in
|
||||
for (const key in observables) {
|
||||
observables[key].subscribe((value: any) => {
|
||||
mockedProps[key] = value;
|
||||
});
|
||||
}
|
||||
return (
|
||||
<Component
|
||||
{...props}
|
||||
{...mockedProps}
|
||||
/>);
|
||||
};
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('./team_list', () => {
|
||||
return jest.fn(() => null); // Mock implementation for TeamList
|
||||
});
|
||||
|
||||
describe('withTeams HOC', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should handle valid data correctly', async () => {
|
||||
queryMyTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([{id: '1', roles: 'team_user'}])),
|
||||
});
|
||||
|
||||
queryJoinedTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([
|
||||
{id: '1', displayName: 'Team 1'},
|
||||
{id: '2', displayName: 'Team 2'},
|
||||
])),
|
||||
});
|
||||
|
||||
queryPreferencesByCategoryAndName.mockReturnValue({
|
||||
observeWithColumns: jest.fn(() => of$([{value: '1,2'}])),
|
||||
});
|
||||
|
||||
render(<TeamListWrapper/>);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(TeamList).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
myOrderedTeams: [{id: '1', roles: 'team_user'}],
|
||||
}),
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle missing team IDs gracefully', async () => {
|
||||
queryMyTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([{id: '1', roles: 'team_user'}])),
|
||||
});
|
||||
|
||||
queryJoinedTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([
|
||||
{id: '1', displayName: 'Team 1'},
|
||||
{id: undefined, displayName: 'Team 2'},
|
||||
])),
|
||||
});
|
||||
|
||||
queryPreferencesByCategoryAndName.mockReturnValue({
|
||||
observeWithColumns: jest.fn(() => of$([{value: '1,2'}])),
|
||||
});
|
||||
|
||||
render(<TeamListWrapper/>);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(TeamList).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
myOrderedTeams: [{id: '1', roles: 'team_user'}],
|
||||
}),
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle empty team order preferences gracefully', async () => {
|
||||
queryMyTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([{id: '1', roles: 'team_user'}])),
|
||||
});
|
||||
|
||||
queryJoinedTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([
|
||||
{id: '1', displayName: 'Team 1'},
|
||||
{id: '2', displayName: 'Team 2'},
|
||||
])),
|
||||
});
|
||||
|
||||
queryPreferencesByCategoryAndName.mockReturnValue({
|
||||
observeWithColumns: jest.fn(() => of$([])),
|
||||
});
|
||||
|
||||
render(<TeamListWrapper/>);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(TeamList).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
myOrderedTeams: [{id: '1', roles: 'team_user'}],
|
||||
}),
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle undefined in team order preferences gracefully', async () => {
|
||||
queryMyTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([
|
||||
{id: '1', roles: 'team_user'},
|
||||
{id: '2', roles: 'team_user'},
|
||||
])),
|
||||
});
|
||||
|
||||
queryJoinedTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([
|
||||
{id: '1', displayName: 'Team 1'},
|
||||
{id: '2', displayName: 'Team 2'},
|
||||
])),
|
||||
});
|
||||
|
||||
queryPreferencesByCategoryAndName.mockReturnValue({
|
||||
observeWithColumns: jest.fn(() => of$([{value: '1,,2'}])),
|
||||
});
|
||||
|
||||
render(<TeamListWrapper/>);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(TeamList).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
myOrderedTeams: [
|
||||
{id: '1', roles: 'team_user'},
|
||||
{id: '2', roles: 'team_user'},
|
||||
],
|
||||
}),
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle wrong data in team order preferences gracefully', async () => {
|
||||
queryMyTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([
|
||||
{id: '1', roles: 'team_user'},
|
||||
{id: '2', roles: 'team_user'},
|
||||
])),
|
||||
});
|
||||
|
||||
queryJoinedTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([
|
||||
{id: '1', displayName: 'Team 1'},
|
||||
{id: '2', displayName: 'Team 2'},
|
||||
])),
|
||||
});
|
||||
|
||||
queryPreferencesByCategoryAndName.mockReturnValue({
|
||||
observeWithColumns: jest.fn(() => of$([{value: '1,undefined,2'}])),
|
||||
});
|
||||
|
||||
render(<TeamListWrapper/>);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(TeamList).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
myOrderedTeams: [
|
||||
{id: '1', roles: 'team_user'},
|
||||
{id: '2', roles: 'team_user'},
|
||||
],
|
||||
}),
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle empty teams list gracefully', async () => {
|
||||
queryMyTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([])),
|
||||
});
|
||||
|
||||
queryJoinedTeams.mockReturnValue({
|
||||
observe: jest.fn(() => of$([])),
|
||||
});
|
||||
|
||||
queryPreferencesByCategoryAndName.mockReturnValue({
|
||||
observeWithColumns: jest.fn(() => of$([])),
|
||||
});
|
||||
|
||||
render(<TeamListWrapper/>);
|
||||
await waitFor(() => {
|
||||
expect(TeamList).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
myOrderedTeams: [],
|
||||
}),
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -14,12 +14,6 @@ import {queryJoinedTeams, queryMyTeams} from '@queries/servers/team';
|
|||
import TeamList from './team_list';
|
||||
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
import type MyTeamModel from '@typings/database/models/servers/my_team';
|
||||
|
||||
interface TeamWithLowerName {
|
||||
myTeam: MyTeamModel;
|
||||
lowerName?: string;
|
||||
}
|
||||
|
||||
const withTeams = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
const myTeams = queryMyTeams(database).observe();
|
||||
|
|
@ -37,35 +31,21 @@ const withTeams = withObservables([], ({database}: WithDatabaseArgs) => {
|
|||
|
||||
if (sortedTeamIds.size) {
|
||||
const mySortedTeams = [...sortedTeamIds].
|
||||
filter((id) => membershipMap.has(id)).
|
||||
filter((id) => id && membershipMap.has(id)).
|
||||
map((id) => membershipMap.get(id)!);
|
||||
|
||||
const extraTeams = teams.
|
||||
filter((t) => !sortedTeamIds.has(t.id) && membershipMap.has(t.id)).
|
||||
map((t) => ({
|
||||
myTeam: membershipMap.get(t.id)!,
|
||||
lowerName: t.displayName.toLocaleLowerCase(),
|
||||
} as TeamWithLowerName)).
|
||||
sort((a, b) => a.lowerName!.localeCompare(b.lowerName!)).
|
||||
map((t) => {
|
||||
delete t.lowerName;
|
||||
return t;
|
||||
});
|
||||
filter((t) => t.id && !sortedTeamIds.has(t.id) && membershipMap.has(t.id)).
|
||||
sort((a, b) => a.displayName.toLocaleLowerCase().localeCompare(b.displayName.toLocaleLowerCase())).
|
||||
map((t) => membershipMap.get(t.id)!);
|
||||
|
||||
return [...mySortedTeams, ...extraTeams];
|
||||
}
|
||||
|
||||
return teams.
|
||||
filter((t) => membershipMap.has(t.id)).
|
||||
map((t) => ({
|
||||
myTeam: membershipMap.get(t.id)!,
|
||||
lowerName: t.displayName.toLocaleLowerCase(),
|
||||
} as TeamWithLowerName)).
|
||||
sort((a, b) => a.lowerName!.localeCompare(b.lowerName!)).
|
||||
map((t) => {
|
||||
delete t.lowerName;
|
||||
return t.myTeam;
|
||||
});
|
||||
filter((t) => t.id && membershipMap.has(t.id)).
|
||||
sort((a, b) => a.displayName.toLocaleLowerCase().localeCompare(b.displayName.toLocaleLowerCase())).
|
||||
map((t) => membershipMap.get(t.id)!);
|
||||
}),
|
||||
);
|
||||
return {
|
||||
|
|
|
|||
Loading…
Reference in a new issue