MM-47287 Refactor/migrate bot accounts to typescript (#28347)

* refactor: convert bot_api_1_spec.js to typescript

- convert file bot_accounts/bot_api_1_spec.js to typescript
- update related data types in order to fix argument issues

* refactor: convert bot_api_not_cloud_spec.js to ts

- convert file bot_accounts/bot_api_not_cloud_spec.js to typescript
- update related data types in order to fix argument issues

* refactor: convert bot_channel_intro_spec.js to ts

- convert file bot_accounts/bot_channel_intro_spec.js to typescript
- convert support/api/bots.js to typescript
- remove data type bot.d.ts and include docs and definitions in
 support/api/bots.ts

* refactor: convert bot_accounts files to ts

- convert files from js to typescript
- move declaration files to ts
- update js docs
- fix lint and type errors

Related to #21303

* fix: replace params undefined on client.createUser

- replace undefined params with empty strings as suggested in review

* fix: add types to variables on spec tags_spec.ts

- add types to variables

* fix: update args for apiCreateBot on api/bots.ts

- update args so that lint issue is fixed

* Apply suggestions from code review

update assertion to 401

---------

Co-authored-by: Saturnino Abril <5334504+saturninoabril@users.noreply.github.com>
Этот коммит содержится в:
Angel Mendez
2024-10-28 03:03:21 -06:00
коммит произвёл GitHub
родитель f4c85a875d
Коммит a358bef3cd
41 изменённых файлов: 2197 добавлений и 2110 удалений

Просмотреть файл

@@ -10,14 +10,17 @@
// Stage: @prod
// Group: @channels @bot_accounts @mfa
import {Channel} from '@mattermost/types/channels';
import {Team} from '@mattermost/types/teams';
import {UserProfile} from '@mattermost/types/users';
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Bot accounts ownership and API', () => {
let newTeam;
let newUser;
let newChannel;
let botId;
let botName;
let newTeam: Team;
let newUser: UserProfile;
let newChannel: Channel;
let botId: string;
let botName: string;
beforeEach(() => {
cy.apiAdminLogin();

Просмотреть файл

@@ -10,16 +10,19 @@
// Stage: @prod
// Group: @channels @bot_accounts @mfa
import {Channel} from '@mattermost/types/channels';
import {Team} from '@mattermost/types/teams';
import {UserProfile} from '@mattermost/types/users';
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Bot accounts ownership and API', () => {
let newTeam;
let newUser;
let newChannel;
let botId;
let botUsername;
let botName;
let adminUser;
let newTeam: Team;
let newUser: UserProfile;
let newChannel: Channel;
let botId: string;
let botUsername: string;
let botName: string;
let adminUser: UserProfile;
beforeEach(() => {
cy.apiAdminLogin().then(({user}) => {
@@ -180,7 +183,7 @@ describe('Bot accounts ownership and API', () => {
// # Create a post
cy.postBotMessage({channelId: channel.id, message: msg2, token, failOnStatus: false}).then(({status}) => {
// * Validate that posting failed
expect(status, 403);
expect(status).to.equal(401);
});
cy.apiAdminLogin();
@@ -238,7 +241,7 @@ describe('Bot accounts ownership and API', () => {
// # Create a post
cy.postBotMessage({channelId: channel.id, message: msg2, token, failOnStatus: false}).then(({status}) => {
// * Validate that posting failed
expect(status, 403);
expect(status).to.equal(401);
});
// # Enable the bot token again
@@ -301,7 +304,7 @@ describe('Bot accounts ownership and API', () => {
// # Create a post
cy.postBotMessage({channelId: channel.id, message: msg2, token, failOnStatus: false}).then(({status}) => {
// * Validate that posting failed
expect(status, 403);
expect(status).to.equal(401);
});
});
});

Просмотреть файл

@@ -10,10 +10,11 @@
// Stage: @prod
// Group: @channels @not_cloud @bot_accounts
import {Team} from '@mattermost/types/teams';
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Bot accounts ownership and API', () => {
let newTeam;
let newTeam: Team;
before(() => {
cy.shouldNotRunOnCloudEdition();

Просмотреть файл

@@ -10,11 +10,13 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Bot} from '@mattermost/types/bots';
import {Team} from '@mattermost/types/teams';
import {createBotPatch} from '../../../support/api/bots';
describe('Bot channel intro and avatar', () => {
let team;
let bot;
let team: Team;
let bot: Bot;
before(() => {
cy.apiInitSetup().then((out) => {
@@ -33,7 +35,7 @@ describe('Bot channel intro and avatar', () => {
cy.visit(`/${team.name}/messages/@${bot.username}`);
// # Get channel intro and bot-post Avatars
cy.get(`#channelIntro .profile-icon > img.Avatar, img.Avatar[alt="${bot.username} profile image"]`).
cy.get<HTMLImageElement[]>(`#channelIntro .profile-icon > img.Avatar, img.Avatar[alt="${bot.username} profile image"]`).
should(($imgs) => {
// * Verify imgs downloaded
expect($imgs[0].naturalWidth).to.be.greaterThan(0);
@@ -44,7 +46,7 @@ describe('Bot channel intro and avatar', () => {
cy.wrap($img).
should('be.visible').
and('have.attr', 'src').
then((url) => cy.request({url, encoding: 'binary'})).
then((url) => cy.request({url, encoding: 'binary'} as unknown as Partial<Cypress.RequestOptions>)).
then(({body}) => {
// * Verify matches expected default bot avatar
cy.fixture('bot-default-avatar.png', 'binary').should('deep.equal', body);

Просмотреть файл

@@ -10,12 +10,14 @@
// Stage: @prod
// Group: @channels @not_cloud @bot_accounts
import {Team} from '@mattermost/types/teams';
import {getRandomId} from '../../../utils';
import {createBotInteractive} from './helpers';
describe('Bot accounts - CRUD Testing', () => {
let newTeam;
let newTeam: Team;
before(() => {
cy.shouldNotRunOnCloudEdition();

Просмотреть файл

@@ -10,13 +10,16 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Bot} from '@mattermost/types/bots';
import {Team} from '@mattermost/types/teams';
import {getRandomId} from '../../../utils';
import {createBotInteractive} from './helpers';
describe('Bot accounts - CRUD Testing', () => {
let newTeam;
let testBot;
let newTeam: Team;
let testBot: Bot & {fullDisplayName: string};
before(() => {
// # Create and visit new channel

Просмотреть файл

@@ -10,9 +10,13 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Bot} from '@mattermost/types/bots';
import {Channel} from '@mattermost/types/channels';
import {UserProfile} from '@mattermost/types/users';
describe('Bot display name', () => {
let offTopicChannel;
let otherSysadmin;
let offTopicChannel: Channel;
let otherSysadmin: UserProfile;
before(() => {
cy.intercept('**/api/v4/**').as('resources');
@@ -77,7 +81,7 @@ describe('Bot display name', () => {
should('have.text', bot.display_name);
}).then(() => {
// # Change display name after prior verification
cy.wrap(client.patchBot(bot.user_id, {display_name: `NEW ${bot.display_name}`})).then((newBot) => {
cy.wrap(client.patchBot(bot.user_id, {display_name: `NEW ${bot.display_name}`})).then((newBot: Bot) => {
cy.postBotMessage({token, message: secondMessage, props, channelId: offTopicChannel.id}).
its('id').
should('exist').

Просмотреть файл

@@ -10,11 +10,12 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Team} from '@mattermost/types/teams';
import * as MESSAGES from '../../../fixtures/messages';
import {getRandomId} from '../../../utils';
describe('Edit bot', () => {
let testTeam;
let testTeam: Team;
before(() => {
cy.apiInitSetup().then(({team, townSquareUrl}) => {

Просмотреть файл

@@ -10,11 +10,12 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Team} from '@mattermost/types/teams';
import * as TIMEOUTS from '../../../fixtures/timeouts';
import {getRandomId} from '../../../utils';
describe('Edit bot username', () => {
let team;
let team: Team;
before(() => {
cy.apiInitSetup().then((out) => {
@@ -68,8 +69,9 @@ describe('Edit bot username', () => {
// # Click update button
cy.get('#saveBot').click();
cy.wrap(newBotName);
return cy.wrap(newBotName);
}
return cy.wrap(null);
}).then((newBotName) => {
// * Set alias for bot entry in bot list, this also checks that the bot entry exists
cy.get('.backstage-list__item').contains('.backstage-list__item', newBotName).as('newbotEntry');
@@ -97,7 +99,7 @@ describe('Edit bot username', () => {
const NAMING_WARNING_STANDARD = 'Usernames have to begin with a lowercase letter and be 3-22 characters long. You can use lowercase letters, numbers, periods, dashes, and underscores.';
const NAMING_WARNING_ENDING_PERIOD = 'Bot usernames cannot have a period as the last character';
function tryUsername(name, warningMessage) {
function tryUsername(name: string, warningMessage?: string) {
cy.get('#username').clear().type(name);
cy.get('#saveBot').click();

Просмотреть файл

@@ -1,10 +1,11 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Team} from '@mattermost/types/teams';
import {getRandomId} from '../../../utils';
import * as TIMEOUTS from '../../../fixtures/timeouts';
export function createBotInteractive(team, username = `bot-${getRandomId()}`) {
export function createBotInteractive(team: Team, username = `bot-${getRandomId()}`) {
// # Visit the Integrations > Bot Accounts page
cy.visit(`/${team.name}/integrations/bots`);

Просмотреть файл

@@ -10,15 +10,19 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Bot} from '@mattermost/types/bots';
import {Channel} from '@mattermost/types/channels';
import {Team} from '@mattermost/types/teams';
import {UserProfile} from '@mattermost/types/users';
import {createBotPatch} from '../../../support/api/bots';
import {generateRandomUser} from '../../../support/api/user';
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Bots in lists', () => {
let team;
let channel;
let bots;
let createdUsers;
let team: Team;
let channel: Channel;
let bots: Bot[];
let createdUsers: UserProfile[];
before(() => {
cy.apiInitSetup().then((out) => {
@@ -36,8 +40,8 @@ describe('Bots in lists', () => {
// # Create users
createdUsers = await Promise.all([
client.createUser(generateRandomUser()),
client.createUser(generateRandomUser()),
client.createUser(generateRandomUser() as UserProfile, '', ''),
client.createUser(generateRandomUser() as UserProfile, '', ''),
]);
await Promise.all([
@@ -48,8 +52,8 @@ describe('Bots in lists', () => {
cy.wrap(user).its('username');
// # Add to team and channel
await client.addToTeam(team.id, user.user_id ?? user.id);
await client.addToChannel(user.user_id ?? user.id, channel.id);
await client.addToTeam(team.id, (user as Bot).user_id ?? (user as UserProfile).id);
await client.addToChannel((user as Bot).user_id ?? (user as UserProfile).id, channel.id);
}));
});
});

Просмотреть файл

@@ -9,13 +9,17 @@
// Group: @channels @bot_accounts
import {Bot} from '@mattermost/types/bots';
import {Channel} from '@mattermost/types/channels';
import {Team} from '@mattermost/types/teams';
import {UserProfile} from '@mattermost/types/users';
import {createBotPatch} from '../../../support/api/bots';
import {generateRandomUser} from '../../../support/api/user';
describe('Bots in lists', () => {
let team;
let channel;
let testUser;
let team: Team;
let channel: Channel;
let testUser: UserProfile;
const STATUS_PRIORITY = {
online: 0,
@@ -42,8 +46,8 @@ describe('Bots in lists', () => {
// # Create users
const createdUsers = await Promise.all([
client.createUser(generateRandomUser()),
client.createUser(generateRandomUser()),
client.createUser(generateRandomUser() as UserProfile, '', ''),
client.createUser(generateRandomUser() as UserProfile, '', ''),
]);
await Promise.all([
@@ -54,8 +58,8 @@ describe('Bots in lists', () => {
cy.wrap(user).its('username');
// # Add to team and channel
await client.addToTeam(team.id, user.user_id ?? user.id);
await client.addToChannel(user.user_id ?? user.id, channel.id);
await client.addToTeam(team.id, (user as Bot).user_id ?? (user as UserProfile).id);
await client.addToChannel((user as Bot).user_id ?? (user as UserProfile).id, channel.id);
}));
});
});

Просмотреть файл

@@ -10,11 +10,13 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Team} from '@mattermost/types/teams';
import {createBotPatch} from '../../../support/api/bots';
import {createChannelPatch} from '../../../support/api/channel';
import {Channel} from '@mattermost/types/channels';
describe('Managing bots in Teams and Channels', () => {
let team;
let team: Team;
before(() => {
cy.apiUpdateConfig({
@@ -45,7 +47,7 @@ describe('Managing bots in Teams and Channels', () => {
it('MM-T1816 Add a BOT to a channel', () => {
cy.makeClient().then(async (client) => {
// # Go to channel
const channel = await client.createChannel(createChannelPatch(team.id, 'a-chan', 'A Channel'));
const channel = await client.createChannel(createChannelPatch(team.id, 'a-chan', 'A Channel') as Channel);
cy.visit(`/${team.name}/channels/${channel.name}`);
// # Add bot to team
@@ -63,7 +65,7 @@ describe('Managing bots in Teams and Channels', () => {
it('MM-T1817 Add a BOT to a channel that is not on the Team', () => {
cy.makeClient().then(async (client) => {
// # Go to channel
const channel = await client.createChannel(createChannelPatch(team.id, 'a-chan', 'A Channel'));
const channel = await client.createChannel(createChannelPatch(team.id, 'a-chan', 'A Channel') as Channel);
cy.visit(`/${team.name}/channels/${channel.name}`);
// # Invite bot to team
@@ -78,7 +80,7 @@ describe('Managing bots in Teams and Channels', () => {
it('MM-T1818 No ephemeral post about Adding a bot to a channel When Bot is mentioned', () => {
cy.makeClient().then(async (client) => {
// # Go to channel
const channel = await client.createChannel(createChannelPatch(team.id, 'a-chan', 'A Channel'));
const channel = await client.createChannel(createChannelPatch(team.id, 'a-chan', 'A Channel') as Channel);
cy.visit(`/${team.name}/channels/${channel.name}`);
// # And bot to team

Просмотреть файл

@@ -10,11 +10,12 @@
// Stage: @prod
// Group: @channels @bot_accounts @plugin @not_cloud
import {Team} from '@mattermost/types/teams';
import * as TIMEOUTS from '../../../fixtures/timeouts';
import {matterpollPlugin} from '../../../utils/plugins';
describe('Managing bot accounts', () => {
let newTeam;
let newTeam: Team;
before(() => {
cy.shouldNotRunOnCloudEdition();

Просмотреть файл

@@ -10,11 +10,12 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Team} from '@mattermost/types/teams';
import * as TIMEOUTS from '../../../fixtures/timeouts';
import {getRandomId} from '../../../utils';
describe('Managing bot accounts', () => {
let newTeam;
let newTeam: Team;
before(() => {
// # Create and visit new channel

Просмотреть файл

@@ -1,6 +1,8 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Channel} from '@mattermost/types/channels';
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
@@ -11,7 +13,7 @@
// Group: @channels @bot_accounts
describe('Bot post message', () => {
let offTopicChannel;
let offTopicChannel: Channel;
before(() => {
cy.apiInitSetup().then(({team}) => {

Просмотреть файл

@@ -10,10 +10,11 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Team} from '@mattermost/types/teams';
import {createBotPatch} from '../../../support/api/bots';
describe('Managing bots in Teams and Channels', () => {
let team;
let team: Team;
before(() => {
cy.apiUpdateConfig({

Просмотреть файл

@@ -10,15 +10,19 @@
// Stage: @prod
// Group: @channels @bot_accounts @not_cloud
import {Bot} from '@mattermost/types/bots';
import {Channel} from '@mattermost/types/channels';
import {Team} from '@mattermost/types/teams';
import {UserProfile} from '@mattermost/types/users';
import {createBotPatch} from '../../../support/api/bots';
import {generateRandomUser} from '../../../support/api/user';
describe('Bot accounts', () => {
let team;
let channel;
let testUser;
let bots;
let createdUsers;
let team: Team;
let channel: Channel;
let testUser: UserProfile;
let bots: Bot[];
let createdUsers: UserProfile[];
before(() => {
cy.shouldNotRunOnCloudEdition();
@@ -39,8 +43,8 @@ describe('Bot accounts', () => {
// # Create users
createdUsers = await Promise.all([
client.createUser(generateRandomUser()),
client.createUser(generateRandomUser()),
client.createUser(generateRandomUser() as UserProfile, '', ''),
client.createUser(generateRandomUser() as UserProfile, '', ''),
]);
await Promise.all([
@@ -51,8 +55,8 @@ describe('Bot accounts', () => {
cy.wrap(user).its('username');
// # Add to team and channel
await client.addToTeam(team.id, user.user_id ?? user.id);
await client.addToChannel(user.user_id ?? user.id, channel.id);
await client.addToTeam(team.id, (user as Bot).user_id ?? (user as UserProfile).id);
await client.addToChannel((user as Bot).user_id ?? (user as UserProfile).id, channel.id);
}));
});
});
@@ -72,7 +76,7 @@ describe('Bot accounts', () => {
// * Verify bot icon exists
cy.wrap($link).find('.Avatar').should('exist').
and('have.attr', 'src').
invoke('attr', 'src').
then((url) => cy.request({url, encoding: 'binary'})).
then(({body}) => {
// * Verify it matches default bot avatar

Просмотреть файл

@@ -10,14 +10,17 @@
// Stage: @prod
// Group: @channels @bot_accounts
import {Channel} from '@mattermost/types/channels';
import {Team} from '@mattermost/types/teams';
import {UserProfile} from '@mattermost/types/users';
import {createBotPatch} from '../../../support/api/bots';
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Bot tags', () => {
let me;
let team;
let channel;
let postId;
let me: UserProfile;
let team: Team;
let channel: Channel;
let postId: string;
before(() => {
cy.apiInitSetup().then((out) => {
@@ -92,6 +95,6 @@ describe('Bot tags', () => {
});
});
function rhsPostHasBotBadge(postId) {
function rhsPostHasBotBadge(postId: string) {
cy.get(`.post#searchResult_${postId} .Tag`).should('be.visible').and('have.text', 'BOT');
}

Просмотреть файл

@@ -11,6 +11,7 @@
// Group: @channels @channel_settings
// node run_tests.js --group='@channel_settings'
import {ChannelType} from '@mattermost/types/channels';
import {getRandomId} from '../../../utils';
import * as TIMEOUTS from '../../../fixtures/timeouts';
@@ -35,7 +36,7 @@ describe('Channel Settings', () => {
it('MM-T1808 Hover effect exists to add a channel description / header (when not already present)', () => {
// # Create a new public channel and then private channel
['O', 'P'].forEach((channelType) => {
cy.apiCreateChannel(testTeam.id, `chan${getRandomId()}`, 'chan', channelType).then(({channel}) => {
cy.apiCreateChannel(testTeam.id, `chan${getRandomId()}`, 'chan', channelType as ChannelType).then(({channel}) => {
// # Go to new channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);

Просмотреть файл

@@ -260,17 +260,17 @@ describe('Group Mentions', () => {
// # Link the group and the channel.
cy.apiLinkGroupChannel(groupID1, channel.id);
cy.apiLogin({username: 'board.one', password: 'Password1'} as any).then((boardOne) => {
cy.apiAddUserToChannel(channel.id, boardOne.id);
cy.apiLogin({username: 'board.one', password: 'Password1'} as any).then(({user}: {user: UserProfile}) => {
cy.apiAddUserToChannel(channel.id, user.id);
// # Make the channel private and group-synced.
cy.apiPatchChannel(channel.id, {group_constrained: true, type: 'P'});
// # Login to create the dev user
cy.apiLogin({username: 'dev.one', password: 'Password1'} as any).then((devOne) => {
cy.apiLogin({username: 'dev.one', password: 'Password1'} as any).then(({user}: {user: UserProfile}) => {
cy.apiAdminLogin();
cy.apiAddUserToTeam(testTeam.id, devOne.id);
cy.apiAddUserToTeam(testTeam.id, user.id);
cy.apiLogin({username: 'board.one', password: 'Password1'} as any);

Просмотреть файл

@@ -22,6 +22,7 @@ import {
reUrl,
verifyEmailBody,
} from '../../../../utils';
import {UserProfile} from '@mattermost/types/users';
describe('Guest Accounts', () => {
let sysadmin: Cypress.UserProfile;
@@ -40,7 +41,7 @@ describe('Guest Accounts', () => {
});
// # Log in as a team admin.
cy.apiAdminLogin().then((user) => {
cy.apiAdminLogin().then(({user}: {user: UserProfile}) => {
sysadmin = user;
});
});

Просмотреть файл

@@ -10,6 +10,7 @@
// Stage: @prod
// Group: @channels @enterprise @ldap
import {UserProfile} from '@mattermost/types/users';
import ldapUsers from '../../../../fixtures/ldap_users.json';
import {getRandomId} from '../../../../utils';
@@ -220,7 +221,7 @@ function setLDAPTestSettings(config) {
}
function disableOnboardingTaskList(ldapLogin) {
cy.apiLogin(ldapLogin).then((user) => {
cy.apiLogin(ldapLogin).then(({user}: {user: UserProfile}) => {
cy.apiSaveOnboardingTaskListPreference(user.id, 'onboarding_task_list_open', 'false');
cy.apiSaveOnboardingTaskListPreference(user.id, 'onboarding_task_list_show', 'false');
cy.apiSaveSkipStepsPreference(user.id, 'true');
@@ -228,7 +229,7 @@ function disableOnboardingTaskList(ldapLogin) {
}
function removeUserFromAllTeams(testUser) {
cy.apiGetUsersByUsernames([testUser.username]).then((users) => {
cy.apiGetUsersByUsernames([testUser.username]).then(({users}) => {
if (users.length > 0) {
users.forEach((user) => {
cy.apiGetTeamsForUser(user.id).then((teams) => {

Просмотреть файл

@@ -20,6 +20,7 @@
// * Change mattermost-server utils/license.go to test public key
// * e.g. see (https://github.com/mattermost/mattermost-server/pull/16778/files)
import {UserProfile} from '@mattermost/types/users';
import * as TIMEOUTS from '../../../../fixtures/timeouts';
function verifyPurchaseModal() {
@@ -136,7 +137,7 @@ function getCurrentUsers(): Cypress.Chainable<number> {
}
describe('Self hosted Purchase', () => {
let adminUser: Cypress.UserProfile | undefined;
let adminUser: UserProfile;
beforeEach(() => {
// prevent failed tests from bleeding over
@@ -145,9 +146,9 @@ describe('Self hosted Purchase', () => {
before(() => {
cy.apiInitSetup().then(() => {
cy.apiAdminLogin().then((result) => {
cy.apiAdminLogin().then(({user}) => {
// assertion because current typings are wrong.
adminUser = (result as unknown as {user: Cypress.UserProfile}).user;
adminUser = user;
cy.apiDeleteLicense();
cy.visit('/');