diff --git a/webapp/channels/src/components/admin_console/group_settings/__snapshots__/group_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/group_settings/__snapshots__/group_settings.test.tsx.snap
index a71b22af6cb..91406916824 100644
--- a/webapp/channels/src/components/admin_console/group_settings/__snapshots__/group_settings.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/group_settings/__snapshots__/group_settings.test.tsx.snap
@@ -1,64 +1,133 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`components/admin_console/group_settings/GroupSettings should match snapshot 1`] = `
-
-
-
-
+
+ Groups
+
+
-
+
+ Groups are a way to organize users and apply actions to all users within that group.
+For more information on Groups, please see
+
+ documentation
+
+ .
+
+
+
+
+
+
+ AD/LDAP Groups
+
+
+ Connect AD/LDAP and create groups in Mattermost. To get started, configure group attributes on the
+
+ AD/LDAP
+
+ configuration page.
+
diff --git a/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_profile.test.tsx.snap b/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_profile.test.tsx.snap
index f5f6016693b..66bd231f359 100644
--- a/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_profile.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_profile.test.tsx.snap
@@ -1,40 +1,52 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`components/admin_console/group_settings/group_details/GroupProfile should match snapshot 1`] = `
-
+
-
-
-
+
+
+
+
+
+
+
-
diff --git a/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_profile_and_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_profile_and_settings.test.tsx.snap
index a9a68b086a7..d9f8969fcae 100644
--- a/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_profile_and_settings.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_profile_and_settings.test.tsx.snap
@@ -1,115 +1,266 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`components/admin_console/group_settings/group_details/GroupProfileAndSettings should match snapshot, with toggle off 1`] = `
-
-
+
+
+
+ Group Profile
+
+
+ The name for this group.
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ When enabled, this group can be mentioned in other channels and teams. This may result in the group member list being visible to all users.
+
+
+
+
-
-
+
`;
exports[`components/admin_console/group_settings/group_details/GroupProfileAndSettings should match snapshot, with toggle on 1`] = `
-
-
+
+
+
+ Group Profile
+
+
+ The name for this group.
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ When enabled, this group can be mentioned in other channels and teams. This may result in the group member list being visible to all users.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
`;
diff --git a/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_teams_and_channels.test.tsx.snap b/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_teams_and_channels.test.tsx.snap
index ab993579016..5aa61fcfd24 100644
--- a/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_teams_and_channels.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_teams_and_channels.test.tsx.snap
@@ -1,176 +1,421 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`components/admin_console/group_settings/group_details/GroupTeamsAndChannels should match snapshot, with teams, with channels and loaded 1`] = `
-
-
+
-
-
-
-
+
+
+ Name
+
+
+ Type
+
+
+ Assigned Roles
+
+
-
-
+
+
+
-
-
-
+
+
+
+
+ Team 1
+
+
+
+ Team
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ Channel 4
+
+
+
+ Channel
+
+
+
+
+
+
+
+
+
+
+ Team 2
+
+
+
+ Team (Private)
+
+
+
+
+
+
+
+
+
+
+ Team 3
+
+
+
+ Team (Private)
+
+
+
+
+
+
+
+
+
+
+
+
+ Team 9
+
+
+
+ Team
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Channel 5
+
+
+
+ Channel (Private)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Channel 6
+
+
+
+ Channel (Private)
+
+
+
+
+
+
+
+
+
`;
exports[`components/admin_console/group_settings/group_details/GroupTeamsAndChannels should match snapshot, with teams, with channels and loading 1`] = `
-
+
-
+
+
+
`;
exports[`components/admin_console/group_settings/group_details/GroupTeamsAndChannels should match snapshot, without teams, without channels and loaded 1`] = `
-
+
-
+
+ No teams or channels specified yet
+
`;
exports[`components/admin_console/group_settings/group_details/GroupTeamsAndChannels should match snapshot, without teams, without channels and loading 1`] = `
-
+
-
+
+
+
`;
diff --git a/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_teams_and_channels_row.test.tsx.snap b/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_teams_and_channels_row.test.tsx.snap
index a7958243864..2a7d0d36b25 100644
--- a/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_teams_and_channels_row.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/group_settings/group_details/__snapshots__/group_teams_and_channels_row.test.tsx.snap
@@ -1,481 +1,312 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`components/admin_console/group_settings/group_details/GroupTeamsAndChannelsRow should match snapshot, for private-channel 1`] = `
-
`;
exports[`components/admin_console/group_settings/group_details/GroupTeamsAndChannelsRow should match snapshot, when has children and is collapsed 1`] = `
-
`;
diff --git a/webapp/channels/src/components/admin_console/group_settings/groups_list/groups_list.test.tsx b/webapp/channels/src/components/admin_console/group_settings/groups_list/groups_list.test.tsx
index 2993eccbbce..089bd492160 100644
--- a/webapp/channels/src/components/admin_console/group_settings/groups_list/groups_list.test.tsx
+++ b/webapp/channels/src/components/admin_console/group_settings/groups_list/groups_list.test.tsx
@@ -1,30 +1,50 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
-import {shallow} from 'enzyme';
+import {fireEvent, waitFor} from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
import React from 'react';
import GroupsList from 'components/admin_console/group_settings/groups_list/groups_list';
+import {renderWithContext, screen} from 'tests/react_testing_utils';
+
+// Helper to open the filter dropdown without it immediately closing.
+// The component registers a document 'click' listener (with {once: true}) to close the dropdown,
+// which fires on the same event that opens it. We temporarily suppress that listener.
+function openFilters() {
+ const originalAddEventListener = document.addEventListener.bind(document);
+ const spy = jest.spyOn(document, 'addEventListener').mockImplementation((...args: Parameters) => {
+ if (args[0] === 'click') {
+ // Suppress the one-time close listener
+ return;
+ }
+ originalAddEventListener(...args);
+ });
+ const caretDown = document.querySelector('i.fa-caret-down')!;
+ fireEvent.click(caretDown);
+ spy.mockRestore();
+}
+
describe('components/admin_console/group_settings/GroupsList.tsx', () => {
test('should match snapshot, while loading', () => {
- const wrapper = shallow(
+ // getLdapGroups never resolves, so component stays in loading state
+ const {container} = renderWithContext(
{})),
link: jest.fn(),
unlink: jest.fn(),
}}
/>,
);
- wrapper.setState({loading: true});
- expect(wrapper).toMatchSnapshot();
+ expect(container).toMatchSnapshot();
});
- test('should match snapshot, with only linked selected', () => {
- const wrapper = shallow(
+ test('should match snapshot, with only linked selected', async () => {
+ const {container} = renderWithContext(
{
}}
/>,
);
- wrapper.setState({checked: {test2: true}});
- expect(wrapper).toMatchSnapshot();
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ // Click on test2 (linked group) to select it
+ await userEvent.click(screen.getByText('test2'));
+
+ expect(container).toMatchSnapshot();
});
- test('should match snapshot, with only not-linked selected', () => {
- const wrapper = shallow(
+ test('should match snapshot, with only not-linked selected', async () => {
+ const {container} = renderWithContext(
{
}}
/>,
);
- wrapper.setState({checked: {test1: true}});
- expect(wrapper).toMatchSnapshot();
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ // Click on test1 (not-linked group) to select it
+ await userEvent.click(screen.getByText('test1'));
+
+ expect(container).toMatchSnapshot();
});
- test('should match snapshot, with mixed types selected', () => {
- const wrapper = shallow(
+ test('should match snapshot, with mixed types selected', async () => {
+ const {container} = renderWithContext(
{
}}
/>,
);
- wrapper.setState({checked: {test1: true, test2: true}});
- expect(wrapper).toMatchSnapshot();
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ // Click both groups to select them
+ await userEvent.click(screen.getByText('test1'));
+ await userEvent.click(screen.getByText('test2'));
+
+ expect(container).toMatchSnapshot();
});
- test('should match snapshot, without selection', () => {
- const wrapper = shallow(
+ test('should match snapshot, without selection', async () => {
+ const {container} = renderWithContext(
{
}}
/>,
);
- wrapper.setState({checked: {}});
- expect(wrapper).toMatchSnapshot();
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ expect(container).toMatchSnapshot();
});
- test('onCheckToggle must toggle the checked data', () => {
- const wrapper = shallow(
+ test('onCheckToggle must toggle the checked data', async () => {
+ renderWithContext(
{
}}
/>,
);
- const instance = wrapper.instance();
- expect(wrapper.state().checked).toEqual({});
- instance.onCheckToggle('test1');
- expect(wrapper.state().checked).toEqual({test1: true});
- instance.onCheckToggle('test1');
- expect(wrapper.state().checked).toEqual({test1: false});
- instance.onCheckToggle('test2');
- expect(wrapper.state().checked).toEqual({test1: false, test2: true});
- instance.onCheckToggle('test2');
- expect(wrapper.state().checked).toEqual({test1: false, test2: false});
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ const test1Group = screen.getByText('test1').closest('.group')!;
+ const test2Group = screen.getByText('test2').closest('.group')!;
+
+ // Initially neither is checked
+ expect(test1Group).not.toHaveClass('checked');
+ expect(test2Group).not.toHaveClass('checked');
+
+ // Toggle test1 on
+ await userEvent.click(screen.getByText('test1'));
+ expect(test1Group).toHaveClass('checked');
+
+ // Toggle test1 off
+ await userEvent.click(screen.getByText('test1'));
+ expect(test1Group).not.toHaveClass('checked');
+
+ // Toggle test2 on
+ await userEvent.click(screen.getByText('test2'));
+ expect(test2Group).toHaveClass('checked');
+
+ // Toggle test2 off
+ await userEvent.click(screen.getByText('test2'));
+ expect(test2Group).not.toHaveClass('checked');
});
- test('linkSelectedGroups must call link for unlinked selected groups', () => {
+ test('linkSelectedGroups must call link for unlinked selected groups', async () => {
const link = jest.fn();
- const wrapper = shallow(
+ renderWithContext(
{
}}
/>,
);
- const instance = wrapper.instance();
- expect(wrapper.state().checked).toEqual({});
- instance.onCheckToggle('test1');
- instance.onCheckToggle('test2');
- instance.linkSelectedGroups();
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ // Select both groups
+ await userEvent.click(screen.getByText('test1'));
+ await userEvent.click(screen.getByText('test2'));
+
+ // When mixed types are selected with an unlinked group, the button should be "Link Selected Groups"
+ await userEvent.click(screen.getByText('Link Selected Groups'));
+
+ // Only test1 (unlinked) should be linked
expect(link).toHaveBeenCalledTimes(1);
expect(link).toHaveBeenCalledWith('test1');
});
- test('unlinkSelectedGroups must call unlink for linked selected groups', () => {
+ test('unlinkSelectedGroups must call unlink for linked selected groups', async () => {
const unlink = jest.fn();
- const wrapper = shallow(
+ renderWithContext(
{
}}
/>,
);
- const instance = wrapper.instance();
- expect(wrapper.state().checked).toEqual({});
- instance.onCheckToggle('test1');
- instance.onCheckToggle('test2');
- instance.unlinkSelectedGroups();
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ // Select test2 (linked) only - this will show "Unlink Selected Groups"
+ await userEvent.click(screen.getByText('test2'));
+
+ // Now only test2 (linked) is selected, button should say "Unlink Selected Groups"
+ await userEvent.click(screen.getByText('Unlink Selected Groups'));
+
expect(unlink).toHaveBeenCalledTimes(1);
expect(unlink).toHaveBeenCalledWith('test2');
});
- test('should match snapshot, without results', () => {
- const wrapper = shallow(
+ test('should match snapshot, without results', async () => {
+ const {container} = renderWithContext(
{
}}
/>,
);
- wrapper.setState({loading: false});
- expect(wrapper).toMatchSnapshot();
+ await waitFor(() => {
+ expect(screen.getByText('No groups found')).toBeInTheDocument();
+ });
+ expect(container).toMatchSnapshot();
});
- test('should match snapshot, with results', () => {
- const wrapper = shallow(
+ test('should match snapshot, with results', async () => {
+ const {container} = renderWithContext(
{
}}
/>,
);
- wrapper.setState({loading: false});
- expect(wrapper).toMatchSnapshot();
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+ expect(container).toMatchSnapshot();
});
- test('should match snapshot, with results and next and previous', () => {
- const wrapper = shallow(
+ test('should match snapshot, with results and next and previous', async () => {
+ const getLdapGroups = jest.fn().mockReturnValue(Promise.resolve());
+ const groups = [
+ {primary_key: 'test1', name: 'test1'},
+ {primary_key: 'test2', name: 'test2', mattermost_group_id: 'group-id-1', has_syncables: false},
+ {primary_key: 'test3', name: 'test3', mattermost_group_id: 'group-id-2', has_syncables: true},
+ {primary_key: 'test4', name: 'test4'},
+ {primary_key: 'test5', name: 'test5'},
+ {primary_key: 'test6', name: 'test6'},
+ {primary_key: 'test7', name: 'test7'},
+ {primary_key: 'test8', name: 'test8'},
+ {primary_key: 'test9', name: 'test9'},
+ {primary_key: 'test10', name: 'test10'},
+ ];
+
+ const {container} = renderWithContext(
+ ,
+ );
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ // Click next to get to page 1 (both prev and next should be available with total=401)
+ const nextButton = screen.getByTitle('Next Icon').closest('button')!;
+ await userEvent.click(nextButton);
+
+ await waitFor(() => {
+ expect(getLdapGroups).toHaveBeenCalledTimes(2);
+ });
+
+ expect(container).toMatchSnapshot();
+ });
+
+ test('should match snapshot, with results and next', async () => {
+ const getLdapGroups = jest.fn().mockReturnValue(Promise.resolve());
+ const {container} = renderWithContext(
{
{primary_key: 'test9', name: 'test9'},
{primary_key: 'test10', name: 'test10'},
]}
- total={33}
+ total={401}
actions={{
- getLdapGroups: jest.fn().mockReturnValue(Promise.resolve()),
+ getLdapGroups,
link: jest.fn(),
unlink: jest.fn(),
}}
/>,
);
- wrapper.setState({page: 1, loading: false});
- expect(wrapper).toMatchSnapshot();
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ // On page 0 with total=401, next is enabled, prev is disabled
+ expect(container).toMatchSnapshot();
});
- test('should match snapshot, with results and next', () => {
- const wrapper = shallow(
- ,
- );
- wrapper.setState({loading: false});
- expect(wrapper).toMatchSnapshot();
- });
-
- test('should match snapshot, with results and previous', () => {
- const wrapper = shallow(
+ test('should match snapshot, with results and previous', async () => {
+ const getLdapGroups = jest.fn().mockReturnValue(Promise.resolve());
+ const {container} = renderWithContext(
,
);
- wrapper.setState({page: 1, loading: false});
- expect(wrapper).toMatchSnapshot();
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
+
+ // Click next to get to page 1, then prev is enabled
+ const nextButton = screen.getByTitle('Next Icon').closest('button')!;
+ await userEvent.click(nextButton);
+
+ await waitFor(() => {
+ expect(getLdapGroups).toHaveBeenCalledTimes(2);
+ });
+
+ expect(container).toMatchSnapshot();
});
test('should change properly the state and call the getLdapGroups, on previousPage when page > 0', async () => {
const getLdapGroups = jest.fn().mockReturnValue(Promise.resolve());
- const wrapper = shallow(
+ renderWithContext(
{
{primary_key: 'test9', name: 'test9'},
{primary_key: 'test10', name: 'test10'},
]}
- total={20}
+ total={401}
actions={{
getLdapGroups,
link: jest.fn(),
@@ -312,32 +417,58 @@ describe('components/admin_console/group_settings/GroupsList.tsx', () => {
}}
/>,
);
- wrapper.setState({page: 2, checked: {test1: true, test2: true}});
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
- await wrapper.instance().previousPage({preventDefault: jest.fn()});
+ const nextButton = screen.getByTitle('Next Icon').closest('button')!;
+ const prevButton = screen.getByTitle('Previous Icon').closest('button')!;
- let state = wrapper.instance().state;
- expect(state.checked).toEqual({});
- expect(state.page).toBe(1);
- expect(state.loading).toBe(false);
+ // Navigate to page 2: click next twice
+ await userEvent.click(nextButton);
+ await waitFor(() => {
+ expect(getLdapGroups).toHaveBeenCalledTimes(2);
+ });
- await wrapper.instance().previousPage({preventDefault: jest.fn()});
- state = wrapper.state();
- expect(state.checked).toEqual({});
- expect(state.page).toBe(0);
- expect(state.loading).toBe(false);
+ await userEvent.click(nextButton);
+ await waitFor(() => {
+ expect(getLdapGroups).toHaveBeenCalledTimes(3);
+ });
+
+ // Select some groups then click previous
+ await userEvent.click(screen.getByText('test1'));
+ await userEvent.click(screen.getByText('test2'));
+
+ // Click previous (page 2 -> 1)
+ await userEvent.click(prevButton);
+ await waitFor(() => {
+ expect(getLdapGroups).toHaveBeenCalledTimes(4);
+ });
+
+ // Checked state should be cleared (groups should not have checked class)
+ const test1Group = screen.getByText('test1').closest('.group')!;
+ expect(test1Group).not.toHaveClass('checked');
+
+ // Click previous again (page 1 -> 0)
+ await userEvent.click(prevButton);
+ await waitFor(() => {
+ expect(getLdapGroups).toHaveBeenCalledTimes(5);
+ });
+
+ // Previous button should now be disabled (page 0)
+ expect(prevButton).toBeDisabled();
});
test('should change properly the state and call the getLdapGroups, on previousPage when page == 0', async () => {
const getLdapGroups = jest.fn().mockReturnValue(Promise.resolve());
- const wrapper = shallow(
+ renderWithContext(
{
}}
/>,
);
- wrapper.setState({page: 0, checked: {test1: true, test2: true}});
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
- await wrapper.instance().previousPage({preventDefault: jest.fn()});
+ const prevButton = screen.getByTitle('Previous Icon').closest('button')!;
- const state = wrapper.instance().state;
- expect(state.checked).toEqual({});
- expect(state.page).toBe(0);
- expect(state.loading).toBe(false);
+ // On page 0, previous button should be disabled
+ expect(prevButton).toBeDisabled();
+
+ // Selections should not matter since we can't go back
+ const test1Group = screen.getByText('test1').closest('.group')!;
+ expect(test1Group).not.toHaveClass('checked');
});
test('should change properly the state and call the getLdapGroups, on nextPage clicked', async () => {
const getLdapGroups = jest.fn().mockReturnValue(Promise.resolve());
- const wrapper = shallow(
+ renderWithContext(
{
{primary_key: 'test9', name: 'test9'},
{primary_key: 'test10', name: 'test10'},
]}
- total={20}
+ total={401}
actions={{
getLdapGroups,
link: jest.fn(),
@@ -379,23 +514,38 @@ describe('components/admin_console/group_settings/GroupsList.tsx', () => {
}}
/>,
);
- wrapper.setState({page: 0, checked: {test1: true, test2: true}});
+ await waitFor(() => {
+ expect(screen.getByText('test1')).toBeInTheDocument();
+ });
- await wrapper.instance().nextPage({preventDefault: jest.fn()});
- let state = wrapper.state();
- expect(state.checked).toEqual({});
- expect(state.page).toBe(1);
- expect(state.loading).toBe(false);
+ const nextButton = screen.getByTitle('Next Icon').closest('button')!;
- await wrapper.instance().nextPage({preventDefault: jest.fn()});
- state = wrapper.state();
- expect(state.checked).toEqual({});
- expect(state.page).toBe(2);
- expect(state.loading).toBe(false);
+ // Select some groups
+ await userEvent.click(screen.getByText('test1'));
+ await userEvent.click(screen.getByText('test2'));
+
+ // Click next (page 0 -> 1)
+ await userEvent.click(nextButton);
+ await waitFor(() => {
+ expect(getLdapGroups).toHaveBeenCalledTimes(2);
+ });
+
+ // Checked state should be cleared
+ const test1Group = screen.getByText('test1').closest('.group')!;
+ expect(test1Group).not.toHaveClass('checked');
+
+ // Click next again (page 1 -> 2)
+ await userEvent.click(nextButton);
+ await waitFor(() => {
+ expect(getLdapGroups).toHaveBeenCalledTimes(3);
+ });
+
+ // Still not checked
+ expect(test1Group).not.toHaveClass('checked');
});
- test('should match snapshot, with filters open', () => {
- const wrapper = shallow(
+ test('should match snapshot, with filters open', async () => {
+ const {container} = renderWithContext(
{
}}
/>,
);
- wrapper.setState({showFilters: true, filterIsLinked: true, filterIsUnlinked: true});
- expect(wrapper).toMatchSnapshot();
+ await waitFor(() => {
+ expect(screen.getByText('No groups found')).toBeInTheDocument();
+ });
+
+ // Open the filter dropdown
+ openFilters();
+
+ // Verify filters are shown
+ expect(screen.getByText('Is Linked')).toBeInTheDocument();
+ expect(screen.getByText('Is Not Linked')).toBeInTheDocument();
+
+ expect(container).toMatchSnapshot();
});
- test('clicking the clear icon clears searchString', () => {
- const wrapper = shallow(
+ test('clicking the clear icon clears searchString', async () => {
+ renderWithContext(
{
}}
/>,
);
- wrapper.setState({searchString: 'foo'});
- wrapper.find('i.fa-times-circle').first().simulate('click');
- expect(wrapper.state().searchString).toEqual('');
+ await waitFor(() => {
+ expect(screen.getByText('No groups found')).toBeInTheDocument();
+ });
+
+ // Type in search input
+ const searchInput = screen.getByPlaceholderText('Search');
+ await userEvent.type(searchInput, 'foo');
+ expect(searchInput).toHaveValue('foo');
+
+ // Click the clear icon
+ await userEvent.click(document.querySelector('i.fa-times-circle')!);
+
+ expect(searchInput).toHaveValue('');
});
- test('clicking the down arrow opens the filters', () => {
- const wrapper = shallow(
+ test('clicking the down arrow opens the filters', async () => {
+ renderWithContext(
{
}}
/>,
);
- expect(wrapper.state().showFilters).toEqual(false);
- wrapper.find('i.fa-caret-down').first().simulate('click');
- expect(wrapper.state().showFilters).toEqual(true);
+ await waitFor(() => {
+ expect(screen.getByText('No groups found')).toBeInTheDocument();
+ });
+
+ // Filters should not be visible initially
+ expect(screen.queryByText('Is Linked')).not.toBeInTheDocument();
+
+ // Click the down arrow
+ openFilters();
+
+ // Filters should now be visible
+ expect(screen.getByText('Is Linked')).toBeInTheDocument();
});
- test('clicking search invokes getLdapGroups', () => {
+ test('clicking search invokes getLdapGroups', async () => {
const getLdapGroups = jest.fn().mockReturnValue(Promise.resolve());
- const wrapper = shallow(
+ renderWithContext(
{
}}
/>,
);
- wrapper.setState({showFilters: true, searchString: 'foo iS:ConfiGuReD is:notlinked'});
- expect(wrapper.state().filterIsConfigured).toEqual(false);
- expect(wrapper.state().filterIsUnlinked).toEqual(false);
+ await waitFor(() => {
+ expect(screen.getByText('No groups found')).toBeInTheDocument();
+ });
- wrapper.find('a.search-groups-btn').first().simulate('click');
+ // Open filters
+ openFilters();
+
+ // Type search string with filter keywords
+ const searchInput = screen.getByPlaceholderText('Search');
+ await userEvent.clear(searchInput);
+ await userEvent.type(searchInput, 'foo iS:ConfiGuReD is:notlinked');
+
+ // Click the Search button in the filter panel
+ await userEvent.click(screen.getByText('Search'));
+
+ // getLdapGroups should have been called: once on mount + once on search
expect(getLdapGroups).toHaveBeenCalledTimes(2);
expect(getLdapGroups).toHaveBeenCalledWith(0, 200, {q: 'foo', is_configured: true, is_linked: false});
- expect(wrapper.state().filterIsConfigured).toEqual(true);
- expect(wrapper.state().filterIsUnlinked).toEqual(true);
});
- test('checking a filter checkbox add the filter to the searchString', () => {
+ test('checking a filter checkbox add the filter to the searchString', async () => {
const getLdapGroups = jest.fn().mockReturnValue(Promise.resolve());
- const wrapper = shallow(
+ renderWithContext(
{
}}
/>,
);
- wrapper.setState({showFilters: true, searchString: 'foo'});
- wrapper.find('span.filter-check').first().simulate('click');
- expect(wrapper.state().searchString).toEqual('foo is:linked');
+ await waitFor(() => {
+ expect(screen.getByText('No groups found')).toBeInTheDocument();
+ });
+
+ // Type 'foo' in search
+ const searchInput = screen.getByPlaceholderText('Search');
+ await userEvent.type(searchInput, 'foo');
+
+ // Open filters
+ openFilters();
+
+ // Click the "Is Linked" filter checkbox
+ const isLinkedCheckbox = screen.getByText('Is Linked').parentElement!.querySelector('.filter-check')!;
+ await userEvent.click(isLinkedCheckbox);
+
+ // The search string should now include 'is:linked'
+ expect(searchInput).toHaveValue('foo is:linked');
});
- test('unchecking a filter checkbox removes the filter from the searchString', () => {
+ test('unchecking a filter checkbox removes the filter from the searchString', async () => {
const getLdapGroups = jest.fn().mockReturnValue(Promise.resolve());
- const wrapper = shallow(
+ renderWithContext(
{
}}
/>,
);
- wrapper.setState({showFilters: true, searchString: 'foo is:linked', filterIsLinked: true});
- wrapper.find('span.filter-check').first().simulate('click');
- expect(wrapper.state().searchString).toEqual('foo');
+ await waitFor(() => {
+ expect(screen.getByText('No groups found')).toBeInTheDocument();
+ });
+
+ // Type 'foo' in search
+ const searchInput = screen.getByPlaceholderText('Search');
+ await userEvent.type(searchInput, 'foo');
+
+ // Open filters
+ openFilters();
+
+ // Click the "Is Linked" filter checkbox to check it
+ const isLinkedCheckbox = screen.getByText('Is Linked').parentElement!.querySelector('.filter-check')!;
+ await userEvent.click(isLinkedCheckbox);
+ expect(searchInput).toHaveValue('foo is:linked');
+
+ // Click it again to uncheck it
+ await userEvent.click(isLinkedCheckbox);
+ expect(searchInput).toHaveValue('foo');
});
});
diff --git a/webapp/channels/src/components/admin_console/license_settings/__snapshots__/license_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/license_settings/__snapshots__/license_settings.test.tsx.snap
index 085149667ac..0e81ef14e87 100644
--- a/webapp/channels/src/components/admin_console/license_settings/__snapshots__/license_settings.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/license_settings/__snapshots__/license_settings.test.tsx.snap
@@ -1,108 +1,476 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`components/admin_console/license_settings/LicenseSettings load screen after upgrading 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 22 days on May 6, 2021.
+
+
+
+
+ Renew your Enterprise E20 license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+ Team Edition
+
+
+
+
+ When using Mattermost Team Edition, the software is offered under a Mattermost MIT Compiled License. See MIT-COMPILED-LICENSE.md in your root install directory for details.
+
+
+ When using Mattermost Enterprise Edition, the software is offered under a commercial license. See
+
+ here
+
+ for “Enterprise Edition License” for details.
+
+
+ See NOTICE.txt for information about open source software used in the system.
+
+ A license is required to unlock enterprise features
+
+
+
+
+ AD/LDAP Group Sync
+
+
+
+ High Availability
+
+
+
+ Advanced compliance
+
+
+
+ And more...
+
+
+
+
+ You have upgraded your binary to mattermost enterprise, please restart the server to start using the new binary. You can do it right here:
+
+
+
+ Restart Server
+
+
+
+
+
@@ -112,108 +480,498 @@ exports[`components/admin_console/license_settings/LicenseSettings load screen a
`;
exports[`components/admin_console/license_settings/LicenseSettings load screen while upgrading 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 22 days on May 6, 2021.
+
+
+
+
+ Renew your Enterprise E20 license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+ Team Edition
+
+
+
+
+ When using Mattermost Team Edition, the software is offered under a Mattermost MIT Compiled License. See MIT-COMPILED-LICENSE.md in your root install directory for details.
+
+
+ When using Mattermost Enterprise Edition, the software is offered under a commercial license. See
+
+ here
+
+ for “Enterprise Edition License” for details.
+
+
+ See NOTICE.txt for information about open source software used in the system.
+
+ A license is required to unlock enterprise features
+
+
+
+
+ AD/LDAP Group Sync
+
+
+
+ High Availability
+
+
+
+ Advanced compliance
+
+
+
+ And more...
+
+
+
+
+
+
+
+ Upgrading 42%
+
+
+
+
+ By clicking
+
+ Upgrade
+
+ , I agree to the terms of the Mattermost
+
+ Enterprise Edition License
+
+ . Upgrading will download the binary and update your team edition.
+
+
+
+
@@ -223,149 +981,659 @@ exports[`components/admin_console/license_settings/LicenseSettings load screen w
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot enterprise build with E10 license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 22 days on May 6, 2021.
+
+
+
+
+ Renew your Enterprise E10 license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+
+ Mattermost Enterprise E10
+
+
+
+ View plans
+
+
+
+
+
+ License details
+
+
+ + Add seats
+
+
+
+
+
+ START DATE:
+
+
+ 2/4/2018
+
+
+
+
+ EXPIRES:
+
+
+ 5/6/2021
+
+
+ Expires in 22 days
+
+
+
+ Remove license and downgrade to Mattermost Free
+
+
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
@@ -375,137 +1643,645 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot enterprise build with E20 license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 22 days on May 6, 2021.
+
+
+
+
+ Renew your Enterprise E20 license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+
+ Mattermost Enterprise E20
+
+
+
+ View plans
+
+
+
+
+
+ License details
+
+
+ + Add seats
+
+
+
+
+
+ START DATE:
+
+
+ 2/4/2018
+
+
+
+
+ EXPIRES:
+
+
+ 5/6/2021
+
+
+ Expires in 22 days
+
+
+
+ Remove license and downgrade to Mattermost Free
+
+
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
@@ -515,137 +2291,661 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot enterprise build with Enterprise license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 22 days on May 6, 2021.
+
+
+
+
+ Renew your Enterprise license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+
+ Mattermost Enterprise
+
+
+
+ View plans
+
+
+
+
+
+ License details
+
+
+ + Add seats
+
+
+
+
+
+ START DATE:
+
+
+ 2/4/2018
+
+
+
+
+ EXPIRES:
+
+
+ 5/6/2021
+
+
+ Expires in 22 days
+
+
+
+ Remove license and downgrade to Mattermost Free
+
+
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
@@ -655,137 +2955,645 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot enterprise build with license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 22 days on May 6, 2021.
+
+
+
+
+ Renew your Enterprise E20 license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+
+ Mattermost Enterprise E20
+
+
+
+ View plans
+
+
+
+
+
+ License details
+
+
+ + Add seats
+
+
+
+
+
+ START DATE:
+
+
+ 2/4/2018
+
+
+
+
+ EXPIRES:
+
+
+ 5/6/2021
+
+
+ Expires in 22 days
+
+
+
+ Remove license and downgrade to Mattermost Free
+
+
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
@@ -795,137 +3603,646 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot enterprise build with license and isDisabled set to true 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 22 days on May 6, 2021.
+
+
+
+
+ Renew your Enterprise E20 license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+
+ Mattermost Enterprise E20
+
+
+
+ View plans
+
+
+
+
+
+ License details
+
+
+ + Add seats
+
+
+
+
+
+ START DATE:
+
+
+ 2/4/2018
+
+
+
+
+ EXPIRES:
+
+
+ 5/6/2021
+
+
+ Expires in 22 days
+
+
+
+ Remove license and downgrade to Mattermost Free
+
+
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
@@ -935,137 +4252,651 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot enterprise build with license and upgraded from TE 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 22 days on May 6, 2021.
+
+
+
+
+ Renew your Enterprise E20 license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+
+ Mattermost Enterprise E20
+
+
+
+ View plans
+
+
+
+
+
+ License details
+
+
+ + Add seats
+
+
+
+
+
+ START DATE:
+
+
+ 2/4/2018
+
+
+
+
+ EXPIRES:
+
+
+ 5/6/2021
+
+
+ Expires in 22 days
+
+
+
+ Remove license and downgrade to Mattermost Free
+
+
+
+
+
+
+ When using Mattermost Enterprise Edition, the software is offered under a commercial license. See
+
+ here
+
+ for "Enterprise Edition License" for details.
+ See NOTICE.txt for information about open source software used in the system.
+
@@ -1075,111 +4906,578 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot enterprise build with trial license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
+
+
+
+
+
+ You’re currently on a free trial of our Mattermost Enterprise Advanced.
+
+
+
+
+ Your free trial will expire in
+
+ 0 days
+
+ . Contact sales to purchase a license and continue using advanced features.
+
+
+ Remove license and downgrade to Mattermost Free
+
+
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
+
+
+
- Curious about upgrading?
-
- Compare Plans
-
+
+
+
+
+
+ Purchase Enterprise Advanced
+
+
+ Continue your access to Enterprise Advanced features by purchasing a license.
+
@@ -1189,119 +5487,537 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot enterprise build without license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
+
+
+
+
+ Start a free 30-day trial of Mattermost Enterprise Advanced
+
+
-
- Current Plan
+
+ Experience all that Mattermost Enterprise Advanced has to offer with a free trial for the next 30 days. No obligation to buy and no credit card required.
+ By clicking
+
+ Start trial
+
+ , I agree to the
+
+ Mattermost Software and Services License Agreement
+
+ ,
+
+ Privacy Policy
+
+ , and receiving product emails.
+
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
- Privacy Policy
-
+
+
-
+
+
+
+ View plans
+
+
+ Free
+
+
+
+
+ Current Plan
+
+
+
+ Purchase Professional or Enterprise to unlock enterprise features.
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
@@ -1311,119 +6027,543 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot enterprise build without license and upgrade from TE 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
+
+
+
+
+ Start a free 30-day trial of Mattermost Enterprise Advanced
+
+
-
- Current Plan
+
+ Experience all that Mattermost Enterprise Advanced has to offer with a free trial for the next 30 days. No obligation to buy and no credit card required.
+ By clicking
+
+ Start trial
+
+ , I agree to the
+
+ Mattermost Software and Services License Agreement
+
+ ,
+
+ Privacy Policy
+
+ , and receiving product emails.
+
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
- Privacy Policy
-
+
+
-
+
+
+
+ View plans
+
+
+ Free
+
+
+
+
+ Current Plan
+
+
+
+ Purchase Professional or Enterprise to unlock enterprise features.
+
+
+
+
+ When using Mattermost Enterprise Edition, the software is offered under a commercial license. See
+
+ here
+
+ for "Enterprise Edition License" for details.
+ See NOTICE.txt for information about open source software used in the system.
+
@@ -1433,108 +6573,488 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot team edition build with license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 22 days on May 6, 2021.
+
+
+
+
+ Renew your Enterprise E20 license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+ Team Edition
+
+
+
+
+ When using Mattermost Team Edition, the software is offered under a Mattermost MIT Compiled License. See MIT-COMPILED-LICENSE.md in your root install directory for details.
+
+
+ When using Mattermost Enterprise Edition, the software is offered under a commercial license. See
+
+ here
+
+ for “Enterprise Edition License” for details.
+
+
+ See NOTICE.txt for information about open source software used in the system.
+
+ A license is required to unlock enterprise features
+
+
+
+
+ AD/LDAP Group Sync
+
+
+
+ High Availability
+
+
+
+ Advanced compliance
+
+
+
+ And more...
+
+
+
+
+
+ Upgrade to Enterprise Edition
+
+
+
+ By clicking
+
+ Upgrade
+
+ , I agree to the terms of the Mattermost
+
+ Enterprise Edition License
+
+ . Upgrading will download the binary and update your team edition.
+
+
+
+
@@ -1544,112 +7064,512 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot team edition build without license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ Start a free 30-day trial of Mattermost Enterprise Advanced
+
+
+
+
+ Upgrade to the Enterprise Edition to unlock a free 30-day trial of Mattermost Enterprise Advanced—our most powerful plan. No credit card required, no obligation to buy.
+
+ When using Mattermost Team Edition, the software is offered under a Mattermost MIT Compiled License. See MIT-COMPILED-LICENSE.md in your root install directory for details.
+
+
+ When using Mattermost Enterprise Edition, the software is offered under a commercial license. See
+
+ here
+
+ for “Enterprise Edition License” for details.
+
+
+ See NOTICE.txt for information about open source software used in the system.
+
+ A license is required to unlock enterprise features
+
+
+
+
+ AD/LDAP Group Sync
+
+
+
+ High Availability
+
+
+
+ Advanced compliance
+
+
+
+ And more...
+
+
+
+
+
+ Upgrade to Enterprise Edition
+
+
+
+ By clicking
+
+ Upgrade
+
+ , I agree to the terms of the Mattermost
+
+ Enterprise Edition License
+
+ . Upgrading will download the binary and update your team edition.
+
@@ -1659,104 +7579,461 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot team edition with expired trial in the past 1`] = `
-
+ Purchase Professional or Enterprise to unlock enterprise features.
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
+ Purchase one of our plans to unlock more features
+
+
+
+
+ Attribute-based access control
+
+
+
+ Channel warning banners
+
+
+
+ AD/LDAP group sync
+
+
+
+ Advanced workflows with Playbooks
+
+
+
+ High availability
+
+
+
+ Advanced compliance
+
+
+
+ And more...
+
+
+
+
+ Contact Sales
+
+
+
+
+
- Privacy Policy
-
-
-
-
-
-
-
-
- Curious about upgrading?
-
- Compare Plans
-
+ Curious about upgrading?
+
+ Compare Plans
+
+
@@ -1766,124 +8043,568 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot with cloud expiring license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
+
+
+
+
+
+ Mattermost Enterprise E20
+
+
+
+ View plans
+
+
+
+
+
+ License details
+
+
+ + Add seats
+
+
+
+
+
+ START DATE:
+
+
+ 2/4/2018
+
+
+
+
+ EXPIRES:
+
+
+ 5/14/2021
+
+
+ Expires in 30 days
+
+
+
+ Remove license and downgrade to Mattermost Free
+
+
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
- Privacy Policy
-
-
-
-
-
-
+
+
+
+
+
+ Upgrade to Enterprise
+
+
+
+
+
+ AD/LDAP Group sync
+
+
+
+ High Availability
+
+
+
+ Advanced compliance
+
+
+
+ Advanced roles and permissions
+
+
+
+ And more...
+
+
+
+
+
+
+ Contact Sales
+
+
+
+
+
@@ -1893,137 +8614,645 @@ exports[`components/admin_console/license_settings/LicenseSettings should match
`;
exports[`components/admin_console/license_settings/LicenseSettings should match snapshot with expiring license 1`] = `
-
-
-
-
+
+ Edition and License
+
+
-
-
-
-
-
-
-
- See also
-
- Enterprise Edition Terms of Use
-
- and
-
+
+
+
+
- Privacy Policy
-
+
+ License expires in 30 days on May 14, 2021.
+
+
+
+
+ Renew your Enterprise E20 license by contacting sales to avoid any disruption.
+
+
+ Review your numbers below to ensure you renew for the right number of users.
+
+
+
+ Licensed Users:
+
+ 100
+
+
+
+ Active Users:
+
+ 10
+
+
+
+
+ Contact Sales
+
+
+
+
+
+
-
+
+
+
+
+
+ Mattermost Enterprise E20
+
+
+
+ View plans
+
+
+
+
+
+ License details
+
+
+ + Add seats
+
+
+
+
+
+ START DATE:
+
+
+ 2/4/2018
+
+
+
+
+ EXPIRES:
+
+
+ 5/14/2021
+
+
+ Expires in 30 days
+
+
+
+ Remove license and downgrade to Mattermost Free
+
+
+
+
+
+
+ This software is offered under a commercial license.
+
+See ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_description should match snapshot with clickable link 1`] = `
-
- This is a clickable description
-
- }
->
+
This is a clickable description
-
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_description should match snapshot with default Props 1`] = `
-
+
This is the description
-
+
`;
diff --git a/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_group.test.tsx.snap b/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_group.test.tsx.snap
index bcd57c9a000..319e3cffce4 100644
--- a/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_group.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_group.test.tsx.snap
@@ -1,723 +1,1511 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
-exports[`components/admin_console/permission_schemes_settings/permission_group should expand and collapse correctly, expanded by default, collapsed and then expanded again 1`] = `
-
-
-
-
-
- name
-
-
-
-
-
-
-
-
-`;
-
-exports[`components/admin_console/permission_schemes_settings/permission_group should expand and collapse correctly, expanded by default, collapsed and then expanded again 2`] = `
-
-
-
-
-
- name
-
-
-
-
-
-
-
-
-`;
-
-exports[`components/admin_console/permission_schemes_settings/permission_group should expand and collapse correctly, expanded by default, collapsed and then expanded again 3`] = `
-
-
-
-
-
- name
-
-
-
-
-
-
-
-
-`;
-
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot on editable with all permissions 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+
+
+ name
+
+
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot on editable with all permissions and read-only 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+
+
+ name
+
+
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot on editable with all permissions from parentRole 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+
+
+ name
+
+
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot on editable with some permissions 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+
+
+ name
+
+
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot on editable with some permissions and read-only 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+
+
+ name
+
+
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot on editable with some permissions from parentRole 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+
+
+ name
+
+
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot on editable without every permission out of the scope 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+ name
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot on editable without permissions 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+ name
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot on editable without permissions and read-only 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+ name
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot with additional values 1`] = `
-
+
-
-
- name
-
-
-
-
-
-
+
+
+
+ name
+
+
+
+
+
+
+
+ invite_user
+
+
+
+
+
+
+ add_user_to_team
+
+
+
+
`;
diff --git a/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_row.test.tsx.snap b/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_row.test.tsx.snap
index 81d2b429518..fd605629caa 100644
--- a/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_row.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_row.test.tsx.snap
@@ -1,139 +1,411 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`components/admin_console/permission_schemes_settings/permission_row should match snapshot on editable and inherited 1`] = `
-
`;
diff --git a/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_schemes_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_schemes_settings.test.tsx.snap
index f92518e8cb9..1a4611b4a91 100644
--- a/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_schemes_settings.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/permission_schemes_settings/__snapshots__/permission_schemes_settings.test.tsx.snap
@@ -1,651 +1,1135 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
-exports[`components/admin_console/permission_schemes_settings/permission_schemes_settings should match snapshot loading 1`] = ``;
-
-exports[`components/admin_console/permission_schemes_settings/permission_schemes_settings should match snapshot with schemes 1`] = `
-
-
-
-
+exports[`components/admin_console/permission_schemes_settings/permission_schemes_settings should match snapshot loading 1`] = `
+
+
+ Loading
+
+
+
+
+
+
+
+`;
+
+exports[`components/admin_console/permission_schemes_settings/permission_schemes_settings should match snapshot with schemes 1`] = `
+
+
+
+ Permission Schemes
+
+
-
-
+
+ Permission Schemes set the default permissions for Team Admins, Channel Admins and everyone else. Learn more about permission schemes in our
+
+ documentation
+
+ .
+
+
+
+
+
+
+
+ System Scheme
+
+
+ Set the default permissions inherited by all teams unless a
+
+ Team Override Scheme
+
+ is applied.
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_schemes_settings should match snapshot without schemes 1`] = `
-
-
-
-
+
+ Permission Schemes
+
+
-
-
-
+
+
+ Permission Schemes set the default permissions for Team Admins, Channel Admins and everyone else. Learn more about permission schemes in our
+
+ documentation
+
+ .
+
+
+
+
+
+
+
+ System Scheme
+
+
+ Set the default permissions inherited by all teams unless a
+
+ Team Override Scheme
+
+ is applied.
+
-
+ Permission Schemes set the default permissions for Team Admins, Channel Admins and everyone else. Learn more about permission schemes in our
+
+ documentation
+
+ .
+
+
+
+
+
+
+
+ System Scheme
+
+
+ Set the default permissions inherited by all teams unless a
+
+ Team Override Scheme
+
+ is applied.
+
+ Migration job in progress: Team Override Schemes are not available until the job server completes the permissions migration. Learn more in the
+
+ documentation
+
+ .
+
-
+ Permission Schemes set the default permissions for Team Admins, Channel Admins and everyone else. Learn more about permission schemes in our
+
+ documentation
+
+ .
+
+
+
+
+
+
+
+ System Scheme
+
+
+ Set the default permissions inherited by all teams unless a
+
+ Team Override Scheme
+
+ is applied.
+
+ Migration job on hold: Team Override Schemes are not available until the job server can execute the permissions migration. The job will be automatically started when the job server is enabled. Learn more in the
+
+ documentation
+
+ .
+
`;
exports[`components/admin_console/permission_schemes_settings/permission_schemes_settings should show normal view (jobs disabled after migration) 1`] = `
-
-
-
-
+
+ Permission Schemes
+
+
-
-
+
+ Permission Schemes set the default permissions for Team Admins, Channel Admins and everyone else. Learn more about permission schemes in our
+
+ documentation
+
+ .
+
+
+
+
+
+
+
+ System Scheme
+
+
+ Set the default permissions inherited by all teams unless a
+
+ Team Override Scheme
+
+ is applied.
+