Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

show message when nothing has been inspected yet #1290

Merged
merged 2 commits into from Feb 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 3 additions & 9 deletions .eslintrc.js
@@ -1,9 +1,5 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:typescript/recommended',
'plugin:prettier/recommended',
],
extends: ['eslint:recommended', 'plugin:typescript/recommended', 'plugin:prettier/recommended'],
plugins: ['import', 'notice'],
env: {
browser: true,
Expand Down Expand Up @@ -39,10 +35,7 @@ module.exports = {
'typescript/no-empty-interface': 'warn',
'typescript/no-object-literal-type-assertion': 'off',
'typescript/no-parameter-properties': 'off',
'typescript/no-use-before-define': [
'error',
{ functions: false, classes: false },
],
'typescript/no-use-before-define': ['error', { functions: false, classes: false }],
},
overrides: [
{
Expand All @@ -56,6 +49,7 @@ module.exports = {
},
rules: {
'typescript/class-name-casing': 'off',
'typescript/no-explicit-any': 'off',
},
},
],
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [docs] Added changelog in PR [#1230](https://github.com/Microsoft/BotFramework-Emulator/pull/1230)
- [style] 💅 Integrated prettier and eslint in PR [#1240](https://github.com/Microsoft/BotFramework-Emulator/pull/1240)
- [main / client] Added app-wide instrumentation in PR [#1251](https://github.com/Microsoft/BotFramework-Emulator/pull/1251)
- [client] Show a message when nothing has been inspected yet, in PR [#1290](https://github.com/Microsoft/BotFramework-Emulator/pull/1290)

### Fixed
- [main] Fixed issue [(#1257)](https://github.com/Microsoft/BotFramework-Emulator/issues/1257) where opening transcripts via the command line was crashing the app, in PR [#1269](https://github.com/Microsoft/BotFramework-Emulator/pull/1269).
Expand Down
Expand Up @@ -40,3 +40,7 @@
white-space: pre-wrap;
user-select: text;
}

.nothing-inspected {
padding: 0 16px;
}
Expand Up @@ -5,3 +5,4 @@ export const accessoryButton: string;
export const accessories: string;
export const accessoryButtonIcon: string;
export const inspectorContainer: string;
export const nothingInspected: string;
Expand Up @@ -254,7 +254,9 @@ const mockExtensions = [
},
];
ExtensionManager.addExtension(mockExtensions[0], '1234');
jest.mock('./inspector.scss', () => ({}));
jest.mock('./inspector.scss', () => ({
webViewContainer: 'webViewContainer',
}));

describe('The Inspector component', () => {
const src = 'file:\\\\c:\\some\\path';
Expand All @@ -268,140 +270,170 @@ describe('The Inspector component', () => {
};
return el;
};

beforeEach(() => {
mockStore.dispatch(switchTheme('light', ['vars.css', 'light.css']));
mockStore.dispatch(loadBotInfos([mockState.bot]));
mockStore.dispatch(setActiveBot(mockState.bot as any));
mockRemoteCallsMade = [];

parent = mount(
<Provider store={mockStore}>
<InspectorContainer document={mockState.document} inspector={{ src }} />
</Provider>
);

node = parent.find(Inspector);
});

it('should render deeply', () => {
expect(parent.find(InspectorContainer)).not.toBe(null);
expect(node).not.toBe(null);
});

it('should render accessory button when accessory buttons exist in the config', () => {
const buttons = node.find('button');
expect(buttons.length).not.toBe(0);
});
describe('when there are no objects to be inspected', () => {
beforeEach(() => {
const docWithoutInspectorObjs = {
...mockState.document,
inspectorObjects: [],
};

parent = mount(
<Provider store={mockStore}>
<InspectorContainer document={docWithoutInspectorObjs} inspector={{ src }} />
</Provider>
);

node = parent.find(Inspector);
});

it('should enable/disable the accessory button when asked to do so by the extension', () => {
const instance = node.instance();
instance.enableAccessory('train', false);
expect(instance.state.buttons[0].enabled).toBeFalsy();
it('shows a helpful message', () => {
expect(node.text()).toMatch(/click on a log item/i);
});

instance.enableAccessory('train', true);
expect(instance.state.buttons[0].enabled).toBeTruthy();
it('does not render a webview container', () => {
expect(node.find('.webViewContainer').exists()).toBe(false);
});
});

it('should set the accessory state when asked to do so by the extension', () => {
const instance = node.instance();
instance.setAccessoryState('train', 'working');
describe('when there is an object to be inspected', () => {
beforeEach(() => {
parent = mount(
<Provider store={mockStore}>
<InspectorContainer document={mockState.document} inspector={{ src }} />
</Provider>
);

expect(instance.state.buttons[0].state).toEqual('working');
});
node = parent.find(Inspector);
});

it('should set the inspector title when asked to do so by the extension', () => {
const instance = node.instance();
instance.setInspectorTitle('Yo!');
it('should render deeply', () => {
expect(parent.find(InspectorContainer)).not.toBe(null);
expect(node).not.toBe(null);
});

expect(instance.state.title).toBe('Yo!');
});
it('should render accessory button when accessory buttons exist in the config', () => {
const buttons = node.find('button');
expect(buttons.length).not.toBe(0);
});

it('should send the initialization stack to the inspector when the dom is ready', () => {
const instance = node.instance();
const instanceSpy = jest.spyOn(instance, 'sendInitializationStackToInspector');
const event = { currentTarget: { removeEventListener: () => true } };
const eventSpy = jest.spyOn(event.currentTarget, 'removeEventListener');
it('should enable/disable the accessory button when asked to do so by the extension', () => {
const instance = node.instance();
instance.enableAccessory('train', false);
expect(instance.state.buttons[0].enabled).toBeFalsy();

instance.onWebViewDOMReady(event as any);
expect(instanceSpy).toHaveBeenCalled();
expect(eventSpy).toHaveBeenCalled();
});
instance.enableAccessory('train', true);
expect(instance.state.buttons[0].enabled).toBeTruthy();
});

describe('should handle the ipc message', () => {
let instance;
let event;
let dateNow;
it('should set the accessory state when asked to do so by the extension', () => {
const instance = node.instance();
instance.setAccessoryState('train', 'working');

beforeAll(() => {
dateNow = Date.now;
Date.now = () => 1;
expect(instance.state.buttons[0].state).toEqual('working');
});

afterAll(() => {
Date.now = dateNow;
});
it('should set the inspector title when asked to do so by the extension', () => {
const instance = node.instance();
instance.setInspectorTitle('Yo!');

beforeEach(() => {
instance = node.instance();
event = { channel: '', args: [1, 2] };
expect(instance.state.title).toBe('Yo!');
});

it('"enable-accessory"', () => {
event.channel = 'enable-accessory';
const spy = jest.spyOn(instance, 'enableAccessory');
instance.ipcMessageEventHandler(event);
it('should send the initialization stack to the inspector when the dom is ready', () => {
const instance = node.instance();
const instanceSpy = jest.spyOn(instance, 'sendInitializationStackToInspector');
const event = { currentTarget: { removeEventListener: () => true } };
const eventSpy = jest.spyOn(event.currentTarget, 'removeEventListener');

expect(spy).toHaveBeenCalledWith(event.args[0], event.args[1]);
instance.onWebViewDOMReady(event as any);
expect(instanceSpy).toHaveBeenCalled();
expect(eventSpy).toHaveBeenCalled();
});

it('"set-accessory-state"', () => {
event.channel = 'set-accessory-state';
const spy = jest.spyOn(instance, 'setAccessoryState');
describe('should handle the ipc message', () => {
let instance;
let event;
let dateNow;

instance.ipcMessageEventHandler(event);
beforeAll(() => {
dateNow = Date.now;
Date.now = () => 1;
});

expect(spy).toHaveBeenCalledWith(event.args[0], event.args[1]);
});
afterAll(() => {
Date.now = dateNow;
});

it('"set-inspector-title"', () => {
event.channel = 'set-inspector-title';
const titleSpy = jest.spyOn(instance, 'setInspectorTitle');
const stateSpy = jest.spyOn(instance, 'setState');
beforeEach(() => {
instance = node.instance();
event = { channel: '', args: [1, 2] };
});

instance.ipcMessageEventHandler(event);
it('"enable-accessory"', () => {
event.channel = 'enable-accessory';
const spy = jest.spyOn(instance, 'enableAccessory');
instance.ipcMessageEventHandler(event);

expect(stateSpy).toHaveBeenCalledWith({ titleOverride: event.args[0] });
expect(titleSpy).toHaveBeenCalledWith(event.args[0]);
});
expect(spy).toHaveBeenCalledWith(event.args[0], event.args[1]);
});

it('"logger.log" or "logger.error"', () => {
event.channel = 'logger.log';
const logSpy = jest.spyOn(LogService, 'logToDocument');
const inspectorName = mockExtensions[0].name;
const text = `[${inspectorName}] ${event.args[0]}`;
instance.ipcMessageEventHandler(event);
it('"set-accessory-state"', () => {
event.channel = 'set-accessory-state';
const spy = jest.spyOn(instance, 'setAccessoryState');

expect(logSpy).toHaveBeenCalledWith(mockState.document.documentId, logEntry(textItem(LogLevel.Info, text)));
});
instance.ipcMessageEventHandler(event);

expect(spy).toHaveBeenCalledWith(event.args[0], event.args[1]);
});

it('"set-inspector-title"', () => {
event.channel = 'set-inspector-title';
const titleSpy = jest.spyOn(instance, 'setInspectorTitle');
const stateSpy = jest.spyOn(instance, 'setState');

instance.ipcMessageEventHandler(event);

expect(stateSpy).toHaveBeenCalledWith({ titleOverride: event.args[0] });
expect(titleSpy).toHaveBeenCalledWith(event.args[0]);
});

it('"track-event"', () => {
event.channel = 'track-event';
event.args[0] = 'someEvent';
event.args[1] = { some: 'data' };
instance.ipcMessageEventHandler(event);
it('"logger.log" or "logger.error"', () => {
event.channel = 'logger.log';
const logSpy = jest.spyOn(LogService, 'logToDocument');
const inspectorName = mockExtensions[0].name;
const text = `[${inspectorName}] ${event.args[0]}`;
instance.ipcMessageEventHandler(event);

expect(mockRemoteCallsMade).toHaveLength(1);
expect(mockRemoteCallsMade[0]).toEqual({
commandName: SharedConstants.Commands.Telemetry.TrackEvent,
args: ['someEvent', { some: 'data' }],
expect(logSpy).toHaveBeenCalledWith(mockState.document.documentId, logEntry(textItem(LogLevel.Info, text)));
});

event.args[1] = undefined;
instance.ipcMessageEventHandler(event);
expect(mockRemoteCallsMade).toHaveLength(2);
expect(mockRemoteCallsMade[1]).toEqual({
commandName: SharedConstants.Commands.Telemetry.TrackEvent,
args: ['someEvent', {}],
it('"track-event"', () => {
event.channel = 'track-event';
event.args[0] = 'someEvent';
event.args[1] = { some: 'data' };
instance.ipcMessageEventHandler(event);

expect(mockRemoteCallsMade).toHaveLength(1);
expect(mockRemoteCallsMade[0]).toEqual({
commandName: SharedConstants.Commands.Telemetry.TrackEvent,
args: ['someEvent', { some: 'data' }],
});

event.args[1] = undefined;
instance.ipcMessageEventHandler(event);
expect(mockRemoteCallsMade).toHaveLength(2);
expect(mockRemoteCallsMade[1]).toEqual({
commandName: SharedConstants.Commands.Telemetry.TrackEvent,
args: ['someEvent', {}],
});
});
});
});
Expand Down