mirror of
https://github.com/mattermost/mattermost.git
synced 2026-02-03 20:40:00 -05:00
MM-66972 Upgrade to node 24 and main dependencies with babel, webpack and jest (#34760)
Some checks are pending
API / build (push) Waiting to run
Server CI / Compute Go Version (push) Waiting to run
Server CI / Check mocks (push) Blocked by required conditions
Server CI / Check go mod tidy (push) Blocked by required conditions
Server CI / check-style (push) Blocked by required conditions
Server CI / Check serialization methods for hot structs (push) Blocked by required conditions
Server CI / Vet API (push) Blocked by required conditions
Server CI / Check migration files (push) Blocked by required conditions
Server CI / Generate email templates (push) Blocked by required conditions
Server CI / Check store layers (push) Blocked by required conditions
Server CI / Check mmctl docs (push) Blocked by required conditions
Server CI / Postgres with binary parameters (push) Blocked by required conditions
Server CI / Postgres (push) Blocked by required conditions
Server CI / Postgres (FIPS) (push) Blocked by required conditions
Server CI / Generate Test Coverage (push) Blocked by required conditions
Server CI / Run mmctl tests (push) Blocked by required conditions
Server CI / Run mmctl tests (FIPS) (push) Blocked by required conditions
Server CI / Build mattermost server app (push) Blocked by required conditions
Web App CI / check-lint (push) Waiting to run
Web App CI / check-i18n (push) Blocked by required conditions
Web App CI / check-types (push) Blocked by required conditions
Web App CI / test (platform) (push) Blocked by required conditions
Web App CI / test (mattermost-redux) (push) Blocked by required conditions
Web App CI / test (channels shard 1/4) (push) Blocked by required conditions
Web App CI / test (channels shard 2/4) (push) Blocked by required conditions
Web App CI / test (channels shard 3/4) (push) Blocked by required conditions
Web App CI / test (channels shard 4/4) (push) Blocked by required conditions
Web App CI / upload-coverage (push) Blocked by required conditions
Web App CI / build (push) Blocked by required conditions
Some checks are pending
API / build (push) Waiting to run
Server CI / Compute Go Version (push) Waiting to run
Server CI / Check mocks (push) Blocked by required conditions
Server CI / Check go mod tidy (push) Blocked by required conditions
Server CI / check-style (push) Blocked by required conditions
Server CI / Check serialization methods for hot structs (push) Blocked by required conditions
Server CI / Vet API (push) Blocked by required conditions
Server CI / Check migration files (push) Blocked by required conditions
Server CI / Generate email templates (push) Blocked by required conditions
Server CI / Check store layers (push) Blocked by required conditions
Server CI / Check mmctl docs (push) Blocked by required conditions
Server CI / Postgres with binary parameters (push) Blocked by required conditions
Server CI / Postgres (push) Blocked by required conditions
Server CI / Postgres (FIPS) (push) Blocked by required conditions
Server CI / Generate Test Coverage (push) Blocked by required conditions
Server CI / Run mmctl tests (push) Blocked by required conditions
Server CI / Run mmctl tests (FIPS) (push) Blocked by required conditions
Server CI / Build mattermost server app (push) Blocked by required conditions
Web App CI / check-lint (push) Waiting to run
Web App CI / check-i18n (push) Blocked by required conditions
Web App CI / check-types (push) Blocked by required conditions
Web App CI / test (platform) (push) Blocked by required conditions
Web App CI / test (mattermost-redux) (push) Blocked by required conditions
Web App CI / test (channels shard 1/4) (push) Blocked by required conditions
Web App CI / test (channels shard 2/4) (push) Blocked by required conditions
Web App CI / test (channels shard 3/4) (push) Blocked by required conditions
Web App CI / test (channels shard 4/4) (push) Blocked by required conditions
Web App CI / upload-coverage (push) Blocked by required conditions
Web App CI / build (push) Blocked by required conditions
* chore: upgrade to node 24 and dependencies mainly with babel, webpack and jest * fix components tests, make trial modal passed on all node 20-24 * fix cache for platform packages * updated test --------- Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
parent
92339d03ab
commit
dab04576a1
53 changed files with 5777 additions and 10651 deletions
3
.github/actions/webapp-setup/action.yml
vendored
3
.github/actions/webapp-setup/action.yml
vendored
|
|
@ -15,6 +15,9 @@ runs:
|
|||
path: |
|
||||
webapp/node_modules
|
||||
webapp/channels/node_modules
|
||||
webapp/platform/client/node_modules
|
||||
webapp/platform/components/node_modules
|
||||
webapp/platform/types/node_modules
|
||||
key: node-modules-${{ runner.os }}-${{ hashFiles('webapp/package-lock.json') }}
|
||||
- name: ci/cache-platform-builds
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
|
|
|
|||
2
.github/workflows/api.yml
vendored
2
.github/workflows/api.yml
vendored
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
cache: "npm"
|
||||
|
|
|
|||
10
.github/workflows/e2e-tests-ci-template.yml
vendored
10
.github/workflows/e2e-tests-ci-template.yml
vendored
|
|
@ -133,7 +133,7 @@ jobs:
|
|||
fetch-depth: 0
|
||||
- name: ci/setup-node
|
||||
if: "${{ inputs.run_preflight_checks }}"
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
id: setup_node
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
|
@ -164,7 +164,7 @@ jobs:
|
|||
fetch-depth: 0
|
||||
- name: ci/setup-node
|
||||
if: "${{ inputs.run_preflight_checks }}"
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
id: setup_node
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
|
@ -246,7 +246,7 @@ jobs:
|
|||
ref: ${{ inputs.commit_sha }}
|
||||
fetch-depth: 0
|
||||
- name: ci/setup-node
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
id: setup_node
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
|
@ -333,7 +333,7 @@ jobs:
|
|||
ln -sfn /usr/local/opt/docker-compose/bin/docker-compose ~/.docker/cli-plugins/docker-compose
|
||||
sudo ln -sf $HOME/.colima/default/docker.sock /var/run/docker.sock
|
||||
- name: ci/setup-node
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
id: setup_node
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
|
@ -412,7 +412,7 @@ jobs:
|
|||
e2e-tests/${{ inputs.TEST }}/results/
|
||||
- name: ci/setup-node
|
||||
if: "${{ inputs.enable_reporting }}"
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
id: setup_node
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
|
|
|||
6
.github/workflows/server-ci.yml
vendored
6
.github/workflows/server-ci.yml
vendored
|
|
@ -282,6 +282,12 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout mattermost project
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: ci/setup-node
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
cache: "npm"
|
||||
cache-dependency-path: "webapp/package-lock.json"
|
||||
- name: Run setup-go-work
|
||||
run: make setup-go-work
|
||||
- name: Build
|
||||
|
|
|
|||
2
.nvmrc
2
.nvmrc
|
|
@ -1 +1 @@
|
|||
20.11
|
||||
24.11
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ $(if mme2e_is_token_in_list "webhook-interactions" "$ENABLED_DOCKER_SERVICES"; t
|
|||
# shellcheck disable=SC2016
|
||||
echo '
|
||||
webhook-interactions:
|
||||
image: mattermostdevelopment/mirrored-node:${NODE_VERSION_REQUIRED}
|
||||
image: node:${NODE_VERSION_REQUIRED}
|
||||
command: sh -c "npm install --global --legacy-peer-deps && exec node webhook_serve.js"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-s", "-o/dev/null", "127.0.0.1:3000"]
|
||||
|
|
@ -275,11 +275,21 @@ $(if mme2e_is_token_in_list "webhook-interactions" "$ENABLED_DOCKER_SERVICES"; t
|
|||
fi)
|
||||
|
||||
$(if mme2e_is_token_in_list "playwright" "$ENABLED_DOCKER_SERVICES"; then
|
||||
# shellcheck disable=SC2016
|
||||
echo '
|
||||
playwright:
|
||||
image: mcr.microsoft.com/playwright:v1.57.0-noble
|
||||
entrypoint: ["/bin/bash", "-c"]
|
||||
command: ["until [ -f /var/run/mm_terminate ]; do sleep 5; done"]
|
||||
command:
|
||||
- |
|
||||
# Install Node.js based on .nvmrc
|
||||
NODE_VERSION=$$(cat /mattermost/.nvmrc)
|
||||
echo "Installing Node.js $${NODE_VERSION}..."
|
||||
curl -fsSL https://deb.nodesource.com/setup_$${NODE_VERSION%%.*}.x | bash -
|
||||
apt-get install -y nodejs
|
||||
echo "Node.js version: $$(node --version)"
|
||||
# Wait for termination signal
|
||||
until [ -f /var/run/mm_terminate ]; do sleep 5; done
|
||||
env_file:
|
||||
- "./.env.playwright"
|
||||
environment:
|
||||
|
|
|
|||
6
e2e-tests/playwright/package-lock.json
generated
6
e2e-tests/playwright/package-lock.json
generated
|
|
@ -5981,9 +5981,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/systeminformation": {
|
||||
"version": "5.30.1",
|
||||
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.1.tgz",
|
||||
"integrity": "sha512-5zK8Sqqn71b0AoYKnj8nurrugOVogo4hBxAeQR9N0lbC5V+Fkw1hRBRWLaKxBmuvX8v4xH3cxifOJjlhQQW1lQ==",
|
||||
"version": "5.30.2",
|
||||
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.2.tgz",
|
||||
"integrity": "sha512-Rrt5oFTWluUVuPlbtn3o9ja+nvjdF3Um4DG0KxqfYvpzcx7Q9plZBTjJiJy9mAouua4+OI7IUGBaG9Zyt9NgxA==",
|
||||
"license": "MIT",
|
||||
"os": [
|
||||
"darwin",
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
save-exact=true
|
||||
engine-strict=true
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ jobs:
|
|||
- name: Check out web app
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
with:
|
||||
node-version: 16.10.0
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Download and install Cypress
|
||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
||||
|
|
|
|||
|
|
@ -149,8 +149,8 @@
|
|||
"imagemin-mozjpeg": "9.0.0",
|
||||
"jest": "30.1.3",
|
||||
"jest-canvas-mock": "2.5.0",
|
||||
"jest-cli": "29.7.0",
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"jest-cli": "30.1.3",
|
||||
"jest-environment-jsdom": "30.1.0",
|
||||
"jest-junit": "16.0.0",
|
||||
"jest-watch-typeahead": "3.0.1",
|
||||
"nock": "13.2.8",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,16 @@
|
|||
|
||||
import {jest} from '@jest/globals';
|
||||
|
||||
const monacoMock = {
|
||||
const monacoMock: {
|
||||
editor: {
|
||||
create: jest.Mock;
|
||||
defineTheme: jest.Mock;
|
||||
setTheme: jest.Mock;
|
||||
};
|
||||
languages: {
|
||||
registerCompletionItemProvider: jest.Mock;
|
||||
};
|
||||
} = {
|
||||
editor: {
|
||||
create: jest.fn(),
|
||||
defineTheme: jest.fn(),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import type {ReactNode} from 'react';
|
||||
import {FormattedMessage, useIntl} from 'react-intl';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
|
||||
|
|
@ -108,7 +107,7 @@ const TrialBanner = ({
|
|||
case TrialLoadStatus.Failed:
|
||||
return formatMessage({id: 'start_trial.modal.failed', defaultMessage: 'Failed'});
|
||||
case TrialLoadStatus.Embargoed:
|
||||
return formatMessage<ReactNode>(
|
||||
return formatMessage(
|
||||
{
|
||||
id: 'admin.license.trial-request.embargoed',
|
||||
defaultMessage: 'We were unable to process the request due to limitations for embargoed countries. <link>Learn more in our documentation</link>, or reach out to legal@mattermost.com for questions around export limitations.',
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_descrip
|
|||
<span>
|
||||
Inherited from
|
||||
<a
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
>
|
||||
All Members
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@import 'utils/mixins';
|
||||
@use 'utils/mixins';
|
||||
|
||||
.channel-invite {
|
||||
&__wrapper {
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ exports[`components/channel_invite_modal/team_warning_banner should match snapsh
|
|||
className="AlertBanner__footerMessage"
|
||||
>
|
||||
<FormattedList
|
||||
key=".0"
|
||||
key="0/.0"
|
||||
value={
|
||||
Array [
|
||||
<Memo(Connect(Component))
|
||||
|
|
@ -299,7 +299,7 @@ exports[`components/channel_invite_modal/team_warning_banner should match snapsh
|
|||
>
|
||||
You can add
|
||||
<FormattedList
|
||||
key=".1"
|
||||
key="1/.1"
|
||||
value={
|
||||
Array [
|
||||
<Memo(Connect(Component))
|
||||
|
|
@ -343,7 +343,7 @@ exports[`components/channel_invite_modal/team_warning_banner should match snapsh
|
|||
</FormattedList>
|
||||
to this channel once they are members of the
|
||||
<strong
|
||||
key=".3"
|
||||
key="3/.3"
|
||||
>
|
||||
Team Name Display
|
||||
</strong>
|
||||
|
|
@ -549,7 +549,7 @@ exports[`components/channel_invite_modal/team_warning_banner should match snapsh
|
|||
className="AlertBanner__footerMessage"
|
||||
>
|
||||
<Connect(Component)
|
||||
key=".$user-0"
|
||||
key="0/.$user-0"
|
||||
mentionName="user-0"
|
||||
>
|
||||
<Memo(AtMention)
|
||||
|
|
@ -563,7 +563,7 @@ exports[`components/channel_invite_modal/team_warning_banner should match snapsh
|
|||
</Connect(Component)>
|
||||
and
|
||||
<WithTooltip
|
||||
key=".2"
|
||||
key="2/.2"
|
||||
title="@user-1, @user-2, @user-3, @user-4, @user-5, @user-6, @user-7, @user-8, @user-9, @user-10"
|
||||
>
|
||||
<span
|
||||
|
|
@ -799,7 +799,7 @@ exports[`components/channel_invite_modal/team_warning_banner should match snapsh
|
|||
>
|
||||
You can add
|
||||
<Connect(Component)
|
||||
key=".$user-0"
|
||||
key="1/.$user-0"
|
||||
mentionName="user-0"
|
||||
>
|
||||
<Memo(AtMention)
|
||||
|
|
@ -813,7 +813,7 @@ exports[`components/channel_invite_modal/team_warning_banner should match snapsh
|
|||
</Connect(Component)>
|
||||
and
|
||||
<WithTooltip
|
||||
key=".3"
|
||||
key="3/.3"
|
||||
title="@user-1, @user-2, @user-3, @user-4, @user-5, @user-6, @user-7, @user-8, @user-9, @user-10"
|
||||
>
|
||||
<span
|
||||
|
|
@ -843,7 +843,7 @@ exports[`components/channel_invite_modal/team_warning_banner should match snapsh
|
|||
</WithTooltip>
|
||||
to this channel once they are members of the
|
||||
<strong
|
||||
key=".5"
|
||||
key="5/.5"
|
||||
>
|
||||
Team Name Display
|
||||
</strong>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
@import "utils/_animations";
|
||||
@use "utils/animations";
|
||||
|
||||
.ChannelSettingsModal__configurationTab {
|
||||
display: flex;
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
}
|
||||
|
||||
.channel_banner_section_body {
|
||||
@include fade-in;
|
||||
@include animations.fade-in;
|
||||
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,21 @@ import {fireEvent, render} from 'tests/react_testing_utils';
|
|||
|
||||
import Scrollbars from './scrollbars';
|
||||
|
||||
const originalGetComputedStyle = window.getComputedStyle;
|
||||
beforeAll(() => {
|
||||
window.getComputedStyle = (elt: Element, pseudoElt?: string | null) => {
|
||||
if (pseudoElt) {
|
||||
// Return an empty CSSStyleDeclaration-like object for pseudo elements
|
||||
return {} as CSSStyleDeclaration;
|
||||
}
|
||||
return originalGetComputedStyle(elt);
|
||||
};
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
window.getComputedStyle = originalGetComputedStyle;
|
||||
});
|
||||
|
||||
describe('Scrollbars', () => {
|
||||
test('should attach scroll handler to the correct element', () => {
|
||||
const onScroll = jest.fn();
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ exports[`components/emoji_picker/EmojiPicker should match snapshot 1`] = `
|
|||
role="grid"
|
||||
>
|
||||
<div
|
||||
style="position: relative; height: 100px; width: 100px; overflow: auto; will-change: transform; direction: ltr;"
|
||||
style="position: relative; height: 100px; width: 100px; overflow: auto; -webkit-overflow-scrolling: touch; will-change: transform; direction: ltr;"
|
||||
>
|
||||
<div
|
||||
style="height: 7740px; width: 100%;"
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ exports[`FileAttachment should match snapshot, after change from file to image 1
|
|||
>
|
||||
<div
|
||||
class="post-image normal"
|
||||
style="background-image: url(thumbnail_id); background-size: cover;"
|
||||
style="background-image: url(\\"thumbnail_id\\"); background-size: cover;"
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ exports[`components/integrations/AbstractOutgoingOAuthConnection should match sn
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -478,7 +478,7 @@ exports[`components/integrations/AbstractOutgoingOAuthConnection should match sn
|
|||
Get help with
|
||||
<a
|
||||
href="https://mattermost.com/pl/outgoing-oauth-connections"
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
>
|
||||
configuring outgoing OAuth connections
|
||||
</a>
|
||||
|
|
@ -590,7 +590,7 @@ exports[`components/integrations/AbstractOutgoingOAuthConnection should match sn
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -1073,7 +1073,7 @@ exports[`components/integrations/AbstractOutgoingOAuthConnection should match sn
|
|||
Get help with
|
||||
<a
|
||||
href="https://mattermost.com/pl/outgoing-oauth-connections"
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
>
|
||||
configuring outgoing OAuth connections
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ exports[`components/integrations/AddOutgoingOAuthConnection should match snapsho
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -467,7 +467,7 @@ exports[`components/integrations/AddOutgoingOAuthConnection should match snapsho
|
|||
Get help with
|
||||
<a
|
||||
href="https://mattermost.com/pl/outgoing-oauth-connections"
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
>
|
||||
configuring outgoing OAuth connections
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ exports[`components/integrations/EditOutgoingOAuthConnection should match snapsh
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -643,7 +643,7 @@ https://myothersite.com/api/v2"
|
|||
Get help with
|
||||
<a
|
||||
href="https://mattermost.com/pl/outgoing-oauth-connections"
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
>
|
||||
configuring outgoing OAuth connections
|
||||
</a>
|
||||
|
|
@ -756,7 +756,7 @@ exports[`components/integrations/EditOutgoingOAuthConnection should match snapsh
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -1385,7 +1385,7 @@ https://myothersite.com/api/v2"
|
|||
Get help with
|
||||
<a
|
||||
href="https://mattermost.com/pl/outgoing-oauth-connections"
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
>
|
||||
configuring outgoing OAuth connections
|
||||
</a>
|
||||
|
|
@ -1498,7 +1498,7 @@ exports[`components/integrations/EditOutgoingOAuthConnection should match snapsh
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -2126,7 +2126,7 @@ https://myothersite.com/api/v2"
|
|||
Get help with
|
||||
<a
|
||||
href="https://mattermost.com/pl/outgoing-oauth-connections"
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
>
|
||||
configuring outgoing OAuth connections
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ exports[`components/integrations/InstalledOutgoingOAuthConnections should match
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -190,7 +190,7 @@ exports[`components/integrations/InstalledOutgoingOAuthConnections should match
|
|||
Create
|
||||
<ForwardRef
|
||||
href="https://mattermost.com/pl/setup-oauth-2.0"
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
location="installed_outgoing_oauth_connections"
|
||||
>
|
||||
<a
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ exports[`components/integrations/outgoing_oauth_connections/OAuthConnectionAudie
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -109,7 +109,7 @@ exports[`components/integrations/outgoing_oauth_connections/OAuthConnectionAudie
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -203,7 +203,7 @@ exports[`components/integrations/outgoing_oauth_connections/OAuthConnectionAudie
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -297,7 +297,7 @@ exports[`components/integrations/outgoing_oauth_connections/OAuthConnectionAudie
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
@ -407,7 +407,7 @@ exports[`components/integrations/outgoing_oauth_connections/OAuthConnectionAudie
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -318,10 +318,8 @@ describe('components/login/Login', () => {
|
|||
|
||||
const button = screen.getByRole('link', {name: 'Gitlab Icon GitLab 2'});
|
||||
|
||||
expect(button.style).toMatchObject({
|
||||
color: 'rgb(0, 255, 0)',
|
||||
borderColor: '#00ff00',
|
||||
});
|
||||
expect(button.style.color).toBe('rgb(0, 255, 0)');
|
||||
expect(button.style.borderColor).toBe('rgb(0, 255, 0)');
|
||||
});
|
||||
|
||||
it('should focus username field when there is an error', async () => {
|
||||
|
|
@ -374,10 +372,8 @@ describe('components/login/Login', () => {
|
|||
|
||||
const button = screen.getByRole('link', {name: 'OpenID Icon OpenID 2'});
|
||||
|
||||
expect(button.style).toMatchObject({
|
||||
color: 'rgb(0, 255, 0)',
|
||||
borderColor: '#00ff00',
|
||||
});
|
||||
expect(button.style.color).toBe('rgb(0, 255, 0)');
|
||||
expect(button.style.borderColor).toBe('rgb(0, 255, 0)');
|
||||
});
|
||||
|
||||
it('should redirect on login', async () => {
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ exports[`components/marketplace/ doesn't show web marketplace banner in FeatureF
|
|||
<span>
|
||||
Error connecting to the marketplace server. Please check your settings in the
|
||||
<Link
|
||||
key=".1"
|
||||
key="1/.1"
|
||||
to="/admin_console/plugins/plugin_management"
|
||||
>
|
||||
System Console
|
||||
|
|
@ -204,7 +204,7 @@ exports[`components/marketplace/ hides search, shows web marketplace banner in F
|
|||
<span>
|
||||
Error connecting to the marketplace server. Please check your settings in the
|
||||
<Link
|
||||
key=".1"
|
||||
key="1/.1"
|
||||
to="/admin_console/plugins/plugin_management"
|
||||
>
|
||||
System Console
|
||||
|
|
@ -501,7 +501,7 @@ exports[`components/marketplace/ should render with error banner 1`] = `
|
|||
<span>
|
||||
Error connecting to the marketplace server. Please check your settings in the
|
||||
<Link
|
||||
key=".1"
|
||||
key="1/.1"
|
||||
to="/admin_console/plugins/plugin_management"
|
||||
>
|
||||
System Console
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ exports[`InviteMembers component should match snapshot when it is cloud 1`] = `
|
|||
id="react-select-2-input"
|
||||
role="combobox"
|
||||
spellcheck="false"
|
||||
style="opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
style="color: inherit; background: 0px; opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
tabindex="0"
|
||||
type="text"
|
||||
value=""
|
||||
|
|
|
|||
|
|
@ -39,8 +39,10 @@ describe('SelectPropertyRenderer', () => {
|
|||
const element = screen.getByTestId('select-property');
|
||||
expect(element).toBeInTheDocument();
|
||||
expect(element).toHaveTextContent('option1');
|
||||
|
||||
// Component applies inline styles via style prop
|
||||
expect(element).toHaveStyle({
|
||||
backgroundColor: 'rgba(var(--button-bg-rgb), 0.08)',
|
||||
backgroundColor: 'var(--sidebar-text-active-border)',
|
||||
color: '#FFF',
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {checkIsFirstAdmin, getCurrentUser, isCurrentUserSystemAdmin} from 'matte
|
|||
|
||||
import {redirectUserToDefaultTeam, emitUserLoggedOutEvent} from 'actions/global_actions';
|
||||
|
||||
import {reloadPage} from 'utils/browser_utils';
|
||||
import {ActionTypes, StoragePrefixes} from 'utils/constants';
|
||||
import {doesCookieContainsMMUserId} from 'utils/utils';
|
||||
|
||||
|
|
@ -165,7 +166,7 @@ export function handleLoginLogoutSignal(e: StorageEvent): ThunkActionFunc<void>
|
|||
|
||||
// detected login from a different tab
|
||||
function reloadOnFocus() {
|
||||
location.reload();
|
||||
reloadPage();
|
||||
}
|
||||
window.addEventListener('focus', reloadOnFocus);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import * as GlobalActions from 'actions/global_actions';
|
|||
|
||||
import testConfigureStore from 'packages/mattermost-redux/test/test_store';
|
||||
import {renderWithContext, waitFor} from 'tests/react_testing_utils';
|
||||
import * as BrowserUtils from 'utils/browser_utils';
|
||||
import {StoragePrefixes} from 'utils/constants';
|
||||
|
||||
import {handleLoginLogoutSignal, redirectToOnboardingOrDefaultTeam} from './actions';
|
||||
|
|
@ -26,6 +27,10 @@ jest.mock('utils/utils', () => ({
|
|||
applyTheme: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('utils/browser_utils', () => ({
|
||||
reloadPage: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('actions/global_actions', () => ({
|
||||
redirectUserToDefaultTeam: jest.fn(),
|
||||
}));
|
||||
|
|
@ -93,11 +98,9 @@ describe('components/Root', () => {
|
|||
};
|
||||
|
||||
let originalMatchMedia: (query: string) => MediaQueryList;
|
||||
let originalReload: () => void;
|
||||
|
||||
beforeAll(() => {
|
||||
originalMatchMedia = window.matchMedia;
|
||||
originalReload = window.location.reload;
|
||||
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
writable: true,
|
||||
|
|
@ -106,22 +109,17 @@ describe('components/Root', () => {
|
|||
media: query,
|
||||
})),
|
||||
});
|
||||
|
||||
Object.defineProperty(window.location, 'reload', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
window.location.reload = jest.fn();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
|
||||
// Reset the reloadPage mock after each test
|
||||
(BrowserUtils.reloadPage as jest.Mock).mockClear();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
window.matchMedia = originalMatchMedia;
|
||||
window.location.reload = originalReload;
|
||||
});
|
||||
|
||||
test('should load config and license on mount and redirect to sign-up page', async () => {
|
||||
|
|
@ -228,7 +226,7 @@ describe('components/Root', () => {
|
|||
window.dispatchEvent(new Event('focus'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(window.location.reload).toHaveBeenCalledTimes(1);
|
||||
expect(BrowserUtils.reloadPage).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ exports[`components/signup/Signup should match snapshot for all signup options e
|
|||
Sign up at
|
||||
<ForwardRef
|
||||
href="https://mattermost.com/security-updates/"
|
||||
key=".1"
|
||||
key="1/.1"
|
||||
location="signup"
|
||||
>
|
||||
https://mattermost.com/security-updates/
|
||||
|
|
@ -336,7 +336,7 @@ exports[`components/signup/Signup should match snapshot for all signup options e
|
|||
Sign up at
|
||||
<ForwardRef
|
||||
href="https://mattermost.com/security-updates/"
|
||||
key=".1"
|
||||
key="1/.1"
|
||||
location="signup"
|
||||
>
|
||||
https://mattermost.com/security-updates/
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ Object {
|
|||
id="react-select-2-input"
|
||||
role="combobox"
|
||||
spellcheck="false"
|
||||
style="opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
style="color: inherit; background: 0px; opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
tabindex="0"
|
||||
type="text"
|
||||
value=""
|
||||
|
|
@ -312,7 +312,7 @@ Object {
|
|||
id="react-select-3-input"
|
||||
role="combobox"
|
||||
spellcheck="false"
|
||||
style="opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
style="color: inherit; background: 0px; opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
tabindex="0"
|
||||
type="text"
|
||||
value=""
|
||||
|
|
|
|||
|
|
@ -507,7 +507,7 @@ exports[`components/threading/channel_threads/thread_footer should report total
|
|||
<span>
|
||||
Last reply
|
||||
<Memo(SemanticTime)
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
value={2019-04-01T23:31:44.000Z}
|
||||
>
|
||||
<time
|
||||
|
|
@ -1021,7 +1021,7 @@ exports[`components/threading/channel_threads/thread_footer should show unread i
|
|||
<span>
|
||||
Last reply
|
||||
<Memo(SemanticTime)
|
||||
key=".$.1"
|
||||
key="1/.1"
|
||||
value={2019-04-01T23:31:44.000Z}
|
||||
>
|
||||
<time
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
import classNames from 'classnames';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import React, {memo, useCallback, useEffect, useState} from 'react';
|
||||
import type {ReactNode} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {useSelector, useDispatch, shallowEqual} from 'react-redux';
|
||||
import {Link, useRouteMatch} from 'react-router-dom';
|
||||
|
|
@ -204,7 +203,7 @@ const GlobalThreads = () => {
|
|||
id: 'globalThreads.threadPane.unselectedTitle',
|
||||
defaultMessage: '{numUnread, plural, =0 {Looks like you’re all caught up} other {Catch up on your threads}}',
|
||||
}, {numUnread})}
|
||||
subtitle={formatMessage<ReactNode>({
|
||||
subtitle={formatMessage({
|
||||
id: 'globalThreads.threadPane.unreadMessageLink',
|
||||
defaultMessage: 'You have {numUnread, plural, =0 {no unread threads} =1 {<link>{numUnread} thread</link>} other {<link>{numUnread} threads</link>}} {numUnread, plural, =0 {} other {with unread messages}}',
|
||||
}, {
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`components/three_days_left_trial_modal/three_days_left_trial_modal should match snapshot 1`] = `
|
||||
"<ContextProvider value={{...}}>
|
||||
<ThreeDaysLeftTrialModal onExited={[Function: mockConstructor] { _isMockFunction: true, getMockImplementation: [Function (anonymous)], mock: Object [Object: null prototype] { calls: [], contexts: [], instances: [], invocationCallOrder: [], results: [] }, mockClear: [Function (anonymous)], mockReset: [Function (anonymous)], mockRestore: [Function (anonymous)], mockReturnValueOnce: [Function (anonymous)], mockResolvedValueOnce: [Function (anonymous)], mockRejectedValueOnce: [Function (anonymous)], mockReturnValue: [Function (anonymous)], mockResolvedValue: [Function (anonymous)], mockRejectedValue: [Function (anonymous)], mockImplementationOnce: [Function (anonymous)], withImplementation: [Function: bound withImplementation], mockImplementation: [Function (anonymous)], mockReturnThis: [Function (anonymous)], mockName: [Function (anonymous)], getMockName: [Function (anonymous)] }} limitsOverpassed={false} />
|
||||
</ContextProvider>"
|
||||
`;
|
||||
|
||||
exports[`components/three_days_left_trial_modal/three_days_left_trial_modal should match snapshot when limits are overpassed and show the limits panel 1`] = `
|
||||
"<ContextProvider value={{...}}>
|
||||
<ThreeDaysLeftTrialModal onExited={[Function: mockConstructor] { _isMockFunction: true, getMockImplementation: [Function (anonymous)], mock: Object [Object: null prototype] { calls: [], contexts: [], instances: [], invocationCallOrder: [], results: [] }, mockClear: [Function (anonymous)], mockReset: [Function (anonymous)], mockRestore: [Function (anonymous)], mockReturnValueOnce: [Function (anonymous)], mockResolvedValueOnce: [Function (anonymous)], mockRejectedValueOnce: [Function (anonymous)], mockReturnValue: [Function (anonymous)], mockResolvedValue: [Function (anonymous)], mockRejectedValue: [Function (anonymous)], mockImplementationOnce: [Function (anonymous)], withImplementation: [Function: bound withImplementation], mockImplementation: [Function (anonymous)], mockReturnThis: [Function (anonymous)], mockName: [Function (anonymous)], getMockName: [Function (anonymous)] }} limitsOverpassed={true} />
|
||||
</ContextProvider>"
|
||||
`;
|
||||
|
|
@ -1,20 +1,14 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {shallow} from 'enzyme';
|
||||
import React from 'react';
|
||||
import {Provider} from 'react-redux';
|
||||
|
||||
import {GenericModal} from '@mattermost/components';
|
||||
|
||||
import ThreeDaysLeftTrialModal from 'components/three_days_left_trial_modal/three_days_left_trial_modal';
|
||||
|
||||
import TestHelper from 'packages/mattermost-redux/test/test_helper';
|
||||
import {mountWithIntl} from 'tests/helpers/intl-test-helper';
|
||||
import mockStore from 'tests/test_store';
|
||||
import {renderWithContext, screen, userEvent, waitFor} from 'tests/react_testing_utils';
|
||||
|
||||
describe('components/three_days_left_trial_modal/three_days_left_trial_modal', () => {
|
||||
// required state to mount using the provider
|
||||
const user = TestHelper.fakeUserWithId();
|
||||
|
||||
const profiles = {
|
||||
|
|
@ -73,70 +67,90 @@ describe('components/three_days_left_trial_modal/three_days_left_trial_modal', (
|
|||
},
|
||||
};
|
||||
|
||||
const props = {
|
||||
const defaultProps = {
|
||||
onExited: jest.fn(),
|
||||
limitsOverpassed: false,
|
||||
};
|
||||
|
||||
const store = mockStore(state);
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const wrapper = shallow(
|
||||
<Provider store={store}>
|
||||
<ThreeDaysLeftTrialModal {...props}/>
|
||||
</Provider>,
|
||||
);
|
||||
expect(wrapper.debug()).toMatchSnapshot();
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('should match snapshot when limits are overpassed and show the limits panel', () => {
|
||||
const wrapper = shallow(
|
||||
<Provider store={store}>
|
||||
<ThreeDaysLeftTrialModal
|
||||
{...props}
|
||||
limitsOverpassed={true}
|
||||
/>
|
||||
</Provider>,
|
||||
);
|
||||
expect(wrapper.debug()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should show the three days left modal with the three cards', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<Provider store={store}>
|
||||
<ThreeDaysLeftTrialModal {...props}/>
|
||||
</Provider>,
|
||||
test('should render the modal with header, subtitle, feature cards, and view plans button', () => {
|
||||
renderWithContext(
|
||||
<ThreeDaysLeftTrialModal {...defaultProps}/>,
|
||||
state,
|
||||
);
|
||||
|
||||
expect(wrapper.find('ThreeDaysLeftTrialModal ThreeDaysLeftTrialCard')).toHaveLength(3);
|
||||
// Header and subtitle
|
||||
expect(screen.getByText('Your trial ends soon')).toBeInTheDocument();
|
||||
expect(screen.getByText('There is still time to explore what our paid plans can help you accomplish.')).toBeInTheDocument();
|
||||
|
||||
// Three feature cards
|
||||
expect(screen.getByText('Use SSO (with OpenID, SAML, Google, O365)')).toBeInTheDocument();
|
||||
expect(screen.getByText('Synchronize your Active Directory/LDAP groups')).toBeInTheDocument();
|
||||
expect(screen.getByText('Provide controlled access to the System Console')).toBeInTheDocument();
|
||||
|
||||
// View plans button
|
||||
expect(screen.getByRole('button', {name: 'View plan options'})).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should show the workspace limits panel when limits are overpassed', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<Provider store={store}>
|
||||
<ThreeDaysLeftTrialModal
|
||||
{...props}
|
||||
limitsOverpassed={true}
|
||||
/>
|
||||
</Provider>,
|
||||
test('should show limits overpassed content when limitsOverpassed is true', () => {
|
||||
renderWithContext(
|
||||
<ThreeDaysLeftTrialModal
|
||||
{...defaultProps}
|
||||
limitsOverpassed={true}
|
||||
/>,
|
||||
state,
|
||||
);
|
||||
expect(wrapper.find('ThreeDaysLeftTrialModal WorkspaceLimitsPanel')).toHaveLength(1);
|
||||
|
||||
// Different header and subtitle
|
||||
expect(screen.getByText('Upgrade before the trial ends')).toBeInTheDocument();
|
||||
expect(screen.getByText('There are 3 days left on your trial. Upgrade to our Professional or Enterprise plan to avoid exceeding your data limits on the Free plan.')).toBeInTheDocument();
|
||||
|
||||
// Shows limits panel instead of feature cards
|
||||
expect(screen.getByText('Limits')).toBeInTheDocument();
|
||||
expect(screen.queryByText('Use SSO (with OpenID, SAML, Google, O365)')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should call on exited', () => {
|
||||
test('should call onExited when modal is closed', async () => {
|
||||
const mockOnExited = jest.fn();
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
<Provider store={store}>
|
||||
<ThreeDaysLeftTrialModal
|
||||
{...props}
|
||||
onExited={mockOnExited}
|
||||
/>
|
||||
</Provider>,
|
||||
renderWithContext(
|
||||
<ThreeDaysLeftTrialModal
|
||||
{...defaultProps}
|
||||
onExited={mockOnExited}
|
||||
/>,
|
||||
state,
|
||||
);
|
||||
|
||||
wrapper.find(GenericModal).props().onExited?.();
|
||||
const closeButton = screen.getByLabelText('Close');
|
||||
await userEvent.click(closeButton);
|
||||
|
||||
expect(mockOnExited).toHaveBeenCalled();
|
||||
await waitFor(() => {
|
||||
expect(mockOnExited).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
test('should not render when modal is not open', () => {
|
||||
const closedState = {
|
||||
...state,
|
||||
views: {
|
||||
modals: {
|
||||
modalState: {
|
||||
three_days_left_trial_modal: {
|
||||
open: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithContext(
|
||||
<ThreeDaysLeftTrialModal {...defaultProps}/>,
|
||||
closedState,
|
||||
);
|
||||
|
||||
expect(screen.queryByText('Your trial ends soon')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ exports[`UserAccountNameMenuItem should not break if no props are passed 1`] = `
|
|||
<div>
|
||||
<li
|
||||
aria-haspopup="true"
|
||||
class="MuiButtonBase-root-JvZdr dKFJFs MuiButtonBase-root MuiMenuItem-root MuiMenuItem-gutters MuiMenuItem-root-dXqYNm kIRdVO MuiMenuItem-root MuiMenuItem-gutters sc-gswNZR koIPww userAccountMenu_nameMenuItem"
|
||||
class="MuiButtonBase-root-JDVeC cxEgXn MuiButtonBase-root MuiMenuItem-root MuiMenuItem-gutters MuiMenuItem-root-dXjcMb iLWjgG MuiMenuItem-root MuiMenuItem-gutters sc-grYavY jmUrfe userAccountMenu_nameMenuItem"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@import "utils/_mixins";
|
||||
@use "utils/mixins";
|
||||
|
||||
#userAccountMenu {
|
||||
.userAccountMenu_nameMenuItem {
|
||||
|
|
@ -21,14 +21,14 @@
|
|||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
@include textEllipsis;
|
||||
@include mixins.textEllipsis;
|
||||
}
|
||||
|
||||
span.userAccountMenu_nameMenuItem_secondaryLabel {
|
||||
max-width: 150px;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
@include textEllipsis;
|
||||
@include mixins.textEllipsis;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
.label-elements {
|
||||
> span {
|
||||
max-width: 196px;
|
||||
@include textEllipsis;
|
||||
@include mixins.textEllipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ exports[`component/user_group_popover/group_member_list should match snapshot 1`
|
|||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "undefinedundefined",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@import 'utils/mixins';
|
||||
@use 'utils/mixins';
|
||||
|
||||
.AdvancedTextbox {
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -76,7 +76,9 @@ describe('components/Menu', () => {
|
|||
);
|
||||
|
||||
const menu = screen.getByRole('menu');
|
||||
expect(menu).toHaveStyle({maxHeight: '200px', backgroundColor: 'red'});
|
||||
|
||||
expect(menu.style.maxHeight).toBe('200px');
|
||||
expect(menu.style.backgroundColor).toBe('red');
|
||||
});
|
||||
|
||||
test('should apply custom className to menu list', () => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import type {ReactNode} from 'react';
|
||||
import {defineMessage, useIntl} from 'react-intl';
|
||||
|
||||
import type {LimitSummary} from 'components/common/hooks/useGetHighestThresholdCloudLimit';
|
||||
|
|
@ -151,7 +150,7 @@ export default function useWords(highestLimit: LimitSummary | false, isAdminUser
|
|||
id: 'workspace_limits.menu_limit.messages',
|
||||
defaultMessage: 'Total messages',
|
||||
}),
|
||||
description: intl.formatMessage<ReactNode>(
|
||||
description: intl.formatMessage(
|
||||
description,
|
||||
values,
|
||||
),
|
||||
|
|
@ -196,7 +195,7 @@ export default function useWords(highestLimit: LimitSummary | false, isAdminUser
|
|||
id: 'workspace_limits.menu_limit.file_storage',
|
||||
defaultMessage: 'File storage limit',
|
||||
}),
|
||||
description: intl.formatMessage<ReactNode>(
|
||||
description: intl.formatMessage(
|
||||
description,
|
||||
values,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ exports[`TooltipContent have correct structure with title and emoji 1`] = `
|
|||
aria-label=":smile:"
|
||||
class="emoticon"
|
||||
data-emoticon="smile"
|
||||
style="background-image: url(/static/emoji/1f604.png); background-size: contain; height: 16px; width: 16px; max-height: 16px; max-width: 16px; min-height: 16px; min-width: 16px; overflow: hidden;"
|
||||
style="background-image: url(\\"/static/emoji/1f604.png\\"); background-size: contain; height: 16px; width: 16px; max-height: 16px; max-width: 16px; min-height: 16px; min-width: 16px; overflow: hidden;"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
|
|
@ -61,7 +61,7 @@ exports[`TooltipContent have correct structure with title and large emoji 1`] =
|
|||
aria-label=":smile:"
|
||||
class="emoticon"
|
||||
data-emoticon="smile"
|
||||
style="background-image: url(/static/emoji/1f604.png); background-size: contain; height: 48px; width: 48px; max-height: 48px; max-width: 48px; min-height: 48px; min-width: 48px; overflow: hidden;"
|
||||
style="background-image: url(\\"/static/emoji/1f604.png\\"); background-size: contain; height: 48px; width: 48px; max-height: 48px; max-width: 48px; min-height: 48px; min-width: 48px; overflow: hidden;"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
|
|
@ -121,7 +121,7 @@ exports[`TooltipContent have correct structure with title, emoji and hint 1`] =
|
|||
aria-label=":smile:"
|
||||
class="emoticon"
|
||||
data-emoticon="smile"
|
||||
style="background-image: url(/static/emoji/1f604.png); background-size: contain; height: 16px; width: 16px; max-height: 16px; max-width: 16px; min-height: 16px; min-width: 16px; overflow: hidden;"
|
||||
style="background-image: url(\\"/static/emoji/1f604.png\\"); background-size: contain; height: 16px; width: 16px; max-height: 16px; max-width: 16px; min-height: 16px; min-width: 16px; overflow: hidden;"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
|
|
|
|||
|
|
@ -70,18 +70,15 @@ describe('selectors/i18n', () => {
|
|||
});
|
||||
|
||||
describe('locale from query parameter', () => {
|
||||
// Helper function to mock window.location.search with locale query parameter
|
||||
const setWindowLocaleQueryParameter = (locale) => {
|
||||
window.location.search = `?locale=${locale}`;
|
||||
};
|
||||
|
||||
// Helper function to reset window.location.search
|
||||
const resetWindowLocationSearch = () => {
|
||||
window.location.search = '';
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('locale', locale);
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
resetWindowLocationSearch();
|
||||
// Reset the URL
|
||||
window.history.replaceState({}, '', 'http://localhost:8065/');
|
||||
});
|
||||
|
||||
test('returns locale from query parameter if provided and not logged in', () => {
|
||||
|
|
|
|||
|
|
@ -26,15 +26,6 @@ module.exports = async () => {
|
|||
configure({adapter: new Adapter()});
|
||||
|
||||
global.window = Object.create(window);
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
href: 'http://localhost:8065',
|
||||
origin: 'http://localhost:8065',
|
||||
port: '8065',
|
||||
protocol: 'http:',
|
||||
search: '',
|
||||
},
|
||||
});
|
||||
|
||||
// The current version of jsdom that's used by jest-environment-jsdom 29 doesn't support fetch, so we have to
|
||||
// use node-fetch despite some mismatched parameters.
|
||||
|
|
@ -116,6 +107,12 @@ afterEach(() => {
|
|||
continue;
|
||||
}
|
||||
|
||||
// jsdom doesn't implement navigation, but this is expected behavior in tests
|
||||
const errorStr = call[0] instanceof Error ? call[0].message : String(call[0]);
|
||||
if (errorStr.includes('Not implemented:')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
errors.push(call);
|
||||
}
|
||||
|
||||
|
|
|
|||
9
webapp/channels/src/utils/browser_utils.ts
Normal file
9
webapp/channels/src/utils/browser_utils.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
/**
|
||||
* Wrapper for window.location.reload to make it mockable in tests.
|
||||
*/
|
||||
export function reloadPage(): void {
|
||||
window.location.reload();
|
||||
}
|
||||
15991
webapp/package-lock.json
generated
15991
webapp/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -2,8 +2,8 @@
|
|||
"name": "@mattermost/webapp",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=18.10.0",
|
||||
"npm": ">=9.0.0 <12.0.0"
|
||||
"node": "^20 || ^22 || ^24",
|
||||
"npm": "^10 || ^11"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "patch-package && npm run build --workspace=platform/types --workspace=platform/client --workspace=platform/components",
|
||||
|
|
@ -23,15 +23,16 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@mattermost/compass-icons": "0.1.52",
|
||||
"react-intl": "7.1.14",
|
||||
"typescript": "5.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.22.0",
|
||||
"@babel/preset-env": "7.21.5",
|
||||
"@babel/preset-react": "7.18.6",
|
||||
"@babel/preset-typescript": "7.21.5",
|
||||
"@babel/core": "7.28.5",
|
||||
"@babel/preset-env": "7.28.5",
|
||||
"@babel/preset-react": "7.28.5",
|
||||
"@babel/preset-typescript": "7.28.5",
|
||||
"@formatjs/cli": "6.7.4",
|
||||
"@types/node": "20.19.18",
|
||||
"@types/node": "24.10.4",
|
||||
"babel-loader": "9.1.2",
|
||||
"babel-plugin-formatjs": "10.5.1",
|
||||
"babel-plugin-typescript-to-proptypes": "2.1.0",
|
||||
|
|
@ -52,9 +53,9 @@
|
|||
"strip-ansi": "7.1.0",
|
||||
"style-loader": "4.0.0",
|
||||
"typescript-eslint-language-service": "5.0.5",
|
||||
"webpack": "5.95.0",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-dev-server": "5.1.0"
|
||||
"webpack": "5.103.0",
|
||||
"webpack-cli": "6.0.1",
|
||||
"webpack-dev-server": "5.2.2"
|
||||
},
|
||||
"overrides": {
|
||||
"@deanwhillier/jest-matchmedia-mock": {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"target": "es2022",
|
||||
"declaration": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"target": "es2022",
|
||||
"declaration": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-transform-runtime": "^7.17.0",
|
||||
"jest-environment-jsdom": "30.1.0",
|
||||
"@rollup/plugin-babel": "^5.3.1",
|
||||
"@rollup/plugin-commonjs": "^21.0.2",
|
||||
"@rollup/plugin-node-resolve": "^13.1.3",
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"target": "es6",
|
||||
"declaration": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
|
|
|
|||
Loading…
Reference in a new issue