update manage token model to work on load (#29022)

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Scott Bishel
2024-11-05 17:00:26 -07:00
коммит произвёл GitHub
родитель 4d4af7dc39
Коммит 311381940d
3 изменённых файлов: 303 добавлений и 23 удалений

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

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/admin_console/manage_tokens_modal/manage_tokens_modal.tsx should match snapshot 1`] = `
exports[`components/admin_console/manage_tokens_modal/manage_tokens_modal.tsx initial call should match snapshot 1`] = `
<Modal
animation={true}
aria-labelledby="manageTokensModalLabel"
@@ -95,3 +95,271 @@ exports[`components/admin_console/manage_tokens_modal/manage_tokens_modal.tsx sh
</ModalBody>
</Modal>
`;
exports[`components/admin_console/manage_tokens_modal/manage_tokens_modal.tsx should display list of tokens 1`] = `
<Modal
animation={true}
aria-labelledby="manageTokensModalLabel"
autoFocus={true}
backdrop={true}
bsClass="modal"
dialogClassName="a11y__modal manage-teams"
dialogComponentClass={[Function]}
enforceFocus={true}
keyboard={true}
manager={
ModalManager {
"add": [Function],
"containers": Array [],
"data": Array [],
"handleContainerOverflow": true,
"hideSiblingNodes": true,
"isTopModal": [Function],
"modals": Array [],
"remove": [Function],
}
}
onExited={[MockFunction]}
onHide={[Function]}
renderBackdrop={[Function]}
restoreFocus={true}
role="dialog"
show={true}
>
<ModalHeader
bsClass="modal-header"
closeButton={true}
closeLabel="Close"
>
<ModalTitle
bsClass="modal-title"
componentClass="h1"
id="manageTokensModalLabel"
>
<MemoizedFormattedMessage
defaultMessage="Manage Personal Access Tokens"
id="admin.manage_tokens.manageTokensTitle"
/>
</ModalTitle>
</ModalHeader>
<ModalBody
bsClass="modal-body"
componentClass="div"
>
<div>
<div
className="manage-teams__user"
>
<Memo(Avatar)
size="lg"
url="/api/v4/users/defaultuser/image"
username="some-user"
/>
<div
className="manage-teams__info"
>
<div
className="manage-teams__name"
>
@some-user
</div>
<div
className="manage-teams__email"
/>
</div>
</div>
<div
className="pt-3"
>
<MemoizedFormattedMessage
defaultMessage="Personal access tokens function similarly to session tokens and can be used by integrations to <linkAuthentication>interact with this Mattermost server</linkAuthentication>. Tokens are disabled if the user is deactivated. Learn more about <linkPersonalAccessTokens>personal access tokens</linkPersonalAccessTokens>."
id="admin.manage_tokens.userAccessTokensDescription"
values={
Object {
"linkAuthentication": [Function],
"linkPersonalAccessTokens": [Function],
}
}
/>
</div>
<div
className="manage-teams__teams"
>
<div
className="manage-teams__team"
key="id1"
>
<div
className="manage-teams__team-name"
>
<div
className="whitespace--nowrap overflow--ellipsis"
>
<MemoizedFormattedMessage
defaultMessage="Token Description: "
id="admin.manage_tokens.userAccessTokensNameLabel"
/>
description
</div>
<div
className="whitespace--nowrap overflow--ellipsis"
>
<MemoizedFormattedMessage
defaultMessage="Token ID: "
id="admin.manage_tokens.userAccessTokensIdLabel"
/>
id1
</div>
</div>
<div
className="manage-teams__team-actions"
>
<Connect(Component)
onError={[Function]}
tokenId="id1"
/>
</div>
</div>
<div
className="manage-teams__team"
key="id2"
>
<div
className="manage-teams__team-name"
>
<div
className="whitespace--nowrap overflow--ellipsis"
>
<MemoizedFormattedMessage
defaultMessage="Token Description: "
id="admin.manage_tokens.userAccessTokensNameLabel"
/>
description
</div>
<div
className="whitespace--nowrap overflow--ellipsis"
>
<MemoizedFormattedMessage
defaultMessage="Token ID: "
id="admin.manage_tokens.userAccessTokensIdLabel"
/>
id2
</div>
</div>
<div
className="manage-teams__team-actions"
>
<Connect(Component)
onError={[Function]}
tokenId="id2"
/>
</div>
</div>
</div>
</div>
</ModalBody>
</Modal>
`;
exports[`components/admin_console/manage_tokens_modal/manage_tokens_modal.tsx should replace loading screen on update 1`] = `
<Modal
animation={true}
aria-labelledby="manageTokensModalLabel"
autoFocus={true}
backdrop={true}
bsClass="modal"
dialogClassName="a11y__modal manage-teams"
dialogComponentClass={[Function]}
enforceFocus={true}
keyboard={true}
manager={
ModalManager {
"add": [Function],
"containers": Array [],
"data": Array [],
"handleContainerOverflow": true,
"hideSiblingNodes": true,
"isTopModal": [Function],
"modals": Array [],
"remove": [Function],
}
}
onExited={[MockFunction]}
onHide={[Function]}
renderBackdrop={[Function]}
restoreFocus={true}
role="dialog"
show={true}
>
<ModalHeader
bsClass="modal-header"
closeButton={true}
closeLabel="Close"
>
<ModalTitle
bsClass="modal-title"
componentClass="h1"
id="manageTokensModalLabel"
>
<MemoizedFormattedMessage
defaultMessage="Manage Personal Access Tokens"
id="admin.manage_tokens.manageTokensTitle"
/>
</ModalTitle>
</ModalHeader>
<ModalBody
bsClass="modal-body"
componentClass="div"
>
<div>
<div
className="manage-teams__user"
>
<Memo(Avatar)
size="lg"
url="/api/v4/users/defaultuser/image"
username="some-user"
/>
<div
className="manage-teams__info"
>
<div
className="manage-teams__name"
>
@some-user
</div>
<div
className="manage-teams__email"
/>
</div>
</div>
<div
className="pt-3"
>
<MemoizedFormattedMessage
defaultMessage="Personal access tokens function similarly to session tokens and can be used by integrations to <linkAuthentication>interact with this Mattermost server</linkAuthentication>. Tokens are disabled if the user is deactivated. Learn more about <linkPersonalAccessTokens>personal access tokens</linkPersonalAccessTokens>."
id="admin.manage_tokens.userAccessTokensDescription"
values={
Object {
"linkAuthentication": [Function],
"linkPersonalAccessTokens": [Function],
}
}
/>
</div>
<div
className="manage-teams__teams"
>
<div
className="manage-row__empty"
>
<MemoizedFormattedMessage
defaultMessage="No personal access tokens."
id="admin.manage_tokens.userAccessTokensNone"
/>
</div>
</div>
</div>
</ModalBody>
</Modal>
`;

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

@@ -4,6 +4,8 @@
import {shallow} from 'enzyme';
import React from 'react';
import LoadingScreen from 'components/loading_screen';
import {TestHelper} from 'utils/test_helper';
import ManageTokensModal from './manage_tokens_modal';
@@ -20,36 +22,51 @@ describe('components/admin_console/manage_tokens_modal/manage_tokens_modal.tsx',
onExited: jest.fn(),
};
test('should match snapshot', () => {
test('initial call should match snapshot', () => {
const wrapper = shallow(
<ManageTokensModal {...baseProps}/>,
);
expect(wrapper).toMatchSnapshot();
expect(baseProps.actions.getUserAccessTokensForUser).toHaveBeenCalledTimes(1);
expect(wrapper.find('.manage-teams__teams').exists()).toBe(true);
expect(wrapper.find(LoadingScreen).exists()).toBe(true);
});
test('should not call getUserAccessTokensForUser on mount', () => {
test('should replace loading screen on update', () => {
const wrapper = shallow(
<ManageTokensModal {...baseProps}/>,
);
expect(baseProps.actions.getUserAccessTokensForUser).toHaveBeenCalledTimes(0);
expect(wrapper.state('userAccessTokens')).toBeUndefined();
});
test('should call getUserAccessTokensForUser on user change', () => {
// create new user as only by then the update method triggers token retrieval
const newProps = {
...baseProps,
user: TestHelper.getUserMock({
id: 'newuser',
}),
userAccessTokens: {},
};
wrapper.setProps(newProps);
expect(wrapper).toMatchSnapshot();
expect(wrapper.find('.manage-teams__teams').exists()).toBe(true);
expect(wrapper.find('.manage-row__empty').exists()).toBe(true);
});
test('should display list of tokens', () => {
const wrapper = shallow(
<ManageTokensModal {...baseProps}/>,
);
const newProps = {
...baseProps,
userAccessTokens: [
{
id: 'id1',
description: 'description',
},
{
id: 'id2',
description: 'description',
},
],
};
wrapper.setProps(newProps);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
wrapper.instance().componentDidUpdate(baseProps, newProps);
expect(newProps.actions.getUserAccessTokensForUser).toHaveBeenCalledTimes(2);
expect(wrapper).toMatchSnapshot();
expect(wrapper.find('.manage-teams__teams').exists()).toBe(true);
expect(wrapper.find('.manage-teams__team').length).toBe(2);
});
});

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

@@ -22,7 +22,7 @@ export type Props = {
/**
* The user the roles are being managed for
*/
user?: UserProfile;
user: UserProfile;
/**
* The personal access tokens for a user, object with token ids as keys
@@ -53,10 +53,9 @@ export default class ManageTokensModal extends React.PureComponent<Props, State>
};
}
public componentDidUpdate(prevProps: Props): void {
public componentDidMount(): void {
const userId = this.props.user ? this.props.user.id : null;
const prevUserId = prevProps.user ? prevProps.user.id : null;
if (userId && prevUserId !== userId) {
if (userId) {
this.props.actions.getUserAccessTokensForUser(userId, 0, 200);
}
}
@@ -74,10 +73,6 @@ export default class ManageTokensModal extends React.PureComponent<Props, State>
private renderContents = (): JSX.Element => {
const {user, userAccessTokens} = this.props;
if (!user) {
return <LoadingScreen/>;
}
let name = UserUtils.getFullName(user);
if (name) {
name += ` (@${user.username})`;