* #1237 - added new copy and updated functionality * Unit test restitution * Removed commented imports * Small tweaks after design review * Unit test restitution
This commit is contained in:
Родитель
6b53181186
Коммит
877843dee4
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -34,11 +34,12 @@
|
|||
.browse-button {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 12px;
|
||||
right: 4px;
|
||||
bottom: 11.5px;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
margin-top: 10px;
|
||||
padding-right: 115px;
|
||||
|
||||
& + div {
|
||||
|
|
|
@ -31,13 +31,12 @@
|
|||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
import { newNotification, SharedConstants } from '@bfemulator/app-shared';
|
||||
import { SharedConstants } from '@bfemulator/app-shared';
|
||||
import { mount } from 'enzyme';
|
||||
import * as React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { combineReducers, createStore } from 'redux';
|
||||
import * as BotActions from '../../../data/action/botActions';
|
||||
import { beginAdd } from '../../../data/action/notificationActions';
|
||||
import { bot } from '../../../data/reducer/bot';
|
||||
import { CommandServiceImpl } from '../../../platform/commands/commandServiceImpl';
|
||||
import { ActiveBotHelper } from '../../helpers/activeBotHelper';
|
||||
|
@ -72,13 +71,11 @@ const bots = [
|
|||
];
|
||||
|
||||
describe('The OpenBotDialog', () => {
|
||||
let mockDispatch;
|
||||
let node;
|
||||
let parent;
|
||||
let instance;
|
||||
beforeEach(() => {
|
||||
mockStore.dispatch(BotActions.load(bots));
|
||||
mockDispatch = jest.spyOn(mockStore, 'dispatch');
|
||||
parent = mount(<Provider store={ mockStore }>
|
||||
<OpenBotDialogContainer/>
|
||||
</Provider>);
|
||||
|
@ -92,47 +89,6 @@ describe('The OpenBotDialog', () => {
|
|||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should orchestrate the appropriate sequences when a recent bot is clicked', async () => {
|
||||
const commandServiceSpy = jest.spyOn(CommandServiceImpl, 'call').mockResolvedValue(true);
|
||||
const dialogSpy = jest.spyOn(DialogService, 'hideDialog');
|
||||
await instance.onBotSelected(bots[0]);
|
||||
const { Switch } = SharedConstants.Commands.Bot;
|
||||
expect(commandServiceSpy).toHaveBeenCalledWith(Switch, '/some/path');
|
||||
expect(dialogSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should send a notification when the bot fails to open', async () => {
|
||||
await instance.onBotSelected(null);
|
||||
const message = `An Error occurred on the Open Bot Dialog: TypeError: Cannot read property 'path' of null`;
|
||||
const notification = newNotification(message);
|
||||
const action = beginAdd(notification);
|
||||
notification.timestamp = jasmine.any(Number) as any;
|
||||
notification.id = jasmine.any(String) as any;
|
||||
expect(mockDispatch).toHaveBeenLastCalledWith(action);
|
||||
});
|
||||
|
||||
it('should make the appropriate calls when onCreateNewBotClick in called', async () => {
|
||||
const commandServiceSpy = jest.spyOn(CommandServiceImpl, 'call').mockResolvedValue(true);
|
||||
const dialogSpy = jest.spyOn(DialogService, 'hideDialog');
|
||||
|
||||
await instance.onCreateNewBotClick();
|
||||
expect(commandServiceSpy).toHaveBeenLastCalledWith(SharedConstants.Commands.UI.ShowBotCreationDialog);
|
||||
expect(dialogSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should send a notification when onCreateNewBotClick fails', async () => {
|
||||
const commandServiceSpy = jest.spyOn(CommandServiceImpl, 'call').mockRejectedValue('oh noes!');
|
||||
await instance.onCreateNewBotClick();
|
||||
const message = `An Error occurred on the Open Bot Dialog: oh noes!`;
|
||||
const notification = newNotification(message);
|
||||
const action = beginAdd(notification);
|
||||
notification.timestamp = jasmine.any(Number) as any;
|
||||
notification.id = jasmine.any(String) as any;
|
||||
expect(mockDispatch).toHaveBeenLastCalledWith(action);
|
||||
|
||||
expect(commandServiceSpy).toHaveBeenLastCalledWith(SharedConstants.Commands.UI.ShowBotCreationDialog);
|
||||
});
|
||||
|
||||
it('should properly set the state when the input changes', () => {
|
||||
instance.onInputChange({
|
||||
target: {
|
||||
|
@ -174,7 +130,7 @@ describe('The OpenBotDialog', () => {
|
|||
} as any);
|
||||
|
||||
const botHelperSpy = jest.spyOn(ActiveBotHelper, 'confirmAndOpenBotFromFile').mockResolvedValue(true);
|
||||
await instance.onOpenClick();
|
||||
await instance.onSubmit();
|
||||
|
||||
expect(botHelperSpy).toHaveBeenCalledWith('some/path/to/myBot.bot');
|
||||
});
|
||||
|
@ -188,7 +144,7 @@ describe('The OpenBotDialog', () => {
|
|||
} as any);
|
||||
|
||||
const commandServiceSpy = jest.spyOn(CommandServiceImpl, 'call');
|
||||
await instance.onOpenClick();
|
||||
await instance.onSubmit();
|
||||
|
||||
expect(commandServiceSpy).toHaveBeenCalledWith(SharedConstants.Commands.Emulator.NewLiveChat,
|
||||
{ endpoint: 'http://localhost:6500/api/messages' });
|
||||
|
|
|
@ -31,16 +31,12 @@
|
|||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
import { BotInfo } from '@bfemulator/app-shared';
|
||||
import { DefaultButton, Dialog, DialogFooter, PrimaryButton, TextField } from '@bfemulator/ui-react';
|
||||
import * as React from 'react';
|
||||
import { ChangeEvent, FocusEvent, ReactNode } from 'react';
|
||||
import { RecentBotsListContainer } from '../../editor/recentBotsList/recentBotsListContainer';
|
||||
import * as styles from '../dialogStyles.scss';
|
||||
import * as openBotStyles from './openBotDialog.scss';
|
||||
|
||||
export interface OpenBotDialogProps {
|
||||
showCreateNewBotDialog?: () => Promise<void>;
|
||||
onDialogCancel?: () => void;
|
||||
openBot?: (urlOrPath: string) => Promise<void>;
|
||||
sendNotification?: (error: Error) => void;
|
||||
|
@ -70,65 +66,45 @@ export class OpenBotDialog extends React.Component<OpenBotDialogProps, OpenBotDi
|
|||
return (
|
||||
<Dialog
|
||||
cancel={ this.props.onDialogCancel }
|
||||
className={ `${ styles.dialogMedium } ${ openBotStyles.themeOverrides }` }
|
||||
title="Open a Bot">
|
||||
<p>
|
||||
{ `You can open a bot using just a URL, choose from a list of recently opened bots or ` }
|
||||
<a href="javascript:void(0);" onClick={ this.onCreateNewBotClick }>create a new bot configuration</a>
|
||||
</p>
|
||||
<TextField
|
||||
errorMessage={ errorMessage }
|
||||
inputContainerClassName={ openBotStyles.inputContainer }
|
||||
label="Bot URL or File Location"
|
||||
onChange={ this.onInputChange }
|
||||
onFocus={ this.onFocus }
|
||||
value={ botUrl }>
|
||||
className={ openBotStyles.themeOverrides }
|
||||
title="Open a bot">
|
||||
<form onSubmit={ this.onSubmit }>
|
||||
<TextField
|
||||
errorMessage={ errorMessage }
|
||||
inputContainerClassName={ openBotStyles.inputContainer }
|
||||
label="Bot URL or file location"
|
||||
onChange={ this.onInputChange }
|
||||
onFocus={ this.onFocus }
|
||||
autoFocus={ true }
|
||||
value={ botUrl }>
|
||||
|
||||
<PrimaryButton
|
||||
className={ openBotStyles.browseButton }>
|
||||
Browse
|
||||
<input
|
||||
className={ openBotStyles.fileInput }
|
||||
onChange={ this.onInputChange }
|
||||
accept=".bot"
|
||||
type="file"/>
|
||||
</PrimaryButton>
|
||||
<PrimaryButton
|
||||
className={ openBotStyles.browseButton }>
|
||||
Browse
|
||||
<input
|
||||
className={ openBotStyles.fileInput }
|
||||
onChange={ this.onInputChange }
|
||||
accept=".bot"
|
||||
type="file"/>
|
||||
</PrimaryButton>
|
||||
|
||||
</TextField>
|
||||
<RecentBotsListContainer onBotSelected={ this.onBotSelected }/>
|
||||
<DialogFooter>
|
||||
<PrimaryButton
|
||||
text="Close"
|
||||
onClick={ this.props.onDialogCancel }
|
||||
/>
|
||||
<DefaultButton
|
||||
disabled={ !!errorMessage }
|
||||
onClick={ this.onOpenClick }
|
||||
text="Open/Connect"
|
||||
/>
|
||||
</DialogFooter>
|
||||
</TextField>
|
||||
<DialogFooter>
|
||||
<DefaultButton
|
||||
text="Cancel"
|
||||
onClick={ this.props.onDialogCancel }
|
||||
/>
|
||||
<PrimaryButton
|
||||
type="submit"
|
||||
disabled={ !!errorMessage || !botUrl }
|
||||
text="Connect"
|
||||
/>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
private onBotSelected = async (bot: BotInfo) => {
|
||||
try {
|
||||
await this.props.switchToBot(bot.path);
|
||||
this.props.onDialogCancel();
|
||||
} catch (e) {
|
||||
this.props.sendNotification(e);
|
||||
}
|
||||
}
|
||||
|
||||
private onCreateNewBotClick = async () => {
|
||||
try {
|
||||
await this.props.showCreateNewBotDialog();
|
||||
this.props.onDialogCancel();
|
||||
} catch (e) {
|
||||
this.props.sendNotification(e);
|
||||
}
|
||||
}
|
||||
|
||||
private onFocus = (event: FocusEvent<HTMLInputElement>) => {
|
||||
const input = event.target as HTMLInputElement;
|
||||
input.setSelectionRange(0, (input.value || '').length);
|
||||
|
@ -140,7 +116,7 @@ export class OpenBotDialog extends React.Component<OpenBotDialogProps, OpenBotDi
|
|||
this.setState({ botUrl });
|
||||
}
|
||||
|
||||
private onOpenClick = async () => {
|
||||
private onSubmit = async () => {
|
||||
try {
|
||||
await this.props.openBot(this.state.botUrl);
|
||||
} catch (e) {
|
||||
|
|
|
@ -32,25 +32,17 @@
|
|||
//
|
||||
|
||||
import { newNotification, SharedConstants } from '@bfemulator/app-shared';
|
||||
import { Action } from 'redux';
|
||||
import { IEndpointService } from 'botframework-config/lib/schema';
|
||||
import { connect } from 'react-redux';
|
||||
import { Action } from 'redux';
|
||||
import { beginAdd } from '../../../data/action/notificationActions';
|
||||
import { RootState } from '../../../data/store';
|
||||
import { CommandServiceImpl } from '../../../platform/commands/commandServiceImpl';
|
||||
import { ActiveBotHelper } from '../../helpers/activeBotHelper';
|
||||
import { DialogService } from '../service';
|
||||
import { OpenBotDialog, OpenBotDialogProps } from './openBotDialog';
|
||||
|
||||
const mapStateToProps = (state: RootState, ownProps: { [propName: string]: any }): OpenBotDialogProps => {
|
||||
return {
|
||||
showCreateNewBotDialog: () => CommandServiceImpl.call(SharedConstants.Commands.UI.ShowBotCreationDialog),
|
||||
...ownProps
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch: (action: Action) => void): OpenBotDialogProps => {
|
||||
const { Commands: { Emulator: { NewLiveChat }, Bot: { Switch } } } = SharedConstants;
|
||||
const { Commands: { Emulator: { NewLiveChat } } } = SharedConstants;
|
||||
return {
|
||||
onDialogCancel: () => DialogService.hideDialog(),
|
||||
openBot: (urlOrPath: string) => {
|
||||
|
@ -62,11 +54,10 @@ const mapDispatchToProps = (dispatch: (action: Action) => void): OpenBotDialogPr
|
|||
},
|
||||
sendNotification: (error: Error) =>
|
||||
dispatch(beginAdd(newNotification(`An Error occurred on the Open Bot Dialog: ${ error }`))),
|
||||
switchToBot: (path: string) => CommandServiceImpl.call(Switch, path)
|
||||
};
|
||||
};
|
||||
|
||||
export const OpenBotDialogContainer = connect(
|
||||
mapStateToProps,
|
||||
null,
|
||||
mapDispatchToProps
|
||||
)(OpenBotDialog);
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
import { ActiveBotHelper } from './activeBotHelper';
|
||||
import { CommandServiceImpl } from '../../platform/commands/commandServiceImpl';
|
||||
import * as editorHelpers from '../../data/editorHelpers';
|
||||
import { store } from '../../data/store';
|
||||
import * as botHelpers from '../../data/botHelpers';
|
||||
import { SharedConstants } from '@bfemulator/app-shared';
|
||||
import { BotConfigWithPath } from '@bfemulator/sdk-shared';
|
||||
import { IEndpointService, ServiceTypes } from 'botframework-config/lib/schema';
|
||||
import { SharedConstants } from '@bfemulator/app-shared';
|
||||
import * as botHelpers from '../../data/botHelpers';
|
||||
import * as editorHelpers from '../../data/editorHelpers';
|
||||
import { store } from '../../data/store';
|
||||
import { CommandServiceImpl } from '../../platform/commands/commandServiceImpl';
|
||||
import { ActiveBotHelper } from './activeBotHelper';
|
||||
|
||||
jest.mock('../../ui/dialogs', () => ({
|
||||
AzureLoginPromptDialogContainer: function mock() {
|
||||
return undefined;
|
||||
},
|
||||
AzureLoginSuccessDialogContainer: function mock() {
|
||||
return undefined;
|
||||
},
|
||||
BotCreationDialog: function mock() {
|
||||
return undefined;
|
||||
},
|
||||
DialogService: { showDialog: () => Promise.resolve(true) },
|
||||
SecretPromptDialog: function mock() {
|
||||
return undefined;
|
||||
AzureLoginPromptDialogContainer: function mock() {
|
||||
return undefined;
|
||||
},
|
||||
AzureLoginSuccessDialogContainer: function mock() {
|
||||
return undefined;
|
||||
},
|
||||
BotCreationDialog: function mock() {
|
||||
return undefined;
|
||||
},
|
||||
DialogService: { showDialog: () => Promise.resolve(true) },
|
||||
SecretPromptDialog: function mock() {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
describe('ActiveBotHelper tests', () => {
|
||||
|
@ -228,6 +228,28 @@ describe('ActiveBotHelper tests', () => {
|
|||
ActiveBotHelper.confirmSwitchBot = backupConfirmSwitchBot;
|
||||
});
|
||||
|
||||
it('should throw an error when confirmAndOpenBotFromFile fails', async () => {
|
||||
jest.spyOn(ActiveBotHelper, 'browseForBotFile').mockRejectedValueOnce('oh noes!');
|
||||
try {
|
||||
await ActiveBotHelper.confirmAndOpenBotFromFile('');
|
||||
expect(false);
|
||||
} catch (e) {
|
||||
expect(e).not.toBeNull();
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw when confirmAndSwitchBots fails', async () => {
|
||||
jest.spyOn(CommandServiceImpl, 'call').mockRejectedValueOnce('oh noes!');
|
||||
jest.spyOn(botHelpers, 'getActiveBot').mockReturnValueOnce({path: ''});
|
||||
try {
|
||||
await ActiveBotHelper.confirmAndSwitchBots('');
|
||||
expect(false);
|
||||
} catch (e) {
|
||||
expect(e).not.toBeNull();
|
||||
}
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('confirmAndSwitchBots() functionality', async () => {
|
||||
const backupBotAlreadyOpen = ActiveBotHelper.botAlreadyOpen;
|
||||
const backupConfirmSwitchBot = ActiveBotHelper.confirmSwitchBot;
|
||||
|
|
|
@ -97,7 +97,7 @@ export const ActiveBotHelper = new class {
|
|||
CommandServiceImpl.remoteCall(SharedConstants.Commands.Electron.SetTitleBar, getBotDisplayName(bot))
|
||||
]);
|
||||
} catch (e) {
|
||||
const errMsg = `Error while setting active bot: ${e}`;
|
||||
const errMsg = `Error while setting active bot: ${ e }`;
|
||||
const notification = newNotification(errMsg);
|
||||
store.dispatch(beginAdd(notification));
|
||||
throw new Error(errMsg);
|
||||
|
@ -112,7 +112,7 @@ export const ActiveBotHelper = new class {
|
|||
CommandServiceImpl.remoteCall(SharedConstants.Commands.Electron.SetTitleBar, '');
|
||||
})
|
||||
.catch(err => {
|
||||
const errMsg = `Error while closing active bot: ${err}`;
|
||||
const errMsg = `Error while closing active bot: ${ err }`;
|
||||
const notification = newNotification(errMsg);
|
||||
store.dispatch(beginAdd(notification));
|
||||
throw new Error(errMsg);
|
||||
|
@ -159,7 +159,7 @@ export const ActiveBotHelper = new class {
|
|||
store.dispatch(NavBarActions.select(Constants.NAVBAR_BOT_EXPLORER));
|
||||
store.dispatch(ExplorerActions.showExplorer(true));
|
||||
} catch (err) {
|
||||
const errMsg = `Error during bot create: ${err}`;
|
||||
const errMsg = `Error during bot create: ${ err }`;
|
||||
const notification = newNotification(errMsg);
|
||||
store.dispatch(beginAdd(notification));
|
||||
throw new Error(errMsg);
|
||||
|
@ -194,34 +194,20 @@ export const ActiveBotHelper = new class {
|
|||
await CommandServiceImpl.call(SharedConstants.Commands.Bot.Switch, activeBot);
|
||||
return;
|
||||
}
|
||||
const result = this.confirmSwitchBot();
|
||||
|
||||
try {
|
||||
const result = this.confirmSwitchBot();
|
||||
|
||||
if (result) {
|
||||
try {
|
||||
store.dispatch(EditorActions.closeNonGlobalTabs());
|
||||
const bot = await CommandServiceImpl.remoteCall(SharedConstants.Commands.Bot.Open, filename)
|
||||
// Secret prompt dialog was closed
|
||||
.catch(_err => null);
|
||||
if (!bot) {
|
||||
return;
|
||||
}
|
||||
await CommandServiceImpl.remoteCall(SharedConstants.Commands.Bot.SetActive, bot);
|
||||
await CommandServiceImpl.call(SharedConstants.Commands.Bot.Load, bot);
|
||||
} catch (err) {
|
||||
console.error('Error while trying to open bot from file: ', err);
|
||||
throw new Error(`[confirmAndOpenBotFromFile] Error while trying to open bot from file: ${err}`);
|
||||
}
|
||||
if (result) {
|
||||
store.dispatch(EditorActions.closeNonGlobalTabs());
|
||||
const bot = await CommandServiceImpl.remoteCall(SharedConstants.Commands.Bot.Open, filename);
|
||||
if (!bot) {
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error while calling confirmSwitchBot: ', err);
|
||||
throw new Error(`[confirmAndOpenBotFromFile] Error while calling confirmSwitchBot: ${err}`);
|
||||
await CommandServiceImpl.remoteCall(SharedConstants.Commands.Bot.SetActive, bot);
|
||||
await CommandServiceImpl.call(SharedConstants.Commands.Bot.Load, bot);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error while calling browseForBotFile: ', err);
|
||||
throw new Error(`[confirmAndOpenBotFromFile] Error while calling browseForBotFile: ${err}`);
|
||||
throw new Error(`[confirmAndOpenBotFromFile] Error while calling browseForBotFile: ${ err }`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,13 +227,13 @@ export const ActiveBotHelper = new class {
|
|||
await CommandServiceImpl.call(
|
||||
SharedConstants.Commands.Emulator.NewLiveChat, currentActiveBot.services[0]);
|
||||
} catch (e) {
|
||||
throw new Error(`[confirmAndSwitchBots] Error while trying to open bot at ${botPath}: ${e}`);
|
||||
throw new Error(`[confirmAndSwitchBots] Error while trying to open bot at ${ botPath }: ${ e }`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: We need to think about merging this with confirmAndCreateBot
|
||||
console.log(`Switching to bot ${botPath}`);
|
||||
console.log(`Switching to bot ${ botPath }`);
|
||||
|
||||
try {
|
||||
// prompt the user to confirm the switch
|
||||
|
@ -261,7 +247,7 @@ export const ActiveBotHelper = new class {
|
|||
try {
|
||||
newActiveBot = await CommandServiceImpl.remoteCall(SharedConstants.Commands.Bot.Open, bot);
|
||||
} catch (e) {
|
||||
throw new Error(`[confirmAndSwitchBots] Error while trying to open bot at ${botPath}: ${e}`);
|
||||
throw new Error(`[confirmAndSwitchBots] Error while trying to open bot at ${ botPath }: ${ e }`);
|
||||
}
|
||||
} else {
|
||||
newActiveBot = bot;
|
||||
|
@ -300,7 +286,7 @@ export const ActiveBotHelper = new class {
|
|||
store.dispatch(ExplorerActions.showExplorer(true));
|
||||
}
|
||||
} catch (e) {
|
||||
const errMsg = `Error while trying to switch to bot: ${botPath}`;
|
||||
const errMsg = `Error while trying to switch to bot: ${ botPath }`;
|
||||
const notification = newNotification(errMsg);
|
||||
store.dispatch(beginAdd(notification));
|
||||
throw new Error(errMsg);
|
||||
|
@ -324,7 +310,7 @@ export const ActiveBotHelper = new class {
|
|||
}
|
||||
})
|
||||
.catch(err => {
|
||||
const errMsg = `Error while closing active bot: ${err}`;
|
||||
const errMsg = `Error while closing active bot: ${ err }`;
|
||||
const notification = newNotification(errMsg);
|
||||
store.dispatch(beginAdd(notification));
|
||||
throw new Error(errMsg);
|
||||
|
|
|
@ -40,20 +40,17 @@
|
|||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
& .explorer-empty-state {
|
||||
padding: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
& .open-bot {
|
||||
margin-top: 13px;
|
||||
margin-bottom: 26px;
|
||||
width: 180px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
& .empty-state-text {
|
||||
margin-top: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.explorer-empty-state {
|
||||
padding: 16px;
|
||||
margin-top: 13px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.open-bot {
|
||||
margin-top: 13px;
|
||||
margin-bottom: 26px;
|
||||
width: 180px;
|
||||
height: 26px;
|
||||
}
|
||||
|
|
|
@ -2,4 +2,3 @@
|
|||
export const botNotOpenExplorer: string;
|
||||
export const explorerEmptyState: string;
|
||||
export const openBot: string;
|
||||
export const emptyStateText: string;
|
||||
|
|
|
@ -40,6 +40,7 @@ import { beginAdd } from '../../../../data/action/notificationActions';
|
|||
import { bot } from '../../../../data/reducer/bot';
|
||||
import { chat } from '../../../../data/reducer/chat';
|
||||
import { CommandServiceImpl } from '../../../../platform/commands/commandServiceImpl';
|
||||
import { ActiveBotHelper } from '../../../helpers/activeBotHelper';
|
||||
import { BotNotOpenExplorer } from './botNotOpenExplorer';
|
||||
import { BotNotOpenExplorerContainer } from './botNotOpenExplorerContainer';
|
||||
|
||||
|
@ -63,27 +64,25 @@ describe('The EndpointExplorer component should', () => {
|
|||
let parent;
|
||||
let node;
|
||||
let mockDispatch;
|
||||
|
||||
let instance;
|
||||
beforeEach(() => {
|
||||
mockDispatch = jest.spyOn(mockStore, 'dispatch');
|
||||
parent = mount(<Provider store={ mockStore }>
|
||||
<BotNotOpenExplorerContainer/>
|
||||
</Provider>);
|
||||
node = parent.find(BotNotOpenExplorer);
|
||||
instance = node.instance();
|
||||
});
|
||||
|
||||
it('should show the OpenBotDialog when onOpenBotClick is called', async () => {
|
||||
const spy = jest.spyOn(CommandServiceImpl, 'call').mockResolvedValue(true);
|
||||
const instance = node.instance();
|
||||
await instance.onOpenBotClick();
|
||||
|
||||
expect(spy).toHaveBeenCalledWith(SharedConstants.Commands.UI.ShowOpenBotDialog);
|
||||
it('should make the appropriate calls when onCreateNewBotClick in called', async () => {
|
||||
const commandServiceSpy = jest.spyOn(CommandServiceImpl, 'call').mockResolvedValue(true);
|
||||
await instance.onCreateNewBotClick();
|
||||
expect(commandServiceSpy).toHaveBeenLastCalledWith(SharedConstants.Commands.UI.ShowBotCreationDialog);
|
||||
});
|
||||
|
||||
it('should send a notification if the call to onOpenBotClick fails', async () => {
|
||||
it('should send a notification when onCreateNewBotClick fails', async () => {
|
||||
const commandServiceSpy = jest.spyOn(CommandServiceImpl, 'call').mockRejectedValue('oh noes!');
|
||||
const instance = node.instance();
|
||||
await instance.onOpenBotClick();
|
||||
await instance.onCreateNewBotClick();
|
||||
const message = `An Error occurred on the Bot Not Open Explorer: oh noes!`;
|
||||
const notification = newNotification(message);
|
||||
const action = beginAdd(notification);
|
||||
|
@ -91,6 +90,25 @@ describe('The EndpointExplorer component should', () => {
|
|||
notification.id = jasmine.any(String) as any;
|
||||
expect(mockDispatch).toHaveBeenLastCalledWith(action);
|
||||
|
||||
expect(commandServiceSpy).toHaveBeenLastCalledWith(SharedConstants.Commands.UI.ShowOpenBotDialog);
|
||||
expect(commandServiceSpy).toHaveBeenLastCalledWith(SharedConstants.Commands.UI.ShowBotCreationDialog);
|
||||
});
|
||||
|
||||
it('should make the appropriate calls when onOpenBotFileClick in called', async () => {
|
||||
const spy = jest.spyOn(ActiveBotHelper, 'confirmAndOpenBotFromFile').mockResolvedValue(true);
|
||||
await instance.onOpenBotFileClick();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should send a notification when onOpenBotFileClick fails', async () => {
|
||||
const spy = jest.spyOn(ActiveBotHelper, 'confirmAndOpenBotFromFile').mockRejectedValue('oh noes!');
|
||||
await instance.onOpenBotFileClick();
|
||||
const message = `An Error occurred on the Bot Not Open Explorer: oh noes!`;
|
||||
const notification = newNotification(message);
|
||||
const action = beginAdd(notification);
|
||||
notification.timestamp = jasmine.any(Number) as any;
|
||||
notification.id = jasmine.any(String) as any;
|
||||
expect(mockDispatch).toHaveBeenLastCalledWith(action);
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -31,22 +31,21 @@
|
|||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
import { ExpandCollapse, ExpandCollapseContent, PrimaryButton } from '@bfemulator/ui-react';
|
||||
import { ExpandCollapse, ExpandCollapseContent } from '@bfemulator/ui-react';
|
||||
import * as React from 'react';
|
||||
import * as styles from './botNotOpenExplorer.scss';
|
||||
|
||||
export interface BotNotOpenExplorerProps {
|
||||
hasChat?: boolean;
|
||||
showOpenBotDialog: () => Promise<any>;
|
||||
openBotFile?: () => Promise<any>;
|
||||
showCreateNewBotDialog?: () => Promise<void>;
|
||||
sendNotification: (error: Error) => void;
|
||||
}
|
||||
|
||||
export class BotNotOpenExplorer extends React.Component<BotNotOpenExplorerProps, {}> {
|
||||
|
||||
public render() {
|
||||
const { hasChat } = this.props;
|
||||
const label = hasChat ? 'Services Not Available' : 'No Bot Opened';
|
||||
const message = hasChat ? 'You are in Direct Connect mode.' : 'You have not yet opened a bot.';
|
||||
const label = 'Services Not Available';
|
||||
return (
|
||||
<ul className={ styles.botNotOpenExplorer }>
|
||||
<li>
|
||||
|
@ -57,8 +56,10 @@ export class BotNotOpenExplorer extends React.Component<BotNotOpenExplorerProps,
|
|||
>
|
||||
<ExpandCollapseContent>
|
||||
<div className={ styles.explorerEmptyState }>
|
||||
<span className={ styles.emptyStateText }>{ message }</span>
|
||||
<PrimaryButton text={ 'Open Bot' } className={ styles.openBot } onClick={ this.onOpenBotClick }/>
|
||||
{ `To connect the Emulator services, ` }
|
||||
<a href="javascript:void(0);" onClick={ this.onOpenBotFileClick }>open a .bot file</a>
|
||||
{ ` or ` }
|
||||
<a href="javascript:void(0)" onClick={ this.onCreateNewBotClick }>create a new bot configuration</a>.
|
||||
</div>
|
||||
</ExpandCollapseContent>
|
||||
</ExpandCollapse>
|
||||
|
@ -67,9 +68,17 @@ export class BotNotOpenExplorer extends React.Component<BotNotOpenExplorerProps,
|
|||
);
|
||||
}
|
||||
|
||||
private onOpenBotClick = async () => {
|
||||
private onCreateNewBotClick = async () => {
|
||||
try {
|
||||
await this.props.showOpenBotDialog();
|
||||
await this.props.showCreateNewBotDialog();
|
||||
} catch (e) {
|
||||
this.props.sendNotification(e);
|
||||
}
|
||||
}
|
||||
|
||||
private onOpenBotFileClick = async () => {
|
||||
try {
|
||||
await this.props.openBotFile();
|
||||
} catch (e) {
|
||||
this.props.sendNotification(e);
|
||||
}
|
||||
|
|
|
@ -37,13 +37,15 @@ import { Action } from 'redux';
|
|||
import { beginAdd } from '../../../../data/action/notificationActions';
|
||||
import { RootState } from '../../../../data/store';
|
||||
import { CommandServiceImpl } from '../../../../platform/commands/commandServiceImpl';
|
||||
import { ActiveBotHelper } from '../../../helpers/activeBotHelper';
|
||||
import { BotNotOpenExplorer as BotNotOpenExplorerComp, BotNotOpenExplorerProps } from './botNotOpenExplorer';
|
||||
|
||||
const mapStateToProps = (state: RootState): any => ({
|
||||
hasChat: !!Object.keys(state.chat.chats).length
|
||||
hasChat: !!Object.keys(state.chat.chats).length,
|
||||
showCreateNewBotDialog: () => CommandServiceImpl.call(SharedConstants.Commands.UI.ShowBotCreationDialog),
|
||||
});
|
||||
const mapDispatchToProps = (dispatch: (action: Action) => void): BotNotOpenExplorerProps => ({
|
||||
showOpenBotDialog: (): Promise<any> => CommandServiceImpl.call(SharedConstants.Commands.UI.ShowOpenBotDialog),
|
||||
openBotFile: () => ActiveBotHelper.confirmAndOpenBotFromFile(),
|
||||
sendNotification: (error: Error) =>
|
||||
dispatch(beginAdd(newNotification(`An Error occurred on the Bot Not Open Explorer: ${ error }`))),
|
||||
});
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
}
|
||||
|
||||
.dialog {
|
||||
--error-text: #A1260D;
|
||||
--input-color: var(--neutral-12);
|
||||
--input-bg: var(--neutral-1);
|
||||
background: var(--dialog-bg);
|
||||
|
|
Загрузка…
Ссылка в новой задаче