Merge branch 'master' into fix-boards-webapp-unit-tests
Этот коммит содержится в:
@@ -46,7 +46,6 @@
|
||||
"glob-parent": "6.0.2",
|
||||
"lodash": "^4.17.21",
|
||||
"marked": "4.0.17",
|
||||
"mattermost-redux": "5.33.1",
|
||||
"mini-create-react-context": "^0.4.1",
|
||||
"moment": "^2.29.1",
|
||||
"nanoevents": "^5.1.13",
|
||||
|
||||
@@ -96,3 +96,9 @@ exports[`components/boardsUnfurl/BoardsUnfurl renders when limited 1`] = `
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`components/boardsUnfurl/BoardsUnfurl test invalid card, invalid block 1`] = `<div />`;
|
||||
|
||||
exports[`components/boardsUnfurl/BoardsUnfurl test invalid card, valid block 1`] = `<div />`;
|
||||
|
||||
exports[`components/boardsUnfurl/BoardsUnfurl test no card 1`] = `<div />`;
|
||||
|
||||
@@ -16,6 +16,8 @@ import {createBoard} from 'src/blocks/board'
|
||||
import octoClient from 'src/octoClient'
|
||||
import {wrapIntl} from 'src/testUtils'
|
||||
|
||||
import {createBoardView} from 'src/blocks/boardView'
|
||||
|
||||
import BoardsUnfurl from './boardsUnfurl'
|
||||
|
||||
jest.mock('src/octoClient')
|
||||
@@ -114,5 +116,118 @@ describe('components/boardsUnfurl/BoardsUnfurl', () => {
|
||||
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('test no card', async () => {
|
||||
const mockStore = configureStore([])
|
||||
const store = mockStore({
|
||||
language: {
|
||||
value: 'en',
|
||||
},
|
||||
teams: {
|
||||
allTeams: [team],
|
||||
current: team,
|
||||
},
|
||||
})
|
||||
|
||||
const board = {...createBoard(), title: 'test board'}
|
||||
// mockedOctoClient.getBoard.mockResolvedValueOnce(board)
|
||||
|
||||
const component = (
|
||||
<ReduxProvider store={store}>
|
||||
{wrapIntl(
|
||||
<BoardsUnfurl
|
||||
embed={{data: JSON.stringify({workspaceID: 'foo', cardID: '', boardID: board.id, readToken: 'abc', originalPath: '/test'})}}
|
||||
/>,
|
||||
)}
|
||||
</ReduxProvider>
|
||||
)
|
||||
|
||||
let container: Element | DocumentFragment | null = null
|
||||
|
||||
await act(async () => {
|
||||
const result = render(component)
|
||||
container = result.container
|
||||
})
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('test invalid card, valid block', async () => {
|
||||
const mockStore = configureStore([])
|
||||
const store = mockStore({
|
||||
language: {
|
||||
value: 'en',
|
||||
},
|
||||
teams: {
|
||||
allTeams: [team],
|
||||
current: team,
|
||||
},
|
||||
})
|
||||
|
||||
const cards = [{...createBoardView(), title: 'test view', updateAt: 12345}]
|
||||
const board = {...createBoard(), title: 'test board'}
|
||||
|
||||
mockedOctoClient.getBlocksWithBlockID.mockResolvedValueOnce(cards)
|
||||
mockedOctoClient.getBoard.mockResolvedValueOnce(board)
|
||||
|
||||
const component = (
|
||||
<ReduxProvider store={store}>
|
||||
{wrapIntl(
|
||||
<BoardsUnfurl
|
||||
embed={{data: JSON.stringify({workspaceID: 'foo', cardID: cards[0].id, boardID: board.id, readToken: 'abc', originalPath: '/test'})}}
|
||||
/>,
|
||||
)}
|
||||
</ReduxProvider>
|
||||
)
|
||||
|
||||
let container: Element | DocumentFragment | null = null
|
||||
|
||||
await act(async () => {
|
||||
const result = render(component)
|
||||
container = result.container
|
||||
})
|
||||
expect(mockedOctoClient.getBoard).toBeCalledWith(board.id)
|
||||
expect(mockedOctoClient.getBlocksWithBlockID).toBeCalledWith(cards[0].id, board.id, 'abc')
|
||||
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('test invalid card, invalid block', async () => {
|
||||
const mockStore = configureStore([])
|
||||
const store = mockStore({
|
||||
language: {
|
||||
value: 'en',
|
||||
},
|
||||
teams: {
|
||||
allTeams: [team],
|
||||
current: team,
|
||||
},
|
||||
})
|
||||
|
||||
const board = {...createBoard(), title: 'test board'}
|
||||
|
||||
mockedOctoClient.getBlocksWithBlockID.mockResolvedValueOnce([])
|
||||
mockedOctoClient.getBoard.mockResolvedValueOnce(board)
|
||||
|
||||
const component = (
|
||||
<ReduxProvider store={store}>
|
||||
{wrapIntl(
|
||||
<BoardsUnfurl
|
||||
embed={{data: JSON.stringify({workspaceID: 'foo', cardID: 'invalidCard', boardID: board.id, readToken: 'abc', originalPath: '/test'})}}
|
||||
/>,
|
||||
)}
|
||||
</ReduxProvider>
|
||||
)
|
||||
|
||||
let container: Element | DocumentFragment | null = null
|
||||
|
||||
await act(async () => {
|
||||
const result = render(component)
|
||||
container = result.container
|
||||
})
|
||||
expect(mockedOctoClient.getBoard).toBeCalledWith(board.id)
|
||||
expect(mockedOctoClient.getBlocksWithBlockID).toBeCalledWith('invalidCard', board.id, 'abc')
|
||||
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ export const BoardsUnfurl = (props: Props): JSX.Element => {
|
||||
],
|
||||
)
|
||||
const [firstCard] = cards as Card[]
|
||||
if (!firstCard || !fetchedBoard) {
|
||||
if (!firstCard || !fetchedBoard || firstCard.type !== 'card') {
|
||||
setLoading(false)
|
||||
return null
|
||||
}
|
||||
@@ -116,7 +116,7 @@ export const BoardsUnfurl = (props: Props): JSX.Element => {
|
||||
useWebsockets(currentTeamId, (wsClient: WSClient) => {
|
||||
const onChangeHandler = (_: WSClient, blocks: Block[]): void => {
|
||||
const cardBlock: Block|undefined = blocks.find((b) => b.id === cardID)
|
||||
if (cardBlock && !cardBlock.deleteAt) {
|
||||
if (cardBlock && !cardBlock.deleteAt && cardBlock.type === 'card') {
|
||||
setCard(cardBlock as Card)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react'
|
||||
import {Post} from 'mattermost-redux/types/posts'
|
||||
import {Post} from '@mattermost/types/posts'
|
||||
|
||||
const PostTypeCloudUpgradeNudge = (props: {post: Post}): JSX.Element => {
|
||||
const ctaHandler = (e: React.MouseEvent) => {
|
||||
|
||||
@@ -6,16 +6,14 @@ import {Store, Action} from 'redux'
|
||||
import {Provider as ReduxProvider} from 'react-redux'
|
||||
import {createBrowserHistory, History} from 'history'
|
||||
|
||||
import {rudderAnalytics, RudderTelemetryHandler} from 'mattermost-redux/client/rudder'
|
||||
|
||||
import {GlobalState} from 'mattermost-redux/types/store'
|
||||
|
||||
import {selectTeam} from 'mattermost-redux/actions/teams'
|
||||
import {GlobalState} from '@mattermost/types/store'
|
||||
|
||||
import {SuiteWindow} from 'src/types/index'
|
||||
|
||||
import {PluginRegistry} from 'src/types/mattermost-webapp'
|
||||
|
||||
import {rudderAnalytics, RudderTelemetryHandler} from 'src/rudder'
|
||||
|
||||
import appBarIcon from 'static/app-bar-icon.png'
|
||||
|
||||
import {Constants} from 'src/constants'
|
||||
@@ -85,7 +83,7 @@ function getSubpath(siteURL: string): string {
|
||||
return url.pathname.replace(/\/+$/, '')
|
||||
}
|
||||
|
||||
const TELEMETRY_RUDDER_KEY = 'placeholder_rudder_key'
|
||||
const TELEMETRY_RUDDER_KEY = 'placeholder_boards_rudder_key'
|
||||
const TELEMETRY_RUDDER_DATAPLANE_URL = 'placeholder_rudder_dataplane_url'
|
||||
const TELEMETRY_OPTIONS = {
|
||||
context: {
|
||||
@@ -294,9 +292,13 @@ export default class Plugin {
|
||||
const currentUserId = mmStore.getState().entities.users.currentUserId
|
||||
if (currentTeamID !== fbPrevTeamID) {
|
||||
fbPrevTeamID = currentTeamID
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
mmStore.dispatch(selectTeam(currentTeamID))
|
||||
|
||||
mmStore.dispatch({
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
type: 'SELECT_TEAM',
|
||||
data: currentTeamID,
|
||||
})
|
||||
localStorage.setItem(`user_prev_team:${currentUserId}`, currentTeamID)
|
||||
}
|
||||
})
|
||||
|
||||
65
webapp/boards/src/rudder.ts
Обычный файл
65
webapp/boards/src/rudder.ts
Обычный файл
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// This file is duplicated from mattermost-redux in the web app with some slight modifications to make it standalone
|
||||
|
||||
// As per rudder-sdk-js documentation, import this only once and use like a singleton.
|
||||
// See https://github.com/rudderlabs/rudder-sdk-js#step-1-install-rudderstack-using-the-code-snippet
|
||||
import * as rudderAnalytics from 'rudder-sdk-js'
|
||||
export {rudderAnalytics}
|
||||
|
||||
import {TelemetryHandler} from '@mattermost/client'
|
||||
|
||||
import {Utils} from 'src/utils'
|
||||
|
||||
export class RudderTelemetryHandler implements TelemetryHandler {
|
||||
trackEvent(userId: string, userRoles: string, category: string, event: string, props?: any) {
|
||||
const properties = Object.assign({
|
||||
category,
|
||||
type: event,
|
||||
user_actual_role: getActualRoles(userRoles),
|
||||
user_actual_id: userId,
|
||||
}, props)
|
||||
const options = {
|
||||
context: {
|
||||
ip: '0.0.0.0',
|
||||
},
|
||||
page: {
|
||||
path: '',
|
||||
referrer: '',
|
||||
search: '',
|
||||
title: '',
|
||||
url: '',
|
||||
},
|
||||
anonymousId: '00000000000000000000000000',
|
||||
}
|
||||
|
||||
rudderAnalytics.track('event', properties, options)
|
||||
}
|
||||
|
||||
pageVisited(userId: string, userRoles: string, category: string, name: string) {
|
||||
rudderAnalytics.page(
|
||||
category,
|
||||
name,
|
||||
{
|
||||
path: '',
|
||||
referrer: '',
|
||||
search: '',
|
||||
title: '',
|
||||
url: '',
|
||||
user_actual_role: getActualRoles(userRoles),
|
||||
user_actual_id: userId,
|
||||
},
|
||||
{
|
||||
context: {
|
||||
ip: '0.0.0.0',
|
||||
},
|
||||
anonymousId: '00000000000000000000000000',
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function getActualRoles(userRoles: string) {
|
||||
return userRoles && Utils.isSystemAdmin(userRoles) ? 'system_admin, system_user' : 'system_user'
|
||||
}
|
||||
2
webapp/boards/src/types/mattermost-webapp/index.d.ts
поставляемый
2
webapp/boards/src/types/mattermost-webapp/index.d.ts
поставляемый
@@ -3,7 +3,7 @@
|
||||
|
||||
import type React from 'react'
|
||||
|
||||
import type {Channel, ChannelMembership} from 'mattermost-redux/types/channels'
|
||||
import type {Channel, ChannelMembership} from '@mattermost/types/channels'
|
||||
|
||||
type ReactResolvable = React.ReactNode | React.ElementType
|
||||
|
||||
|
||||
@@ -53,8 +53,6 @@ const config = {
|
||||
resolve: {
|
||||
alias: {
|
||||
src: path.resolve(__dirname, './src/'),
|
||||
// 'mattermost-redux': path.resolve(__dirname, '../channels/src/packages/mattermost-redux/src/'),
|
||||
// reselect: path.resolve(__dirname, '../channels/src/packages/reselect/src/index'),
|
||||
'@mattermost/client': path.resolve(__dirname, '../platform/client/src/'),
|
||||
'@mattermost/components': path.resolve(__dirname, '../platform/components/src/'),
|
||||
},
|
||||
|
||||
Ссылка в новой задаче
Block a user