mattermost-mobile/app/client/rest/general.test.ts
Jesse Hallam 15f59b7eee
[MM-63728] Add license load metric to About screen (#8769)
* Add license load metric to About screen

- Add REST endpoint to fetch license load percentage
- Display load metric in About screen next to server version

Fixes: https://mattermost.atlassian.net/browse/MM-63728

* MM-63728: Address PR feedback from enahum

- Move license load metric fetch to a remote action
- Use isMinimumServerVersion to check for server 10.8.0 or higher

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* MM-63728: Simplify getLicenseLoadMetric to directly return number

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* MM-63728: Move getLicenseLoadMetric to dedicated license.ts file

- Create new remote action file specifically for license-related functions
- Add test file for the license actions
- Update imports in about.tsx

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* MM-63728: Remove redundant license check in about.tsx

- Rely on getLicenseLoadMetric to handle the license check

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* MM-63728: Update E2E tests for license load metric

- Add license load metric test IDs to about screen
- Update E2E test to check for load metric when license is enabled
- Handle cases where server might not support the feature

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* recover app/actions/remote/general.ts

* MM-63728: Return error from getLicenseLoadMetric instead of silent failure

- Remove silent failure and debug logging
- Return the error object when API call fails
- Update the About component to handle possible error responses
- Update tests to verify error handling

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* MM-63728: Remove groupLabel parameter from getLicenseLoadMetric

- Remove groupLabel parameter from client getLicenseLoadMetric method in interface and implementation
- Update client tests to reflect the parameter removal
- Update license action test to verify no parameter is passed

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* simplify about screen checks

* MM-63728: Use jest.mocked and real version checks in license tests

- Removed isMinimumServerVersion mock, letting tests use real version checking
- Used proper type casting for mock Client
- Added comprehensive version compatibility test cases
- Simplified test setup

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* MM-63728: Remove redundant server version test

- Removed redundant test for different server versions
- Existing tests already cover the necessary version compatibility cases

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* MM-63728: Refactor license test to use better mocking pattern

- Refactored the test file to use a better mocking pattern similar to custom_emoji.test.ts
- Simplified mock declarations using jest.mock()
- Added type import for Client for better readability
- Improved type casting for mock objects

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* npm run fix

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-04-17 17:29:47 -03:00

177 lines
6.8 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import TestHelper from '@test/test_helper';
import {buildQueryString} from '@utils/helpers';
import {PER_PAGE_DEFAULT} from './constants';
import ClientError from './error';
import type ClientBase from './base';
import type {ClientGeneralMix} from './general';
describe('ClientGeneral', () => {
let client: ClientGeneralMix & ClientBase;
beforeAll(() => {
client = TestHelper.createClient();
client.doFetch = jest.fn();
});
test('ping', async () => {
const deviceId = 'device1';
const timeoutInterval = 1000;
const groupLabel = 'DeepLink';
const expectedUrl = `${client.urlVersion}/system/ping`;
const expectedOptions = {method: 'get', timeoutInterval, groupLabel};
await client.ping(deviceId, timeoutInterval, groupLabel);
expect(client.doFetch).toHaveBeenCalledWith(expect.stringContaining(expectedUrl), expectedOptions, false);
});
test('logClientError', async () => {
client.enableLogging = true;
const message = 'debug message';
const level = 'DEBUG';
const expectedUrl = `${client.urlVersion}/logs`;
const expectedOptions = {method: 'post', body: {message, level}};
await client.logClientError(message, level);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
// Test with default level
await client.logClientError(message);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, {method: 'post', body: {message, level: 'ERROR'}});
});
test('logClientError should throw error if logging is disabled', async () => {
client.enableLogging = false;
const message = 'error message';
const level = 'ERROR';
const expectedUrl = `${client.urlVersion}/logs`;
await expect(client.logClientError(message, level)).rejects.toThrow(new ClientError(client.apiClient.baseUrl, {
message: 'Logging disabled.',
url: expectedUrl,
}));
});
test('getClientConfigOld', async () => {
const groupLabel = 'Notification';
const expectedUrl = `${client.urlVersion}/config/client?format=old`;
const expectedOptions = {method: 'get', groupLabel};
await client.getClientConfigOld(groupLabel);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
});
test('getClientLicenseOld', async () => {
const groupLabel = 'Notification';
const expectedUrl = `${client.urlVersion}/license/client?format=old`;
const expectedOptions = {method: 'get', groupLabel};
await client.getClientLicenseOld(groupLabel);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
});
test('getLicenseLoadMetric', async () => {
const expectedUrl = `${client.urlVersion}/license/load_metric`;
const expectedOptions = {method: 'get'};
await client.getLicenseLoadMetric();
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
});
test('getTimezones', async () => {
const expectedUrl = client.getTimezonesRoute();
const expectedOptions = {method: 'get'};
await client.getTimezones();
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
});
test('getGlobalDataRetentionPolicy', async () => {
const groupLabel = 'Notification';
const expectedUrl = `${client.getGlobalDataRetentionRoute()}/policy`;
const expectedOptions = {method: 'get', groupLabel};
await client.getGlobalDataRetentionPolicy(groupLabel);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
});
test('getTeamDataRetentionPolicies', async () => {
const userId = 'user1';
const page = 1;
const perPage = 10;
const groupLabel = 'Notification';
const expectedUrl = `${client.getGranularDataRetentionRoute(userId)}/team_policies${buildQueryString({page, per_page: perPage})}`;
const expectedOptions = {method: 'get', groupLabel};
await client.getTeamDataRetentionPolicies(userId, page, perPage, groupLabel);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
// Test with default values
await client.getTeamDataRetentionPolicies(userId);
expect(client.doFetch).toHaveBeenCalledWith(`${client.getGranularDataRetentionRoute(userId)}/team_policies${buildQueryString({page: 0, per_page: PER_PAGE_DEFAULT})}`, {method: 'get', groupLabel: undefined});
});
test('getChannelDataRetentionPolicies', async () => {
const userId = 'user1';
const page = 1;
const perPage = 10;
const groupLabel = 'Notification';
const expectedUrl = `${client.getGranularDataRetentionRoute(userId)}/channel_policies${buildQueryString({page, per_page: perPage})}`;
const expectedOptions = {method: 'get', groupLabel};
await client.getChannelDataRetentionPolicies(userId, page, perPage, groupLabel);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
// Test with default values
await client.getChannelDataRetentionPolicies(userId);
expect(client.doFetch).toHaveBeenCalledWith(`${client.getGranularDataRetentionRoute(userId)}/channel_policies${buildQueryString({page: 0, per_page: PER_PAGE_DEFAULT})}`, {method: 'get', groupLabel: undefined});
});
test('getRolesByNames', async () => {
const rolesNames = ['role1', 'role2'];
const groupLabel = 'Notification';
const expectedUrl = `${client.getRolesRoute()}/names`;
const expectedOptions = {method: 'post', body: rolesNames, groupLabel};
await client.getRolesByNames(rolesNames, groupLabel);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
});
test('getRedirectLocation', async () => {
const urlParam = 'http://example.com';
const expectedUrl = `${client.getRedirectLocationRoute()}${buildQueryString({url: urlParam})}`;
const expectedOptions = {method: 'get'};
// Test with empty url
await client.getRedirectLocation('');
expect(client.doFetch).not.toHaveBeenCalled();
// Test with non-empty url
await client.getRedirectLocation(urlParam);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
});
test('sendPerformanceReport', async () => {
const report = {start: 0, end: 1} as PerformanceReport;
const expectedUrl = client.getPerformanceRoute();
const expectedOptions = {method: 'post', body: report};
await client.sendPerformanceReport(report);
expect(client.doFetch).toHaveBeenCalledWith(expectedUrl, expectedOptions);
});
});