V4.10.0 (#2180)
* Webchat Upgrade and Version number change Signed-off-by: Srinaath Ravichandran <srravich@microsoft.com> * Handle change to middleware (#2177) * Handle change to middleware * Updated babel preset env Signed-off-by: Srinaath Ravichandran <srravich@microsoft.com> * Reverted change to babel Signed-off-by: Srinaath Ravichandran <srravich@microsoft.com> Locks updated to pre webchat change Signed-off-by: Srinaath Ravichandran <srravich@microsoft.com> Post wechat check Signed-off-by: Srinaath Ravichandran <srravich@microsoft.com> Prevent hoisting bf-chatdown Signed-off-by: Srinaath Ravichandran <srravich@microsoft.com> * Updated babel preset env Signed-off-by: Srinaath Ravichandran <srravich@microsoft.com> * fix: Webchat socket instantiation delay (#2179) * Updated websocket server code to backup messages if it is not connected * Refactored more occurances of socket send * Renaming variables * Added unit test to make sure backedup messages are cleared before connection starts * Lint fix * Updated release date Signed-off-by: Srinaath Ravichandran <srravich@microsoft.com> * All tests working Signed-off-by: Srinaath Ravichandran <srravich@microsoft.com> Co-authored-by: Srinaath Ravichandran <srravich@microsoft.com>
This commit is contained in:
Родитель
9042e38719
Коммит
7829dbd1f8
|
@ -4,14 +4,18 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
## v4.10.0 - 2020 - 08 - 21
|
||||
## Added
|
||||
- [client] Added a log panel entry at the start of a conversation that displays the bot endpoint in PR [2149](https://github.com/microsoft/BotFramework-Emulator/pull/2149)
|
||||
- [client] - Bumped `botframework-webchat` to v4.10.0 in PR [2177](https://github.com/microsoft/BotFramework-Emulator/pull/2177)
|
||||
|
||||
## Fixed
|
||||
- [client] Added missing content to signed in view of Cosmos DB service dialog and fixed product page link in PR [2150](https://github.com/microsoft/BotFramework-Emulator/pull/2150)
|
||||
- [docs] Modified CONTRIBUTING.md to include updated information about global dependencies required to build from source in PR [2153](https://github.com/microsoft/BotFramework-Emulator/pull/2153)
|
||||
- [client] Fixed a bug where trying to open the sign-in link on an OAuth card would open the file explorer if ngrok was not configured in PR [2155](https://github.com/microsoft/BotFramework-Emulator/pull/2155)
|
||||
- [client] Change to a warning message in inspector when clicking on LUIS trace [2160](https://github.com/microsoft/BotFramework-Emulator/pull/2160)
|
||||
- [client] Handle result from webchat middleware gracefully [2177](https://github.com/microsoft/BotFramework-Emulator/pull/2177)
|
||||
- [client] Handle Webchat socket instantiation delay [2179](https://github.com/microsoft/BotFramework-Emulator/pull/2179)
|
||||
|
||||
## v4.9.0 - 2020 - 05 - 11
|
||||
## Added
|
||||
|
|
|
@ -14,5 +14,12 @@
|
|||
"packages/extensions/json",
|
||||
"packages/tools"
|
||||
],
|
||||
"command": {
|
||||
"bootstrap": {
|
||||
"nohoist": [
|
||||
"@microsoft/bf-chatdown"
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": "independent"
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -48,7 +48,7 @@
|
|||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@types/enzyme": "^3.1.10",
|
||||
"@types/jest": "24.0.13",
|
||||
|
@ -93,10 +93,10 @@
|
|||
"url-loader": "^1.0.1",
|
||||
"webpack": "^4.32.2",
|
||||
"webpack-cli": "^3.3.2",
|
||||
"webpack-dev-server": "^3.4.1"
|
||||
"webpack-dev-server": "^3.4.1",
|
||||
"@babel/runtime": "^7.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.5",
|
||||
"@bfemulator/app-shared": "^1.0.0",
|
||||
"@bfemulator/sdk-client": "^1.0.0",
|
||||
"@bfemulator/sdk-shared": "^1.0.0",
|
||||
|
@ -107,8 +107,8 @@
|
|||
"base64url": "3.0.0",
|
||||
"botframework-config": "4.4.0",
|
||||
"botframework-schema": "^4.3.4",
|
||||
"botframework-webchat": "4.9.0",
|
||||
"botframework-webchat-core": "4.9.0",
|
||||
"botframework-webchat": "4.10.0",
|
||||
"botframework-webchat-core": "4.10.0",
|
||||
"eslint-plugin-react": "^7.12.3",
|
||||
"markdown-it": "^8.4.2",
|
||||
"react": "16.8.6",
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
//
|
||||
|
||||
import { ValueTypes, RestartConversationStatus } from '@bfemulator/app-shared';
|
||||
import { User } from '@bfemulator/sdk-shared';
|
||||
import { Activity, ActivityTypes } from 'botframework-schema';
|
||||
import ReactWebChat, { createStyleSet } from 'botframework-webchat';
|
||||
import * as React from 'react';
|
||||
|
@ -139,6 +138,11 @@ export class Chat extends PureComponent<ChatProps, ChatState> {
|
|||
}
|
||||
|
||||
private activityWrapper(next, card, children): ReactNode {
|
||||
let childrenContents = null;
|
||||
const middlewareResult = next(card);
|
||||
if (middlewareResult) {
|
||||
childrenContents = middlewareResult(children);
|
||||
}
|
||||
return (
|
||||
<OuterActivityWrapperContainer
|
||||
card={card}
|
||||
|
@ -147,7 +151,7 @@ export class Chat extends PureComponent<ChatProps, ChatState> {
|
|||
onItemRendererClick={this.onItemRendererClick}
|
||||
onItemRendererKeyDown={this.onItemRendererKeyDown}
|
||||
>
|
||||
{next(card)(children)}
|
||||
{childrenContents}
|
||||
</OuterActivityWrapperContainer>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@bfemulator/main",
|
||||
"packagename": "BotFramework-Emulator",
|
||||
"version": "4.9.0",
|
||||
"version": "4.10.0",
|
||||
"private": true,
|
||||
"description": "Development tool for the Microsoft Bot Framework. Allows developers to test and debug bots on localhost.",
|
||||
"main": "./app/server/main.js",
|
||||
|
@ -79,7 +79,7 @@
|
|||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@types/async": "^2.0.47",
|
||||
"@types/chokidar": "^1.7.5",
|
||||
|
|
|
@ -42,13 +42,17 @@ jest.mock('../../../../utils/oauthLinkEncoder', () => ({
|
|||
}),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../webSocketServer', () => ({
|
||||
WebSocketServer: {
|
||||
getSocketByConversationId: () => ({
|
||||
send: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
const mockSocket = {
|
||||
send: jest.fn(),
|
||||
};
|
||||
|
||||
jest.mock('../../../../webSocketServer', () => {
|
||||
return {
|
||||
WebSocketServer: {
|
||||
sendToSubscribers: (...args) => mockSocket.send(...args),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('replyToActivity route middleware', () => {
|
||||
const mockReq: any = {
|
||||
|
|
|
@ -58,10 +58,7 @@ export function createReplyToActivityHandler(emulatorServer: EmulatorRestServer)
|
|||
|
||||
// post activity
|
||||
activity = conversation.prepActivityToBeSentToUser(conversation.user.id, activity);
|
||||
const payload = { activities: [activity] };
|
||||
const socket = WebSocketServer.getSocketByConversationId(conversationId);
|
||||
socket && socket.send(JSON.stringify(payload));
|
||||
|
||||
WebSocketServer.sendToSubscribers(conversation.conversationId, activity);
|
||||
res.send(HttpStatus.OK, { id: activity.id });
|
||||
res.end();
|
||||
};
|
||||
|
|
|
@ -35,13 +35,17 @@ import * as HttpStatus from 'http-status-codes';
|
|||
|
||||
import { sendActivityToConversation } from './sendActivityToConversation';
|
||||
|
||||
jest.mock('../../../../webSocketServer', () => ({
|
||||
WebSocketServer: {
|
||||
getSocketByConversationId: () => ({
|
||||
send: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
const mockSocket = {
|
||||
send: jest.fn(),
|
||||
};
|
||||
|
||||
jest.mock('../../../../webSocketServer', () => {
|
||||
return {
|
||||
WebSocketServer: {
|
||||
sendToSubscribers: (...args) => mockSocket.send(...args),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const mockSendErrorResponse = jest.fn();
|
||||
jest.mock('../../../../utils/sendErrorResponse', () => ({
|
||||
|
|
|
@ -48,10 +48,7 @@ export function sendActivityToConversation(req: Request, res: Response, next: Ne
|
|||
|
||||
// post activity
|
||||
activity = conversation.prepActivityToBeSentToUser(conversation.user.id, activity);
|
||||
const payload = { activities: [activity] };
|
||||
const socket = WebSocketServer.getSocketByConversationId(conversation.conversationId);
|
||||
socket && socket.send(JSON.stringify(payload));
|
||||
|
||||
WebSocketServer.sendToSubscribers(conversation.conversationId, activity);
|
||||
res.send(HttpStatus.OK, { id: activity.id });
|
||||
res.end();
|
||||
} catch (err) {
|
||||
|
|
|
@ -47,9 +47,7 @@ export function sendHistoryToConversation(req: Request, res: Response, next: Nex
|
|||
for (const activity of activities) {
|
||||
try {
|
||||
const updatedActivity = conversation.prepActivityToBeSentToUser(conversation.user.id, activity);
|
||||
const payload = { activities: [updatedActivity] };
|
||||
const socket = WebSocketServer.getSocketByConversationId(conversation.conversationId);
|
||||
socket && socket.send(JSON.stringify(payload));
|
||||
WebSocketServer.sendToSubscribers(conversation.conversationId, updatedActivity);
|
||||
successCount++;
|
||||
} catch (err) {
|
||||
if (firstErrorMessage === '') {
|
||||
|
|
|
@ -43,11 +43,14 @@ jest.mock('../../../utils/sendErrorResponse', () => ({
|
|||
const mockSocket = {
|
||||
send: jest.fn(),
|
||||
};
|
||||
jest.mock('../../../webSocketServer', () => ({
|
||||
WebSocketServer: {
|
||||
getSocketByConversationId: () => mockSocket,
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../webSocketServer', () => {
|
||||
return {
|
||||
WebSocketServer: {
|
||||
sendToSubscribers: (...args) => mockSocket.send(...args),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('postActivity handler', () => {
|
||||
beforeEach(() => {
|
||||
|
@ -56,14 +59,16 @@ describe('postActivity handler', () => {
|
|||
});
|
||||
|
||||
it('should return a 200 and the id of the posted activity', async () => {
|
||||
const activity = {
|
||||
id: 'activity1',
|
||||
};
|
||||
|
||||
const mockEmulatorServer: any = {
|
||||
logger: {
|
||||
logMessage: jest.fn(),
|
||||
},
|
||||
};
|
||||
const activity = {
|
||||
id: 'activity1',
|
||||
};
|
||||
|
||||
const req: any = {
|
||||
body: activity,
|
||||
conversation: {
|
||||
|
@ -72,6 +77,7 @@ describe('postActivity handler', () => {
|
|||
response: {},
|
||||
statusCode: HttpStatus.OK,
|
||||
}),
|
||||
conversationId: 'convo1',
|
||||
},
|
||||
params: {
|
||||
conversationId: 'convo1',
|
||||
|
@ -88,11 +94,7 @@ describe('postActivity handler', () => {
|
|||
expect(res.send).toHaveBeenCalledWith(HttpStatus.OK, activity);
|
||||
expect(res.end).toHaveBeenCalled();
|
||||
expect(next).toHaveBeenCalled();
|
||||
expect(mockSocket.send).toHaveBeenCalledWith(
|
||||
JSON.stringify({
|
||||
activities: [{ ...req.body, id: 'activity1' }],
|
||||
})
|
||||
);
|
||||
expect(mockSocket.send).toHaveBeenCalledWith(req.params.conversationId, activity);
|
||||
});
|
||||
|
||||
it('should return a 200 but not send the /INSPECT open command over the web socket', async () => {
|
||||
|
|
|
@ -85,9 +85,7 @@ export function createPostActivityHandler(emulatorServer: EmulatorRestServer) {
|
|||
res.end();
|
||||
return next();
|
||||
}
|
||||
const payload = { activities: [{ ...activity, id: activity.id }] };
|
||||
const socket = WebSocketServer.getSocketByConversationId(conversation.conversationId);
|
||||
socket && socket.send(JSON.stringify(payload));
|
||||
WebSocketServer.sendToSubscribers(conversation.conversationId, activity);
|
||||
}
|
||||
} catch (err) {
|
||||
sendErrorResponse(req, res, next, err);
|
||||
|
|
|
@ -38,11 +38,14 @@ import { createFeedActivitiesAsTranscriptHandler } from './feedActivitiesAsTrans
|
|||
const mockSocket = {
|
||||
send: jest.fn(),
|
||||
};
|
||||
jest.mock('../../../webSocketServer', () => ({
|
||||
WebSocketServer: {
|
||||
getSocketByConversationId: () => mockSocket,
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../webSocketServer', () => {
|
||||
return {
|
||||
WebSocketServer: {
|
||||
sendToSubscribers: (...args) => mockSocket.send(...args),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('feedActivitiesAsTranscript handler', () => {
|
||||
it('should send a 200 after sending all activities over the web socket connection', () => {
|
||||
|
|
|
@ -52,9 +52,7 @@ export function createFeedActivitiesAsTranscriptHandler(emulatorServer: Emulator
|
|||
}
|
||||
activities = conversation.prepTranscriptActivities(activities);
|
||||
activities.forEach(activity => {
|
||||
const payload = { activities: [activity] };
|
||||
const socket = WebSocketServer.getSocketByConversationId(conversation.conversationId);
|
||||
socket && socket.send(JSON.stringify(payload));
|
||||
WebSocketServer.sendToSubscribers(conversation.conversationId, activity);
|
||||
emulatorServer.logger.logActivity(conversation.conversationId, activity, activity.recipient.role);
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
import { Activity } from 'botframework-schema';
|
||||
|
||||
import { WebSocketServer } from './webSocketServer';
|
||||
|
||||
const mockWSServer = {
|
||||
|
@ -157,4 +159,84 @@ describe('WebSocketServer', () => {
|
|||
expect(Object.keys((WebSocketServer as any)._servers)).toEqual([mockConversationId]);
|
||||
expect(mockWSServer.handleUpgrade).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should clear the messages backed up before websocket connection is started', async () => {
|
||||
let onConnectionFunction = null;
|
||||
let websocketHandler = null;
|
||||
|
||||
(WebSocketServer as any)._restServer = undefined;
|
||||
(WebSocketServer as any)._servers = {};
|
||||
(WebSocketServer as any)._sockets = {};
|
||||
|
||||
mockWSServer.on.mockImplementation((event, implementation) => {
|
||||
if (event === 'connection') {
|
||||
onConnectionFunction = implementation;
|
||||
}
|
||||
});
|
||||
|
||||
mockCreateServer.mockReturnValueOnce({
|
||||
address: () => ({ port: 55523 }),
|
||||
get: (route, handler) => {
|
||||
websocketHandler = handler;
|
||||
},
|
||||
listen: jest.fn((_port, cb) => {
|
||||
cb();
|
||||
}),
|
||||
once: jest.fn(),
|
||||
});
|
||||
await WebSocketServer.init();
|
||||
|
||||
WebSocketServer.queueActivities('conv-123', { id: 'activity-1' } as Activity);
|
||||
WebSocketServer.queueActivities('conv-234', { id: 'activity-1' } as Activity);
|
||||
|
||||
WebSocketServer.queueActivities('conv-123', { id: 'activity-2' } as Activity);
|
||||
WebSocketServer.queueActivities('conv-234', { id: 'activity-2' } as Activity);
|
||||
websocketHandler(
|
||||
{
|
||||
params: {
|
||||
conversationId: 'conv-234',
|
||||
},
|
||||
},
|
||||
{
|
||||
claimUpgrade: jest.fn(() => {
|
||||
return {
|
||||
head: jest.fn(),
|
||||
socket: jest.fn(),
|
||||
};
|
||||
}),
|
||||
}
|
||||
);
|
||||
const socketSendMock = jest.fn();
|
||||
onConnectionFunction({
|
||||
send: socketSendMock,
|
||||
on: jest.fn(),
|
||||
});
|
||||
expect(socketSendMock).toHaveBeenCalledTimes(2);
|
||||
expect(socketSendMock).toHaveBeenNthCalledWith(1, JSON.stringify({ activities: [{ id: 'activity-1' }] }));
|
||||
expect(socketSendMock).toHaveBeenNthCalledWith(2, JSON.stringify({ activities: [{ id: 'activity-2' }] }));
|
||||
socketSendMock.mockClear();
|
||||
|
||||
websocketHandler(
|
||||
{
|
||||
params: {
|
||||
conversationId: 'conv-123',
|
||||
},
|
||||
},
|
||||
{
|
||||
claimUpgrade: jest.fn(() => {
|
||||
return {
|
||||
head: jest.fn(),
|
||||
socket: jest.fn(),
|
||||
};
|
||||
}),
|
||||
}
|
||||
);
|
||||
onConnectionFunction({
|
||||
send: socketSendMock,
|
||||
on: jest.fn(),
|
||||
});
|
||||
expect(socketSendMock).toHaveBeenCalledTimes(2);
|
||||
expect(socketSendMock).toHaveBeenNthCalledWith(1, JSON.stringify({ activities: [{ id: 'activity-1' }] }));
|
||||
expect(socketSendMock).toHaveBeenNthCalledWith(2, JSON.stringify({ activities: [{ id: 'activity-2' }] }));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
import { createServer, Next, Request, Response, Server } from 'restify';
|
||||
import { Server as WSServer } from 'ws';
|
||||
import { Activity } from 'botframework-schema';
|
||||
|
||||
// can't import WebSocket type from ws types :|
|
||||
interface WebSocket {
|
||||
|
@ -45,11 +46,40 @@ export class WebSocketServer {
|
|||
private static _restServer: Server;
|
||||
private static _servers: { [conversationId: string]: WSServer } = {};
|
||||
private static _sockets: { [conversationId: string]: WebSocket } = {};
|
||||
private static queuedMessages: { [conversationId: string]: Activity[] } = {};
|
||||
|
||||
private static sendBackedUpMessages(conversationId: string, socket: WebSocket) {
|
||||
if (this.queuedMessages[conversationId]) {
|
||||
while (this.queuedMessages[conversationId].length > 0) {
|
||||
const activity: Activity = this.queuedMessages[conversationId].shift();
|
||||
const payload = { activities: [activity] };
|
||||
socket.send(JSON.stringify(payload));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static getSocketByConversationId(conversationId: string): WebSocket {
|
||||
return this._sockets[conversationId];
|
||||
}
|
||||
|
||||
public static queueActivities(conversationId: string, activity: Activity): void {
|
||||
if (!this.queuedMessages[conversationId]) {
|
||||
this.queuedMessages[conversationId] = [];
|
||||
}
|
||||
this.queuedMessages[conversationId].push(activity);
|
||||
}
|
||||
|
||||
public static sendToSubscribers(conversationId: string, activity: Activity): void {
|
||||
const socket = this._sockets[conversationId];
|
||||
if (socket) {
|
||||
const payload = { activities: [activity] };
|
||||
this.sendBackedUpMessages(conversationId, socket);
|
||||
socket.send(JSON.stringify(payload));
|
||||
} else {
|
||||
this.queueActivities(conversationId, activity);
|
||||
}
|
||||
}
|
||||
|
||||
/** Initializes the server and returns the port it is listening on, or if already initialized,
|
||||
* is a no-op.
|
||||
*/
|
||||
|
@ -69,10 +99,13 @@ export class WebSocketServer {
|
|||
noServer: true,
|
||||
});
|
||||
wsServer.on('connection', (socket, req) => {
|
||||
this.sendBackedUpMessages(conversationId, socket);
|
||||
this._sockets[conversationId] = socket;
|
||||
|
||||
socket.on('close', (code, reason) => {
|
||||
delete this._servers[conversationId];
|
||||
delete this._sockets[conversationId];
|
||||
delete this.queuedMessages[conversationId];
|
||||
});
|
||||
});
|
||||
// upgrade the connection to a ws connection
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@types/jest": "24.0.13",
|
||||
"babel-jest": "24.8.0",
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@types/deep-diff": "^1.0.0",
|
||||
"@types/jest": "24.0.13",
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@types/jest": "24.0.13",
|
||||
"@types/lscache": "^1.0.29",
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@babel/runtime": "^7.1.5",
|
||||
"@types/jest": "24.0.13",
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@types/jest": "24.0.13",
|
||||
"babel-jest": "24.8.0",
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@types/jest": "24.0.13",
|
||||
"babel-jest": "24.8.0",
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@types/jest": "24.0.13",
|
||||
"@types/react": "16.9.17",
|
||||
|
|
Загрузка…
Ссылка в новой задаче