Skip to content

Commit

Permalink
Merge pull request #1045 from Microsoft/jwilaby/#991-multiple-convers…
Browse files Browse the repository at this point in the history
…ation-update-calls

Jwilaby/#991 multiple conversation update calls
  • Loading branch information
vishwacsena committed Oct 26, 2018
2 parents 6e349c9 + 1628c00 commit f753387
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ deploy:
prerelease: false
draft: true
name: $BUILD_TAG
body: This release is an early preview of the new Bot Framework Emulator. Please consider it to be experimental, and we'd love to hear your feedback.
body: We'd love to hear your feedback on GitHub.
on:
branch: v4
condition: $BUILD_TAG
Expand Down
22 changes: 11 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 67 additions & 0 deletions packages/app/main/src/commands/connectedServiceCommands.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { SharedConstants } from '@bfemulator/app-shared';
import { CommandRegistryImpl } from '@bfemulator/sdk-shared';
import { ServiceTypes } from 'botframework-config/lib/schema';
import { registerCommands } from './connectedServiceCommands';

const mockServiceTypes = ServiceTypes;
jest.mock('../services/luisApiService', () => ({
LuisApi: {
getServices: function* () {
yield { label: 'Retrieving luis models', progress: 50 };
return { services: [{ type: mockServiceTypes.Luis }] };
}
}
}));

jest.mock('../services/qnaApiService', () => ({
QnaApiService: {
getKnowledgeBases: function* () {
yield { label: 'Retrieving knowledge bases', progress: 50 };
return { services: [{ type: mockServiceTypes.QnA }] };
}
}
}));

jest.mock('../main', () => ({
mainWindow: {
commandService: {
call: async () => true,
remoteCall: async () => true
},
browserWindow: {}
}
}));
const mockCommandRegistry = new CommandRegistryImpl();
registerCommands(mockCommandRegistry);

describe('The connected service commands', () => {

it('should retrieve luis models when the ServiceTypes.Luis is specified', async () => {
const { handler } = mockCommandRegistry
.getCommand(SharedConstants.Commands.ConnectedService.GetConnectedServicesByType);

const result = await handler('', mockServiceTypes.Luis);
expect(result.services[0].type).toBe(mockServiceTypes.Luis);

});

it('should retrieve knowledge bases when the ServiceTypes.QnA is specified', async () => {
const { handler } = mockCommandRegistry
.getCommand(SharedConstants.Commands.ConnectedService.GetConnectedServicesByType);

const result = await handler('', mockServiceTypes.QnA);
expect(result.services[0].type).toBe(mockServiceTypes.QnA);
});

it('should throw if an unexpected service type is specified', async () => {
const { handler } = mockCommandRegistry
.getCommand(SharedConstants.Commands.ConnectedService.GetConnectedServicesByType);
let error;
try {
await handler('', mockServiceTypes.BlobStorage);
} catch (e) {
error = e;
}
expect(error.message).toBe(`The ServiceTypes ${mockServiceTypes.BlobStorage} is not a know service type`);
});
});
142 changes: 142 additions & 0 deletions packages/app/main/src/commands/electronCommands.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { SharedConstants } from '@bfemulator/app-shared';
import { CommandRegistryImpl } from '@bfemulator/sdk-shared';
import { rename } from 'fs-extra';
import { AppMenuBuilder } from '../appMenuBuilder';
import { load } from '../botData/actions/botActions';
import { getStore } from '../botData/store';
import { mainWindow } from '../main';
import { registerCommands } from './electronCommands';
import * as Electron from 'electron';
import * as fs from 'fs-extra';
let renameArgs;
jest.mock('fs-extra', () => ({
stat: async () => ({ isFile: () => true }),
statSync: () => ({ isFile: () => false }),
pathExists: async () => true,
rename: async (...args: any[]) => renameArgs = args
// readFile: async () => JSON.stringify((mockConversation as any).transcript)
}));

jest.mock('electron', () => ({
app: {
getName: () => 'BotFramework Emulator',
setName: (name: string) => void 0,
getVersion: () => '4.x'
},
Menu: {
setApplicationMenu: () => void 0,
buildFromTemplate: () => void 0
},
dialog: {
showMessageBox: () => void 0,
showOpenDialog: () => void 0,
showSaveDialog: () => void 0
}
}));

