mirror of
https://github.com/hanzoai/team.git
synced 2026-09-30 01:57:35 +00:00
The base moves off /v1/team for two reasons that point the same way. It collided: /v1/team on hanzo.team is a carve-out routed to the older cloud service, so the moment this image shipped its own API would have been answered by something else -- a 404 on our own endpoints, on the host we serve from. And workspace is the better noun. It is what the product calls itself in its own words, and it does not read as though the API belongs to one team among several. No /api/ anywhere in a path we own. Co-authored-by: Hanzo Dev <[email protected]>
146 lines
6.8 KiB
TypeScript
146 lines
6.8 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import type {AdminConfig} from '@mattermost/types/config';
|
|
|
|
import {expect, test} from '@mattermost/playwright-lib';
|
|
|
|
// Wait for the GET /v1/workspace/config re-fetch that our config_changed websocket
|
|
// handler triggers. This is the signal that entities.admin.config in the
|
|
// browser's Redux store is now up-to-date with the server's current state.
|
|
async function waitForAdminConfigRefresh(page: import('@playwright/test').Page) {
|
|
return page.waitForResponse(
|
|
(resp) => resp.url().endsWith('/v1/workspace/config') && resp.request().method() === 'GET' && resp.status() === 200,
|
|
{timeout: 10000},
|
|
);
|
|
}
|
|
|
|
// Each test case opens a System Console page, makes a parallel API change to a
|
|
// completely separate config section (simulating another admin), then saves the
|
|
// open page and asserts both changes survived.
|
|
test.describe('System Console > Concurrent config saves', () => {
|
|
test('Emoji page: parallel change to TeamSettings is not clobbered', async ({pw}) => {
|
|
const {adminUser, adminClient} = await pw.initSetup();
|
|
|
|
if (!adminUser) {
|
|
throw new Error('Failed to create admin user');
|
|
}
|
|
|
|
// # Set a known baseline for both sections under test
|
|
await adminClient.patchConfig({
|
|
ServiceSettings: {EnableCustomEmoji: false},
|
|
TeamSettings: {MaxUsersPerTeam: 50},
|
|
} as Partial<AdminConfig>);
|
|
|
|
// # Open the Emoji settings page
|
|
const {page} = await pw.testBrowser.login(adminUser);
|
|
await page.goto('/admin_console/site_config/emoji');
|
|
|
|
const emojiSection = page.getByTestId('sysconsole_section_EmojiSettings');
|
|
await expect(emojiSection).toBeVisible();
|
|
const saveButton = emojiSection.getByRole('button', {name: 'Save'});
|
|
|
|
// # Simulate another admin saving an unrelated section via API.
|
|
// Set up the response listener before triggering the change so we don't
|
|
// miss the GET /v1/workspace/config that our config_changed handler dispatches.
|
|
const configRefresh = waitForAdminConfigRefresh(page);
|
|
await adminClient.patchConfig({TeamSettings: {MaxUsersPerTeam: 99}} as Partial<AdminConfig>);
|
|
|
|
// # Wait for the browser to re-fetch the admin config before we save,
|
|
// confirming that this.props.config is now fresh. Then assert the
|
|
// toggle's current state to confirm the Redux store update has
|
|
// propagated to the UI before we interact.
|
|
await configRefresh;
|
|
const emojiToggle = emojiSection.getByTestId('ServiceSettings.EnableCustomEmojitrue');
|
|
await expect(emojiToggle).not.toBeChecked();
|
|
|
|
// # Change a setting on the open Emoji page and save
|
|
await emojiToggle.click();
|
|
await saveButton.click();
|
|
await pw.waitUntil(async () => (await saveButton.textContent()) === 'Save');
|
|
|
|
// * Both the UI change and the parallel API change must be present
|
|
const finalConfig = await adminClient.getConfig();
|
|
expect(finalConfig.ServiceSettings.EnableCustomEmoji).toBe(true);
|
|
expect(finalConfig.TeamSettings.MaxUsersPerTeam).toBe(99);
|
|
});
|
|
|
|
test('Announcement Banner page: parallel change to ServiceSettings is not clobbered', async ({pw}) => {
|
|
const {adminUser, adminClient} = await pw.initSetup();
|
|
|
|
if (!adminUser) {
|
|
throw new Error('Failed to create admin user');
|
|
}
|
|
|
|
// # Set a known baseline for both sections under test
|
|
await adminClient.patchConfig({
|
|
AnnouncementSettings: {EnableBanner: false},
|
|
ServiceSettings: {EnableCustomEmoji: false},
|
|
} as Partial<AdminConfig>);
|
|
|
|
// # Open the Announcement Banner settings page
|
|
const {page} = await pw.testBrowser.login(adminUser);
|
|
await page.goto('/admin_console/site_config/announcement_banner');
|
|
|
|
const bannerSection = page.getByTestId('sysconsole_section_AnnouncementSettings');
|
|
await expect(bannerSection).toBeVisible();
|
|
const saveButton = bannerSection.getByRole('button', {name: 'Save'});
|
|
|
|
// # Simulate another admin saving an unrelated section via API
|
|
const configRefresh = waitForAdminConfigRefresh(page);
|
|
await adminClient.patchConfig({ServiceSettings: {EnableCustomEmoji: true}} as Partial<AdminConfig>);
|
|
await configRefresh;
|
|
const bannerToggle = bannerSection.getByTestId('AnnouncementSettings.EnableBannertrue');
|
|
await expect(bannerToggle).not.toBeChecked();
|
|
|
|
// # Change a setting on the open Announcement Banner page and save
|
|
await bannerToggle.click();
|
|
await saveButton.click();
|
|
await pw.waitUntil(async () => (await saveButton.textContent()) === 'Save');
|
|
|
|
// * Both changes must be present
|
|
const finalConfig = await adminClient.getConfig();
|
|
expect(finalConfig.AnnouncementSettings.EnableBanner).toBe(true);
|
|
expect(finalConfig.ServiceSettings.EnableCustomEmoji).toBe(true);
|
|
});
|
|
|
|
test('Users and Teams page: parallel change to EmailSettings is not clobbered', async ({pw}) => {
|
|
const {adminUser, adminClient} = await pw.initSetup();
|
|
|
|
if (!adminUser) {
|
|
throw new Error('Failed to create admin user');
|
|
}
|
|
|
|
// # Set a known baseline for both sections under test
|
|
await adminClient.patchConfig({
|
|
TeamSettings: {EnableJoinLeaveMessageByDefault: false},
|
|
EmailSettings: {EnableSignUpWithEmail: true},
|
|
} as Partial<AdminConfig>);
|
|
|
|
// # Open the Users and Teams settings page
|
|
const {page} = await pw.testBrowser.login(adminUser);
|
|
await page.goto('/admin_console/site_config/users_and_teams');
|
|
|
|
const teamSection = page.getByTestId('sysconsole_section_UserAndTeamsSettings');
|
|
await expect(teamSection).toBeVisible();
|
|
const saveButton = teamSection.getByRole('button', {name: 'Save'});
|
|
|
|
// # Simulate another admin saving EmailSettings via API
|
|
const configRefresh = waitForAdminConfigRefresh(page);
|
|
await adminClient.patchConfig({EmailSettings: {EnableSignUpWithEmail: false}} as Partial<AdminConfig>);
|
|
await configRefresh;
|
|
const joinLeaveToggle = teamSection.getByTestId('TeamSettings.EnableJoinLeaveMessageByDefaulttrue');
|
|
await expect(joinLeaveToggle).not.toBeChecked();
|
|
|
|
// # Toggle Enable Join/Leave messages on the Users and Teams page and save
|
|
await joinLeaveToggle.click();
|
|
await saveButton.click();
|
|
await pw.waitUntil(async () => (await saveButton.textContent()) === 'Save');
|
|
|
|
// * Both changes must be present
|
|
const finalConfig = await adminClient.getConfig();
|
|
expect(finalConfig.TeamSettings.EnableJoinLeaveMessageByDefault).toBe(true);
|
|
expect(finalConfig.EmailSettings.EnableSignUpWithEmail).toBe(false);
|
|
});
|
|
});
|