Improve types of testing utilities and fix some types in unit test code (#26122)

* Improve type of DeepPartial and make mergeObjects handle Sets/Maps properly

* Fix linting

* Remove undefined fields from menu_cloud_trial.test

* Prevent importing the wrong version of DeepPartial
This commit is contained in:
Harrison Healey 2024-02-13 11:48:13 -05:00 committed by GitHub
parent bdce9f42d8
commit daab9d5ff5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 303 additions and 292 deletions

View File

@ -114,13 +114,20 @@
{ {
"patterns": [ "patterns": [
{ {
"group": ["react-bootstrap"], "group": ["@mattermost/compass-components/*"],
"message": "compass-components is now archived."
}
],
"paths": [
{
"name": "react-bootstrap",
"importNames": ["OverlayTrigger"], "importNames": ["OverlayTrigger"],
"message": "Please use OverlayTrigger from '/components/overlay_trigger' instead." "message": "Use OverlayTrigger from '/components/overlay_trigger' instead."
}, },
{ {
"group": ["@mattermost/compass-components/*"], "name": "redux",
"message": "compass-components is now archived" "importNames": ["DeepPartial"],
"message": "Use DeepPartial from '@mattermost/types/utilities instead."
} }
] ]
} }

View File

@ -10,6 +10,7 @@ import {
import {loadProfilesForSidebar} from 'actions/user_actions'; import {loadProfilesForSidebar} from 'actions/user_actions';
import mockStore from 'tests/test_store'; import mockStore from 'tests/test_store';
import {TestHelper} from 'utils/test_helper';
const initialState = { const initialState = {
entities: { entities: {
@ -25,22 +26,22 @@ const initialState = {
}, },
}, },
channels: { channels: {
current_channel_id: { current_channel_id: TestHelper.getChannelMock({
id: 'current_channel_id', id: 'current_channel_id',
name: 'default-name', name: 'default-name',
display_name: 'Default', display_name: 'Default',
delete_at: 0, delete_at: 0,
type: 'O', type: 'O',
team_id: 'team_id', team_id: 'team_id',
}, }),
current_user_id__existingId: { current_user_id__existingId: TestHelper.getChannelMock({
id: 'current_user_id__existingId', id: 'current_user_id__existingId',
name: 'current_user_id__existingId', name: 'current_user_id__existingId',
display_name: 'Default', display_name: 'Default',
delete_at: 0, delete_at: 0,
type: '0', type: 'O',
team_id: 'team_id', team_id: 'team_id',
}, }),
}, },
channelsInTeam: { channelsInTeam: {
'team-id': ['current_channel_id'], 'team-id': ['current_channel_id'],
@ -56,7 +57,7 @@ const initialState = {
'team-id': { 'team-id': {
id: 'team_id', id: 'team_id',
name: 'team-1', name: 'team-1',
displayName: 'Team 1', display_name: 'Team 1',
}, },
}, },
myMembers: { myMembers: {
@ -95,7 +96,7 @@ const initialState = {
general: { general: {
license: {IsLicensed: 'false'}, license: {IsLicensed: 'false'},
serverVersion: '5.4.0', serverVersion: '5.4.0',
config: {PostEditTimeLimit: -1}, config: {PostEditTimeLimit: '-1'},
}, },
}, },
}; };

View File

@ -90,8 +90,8 @@ describe('actions/global_actions', () => {
team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0}, team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0},
}, },
myMembers: { myMembers: {
team1: {id: 'team1'}, team1: {team_id: 'team1'},
team2: {id: 'team2'}, team2: {team_id: 'team2'},
}, },
}, },
channels: { channels: {
@ -164,8 +164,8 @@ describe('actions/global_actions', () => {
team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0}, team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0},
}, },
myMembers: { myMembers: {
team1: {id: 'team1'}, team1: {team_id: 'team1'},
team2: {id: 'team2'}, team2: {team_id: 'team2'},
}, },
}, },
channels: { channels: {
@ -237,8 +237,8 @@ describe('actions/global_actions', () => {
team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0}, team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0},
}, },
myMembers: { myMembers: {
team1: {id: 'team1'}, team1: {team_id: 'team1'},
team2: {id: 'team2'}, team2: {team_id: 'team2'},
}, },
}, },
channels: { channels: {
@ -303,8 +303,8 @@ describe('actions/global_actions', () => {
team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0}, team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0},
}, },
myMembers: { myMembers: {
team1: {id: 'team1'}, team1: {team_id: 'team1'},
team2: {id: 'team2'}, team2: {team_id: 'team2'},
}, },
}, },
users: { users: {
@ -344,8 +344,8 @@ describe('actions/global_actions', () => {
team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0}, team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0},
}, },
myMembers: { myMembers: {
team1: {id: 'team1'}, team1: {team_id: 'team1'},
team2: {id: 'team2'}, team2: {team_id: 'team2'},
}, },
}, },
channels: { channels: {
@ -440,8 +440,8 @@ describe('actions/global_actions', () => {
team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0}, team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0},
}, },
myMembers: { myMembers: {
team1: {id: 'team1'}, team1: {team_id: 'team1'},
team2: {id: 'team2'}, team2: {team_id: 'team2'},
}, },
}, },
channels: { channels: {
@ -532,8 +532,8 @@ describe('actions/global_actions', () => {
team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0}, team2: {id: 'team2', display_name: 'Team 2', name: 'team2', delete_at: 0},
}, },
myMembers: { myMembers: {
team1: {id: 'team1'}, team1: {team_id: 'team1'},
team2: {id: 'team2'}, team2: {team_id: 'team2'},
}, },
}, },
channels: { channels: {

View File

@ -8,6 +8,7 @@ import {sendMembersInvites, sendGuestsInvites} from 'actions/invite_actions';
import mockStore from 'tests/test_store'; import mockStore from 'tests/test_store';
import {ConsolePages} from 'utils/constants'; import {ConsolePages} from 'utils/constants';
import {TestHelper} from 'utils/test_helper';
jest.mock('actions/team_actions', () => ({ jest.mock('actions/team_actions', () => ({
addUsersToTeam: () => ({ // since we are using addUsersToTeamGracefully, this call will always succeed addUsersToTeam: () => ({ // since we are using addUsersToTeamGracefully, this call will always succeed
@ -76,18 +77,18 @@ describe('actions/invite_actions', () => {
}, },
membersInTeam: { membersInTeam: {
correct: { correct: {
user1: {id: 'user1'}, user1: TestHelper.getTeamMembershipMock({user_id: 'user1', team_id: 'correct'}),
user2: {id: 'user2'}, user2: TestHelper.getTeamMembershipMock({user_id: 'user2', team_id: 'correct'}),
guest1: {id: 'guest1'}, guest1: TestHelper.getTeamMembershipMock({user_id: 'guest1', team_id: 'correct'}),
guest2: {id: 'guest2'}, guest2: TestHelper.getTeamMembershipMock({user_id: 'guest2', team_id: 'correct'}),
guest3: {id: 'guest3'}, guest3: TestHelper.getTeamMembershipMock({user_id: 'guest3', team_id: 'correct'}),
}, },
error: { error: {
user1: {id: 'user1'}, user1: TestHelper.getTeamMembershipMock({user_id: 'user1', team_id: 'error'}),
user2: {id: 'user2'}, user2: TestHelper.getTeamMembershipMock({user_id: 'user2', team_id: 'error'}),
guest1: {id: 'guest1'}, guest1: TestHelper.getTeamMembershipMock({user_id: 'guest1', team_id: 'error'}),
guest2: {id: 'guest2'}, guest2: TestHelper.getTeamMembershipMock({user_id: 'guest2', team_id: 'error'}),
guest3: {id: 'guest3'}, guest3: TestHelper.getTeamMembershipMock({user_id: 'guest3', team_id: 'error'}),
}, },
}, },
myMembers: {}, myMembers: {},
@ -97,15 +98,15 @@ describe('actions/invite_actions', () => {
channels: {}, channels: {},
membersInChannel: { membersInChannel: {
correct: { correct: {
guest2: {id: 'guest2'}, guest2: TestHelper.getChannelMembershipMock({user_id: 'guest2', channel_id: 'correct'}),
guest3: {id: 'guest3'}, guest3: TestHelper.getChannelMembershipMock({user_id: 'guest3', channel_id: 'correct'}),
}, },
correct2: { correct2: {
guest2: {id: 'guest2'}, guest2: TestHelper.getChannelMembershipMock({user_id: 'guest2', channel_id: 'correct2'}),
}, },
error: { error: {
guest2: {id: 'guest2'}, guest2: TestHelper.getChannelMembershipMock({user_id: 'guest2', channel_id: 'error'}),
guest3: {id: 'guest3'}, guest3: TestHelper.getChannelMembershipMock({user_id: 'guest3', channel_id: 'error'}),
}, },
}, },
}, },

View File

@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import type * as Redux from 'redux'; import type {AnyAction} from 'redux';
import {batchActions} from 'redux-batched-actions'; import {batchActions} from 'redux-batched-actions';
import type {Post} from '@mattermost/types/posts'; import type {Post} from '@mattermost/types/posts';
@ -48,7 +48,7 @@ export function completePostReceive(post: Post, websocketMessageProps: NewPostMe
return {error: result.error}; return {error: result.error};
} }
} }
const actions: Redux.AnyAction[] = []; const actions: AnyAction[] = [];
if (post.channel_id === getCurrentChannelId(getState())) { if (post.channel_id === getCurrentChannelId(getState())) {
actions.push({ actions.push({
@ -85,7 +85,7 @@ export function completePostReceive(post: Post, websocketMessageProps: NewPostMe
// setChannelReadAndViewed returns an array of actions to mark the channel read and viewed, and it dispatches an action // setChannelReadAndViewed returns an array of actions to mark the channel read and viewed, and it dispatches an action
// to asynchronously mark the channel as read on the server if necessary. // to asynchronously mark the channel as read on the server if necessary.
export function setChannelReadAndViewed(dispatch: DispatchFunc, getState: GetStateFunc, post: Post, websocketMessageProps: NewPostMessageProps, fetchedChannelMember?: boolean): Redux.AnyAction[] { export function setChannelReadAndViewed(dispatch: DispatchFunc, getState: GetStateFunc, post: Post, websocketMessageProps: NewPostMessageProps, fetchedChannelMember?: boolean): AnyAction[] {
const state = getState(); const state = getState();
const currentUserId = getCurrentUserId(state); const currentUserId = getCurrentUserId(state);

View File

@ -71,7 +71,7 @@ jest.mock('actions/telemetry_actions.jsx', () => {
}); });
describe('Actions.User', () => { describe('Actions.User', () => {
const initialState: GlobalState = { const initialState = {
entities: { entities: {
channels: { channels: {
currentChannelId: 'current_channel_id', currentChannelId: 'current_channel_id',
@ -100,12 +100,12 @@ describe('Actions.User', () => {
current_user_id: {channel_id: 'current_user_id'} as ChannelMembership, current_user_id: {channel_id: 'current_user_id'} as ChannelMembership,
}, },
}, },
} as unknown as GlobalState['entities']['channels'], },
general: { general: {
config: { config: {
EnableUserStatuses: 'true', EnableUserStatuses: 'true',
}, },
} as GlobalState['entities']['general'], },
preferences: { preferences: {
myPreferences: { myPreferences: {
'theme--team_1': { 'theme--team_1': {
@ -142,13 +142,13 @@ describe('Actions.User', () => {
current_user_id: {id: 'current_user_id'} as unknown as TeamMembership, current_user_id: {id: 'current_user_id'} as unknown as TeamMembership,
}, },
}, },
} as unknown as GlobalState['entities']['teams'], },
users: { users: {
currentUserId: 'current_user_id', currentUserId: 'current_user_id',
profilesInChannel: { profilesInChannel: {
group_channel_2: ['user_1', 'user_2'], group_channel_2: new Set(['user_1', 'user_2']),
}, },
} as unknown as GlobalState['entities']['users'], },
posts: { posts: {
posts: { posts: {
sample_post_id: { sample_post_id: {
@ -161,25 +161,25 @@ describe('Actions.User', () => {
order: ['sample_post_id'], order: ['sample_post_id'],
}, },
]}, ]},
} as unknown as GlobalState['entities']['posts'], },
} as unknown as GlobalState['entities'], },
storage: { storage: {
storage: {}, storage: {},
initialized: true, initialized: true,
}, },
views: { views: {
channel: { channel: {
} as GlobalState['views']['channel'], },
channelSidebar: { channelSidebar: {
unreadFilterEnabled: false, unreadFilterEnabled: false,
} as GlobalState['views']['channelSidebar'], },
} as GlobalState['views'], },
} as GlobalState; };
test('loadProfilesAndTeamMembers', async () => { test('loadProfilesAndTeamMembers', async () => {
const expectedActions = [{type: 'MOCK_GET_PROFILES_IN_TEAM', args: ['team_1', 0, 60, '', {}]}]; const expectedActions = [{type: 'MOCK_GET_PROFILES_IN_TEAM', args: ['team_1', 0, 60, '', {}]}];
let testStore = mockStore({} as GlobalState); let testStore = mockStore({});
await testStore.dispatch(UserActions.loadProfilesAndTeamMembers(0, 60, 'team_1', {})); await testStore.dispatch(UserActions.loadProfilesAndTeamMembers(0, 60, 'team_1', {}));
let actualActions = testStore.getActions(); let actualActions = testStore.getActions();
expect(actualActions[0].args).toEqual(expectedActions[0].args); expect(actualActions[0].args).toEqual(expectedActions[0].args);
@ -337,7 +337,6 @@ describe('Actions.User', () => {
entities: { entities: {
...initialState.entities, ...initialState.entities,
channelCategories: { channelCategories: {
...initialState.entities.channelCategories,
byId: { byId: {
dmsCategory, dmsCategory,
}, },

View File

@ -24,7 +24,7 @@ describe('components/admin_console/license_settings/modals/confirm_license_remov
modals: { modals: {
modalState: { modalState: {
confirm_license_removal: { confirm_license_removal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -44,7 +44,7 @@ describe('components/admin_console/license_settings/modals/upload_license_modal'
modals: { modals: {
modalState: { modalState: {
upload_license: { upload_license: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -63,7 +63,7 @@ describe('components/channel_invite_modal/team_warning_banner', () => {
profiles: {}, profiles: {},
}, },
groups: { groups: {
myGroups: {}, myGroups: [],
groups: {}, groups: {},
}, },
emojis: { emojis: {

View File

@ -48,10 +48,10 @@ jest.mock('utils/channel_utils', () => ({
describe('Actions', () => { describe('Actions', () => {
const channel1 = {id: 'channel_id1', name: 'achannel', team_id: 'team_id1'}; const channel1 = {id: 'channel_id1', name: 'achannel', team_id: 'team_id1'};
const channel2 = {id: 'channel_id2', name: 'achannel', team_id: 'team_id2'}; const channel2 = {id: 'channel_id2', name: 'achannel', team_id: 'team_id2'};
const channel3 = {id: 'channel_id3', name: 'achannel3', team_id: 'team_id1', type: 'O'}; const channel3 = {id: 'channel_id3', name: 'achannel3', team_id: 'team_id1', type: 'O' as const};
const channel4 = {id: 'channel_id4', name: 'additional-abilities---community-systems', team_id: 'team_id1', type: 'O'}; const channel4 = {id: 'channel_id4', name: 'additional-abilities---community-systems', team_id: 'team_id1', type: 'O' as const};
const channel5 = {id: 'channel_id5', name: 'some-group-channel', team_id: 'team_id1', type: 'G'}; const channel5 = {id: 'channel_id5', name: 'some-group-channel', team_id: 'team_id1', type: 'G' as const};
const channel6 = {id: 'channel_id6', name: '12345678901234567890123456', team_id: 'team_id1', type: 'O'}; const channel6 = {id: 'channel_id6', name: '12345678901234567890123456', team_id: 'team_id1', type: 'O' as const};
const initialState = { const initialState = {
entities: { entities: {

View File

@ -58,7 +58,7 @@ describe('components/cloud_start_trial_btn/cloud_start_trial_btn', () => {
modals: { modals: {
modalState: { modalState: {
learn_more_trial_modal: { learn_more_trial_modal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -40,7 +40,7 @@ describe('components/request_business_email_modal/request_business_email_modal',
modals: { modals: {
modalState: { modalState: {
request_business_email_modal: { request_business_email_modal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -34,7 +34,7 @@ describe('components/pricing_modal/downgrade_team_removal_modal', () => {
modals: { modals: {
modalState: { modalState: {
success_modal: { success_modal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -30,7 +30,7 @@ describe('components/pricing_modal/downgrade_team_removal_modal', () => {
modals: { modals: {
modalState: { modalState: {
success_modal: { success_modal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -76,7 +76,7 @@ describe('components/dot_menu/DotMenu', () => {
}, },
currentUserId: 'current_user_id', currentUserId: 'current_user_id',
profilesInChannel: { profilesInChannel: {
current_user_id: ['user_1'], current_user_id: new Set(['user_1']),
}, },
}, },
teams: { teams: {

View File

@ -4,7 +4,8 @@
import {mount} from 'enzyme'; import {mount} from 'enzyme';
import React from 'react'; import React from 'react';
import {Provider} from 'react-redux'; import {Provider} from 'react-redux';
import type {DeepPartial} from 'redux';
import type {DeepPartial} from '@mattermost/types/utilities';
import {renderWithContext, screen} from 'tests/react_testing_utils'; import {renderWithContext, screen} from 'tests/react_testing_utils';
import mockStore from 'tests/test_store'; import mockStore from 'tests/test_store';

View File

@ -64,7 +64,7 @@ describe('components/learn_more_trial_modal/learn_more_trial_modal', () => {
modals: { modals: {
modalState: { modalState: {
learn_more_trial_modal: { learn_more_trial_modal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -36,7 +36,7 @@ describe('components/learn_more_trial_modal/learn_more_trial_modal_step', () =>
modals: { modals: {
modalState: { modalState: {
learn_more_trial_modal: { learn_more_trial_modal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -64,7 +64,7 @@ describe('components/learn_more_trial_modal/start_trial_btn', () => {
modals: { modals: {
modalState: { modalState: {
learn_more_trial_modal: { learn_more_trial_modal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -80,7 +80,7 @@ describe('components/Menu', () => {
const defaultState = { const defaultState = {
entities: { entities: {
channels: { channels: {
myMembers: [], myMembers: {},
}, },
general: { general: {
config: {}, config: {},
@ -95,7 +95,7 @@ describe('components/Menu', () => {
team_id: 'team-id', team_id: 'team-id',
user_id: 'test-user-id', user_id: 'test-user-id',
roles: 'team_user', roles: 'team_user',
scheme_user: 'true', scheme_user: true,
}, },
}, },
}, },

View File

@ -9,6 +9,8 @@ import type {ComponentProps} from 'react';
import {act} from 'react-dom/test-utils'; import {act} from 'react-dom/test-utils';
import type {match} from 'react-router-dom'; import type {match} from 'react-router-dom';
import {CollapsedThreads} from '@mattermost/types/config';
import {getPostThread} from 'mattermost-redux/actions/posts'; import {getPostThread} from 'mattermost-redux/actions/posts';
import {Client4} from 'mattermost-redux/client'; import {Client4} from 'mattermost-redux/client';
import {Preferences} from 'mattermost-redux/constants'; import {Preferences} from 'mattermost-redux/constants';
@ -151,9 +153,9 @@ describe('components/PermalinkView', () => {
}, },
channels: { channels: {
channels: { channels: {
channelid1: {id: 'channelid1', name: 'channel1', type: 'O', team_id: 'current_team_id'}, channelid1: TestHelper.getChannelMock({id: 'channelid1', name: 'channel1', type: 'O', team_id: 'current_team_id'}),
dmchannelid: {id: 'dmchannelid', name: 'dmchannel__current_user_id', type: 'D', team_id: ''}, dmchannelid: TestHelper.getChannelMock({id: 'dmchannelid', name: 'dmchannel__current_user_id', type: 'D', team_id: ''}),
gmchannelid: {id: 'gmchannelid', name: 'gmchannel', type: 'G', team_id: ''}, gmchannelid: TestHelper.getChannelMock({id: 'gmchannelid', name: 'gmchannel', type: 'G', team_id: ''}),
}, },
myMembers: {channelid1: {channel_id: 'channelid1', user_id: 'current_user_id'}}, myMembers: {channelid1: {channel_id: 'channelid1', user_id: 'current_user_id'}},
}, },
@ -335,7 +337,7 @@ describe('components/PermalinkView', () => {
...initialState.entities, ...initialState.entities,
general: { general: {
config: { config: {
CollapsedThreads: 'default_on', CollapsedThreads: CollapsedThreads.DEFAULT_ON,
}, },
}, },
}, },

View File

@ -18,7 +18,7 @@ describe('components/permissions_gates', () => {
channel_id: {channel_id: 'channel_id', roles: 'channel_role'}, channel_id: {channel_id: 'channel_id', roles: 'channel_role'},
}, },
roles: { roles: {
channel_id: ['channel_role'], channel_id: new Set(['channel_role']),
}, },
}, },
teams: { teams: {

View File

@ -23,22 +23,17 @@ const preferenceKeys = {
}; };
const openGraphData = { const openGraphData = {
audios: null,
description: 'Mattermost is a secure, open source platform for communication, collaboration, and workflow orchestration across tools and teams.', description: 'Mattermost is a secure, open source platform for communication, collaboration, and workflow orchestration across tools and teams.',
determiner: '',
images: [{ images: [{
height: 1256, height: 1256,
secure_url: 'http://localhost:8065/api/v4/image?url=http%3A%2F%2Fmattermo…t.com%2Fwp-content%2Fuploads%2F2021%2F09%2FHomepage%402x.png', secure_url: 'http://localhost:8065/api/v4/image?url=http%3A%2F%2Fmattermo…t.com%2Fwp-content%2Fuploads%2F2021%2F09%2FHomepage%402x.png',
type: 'image/png', type: 'image/png',
url: '', url: '',
width: 2400}], width: 2400}],
locale: '',
locales_alternate: null,
site_name: 'Mattermost.com', site_name: 'Mattermost.com',
title: 'Mattermost | Open Source Collaboration for Developers', title: 'Mattermost | Open Source Collaboration for Developers',
type: 'website', type: 'website',
url: 'https://www.mattermost.com', url: 'https://www.mattermost.com',
videos: null,
}; };
const initialState = { const initialState = {
@ -64,7 +59,9 @@ const initialState = {
}, },
posts: { posts: {
openGraph: { openGraph: {
post_id_1: openGraphData, post_id_1: {
[openGraphData.url]: openGraphData,
},
}, },
}, },
}, },

View File

@ -4,6 +4,8 @@
import {mount} from 'enzyme'; import {mount} from 'enzyme';
import React from 'react'; import React from 'react';
import {CollapsedThreads} from '@mattermost/types/config';
import {Preferences} from 'mattermost-redux/constants'; import {Preferences} from 'mattermost-redux/constants';
import FollowButton from 'components/threading/common/follow_button'; import FollowButton from 'components/threading/common/follow_button';
@ -46,7 +48,7 @@ describe('rhs_header_post', () => {
general: { general: {
config: { config: {
FeatureFlagCollapsedThreads: 'true', FeatureFlagCollapsedThreads: 'true',
CollapsedThreads: 'default_off', CollapsedThreads: CollapsedThreads.DEFAULT_OFF,
}, },
}, },
preferences: { preferences: {
@ -58,27 +60,27 @@ describe('rhs_header_post', () => {
}, },
posts: { posts: {
posts: { posts: {
42: { 42: TestHelper.getPostMock({
id: 42, id: '42',
message: 'where is @jessica.hyde?', message: 'where is @jessica.hyde?',
}, }),
43: { 43: TestHelper.getPostMock({
id: 43, id: '43',
message: 'not a mention', message: 'not a mention',
}, }),
}, },
}, },
threads: { threads: {
threads: { threads: {
42: { 42: {
id: 42, id: '42',
reply_count: 0, reply_count: 0,
is_following: null, is_following: null as any, // This is supposed to be boolean based on the type definitions, but this relies on this being null in some cases
}, },
43: { 43: {
id: 43, id: '43',
reply_count: 0, reply_count: 0,
is_following: null, is_following: null as any, // This is supposed to be boolean based on the type definitions, but this relies on this being null in some cases
}, },
}, },
}, },
@ -90,9 +92,6 @@ describe('rhs_header_post', () => {
browser: { browser: {
windowSize: WindowSizes.DESKTOP_VIEW, windowSize: WindowSizes.DESKTOP_VIEW,
}, },
channelSidebar: {
firstChannelName: 'town-square',
},
}, },
}; };

View File

@ -75,8 +75,6 @@ describe('components/select_results/SearchLimitsBanner', () => {
}, },
}, },
cloud: { cloud: {
subscription: null,
products: null,
limits: { limits: {
limits: {}, limits: {},
limitsLoaded: false, limitsLoaded: false,
@ -106,8 +104,6 @@ describe('components/select_results/SearchLimitsBanner', () => {
}, },
}, },
cloud: { cloud: {
subscription: null,
products: null,
limits: { limits: {
limits: {}, limits: {},
limitsLoaded: false, limitsLoaded: false,

View File

@ -15,11 +15,6 @@ describe('components/sidebar/invite_members_button', () => {
// required state to mount using the provider // required state to mount using the provider
const state = { const state = {
entities: { entities: {
general: {
config: {
FeatureFlagInviteMembersButton: 'user_icon',
},
},
teams: { teams: {
teams: { teams: {
team_id: {id: 'team_id', delete_at: 0}, team_id: {id: 'team_id', delete_at: 0},
@ -40,7 +35,7 @@ describe('components/sidebar/invite_members_button', () => {
}, },
stats: { stats: {
total_users_count: 10, total_users_count: 10,
}, } as any, // HARRISONTODO The defined type of entities.users.stats is incorrect
}, },
roles: { roles: {
roles: { roles: {

View File

@ -165,7 +165,7 @@ describe('components/sidebar', () => {
}; };
test('should not render unreads category when disabled by user preference', () => { test('should not render unreads category when disabled by user preference', () => {
const testState = mergeObjects(baseState, { const testState = {
entities: { entities: {
channels: { channels: {
messageCounts: { messageCounts: {
@ -178,7 +178,7 @@ describe('components/sidebar', () => {
]), ]),
}, },
}, },
}); };
renderWithContext( renderWithContext(
<Sidebar {...baseProps}/>, <Sidebar {...baseProps}/>,

View File

@ -4,6 +4,7 @@
import store from 'stores/redux_store'; import store from 'stores/redux_store';
import mockStore from 'tests/test_store'; import mockStore from 'tests/test_store';
import {TestHelper} from 'utils/test_helper';
import SearchChannelWithPermissionsProvider from './search_channel_with_permissions_provider'; import SearchChannelWithPermissionsProvider from './search_channel_with_permissions_provider';
@ -40,54 +41,54 @@ describe('components/SearchChannelWithPermissionsProvider', () => {
}, },
}, },
roles: { roles: {
somePublicMemberChannelId: [], somePublicMemberChannelId: new Set<string>(),
somePrivateMemberChannelId: [], somePrivateMemberChannelId: new Set<string>(),
someDirectConversation: [], someDirectConversation: new Set<string>(),
someGroupConversation: [], someGroupConversation: new Set<string>(),
}, },
channels: { channels: {
somePublicMemberChannelId: { somePublicMemberChannelId: TestHelper.getChannelMock({
id: 'somePublicMemberChannelId', id: 'somePublicMemberChannelId',
type: 'O', type: 'O',
name: 'some-public-member-channel', name: 'some-public-member-channel',
display_name: 'Some Public Member Channel', display_name: 'Some Public Member Channel',
delete_at: 0, delete_at: 0,
}, }),
somePrivateMemberChannelId: { somePrivateMemberChannelId: TestHelper.getChannelMock({
id: 'somePrivateMemberChannelId', id: 'somePrivateMemberChannelId',
type: 'P', type: 'P',
name: 'some-private-member-channel', name: 'some-private-member-channel',
display_name: 'Some Private Member Channel', display_name: 'Some Private Member Channel',
delete_at: 0, delete_at: 0,
}, }),
somePublicNonMemberChannelId: { somePublicNonMemberChannelId: TestHelper.getChannelMock({
id: 'somePublicNonMemberChannelId', id: 'somePublicNonMemberChannelId',
type: 'O', type: 'O',
name: 'some-public-non-member-channel', name: 'some-public-non-member-channel',
display_name: 'Some Public Non-Member Channel', display_name: 'Some Public Non-Member Channel',
delete_at: 0, delete_at: 0,
}, }),
somePrivateNonMemberChannelId: { somePrivateNonMemberChannelId: TestHelper.getChannelMock({
id: 'somePrivateNonMemberChannelId', id: 'somePrivateNonMemberChannelId',
type: 'P', type: 'P',
name: 'some-private=non-member-channel', name: 'some-private=non-member-channel',
display_name: 'Some Private Non-Member Channel', display_name: 'Some Private Non-Member Channel',
delete_at: 0, delete_at: 0,
}, }),
someDirectConversation: { someDirectConversation: TestHelper.getChannelMock({
id: 'someDirectConversation', id: 'someDirectConversation',
type: 'D', type: 'D',
name: 'some-direct-conversation', name: 'some-direct-conversation',
display_name: 'Some Direct Conversation', display_name: 'Some Direct Conversation',
delete_at: 0, delete_at: 0,
}, }),
someGroupConversation: { someGroupConversation: TestHelper.getChannelMock({
id: 'someGroupConversation', id: 'someGroupConversation',
type: 'GM', type: 'G',
name: 'some-group-conversation', name: 'some-group-conversation',
display_name: 'Some Group Conversation', display_name: 'Some Group Conversation',
delete_at: 0, delete_at: 0,
}, }),
}, },
channelsInTeam: { channelsInTeam: {
someTeamId: [ someTeamId: [

View File

@ -1,6 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import {CollapsedThreads} from '@mattermost/types/config';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
import {Preferences} from 'mattermost-redux/constants'; import {Preferences} from 'mattermost-redux/constants';
@ -68,11 +69,10 @@ describe('components/SwitchChannelProvider', () => {
}, },
}, },
channels: { channels: {
direct_other_user: { direct_other_user: TestHelper.getChannelMock({
id: 'direct_other_user', id: 'direct_other_user',
name: 'current_user_id__other_user', name: 'current_user_id__other_user',
}, }),
myMembers: {},
}, },
messageCounts: { messageCounts: {
direct_other_user: { direct_other_user: {
@ -99,27 +99,26 @@ describe('components/SwitchChannelProvider', () => {
}, },
users: { users: {
profiles: { profiles: {
current_user_id: {roles: 'system_role'}, current_user_id: TestHelper.getUserMock({roles: 'system_role'}),
other_user1: { other_user1: TestHelper.getUserMock({
id: 'other_user1', id: 'other_user1',
display_name: 'other_user1',
username: 'other_user1', username: 'other_user1',
}, }),
}, },
currentUserId: 'current_user_id', currentUserId: 'current_user_id',
profilesInChannel: { profilesInChannel: {
current_user_id: ['user_1'], current_user_id: new Set(['user_1']),
}, },
}, },
teams: { teams: {
currentTeamId: 'currentTeamId', currentTeamId: 'currentTeamId',
teams: { teams: {
currentTeamId: { currentTeamId: TestHelper.getTeamMock({
id: 'currentTeamId', id: 'currentTeamId',
display_name: 'test', display_name: 'test',
type: 'O', type: 'O',
delete_at: 0, delete_at: 0,
}, }),
}, },
}, },
posts: { posts: {
@ -294,7 +293,7 @@ describe('components/SwitchChannelProvider', () => {
}, },
currentUserId: 'current_user_id', currentUserId: 'current_user_id',
profilesInChannel: { profilesInChannel: {
current_user_id: ['user_1'], current_user_id: new Set(['user_1']),
}, },
}, },
}, },
@ -306,25 +305,29 @@ describe('components/SwitchChannelProvider', () => {
}); });
it('should sort results in aplhabetical order', () => { it('should sort results in aplhabetical order', () => {
const channels = [{ const channels = [
id: 'channel_other_user', TestHelper.getChannelMock({
type: 'O', id: 'channel_other_user',
name: 'blah_other_user', type: 'O',
display_name: 'blah_other_user', name: 'blah_other_user',
delete_at: 0, display_name: 'blah_other_user',
}, { delete_at: 0,
id: 'direct_other_user1', }),
type: 'D', TestHelper.getChannelMock({
name: 'current_user_id__other_user1', id: 'direct_other_user1',
display_name: 'other_user1', type: 'D',
delete_at: 0, name: 'current_user_id__other_user1',
}, { display_name: 'other_user1',
id: 'direct_other_user2', delete_at: 0,
type: 'D', }),
name: 'current_user_id__other_user2', TestHelper.getChannelMock({
display_name: 'other_user2', id: 'direct_other_user2',
delete_at: 0, type: 'D',
}]; name: 'current_user_id__other_user2',
display_name: 'other_user2',
delete_at: 0,
}),
];
const users = [ const users = [
TestHelper.getUserMock({ TestHelper.getUserMock({
@ -411,31 +414,36 @@ describe('components/SwitchChannelProvider', () => {
}), }),
]; ];
const channels = [{ const channels = [
id: 'channel_other_user', TestHelper.getChannelMock({
type: 'O', id: 'channel_other_user',
name: 'blah_other_user', type: 'O',
display_name: 'blah_other_user', name: 'blah_other_user',
delete_at: 0, display_name: 'blah_other_user',
}, { delete_at: 0,
id: 'direct_other_user1', }),
type: 'D', TestHelper.getChannelMock({
name: 'current_user_id__other_user1', id: 'direct_other_user1',
display_name: 'other_user1', type: 'D',
delete_at: 0, name: 'current_user_id__other_user1',
}, { display_name: 'other_user1',
id: 'direct_other_user2', delete_at: 0,
type: 'D', }),
name: 'current_user_id__other_user2', TestHelper.getChannelMock({
display_name: 'other_user2', id: 'direct_other_user2',
delete_at: 0, type: 'D',
}, { name: 'current_user_id__other_user2',
id: 'direct_other_user4', display_name: 'other_user2',
type: 'D', delete_at: 0,
name: 'current_user_id__other_user4', }),
display_name: 'other_user4', TestHelper.getChannelMock({
delete_at: 0, id: 'direct_other_user4',
}]; type: 'D',
name: 'current_user_id__other_user4',
display_name: 'other_user4',
delete_at: 0,
}),
];
const modifiedState = { const modifiedState = {
...defaultState, ...defaultState,
@ -528,7 +536,7 @@ describe('components/SwitchChannelProvider', () => {
channels: { channels: {
channel_other_user: { channel_other_user: {
id: 'channel_other_user', id: 'channel_other_user',
type: 'O', type: 'O' as const,
name: 'other_user', name: 'other_user',
display_name: 'other_user', display_name: 'other_user',
delete_at: 0, delete_at: 0,
@ -536,16 +544,14 @@ describe('components/SwitchChannelProvider', () => {
}, },
other_gm_channel: { other_gm_channel: {
id: 'other_gm_channel', id: 'other_gm_channel',
msg_count: 1, type: 'G' as const,
last_viewed_at: 3,
type: 'G',
name: 'other_gm_channel', name: 'other_gm_channel',
delete_at: 0, delete_at: 0,
display_name: 'other_gm_channel', display_name: 'other_gm_channel',
}, },
other_user1: { other_user1: {
id: 'other_user1', id: 'other_user1',
type: 'D', type: 'D' as const,
name: 'current_user_id__other_user1', name: 'current_user_id__other_user1',
display_name: 'current_user_id__other_user1', display_name: 'current_user_id__other_user1',
}, },
@ -601,7 +607,7 @@ describe('components/SwitchChannelProvider', () => {
channels: { channels: {
channel_other_user: { channel_other_user: {
id: 'channel_other_user', id: 'channel_other_user',
type: 'O', type: 'O' as const,
name: 'other_user', name: 'other_user',
display_name: 'other_user', display_name: 'other_user',
delete_at: 0, delete_at: 0,
@ -609,16 +615,14 @@ describe('components/SwitchChannelProvider', () => {
}, },
other_gm_channel: { other_gm_channel: {
id: 'other_gm_channel', id: 'other_gm_channel',
msg_count: 1, type: 'G' as const,
last_viewed_at: 3,
type: 'G',
name: 'other_gm_channel', name: 'other_gm_channel',
delete_at: 0, delete_at: 0,
display_name: 'other.user1, other.user2', display_name: 'other.user1, other.user2',
}, },
other_user1: { other_user1: {
id: 'other_user1', id: 'other_user1',
type: 'D', type: 'D' as const,
name: 'current_user_id__other_user1', name: 'current_user_id__other_user1',
display_name: 'other user1', display_name: 'other user1',
}, },
@ -635,7 +639,7 @@ describe('components/SwitchChannelProvider', () => {
}, },
currentUserId: 'current_user_id', currentUserId: 'current_user_id',
profilesInChannel: { profilesInChannel: {
current_user_id: ['user_1'], current_user_id: new Set(['user_1']),
}, },
}, },
}, },
@ -701,7 +705,7 @@ describe('components/SwitchChannelProvider', () => {
channels: { channels: {
channel_other_user: { channel_other_user: {
id: 'channel_other_user', id: 'channel_other_user',
type: 'O', type: 'O' as const,
name: 'other_user', name: 'other_user',
display_name: 'other_user', display_name: 'other_user',
delete_at: 0, delete_at: 0,
@ -709,16 +713,14 @@ describe('components/SwitchChannelProvider', () => {
}, },
other_gm_channel: { other_gm_channel: {
id: 'other_gm_channel', id: 'other_gm_channel',
msg_count: 1, type: 'G' as const,
last_viewed_at: 3,
type: 'G',
name: 'other_gm_channel', name: 'other_gm_channel',
delete_at: 0, delete_at: 0,
display_name: 'other_gm_channel', display_name: 'other_gm_channel',
}, },
other_user1: { other_user1: {
id: 'other_user1', id: 'other_user1',
type: 'D', type: 'D' as const,
name: 'current_user_id__other_user1', name: 'current_user_id__other_user1',
display_name: 'current_user_id__other_user1', display_name: 'current_user_id__other_user1',
}, },
@ -776,21 +778,19 @@ describe('components/SwitchChannelProvider', () => {
}, },
}, },
channels: { channels: {
other_gm_channel: { other_gm_channel: TestHelper.getChannelMock({
id: 'other_gm_channel', id: 'other_gm_channel',
msg_count: 1,
last_viewed_at: 3,
type: 'G', type: 'G',
name: 'other_gm_channel', name: 'other_gm_channel',
delete_at: 0, delete_at: 0,
display_name: 'other_gm_channel', display_name: 'other_gm_channel',
}, }),
other_user1: { other_user1: TestHelper.getChannelMock({
id: 'other_user1', id: 'other_user1',
type: 'D', type: 'D',
name: 'current_user_id__other_user1', name: 'current_user_id__other_user1',
display_name: 'current_user_id__other_user1', display_name: 'current_user_id__other_user1',
}, }),
}, },
channelsInTeam: { channelsInTeam: {
'': ['other_gm_channel'], '': ['other_gm_channel'],
@ -860,22 +860,22 @@ describe('components/SwitchChannelProvider', () => {
channel_2: {}, channel_2: {},
}, },
channels: { channels: {
channel_1: { channel_1: TestHelper.getChannelMock({
id: 'channel_1', id: 'channel_1',
type: 'O', type: 'O',
name: 'channel_1', name: 'channel_1',
display_name: 'channel 1', display_name: 'channel 1',
delete_at: 0, delete_at: 0,
team_id: 'currentTeamId', team_id: 'currentTeamId',
}, }),
channel_2: { channel_2: TestHelper.getChannelMock({
id: 'channel_2', id: 'channel_2',
type: 'O', type: 'O',
name: 'channel_2', name: 'channel_2',
display_name: 'channel 2', display_name: 'channel 2',
delete_at: 0, delete_at: 0,
team_id: 'archivedTeam', team_id: 'archivedTeam',
}, }),
}, },
}, },
}, },
@ -905,7 +905,7 @@ describe('components/SwitchChannelProvider', () => {
...defaultState.entities, ...defaultState.entities,
general: { general: {
config: { config: {
CollapsedThreads: 'default_off', CollapsedThreads: CollapsedThreads.DEFAULT_OFF,
}, },
}, },
threads: { threads: {
@ -953,9 +953,7 @@ describe('components/SwitchChannelProvider', () => {
channels: { channels: {
thread_gm_channel: { thread_gm_channel: {
id: 'thread_gm_channel', id: 'thread_gm_channel',
msg_count: 1, type: 'G' as const,
last_viewed_at: 3,
type: 'G',
name: 'thread_gm_channel', name: 'thread_gm_channel',
delete_at: 0, delete_at: 0,
display_name: 'thread_gm_channel', display_name: 'thread_gm_channel',

View File

@ -31,14 +31,6 @@ describe('components/team_controller/actions', () => {
myPreferences: {}, myPreferences: {},
}, },
}, },
requests: {
channels: {
getChannelsMembersCategories: {
status: 'not_started',
error: null,
},
},
},
}; };
describe('joinTeam', () => { describe('joinTeam', () => {

View File

@ -66,7 +66,7 @@ describe('components/three_days_left_trial_modal/three_days_left_trial_modal', (
modals: { modals: {
modalState: { modalState: {
three_days_left_trial_modal: { three_days_left_trial_modal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -52,7 +52,7 @@ describe('components/trial_benefits_modal/trial_benefits_modal', () => {
modals: { modals: {
modalState: { modalState: {
trial_benefits_modal: { trial_benefits_modal: {
open: 'true', open: true,
}, },
}, },
}, },

View File

@ -84,7 +84,7 @@ describe('component/user_group_popover', () => {
}, },
users: { users: {
profiles, profiles,
profilesInGroup, profilesInGroup: profilesInGroup as any, // HARRISONTODO The type entities.users.profilesInGroup is incorrectly an array when it should be a Set
}, },
preferences: { preferences: {
myPreferences: {}, myPreferences: {},

View File

@ -38,7 +38,7 @@ describe('component/user_groups_modal/ad_ldap_upsell_banner', () => {
license: { license: {
Cloud: 'false', Cloud: 'false',
SkuShortName: LicenseSkus.Professional, SkuShortName: LicenseSkus.Professional,
ExpiresAt: 100000000, ExpiresAt: '100000000',
}, },
config: {}, config: {},
}, },

View File

@ -110,10 +110,6 @@ describe('components/widgets/menu/menu_items/menu_cloud_trial', () => {
}, },
}, },
cloud: { cloud: {
customer: null,
subscription: null,
products: null,
invoices: null,
limits, limits,
}, },
usage, usage,
@ -130,10 +126,6 @@ describe('components/widgets/menu/menu_items/menu_cloud_trial', () => {
users, users,
general: {}, general: {},
cloud: { cloud: {
customer: null,
subscription: null,
products: null,
invoices: null,
limits, limits,
}, },
usage, usage,

View File

@ -24,7 +24,7 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
}, },
general: { general: {
config: { config: {
EnableTutorial: true, EnableTutorial: 'true',
}, },
license: { license: {
IsLicensed: 'false', IsLicensed: 'false',
@ -62,7 +62,7 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
}, },
general: { general: {
config: { config: {
EnableTutorial: true, EnableTutorial: 'true',
}, },
license: { license: {
IsLicensed: 'false', IsLicensed: 'false',
@ -101,7 +101,7 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
}, },
general: { general: {
config: { config: {
EnableTutorial: true, EnableTutorial: 'true',
}, },
license: { license: {
IsLicensed: 'true', IsLicensed: 'true',
@ -140,7 +140,7 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
}, },
general: { general: {
config: { config: {
EnableTutorial: true, EnableTutorial: 'true',
}, },
license: { license: {
IsLicensed: 'true', IsLicensed: 'true',
@ -180,7 +180,7 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
}, },
general: { general: {
config: { config: {
EnableTutorial: true, EnableTutorial: 'true',
}, },
license: { license: {
IsLicensed: 'false', IsLicensed: 'false',

View File

@ -39,7 +39,7 @@ describe('components/widgets/users/Avatars', () => {
nickname: 'nickname1', nickname: 'nickname1',
first_name: 'First1', first_name: 'First1',
last_name: 'Last1', last_name: 'Last1',
last_picture_update: '1620680333191', last_picture_update: 1620680333191,
}, },
2: { 2: {
@ -48,7 +48,7 @@ describe('components/widgets/users/Avatars', () => {
nickname: 'nickname2', nickname: 'nickname2',
first_name: 'First2', first_name: 'First2',
last_name: 'Last2', last_name: 'Last2',
last_picture_update: '1620680333191', last_picture_update: 1620680333191,
}, },
3: { 3: {
id: '3', id: '3',
@ -56,7 +56,7 @@ describe('components/widgets/users/Avatars', () => {
nickname: 'nickname3', nickname: 'nickname3',
first_name: 'First3', first_name: 'First3',
last_name: 'Last3', last_name: 'Last3',
last_picture_update: '1620680333191', last_picture_update: 1620680333191,
}, },
4: { 4: {
id: '4', id: '4',
@ -64,7 +64,7 @@ describe('components/widgets/users/Avatars', () => {
nickname: 'nickname4', nickname: 'nickname4',
first_name: 'First4', first_name: 'First4',
last_name: 'Last4', last_name: 'Last4',
last_picture_update: '1620680333191', last_picture_update: 1620680333191,
}, },
5: { 5: {
id: '5', id: '5',
@ -72,7 +72,7 @@ describe('components/widgets/users/Avatars', () => {
nickname: 'nickname5', nickname: 'nickname5',
first_name: 'First5', first_name: 'First5',
last_name: 'Last5', last_name: 'Last5',
last_picture_update: '1620680333191', last_picture_update: 1620680333191,
}, },
}, },
}, },

View File

@ -4,7 +4,8 @@
import {mount, shallow} from 'enzyme'; import {mount, shallow} from 'enzyme';
import React from 'react'; import React from 'react';
import {Provider} from 'react-redux'; import {Provider} from 'react-redux';
import type {DeepPartial} from 'redux';
import type {DeepPartial} from '@mattermost/types/utilities';
import ExternalImage from 'components/external_image'; import ExternalImage from 'components/external_image';

View File

@ -1018,9 +1018,9 @@ describe('Actions.Admin', () => {
const state = store.getState(); const state = store.getState();
const metadataResponse = state.entities.admin.samlMetadataResponse; const metadataResponse = state.entities.admin.samlMetadataResponse;
expect(metadataResponse).toBeTruthy(); expect(metadataResponse).toBeTruthy();
expect(metadataResponse.idp_url === samlIdpURL).toBeTruthy(); expect(metadataResponse!.idp_url === samlIdpURL).toBeTruthy();
expect(metadataResponse.idp_descriptor_url === samlIdpDescriptorURL).toBeTruthy(); expect(metadataResponse!.idp_descriptor_url === samlIdpDescriptorURL).toBeTruthy();
expect(metadataResponse.idp_public_certificate === samlIdpPublicCertificateText).toBeTruthy(); expect(metadataResponse!.idp_public_certificate === samlIdpPublicCertificateText).toBeTruthy();
}); });
it('setSamlIdpCertificateFromMetadata', async () => { it('setSamlIdpCertificateFromMetadata', async () => {

View File

@ -53,7 +53,8 @@ describe('Actions.Users', () => {
post('/users'). post('/users').
reply(201, {...userToCreate, id: TestHelper.generateId()}); reply(201, {...userToCreate, id: TestHelper.generateId()});
const {data: user} = await store.dispatch(Actions.createUser(userToCreate, '', '', '')); const response = await store.dispatch(Actions.createUser(userToCreate, '', '', ''));
const user = response.data!;
const state = store.getState(); const state = store.getState();
const {profiles} = state.entities.users; const {profiles} = state.entities.users;
@ -122,10 +123,10 @@ describe('Actions.Users', () => {
await store.dispatch(Actions.updateMyTermsOfServiceStatus('1', false)); await store.dispatch(Actions.updateMyTermsOfServiceStatus('1', false));
const {currentUserId, myAcceptedTermsOfServiceId} = store.getState().entities.users; const {currentUserId, profiles} = store.getState().entities.users;
expect(currentUserId).toBeTruthy(); expect(currentUserId).toBeTruthy();
expect(myAcceptedTermsOfServiceId).not.toEqual('1'); expect(profiles[currentUserId]).not.toEqual('1');
}); });
it('logout', async () => { it('logout', async () => {
@ -880,7 +881,7 @@ describe('Actions.Users', () => {
mention_keys: '', mention_keys: '',
user_id: currentUser.id, user_id: currentUser.id,
}, },
} as UserProfile)); } as unknown as UserProfile));
const updateRequest = store.getState().requests.users.updateMe; const updateRequest = store.getState().requests.users.updateMe;
const {currentUserId, profiles} = store.getState().entities.users; const {currentUserId, profiles} = store.getState().entities.users;
@ -933,7 +934,7 @@ describe('Actions.Users', () => {
mention_keys: '', mention_keys: '',
user_id: currentUser.id, user_id: currentUser.id,
}, },
} as UserProfile)); } as unknown as UserProfile));
const {profiles} = store.getState().entities.users; const {profiles} = store.getState().entities.users;
const updateNotifyProps = profiles[currentUserId].notify_props; const updateNotifyProps = profiles[currentUserId].notify_props;
@ -1026,7 +1027,8 @@ describe('Actions.Users', () => {
post('/users'). post('/users').
reply(200, TestHelper.fakeUserWithId()); reply(200, TestHelper.fakeUserWithId());
const {data: user} = await store.dispatch(Actions.createUser(TestHelper.fakeUser(), '', '', '')); const response = await store.dispatch(Actions.createUser(TestHelper.fakeUser(), '', '', ''));
const user = response.data!;
const beforeTime = new Date().getTime(); const beforeTime = new Date().getTime();
@ -1186,7 +1188,8 @@ describe('Actions.Users', () => {
post(`/users/${currentUserId}/tokens`). post(`/users/${currentUserId}/tokens`).
reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId}); reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId});
const {data} = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token')); const response = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token'));
const data = response.data!;
const {myUserAccessTokens} = store.getState().entities.users; const {myUserAccessTokens} = store.getState().entities.users;
const {userAccessTokensByUser} = store.getState().entities.admin; const {userAccessTokensByUser} = store.getState().entities.admin;
@ -1195,9 +1198,9 @@ describe('Actions.Users', () => {
expect(myUserAccessTokens[data.id]).toBeTruthy(); expect(myUserAccessTokens[data.id]).toBeTruthy();
expect(!myUserAccessTokens[data.id].token).toBeTruthy(); expect(!myUserAccessTokens[data.id].token).toBeTruthy();
expect(userAccessTokensByUser).toBeTruthy(); expect(userAccessTokensByUser).toBeTruthy();
expect(userAccessTokensByUser[currentUserId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId]).toBeTruthy();
expect(userAccessTokensByUser[currentUserId][data.id]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId][data.id]).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][data.id].token).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][data.id].token).toBeTruthy();
done(); done();
} }
@ -1217,7 +1220,8 @@ describe('Actions.Users', () => {
post(`/users/${currentUserId}/tokens`). post(`/users/${currentUserId}/tokens`).
reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId}); reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId});
const {data} = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token')); const response = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token'));
const data = response.data!;
nock(Client4.getBaseRoute()). nock(Client4.getBaseRoute()).
get(`/users/tokens/${data.id}`). get(`/users/tokens/${data.id}`).
@ -1232,9 +1236,9 @@ describe('Actions.Users', () => {
expect(myUserAccessTokens[data.id]).toBeTruthy(); expect(myUserAccessTokens[data.id]).toBeTruthy();
expect(!myUserAccessTokens[data.id].token).toBeTruthy(); expect(!myUserAccessTokens[data.id].token).toBeTruthy();
expect(userAccessTokensByUser).toBeTruthy(); expect(userAccessTokensByUser).toBeTruthy();
expect(userAccessTokensByUser[currentUserId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId]).toBeTruthy();
expect(userAccessTokensByUser[currentUserId][data.id]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId][data.id]).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][data.id].token).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][data.id].token).toBeTruthy();
expect(userAccessTokens).toBeTruthy(); expect(userAccessTokens).toBeTruthy();
expect(userAccessTokens[data.id]).toBeTruthy(); expect(userAccessTokens[data.id]).toBeTruthy();
expect(!userAccessTokens[data.id].token).toBeTruthy(); expect(!userAccessTokens[data.id].token).toBeTruthy();
@ -1253,7 +1257,8 @@ describe('Actions.Users', () => {
post(`/users/${currentUserId}/tokens`). post(`/users/${currentUserId}/tokens`).
reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId}); reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId});
const {data} = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token')); const response = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token'));
const data = response.data!;
nock(Client4.getBaseRoute()). nock(Client4.getBaseRoute()).
get(`/users/${currentUserId}/tokens`). get(`/users/${currentUserId}/tokens`).
@ -1269,9 +1274,9 @@ describe('Actions.Users', () => {
expect(myUserAccessTokens[data.id]).toBeTruthy(); expect(myUserAccessTokens[data.id]).toBeTruthy();
expect(!myUserAccessTokens[data.id].token).toBeTruthy(); expect(!myUserAccessTokens[data.id].token).toBeTruthy();
expect(userAccessTokensByUser).toBeTruthy(); expect(userAccessTokensByUser).toBeTruthy();
expect(userAccessTokensByUser[currentUserId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId]).toBeTruthy();
expect(userAccessTokensByUser[currentUserId][data.id]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId][data.id]).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][data.id].token).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][data.id].token).toBeTruthy();
expect(userAccessTokens).toBeTruthy(); expect(userAccessTokens).toBeTruthy();
expect(userAccessTokens[data.id]).toBeTruthy(); expect(userAccessTokens[data.id]).toBeTruthy();
expect(!userAccessTokens[data.id].token).toBeTruthy(); expect(!userAccessTokens[data.id].token).toBeTruthy();
@ -1290,7 +1295,8 @@ describe('Actions.Users', () => {
post(`/users/${currentUserId}/tokens`). post(`/users/${currentUserId}/tokens`).
reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId}); reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId});
const {data} = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token')); const response = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token'));
const data = response.data!;
let {myUserAccessTokens} = store.getState().entities.users; let {myUserAccessTokens} = store.getState().entities.users;
let {userAccessTokensByUser, userAccessTokens} = store.getState().entities.admin; let {userAccessTokensByUser, userAccessTokens} = store.getState().entities.admin;
@ -1299,9 +1305,9 @@ describe('Actions.Users', () => {
expect(myUserAccessTokens[data.id]).toBeTruthy(); expect(myUserAccessTokens[data.id]).toBeTruthy();
expect(!myUserAccessTokens[data.id].token).toBeTruthy(); expect(!myUserAccessTokens[data.id].token).toBeTruthy();
expect(userAccessTokensByUser).toBeTruthy(); expect(userAccessTokensByUser).toBeTruthy();
expect(userAccessTokensByUser[currentUserId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId]).toBeTruthy();
expect(userAccessTokensByUser[currentUserId][data.id]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId][data.id]).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][data.id].token).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][data.id].token).toBeTruthy();
expect(userAccessTokens).toBeTruthy(); expect(userAccessTokens).toBeTruthy();
expect(userAccessTokens[data.id]).toBeTruthy(); expect(userAccessTokens[data.id]).toBeTruthy();
expect(!userAccessTokens[data.id].token).toBeTruthy(); expect(!userAccessTokens[data.id].token).toBeTruthy();
@ -1319,8 +1325,8 @@ describe('Actions.Users', () => {
expect(myUserAccessTokens).toBeTruthy(); expect(myUserAccessTokens).toBeTruthy();
expect(!myUserAccessTokens[data.id]).toBeTruthy(); expect(!myUserAccessTokens[data.id]).toBeTruthy();
expect(userAccessTokensByUser).toBeTruthy(); expect(userAccessTokensByUser).toBeTruthy();
expect(userAccessTokensByUser[currentUserId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId]).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][data.id]).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][data.id]).toBeTruthy();
expect(userAccessTokens).toBeTruthy(); expect(userAccessTokens).toBeTruthy();
expect(!userAccessTokens[data.id]).toBeTruthy(); expect(!userAccessTokens[data.id]).toBeTruthy();
}); });
@ -1338,7 +1344,8 @@ describe('Actions.Users', () => {
post(`/users/${currentUserId}/tokens`). post(`/users/${currentUserId}/tokens`).
reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId}); reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId});
const {data} = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token')); const response = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token'));
const data = response.data!;
const testId = data.id; const testId = data.id;
let {myUserAccessTokens} = store.getState().entities.users; let {myUserAccessTokens} = store.getState().entities.users;
@ -1348,9 +1355,9 @@ describe('Actions.Users', () => {
expect(myUserAccessTokens[testId]).toBeTruthy(); expect(myUserAccessTokens[testId]).toBeTruthy();
expect(!myUserAccessTokens[testId].token).toBeTruthy(); expect(!myUserAccessTokens[testId].token).toBeTruthy();
expect(userAccessTokensByUser).toBeTruthy(); expect(userAccessTokensByUser).toBeTruthy();
expect(userAccessTokensByUser[currentUserId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId]).toBeTruthy();
expect(userAccessTokensByUser[currentUserId][testId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId][testId]).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][testId].token).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][testId].token).toBeTruthy();
expect(userAccessTokens).toBeTruthy(); expect(userAccessTokens).toBeTruthy();
expect(userAccessTokens[data.id]).toBeTruthy(); expect(userAccessTokens[data.id]).toBeTruthy();
expect(!userAccessTokens[data.id].token).toBeTruthy(); expect(!userAccessTokens[data.id].token).toBeTruthy();
@ -1370,10 +1377,10 @@ describe('Actions.Users', () => {
expect(!myUserAccessTokens[testId].is_active).toBeTruthy(); expect(!myUserAccessTokens[testId].is_active).toBeTruthy();
expect(!myUserAccessTokens[testId].token).toBeTruthy(); expect(!myUserAccessTokens[testId].token).toBeTruthy();
expect(userAccessTokensByUser).toBeTruthy(); expect(userAccessTokensByUser).toBeTruthy();
expect(userAccessTokensByUser[currentUserId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId]).toBeTruthy();
expect(userAccessTokensByUser[currentUserId][testId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId][testId]).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][testId].is_active).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][testId].is_active).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][testId].token).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][testId].token).toBeTruthy();
expect(userAccessTokens).toBeTruthy(); expect(userAccessTokens).toBeTruthy();
expect(userAccessTokens[testId]).toBeTruthy(); expect(userAccessTokens[testId]).toBeTruthy();
expect(!userAccessTokens[testId].is_active).toBeTruthy(); expect(!userAccessTokens[testId].is_active).toBeTruthy();
@ -1393,7 +1400,8 @@ describe('Actions.Users', () => {
post(`/users/${currentUserId}/tokens`). post(`/users/${currentUserId}/tokens`).
reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId}); reply(201, {id: 'someid', token: 'sometoken', description: 'test token', user_id: currentUserId});
const {data} = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token')); const response = await store.dispatch(Actions.createUserAccessToken(currentUserId, 'test token'));
const data = response.data!;
const testId = data.id; const testId = data.id;
let {myUserAccessTokens} = store.getState().entities.users; let {myUserAccessTokens} = store.getState().entities.users;
@ -1403,9 +1411,9 @@ describe('Actions.Users', () => {
expect(myUserAccessTokens[testId]).toBeTruthy(); expect(myUserAccessTokens[testId]).toBeTruthy();
expect(!myUserAccessTokens[testId].token).toBeTruthy(); expect(!myUserAccessTokens[testId].token).toBeTruthy();
expect(userAccessTokensByUser).toBeTruthy(); expect(userAccessTokensByUser).toBeTruthy();
expect(userAccessTokensByUser[currentUserId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId]).toBeTruthy();
expect(userAccessTokensByUser[currentUserId][testId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId][testId]).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][testId].token).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][testId].token).toBeTruthy();
expect(userAccessTokens).toBeTruthy(); expect(userAccessTokens).toBeTruthy();
expect(userAccessTokens[testId]).toBeTruthy(); expect(userAccessTokens[testId]).toBeTruthy();
expect(!userAccessTokens[testId].token).toBeTruthy(); expect(!userAccessTokens[testId].token).toBeTruthy();
@ -1425,10 +1433,10 @@ describe('Actions.Users', () => {
expect(myUserAccessTokens[testId].is_active).toBeTruthy(); expect(myUserAccessTokens[testId].is_active).toBeTruthy();
expect(!myUserAccessTokens[testId].token).toBeTruthy(); expect(!myUserAccessTokens[testId].token).toBeTruthy();
expect(userAccessTokensByUser).toBeTruthy(); expect(userAccessTokensByUser).toBeTruthy();
expect(userAccessTokensByUser[currentUserId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId]).toBeTruthy();
expect(userAccessTokensByUser[currentUserId][testId]).toBeTruthy(); expect(userAccessTokensByUser![currentUserId][testId]).toBeTruthy();
expect(userAccessTokensByUser[currentUserId][testId].is_active).toBeTruthy(); expect(userAccessTokensByUser![currentUserId][testId].is_active).toBeTruthy();
expect(!userAccessTokensByUser[currentUserId][testId].token).toBeTruthy(); expect(!userAccessTokensByUser![currentUserId][testId].token).toBeTruthy();
expect(userAccessTokens).toBeTruthy(); expect(userAccessTokens).toBeTruthy();
expect(userAccessTokens[testId]).toBeTruthy(); expect(userAccessTokens[testId]).toBeTruthy();
expect(userAccessTokens[testId].is_active).toBeTruthy(); expect(userAccessTokens[testId].is_active).toBeTruthy();

View File

@ -5,6 +5,14 @@ function isObject(obj: any): obj is Record<string, any> {
return Boolean(obj && typeof obj === 'object' && !Array.isArray(obj)); return Boolean(obj && typeof obj === 'object' && !Array.isArray(obj));
} }
function isSet(obj: unknown): obj is Set<any> {
return Object.getPrototypeOf(obj) === Set.prototype;
}
function isMap(obj: unknown): obj is Map<any, any> {
return Object.getPrototypeOf(obj) === Map.prototype;
}
export default function mergeObjects(a: Record<string, any>, b: Record<string, any>, path = '.') { export default function mergeObjects(a: Record<string, any>, b: Record<string, any>, path = '.') {
if (a === null || a === undefined) { if (a === null || a === undefined) {
return b; return b;
@ -14,7 +22,15 @@ export default function mergeObjects(a: Record<string, any>, b: Record<string, a
let result: any; let result: any;
if (isObject(a) && isObject(b)) { if (isSet(a) && isSet(b)) {
result = b;
} else if (isSet(a) || isSet(b)) {
throw new Error(`Mismatched types: ${path} is a Set from one source but not the other`);
} else if (isMap(a) && isMap(b)) {
result = b;
} else if (isMap(a) || isMap(b)) {
throw new Error(`Mismatched types: ${path} is a Map from one source but not the other`);
} else if (isObject(a) && isObject(b)) {
result = {}; result = {};
for (const key of Object.keys(a)) { for (const key of Object.keys(a)) {

View File

@ -9,15 +9,17 @@ import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk'; import thunk from 'redux-thunk';
import type {ThunkDispatch} from 'redux-thunk'; import type {ThunkDispatch} from 'redux-thunk';
import type {DeepPartial} from '@mattermost/types/utilities';
import type {GlobalState} from 'types/store'; import type {GlobalState} from 'types/store';
import {defaultIntl} from './helpers/intl-test-helper'; import {defaultIntl} from './helpers/intl-test-helper';
export default function testConfigureStore(initialState = {}) { export default function testConfigureStore<State extends GlobalState>(initialState?: DeepPartial<State>) {
return configureStore<GlobalState, ThunkDispatch<GlobalState, Record<string, never>, AnyAction>>([thunk])(initialState as GlobalState); return configureStore<State, ThunkDispatch<State, Record<string, never>, AnyAction>>([thunk])(initialState as State);
} }
export function mockStore(initialState = {}, intl = defaultIntl) { export function mockStore<State extends GlobalState>(initialState?: DeepPartial<State>, intl = defaultIntl) {
const store = testConfigureStore(initialState); const store = testConfigureStore(initialState);
return { return {
store, store,

View File

@ -16,6 +16,9 @@ export type IDMappedObjects<E extends {id: string}> = RelationOneToOne<E, E>;
export type DeepPartial<T> = { export type DeepPartial<T> = {
// For each field of T, make it optional and... // For each field of T, make it optional and...
[K in keyof T]?: [K in keyof T]?:
// If that field is a Set or a Map, don't go further
T[K] extends Set<any> ? T[K] :
T[K] extends Map<any, any> ? T[K] :
// If that field is an object, make it a deep partial object // If that field is an object, make it a deep partial object
T[K] extends object ? DeepPartial<T[K]> : T[K] extends object ? DeepPartial<T[K]> :
// Else if that field is an optional object, make that a deep partial object // Else if that field is an optional object, make that a deep partial object