jest.mock('../main', () => ({
mainWindow: {
browserWindow: {
setFullScreen: () => void 0,
setTitle: () => void 0
}
}
}));

jest.mock('mkdirp', () => ({
sync: () => ({})
}));

jest.mock('../utils/ensureStoragePath', () => ({
ensureStoragePath: () => ''
}));

const mockCommandRegistry = new CommandRegistryImpl();
registerCommands(mockCommandRegistry);

describe('the electron commands', () => {
it('should show a message box', async () => {
const { handler } = mockCommandRegistry.getCommand(SharedConstants.Commands.Electron.ShowMessageBox);
const showMessageBoxSpy = jest.spyOn(Electron.dialog, 'showMessageBox');
await handler(true, {});
expect(showMessageBoxSpy).toHaveBeenCalledWith(mainWindow.browserWindow, {
message: '',
title: 'BotFramework Emulator'
});
});

it('should show the open dialog', async () => {
const { handler } = mockCommandRegistry.getCommand(SharedConstants.Commands.Electron.ShowOpenDialog);
const showOpenDialogSpy = jest.spyOn(Electron.dialog, 'showOpenDialog');
await handler({});

expect(showOpenDialogSpy).toHaveBeenCalledWith(mainWindow.browserWindow, {});
});

it('should show the save dialog', async () => {
const { handler } = mockCommandRegistry.getCommand(SharedConstants.Commands.Electron.ShowSaveDialog);
const showSaveDialogSpy = jest.spyOn(Electron.dialog, 'showSaveDialog');

await handler({});
expect(showSaveDialogSpy).toHaveBeenCalledWith(mainWindow.browserWindow, {});
});

it('should update the file menu', async () => {
const { handler } = mockCommandRegistry.getCommand(SharedConstants.Commands.Electron.UpdateFileMenu);
const mockBotInfo = {
path: 'this/is/my.json',
displayName: 'AuthBot',
secret: 'secret'
};
const store = getStore();
store.dispatch(load([mockBotInfo]));

const buildMenuFromTemplateSpy = jest.spyOn(Electron.Menu, 'buildFromTemplate');
const setApplicationMenuSpy = jest.spyOn(Electron.Menu, 'setApplicationMenu');

await handler();

expect(buildMenuFromTemplateSpy).toHaveBeenCalled();
expect(setApplicationMenuSpy).toHaveBeenCalled();
});

it('should set full screen mode and set the application menu to null', async () => {
const { handler } = mockCommandRegistry.getCommand(SharedConstants.Commands.Electron.SetFullscreen);
const fullScreenSpy = jest.spyOn(mainWindow.browserWindow, 'setFullScreen');
const setApplicationMenuSpy = jest.spyOn(Electron.Menu, 'setApplicationMenu');

await handler(true);
expect(fullScreenSpy).toHaveBeenCalledWith(true);
expect(setApplicationMenuSpy).toHaveBeenCalledWith(null);
});

it('should remove full screen mode and set the application menu back to normal', async () => {
const { handler } = mockCommandRegistry.getCommand(SharedConstants.Commands.Electron.SetFullscreen);
const fullScreenSpy = jest.spyOn(mainWindow.browserWindow, 'setFullScreen');
const setApplicationMenuSpy = jest.spyOn(Electron.Menu, 'setApplicationMenu');
const buildFromTemplateSpy = jest.spyOn(Electron.Menu, 'buildFromTemplate');

await handler(false);
expect(fullScreenSpy).toHaveBeenCalledWith(false);
expect(buildFromTemplateSpy).toHaveBeenCalledWith(AppMenuBuilder.menuTemplate);
expect(setApplicationMenuSpy).toHaveBeenCalledWith(undefined);
});

it('should set the title bar', async () => {
const { handler } = mockCommandRegistry.getCommand(SharedConstants.Commands.Electron.SetTitleBar);
let setTitleSpy = jest.spyOn(mainWindow.browserWindow, 'setTitle');

await handler();
expect(setTitleSpy).toHaveBeenCalledWith(Electron.app.getName());

setTitleSpy = jest.spyOn(mainWindow.browserWindow, 'setTitle');
await (handler('preview'));
expect(setTitleSpy).toHaveBeenCalledWith(`${Electron.app.getName()} - preview`);
});

it('should rename a file', async () => {
const {handler} = mockCommandRegistry.getCommand(SharedConstants.Commands.Electron.RenameFile);
await handler({path: 'my/path/bot.bot', newPath: 'my/path/bot1.bot' });
expect(renameArgs).toEqual(['my/path/bot.bot', 'my/path/bot1.bot']);
});
});
4 changes: 2 additions & 2 deletions packages/app/main/src/commands/electronCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import * as path from 'path';
import * as fs from 'fs-extra';
import * as Electron from 'electron';
import { app, Menu } from 'electron';
import { app, Menu, MessageBoxOptions } from 'electron';
import { mainWindow } from '../main';
import { showOpenDialog, showSaveDialog } from '../utils';
import { AppMenuBuilder } from '../appMenuBuilder';
Expand All @@ -52,7 +52,7 @@ export function registerCommands(commandRegistry: CommandRegistryImpl) {

// ---------------------------------------------------------------------------
// Show OS-native messsage box
commandRegistry.registerCommand(Commands.ShowMessageBox, (modal: boolean, options: Electron.MessageBoxOptions) => {
commandRegistry.registerCommand(Commands.ShowMessageBox, (modal: boolean, options: MessageBoxOptions) => {
options = {
message: '',
title: app.getName(),
Expand Down
2 changes: 1 addition & 1 deletion packages/app/main/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const store = getStore();
// -----------------------------------------------------------------------------
// TODO - localization
if (app) {
app.setName('Bot Framework Emulator (V4 PREVIEW)');
app.setName('Bot Framework Emulator');
}

// -----------------------------------------------------------------------------
Expand Down
33 changes: 33 additions & 0 deletions packages/app/main/src/services/contextMenuService.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { MenuItemConstructorOptions } from 'electron';
import { ContextMenuService } from './contextMenuService';

jest.mock('electron', () => ({
Menu: class {
public static buildFromTemplate(...args: any[]) {
return {
popup: () => void 0
};
}
},
MenuItemConstructorOptions: class {
}
}));

describe('The ContextMenuService', () => {
beforeAll(() => {
(ContextMenuService as any).currentMenu = { closePopup: () => void 0 };
});

it('should show the menu and wait for user input', async () => {
const options = {} as MenuItemConstructorOptions;
let resolved = false;
const closePopupSpy = jest.spyOn((ContextMenuService as any).currentMenu, 'closePopup');
ContextMenuService.showMenuAndWaitForInput([options]).then(() => {
resolved = true;
});
expect(closePopupSpy).toHaveBeenCalled();
expect(options.click).not.toBeNull();
await options.click({} as any, null, null);
expect(resolved).toBeTruthy();
});
});
8 changes: 5 additions & 3 deletions packages/app/main/src/services/conversationService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ describe('The ConversationService should call "fetch" with the expected paramete
expect(headers instanceof nodeFetch.Headers).toBeTruthy();
expect(headers === headers).toBeTruthy();
expect(method).toBe('POST');
expect(body[0].name).toBeFalsy();
expect(body[0].id).toBeFalsy();
const members = JSON.parse(body);
expect(members[0].name).toBeFalsy();
expect(members[0].id).toBeFalsy();
expect(headersInstance).toEqual(headers);
});

Expand All @@ -54,7 +55,8 @@ describe('The ConversationService should call "fetch" with the expected paramete
expect(headers instanceof nodeFetch.Headers).toBeTruthy();
expect(headers === headers).toBeTruthy();
expect(method).toBe('DELETE');
expect(body[0].id).toBe('1234');
const users = JSON.parse(body);
expect(users[0].id).toBe('1234');
expect(headersInstance).toEqual(headers);
});

Expand Down
Loading

0 comments on commit f753387

Please sign in to comment.