From 2fad44fae0a1aacc039a05e3d8da215c6c57be78 Mon Sep 17 00:00:00 2001 From: Joseph Baylon Date: Mon, 11 Jan 2021 01:10:59 -0800 Subject: [PATCH] MM-31272 Detox/E2E - Add e2e test for MM-T3646 (#5092) * MM-31272 Detox/E2E - Add e2e test for MM-T3646 * Remove unnecessary async --- detox/e2e/support/server_api/index.js | 2 + detox/e2e/support/server_api/preference.js | 60 +++++++++++++++ detox/e2e/support/server_api/user.js | 2 +- detox/e2e/support/utils.js | 29 +++----- detox/e2e/test/teams/teams_order.e2e.js | 85 ++++++++++++++++++++++ 5 files changed, 159 insertions(+), 19 deletions(-) create mode 100644 detox/e2e/support/server_api/preference.js create mode 100644 detox/e2e/test/teams/teams_order.e2e.js diff --git a/detox/e2e/support/server_api/index.js b/detox/e2e/support/server_api/index.js index 25a4e4da3..1cff9ba25 100644 --- a/detox/e2e/support/server_api/index.js +++ b/detox/e2e/support/server_api/index.js @@ -4,6 +4,7 @@ import Channel from './channel'; import Ldap from './ldap'; import Post from './post'; +import Preference from './preference'; import Setup from './setup'; import System from './system'; import Team from './team'; @@ -13,6 +14,7 @@ export { Channel, Ldap, Post, + Preference, Setup, System, Team, diff --git a/detox/e2e/support/server_api/preference.js b/detox/e2e/support/server_api/preference.js new file mode 100644 index 000000000..a84e7cfba --- /dev/null +++ b/detox/e2e/support/server_api/preference.js @@ -0,0 +1,60 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import client from './client'; +import {getResponseFromError} from './common'; + +// **************************************************************** +// Preferences +// See https://api.mattermost.com/#tag/preferences +// +// Exported API function should have the following: +// - documented using JSDoc +// - meaningful description +// - match the referenced API endpoints +// - parameter/s defined by `@param` +// - return value defined by `@return` +// **************************************************************** + +/** + * Save the user's preferences. + * @param {string} userId - the user ID + * @param {Array} preferences - a list of user's preferences + * @return {string} returns {status} on success or {error, status} on error + */ +export const apiSaveUserPreferences = async (userId, preferences = []) => { + try { + const response = await client.put( + `/api/v4/users/${userId}/preferences`, + preferences, + ); + + return {status: response.status}; + } catch (err) { + return getResponseFromError(err); + } +}; + +/** + * Save the user's teams order preference. + * @param {string} userId - the user ID + * @param {Array} orderedTeamIds - ordered array of team IDs + * @return {string} returns {status} on success or {error, status} on error + */ +export const apiSaveTeamsOrderPreference = (userId, orderedTeamIds = []) => { + const preference = { + user_id: userId, + category: 'teams_order', + name: '', + value: orderedTeamIds.toString(), + }; + + return apiSaveUserPreferences(userId, [preference]); +}; + +export const Preference = { + apiSaveUserPreferences, + apiSaveTeamsOrderPreference, +}; + +export default Preference; diff --git a/detox/e2e/support/server_api/user.js b/detox/e2e/support/server_api/user.js index 5b0bd522b..f44c0a4fe 100644 --- a/detox/e2e/support/server_api/user.js +++ b/detox/e2e/support/server_api/user.js @@ -50,7 +50,7 @@ export const apiLogin = async (user) => { /** * Login to Mattermost server as sysadmin. */ -export const apiAdminLogin = async () => { +export const apiAdminLogin = () => { return apiLogin({ username: testConfig.adminUsername, password: testConfig.adminPassword, diff --git a/detox/e2e/support/utils.js b/detox/e2e/support/utils.js index c6009d83e..192e9bbd6 100644 --- a/detox/e2e/support/utils.js +++ b/detox/e2e/support/utils.js @@ -6,20 +6,30 @@ import {v4 as uuidv4} from 'uuid'; /** * Explicit `wait` should not normally used but made available for special cases. * @param {number} ms - duration in millisecond + * @return {Promise} promise with timeout */ export const wait = async (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; +/** + * Check if android. + * @return {boolean} true if android + */ export const isAndroid = () => { return device.getPlatform() === 'android'; }; +/** + * Check if ios. + * @return {boolean} true if ios + */ export const isIos = () => { return device.getPlatform() === 'ios'; }; /** + * Get random id. * @param {number} length - length on random string to return, e.g. 6 (default) * @return {string} random string */ @@ -30,6 +40,7 @@ export const getRandomId = (length = 6) => { }; /** + * Capitalize first character of text. * @param {string} text * @return {string} capitalized text */ @@ -37,24 +48,6 @@ export const capitalize = (text) => { return text.charAt(0).toUpperCase() + text.slice(1); }; -/** - * @param {map} testIDMap - map of testIDs - * @return {map} map of testID matchers - */ -export const testIDMatcherMap = (testIDMap) => { - const testIDFilter = (k, v) => { - const key = k.toLowerCase(); - if (key.endsWith('prefix') || - key.endsWith('suffix') || - v.startsWith('.') || - v.endsWith('.')) { - return false; - } - return true; - }; - return testIDMap.filter(([k, v]) => testIDFilter(k, v)).map(([k, v]) => [k, by.id(v)]); -}; - const SECOND = 1000; const MINUTE = 60 * 1000; diff --git a/detox/e2e/test/teams/teams_order.e2e.js b/detox/e2e/test/teams/teams_order.e2e.js new file mode 100644 index 000000000..ae47cc69c --- /dev/null +++ b/detox/e2e/test/teams/teams_order.e2e.js @@ -0,0 +1,85 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ******************************************************************* +// - [#] indicates a test step (e.g. # Go to a screen) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element testID when selecting an element. Create one if none. +// ******************************************************************* + +import {MainSidebar} from '@support/ui/component'; +import {ChannelScreen} from '@support/ui/screen'; +import { + Preference, + Setup, + Team, +} from '@support/server_api'; + +describe('Teams Order', () => { + let testUser; + let testTeam1; + let testTeam2; + let testTeam3; + let testTeam4; + let testTeam5; + let testTeam6; + + beforeAll(async () => { + const {team, user} = await Setup.apiInit({teamOptions: {prefix: 'team-a'}}); + testUser = user; + testTeam1 = team; + + ({team: testTeam2} = await Team.apiCreateTeam({prefix: 'team-b'})); + await Team.apiAddUserToTeam(user.id, testTeam2.id); + + ({team: testTeam3} = await Team.apiCreateTeam({prefix: 'team-c'})); + await Team.apiAddUserToTeam(user.id, testTeam3.id); + + // # Open channel screen + await ChannelScreen.open(user); + }); + + afterAll(async () => { + await ChannelScreen.logout(); + }); + + it('MM-T3646 should follow teams order preference', async () => { + const { + closeTeamSidebar, + openTeamSidebar, + } = ChannelScreen; + const {hasTeamDisplayNameAtIndex} = MainSidebar; + + // * Verify initial teams order + await openTeamSidebar(); + await hasTeamDisplayNameAtIndex(0, testTeam1.display_name); + await hasTeamDisplayNameAtIndex(1, testTeam2.display_name); + await hasTeamDisplayNameAtIndex(2, testTeam3.display_name); + + // # Re-arrange teams order via API + await Preference.apiSaveTeamsOrderPreference(testUser.id, [testTeam3.id, testTeam1.id, testTeam2.id]); + + // * Verify updated teams order + await hasTeamDisplayNameAtIndex(0, testTeam3.display_name); + await hasTeamDisplayNameAtIndex(1, testTeam1.display_name); + await hasTeamDisplayNameAtIndex(2, testTeam2.display_name); + + // # Add 3 more teams in descending order via API + ({team: testTeam4} = await Team.apiCreateTeam({prefix: 'team-f'})); + await Team.apiAddUserToTeam(testUser.id, testTeam4.id); + ({team: testTeam5} = await Team.apiCreateTeam({prefix: 'team-e'})); + await Team.apiAddUserToTeam(testUser.id, testTeam5.id); + ({team: testTeam6} = await Team.apiCreateTeam({prefix: 'team-d'})); + await Team.apiAddUserToTeam(testUser.id, testTeam6.id); + + // * Verify additional teams order is ascending + await device.reloadReactNative(); + await openTeamSidebar(); + await hasTeamDisplayNameAtIndex(3, testTeam6.display_name); + await hasTeamDisplayNameAtIndex(4, testTeam5.display_name); + await hasTeamDisplayNameAtIndex(5, testTeam4.display_name); + + // # Close team sidebar + await closeTeamSidebar(); + }); +});