Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Fixed
- [main] Fixed an issue where uploaded attachments weren't being encoded and decoded properly in PR [1678](https://github.com/microsoft/BotFramework-Emulator/pull/1678)
- [client] Fixed issue where adaptive card inputs were being reset when clicking or typing within adaptive card input fields in PR [1681](https://github.com/microsoft/BotFramework-Emulator/pull/1681)

## v4.5.0 - 2019 - 07 - 11
## Added
Expand Down
59 changes: 35 additions & 24 deletions packages/app/client/src/ui/editor/emulator/parts/chat/chat.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ import { chat } from '../../../../../data/reducer/chat';
import { editor } from '../../../../../data/reducer/editor';
import { clientAwareSettings } from '../../../../../data/reducer/clientAwareSettingsReducer';
import { BotCommands } from '../../../../../commands/botCommands';
import {
setInspectorObjects,
showContextMenuForActivity,
setHighlightedObjects,
} from '../../../../../data/action/chatActions';

import webChatStyleOptions from './webChatTheme';
import { ChatContainer } from './chatContainer';
Expand Down Expand Up @@ -250,10 +255,12 @@ describe('<ChatContainer />', () => {
});

describe('event handlers', () => {
let dispatchSpy;
let dispatchSpy: jest.SpyInstance;

beforeEach(() => {
dispatchSpy = jest.spyOn(mockStore, 'dispatch').mockReturnValue(true);
});

it('should invoke the appropriate functions defined in the props', () => {
const next = () => (kids: any) => kids;
const chat = render({ document: { ...defaultDocument, mode: 'debug' } as any });
Expand All @@ -269,31 +276,35 @@ describe('event handlers', () => {
const middleware = webChat.prop('activityMiddleware') as any;
const children = 'a child node';
const activityWrapper = mount(middleware()(next)(card)(children));

// keydown on activity
activityWrapper.simulate('keyDown', { key: ' ', target: { tagName: 'DIV', classList: [] } });
expect(dispatchSpy).toHaveBeenCalledWith({
payload: {
documentId: undefined,
objs: [
{
id: 'activity-id',
showInInspector: true,
type: 'trace',
value: { type: 'event' },
valueType: 'https://www.botframework.com/schemas/botState',
},
],
},
type: 'CHAT/INSPECTOR/OBJECTS/SET',
});
expect(dispatchSpy).toHaveBeenCalledWith(setHighlightedObjects(undefined, []));
expect(dispatchSpy).toHaveBeenCalledWith(
setInspectorObjects(undefined, { ...card.activity, showInInspector: true })
);

// hitting spacebar on input field within adaptive card
dispatchSpy.mockClear();
activityWrapper.simulate('keyDown', { key: ' ', target: { tagName: 'INPUT', classList: [] } });
expect(dispatchSpy).not.toHaveBeenCalled();

// click on activity
dispatchSpy.mockClear();
activityWrapper.simulate('click', { target: { tagName: 'DIV', classList: [] } });
expect(dispatchSpy).toHaveBeenCalledWith({
payload: {
documentId: undefined,
objs: [{ showInInspector: true }],
},
type: 'CHAT/INSPECTOR/OBJECTS/SET',
});
expect(dispatchSpy).toHaveBeenCalledWith(setHighlightedObjects(undefined, []));
expect(dispatchSpy).toHaveBeenCalledWith(
setInspectorObjects(undefined, { ...card.activity, showInInspector: true })
);

// click on input field within adaptive card
dispatchSpy.mockClear();
activityWrapper.simulate('click', { target: { tagName: 'INPUT', classList: [] } });
expect(dispatchSpy).not.toHaveBeenCalled();

// show context menu for activity
dispatchSpy.mockClear();
activityWrapper.simulate('contextmenu', { target: { tagName: 'DIV', classList: [] } });
expect(dispatchSpy).toHaveBeenCalledWith({ payload: undefined, type: 'CHAT/CONTEXT_MENU/SHOW' });
expect(dispatchSpy).toHaveBeenCalledWith(showContextMenuForActivity(card.activity));
});
});
17 changes: 12 additions & 5 deletions packages/app/client/src/ui/editor/emulator/parts/chat/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ export interface ChatProps {
}

interface ChatState {
selectedActivity?: Activity;
highlightedActivities?: Activity[];
document?: ChatDocument;
}

export class Chat extends Component<ChatProps, ChatState> {
Expand All @@ -84,8 +82,6 @@ export class Chat extends Component<ChatProps, ChatState> {
selectedActivity,
]);
return {
document: newProps.document,
selectedActivity,
highlightedActivities,
};
}
Expand Down Expand Up @@ -245,7 +241,6 @@ export class Chat extends Component<ChatProps, ChatState> {

protected updateSelectedActivity(id: string): void {
const selectedActivity: Activity & { showInInspector?: boolean } = this.activityMap[id];
this.setState({ selectedActivity });
this.props.setInspectorObject(this.props.document.documentId, { ...selectedActivity, showInInspector: true });
}

Expand All @@ -254,6 +249,12 @@ export class Chat extends Component<ChatProps, ChatState> {
}

private onItemRendererClick = (event: MouseEvent<HTMLDivElement | HTMLButtonElement>): void => {
// if we click inside of an input within an adaptive card, we want to avoid selecting the activity
// because it will cause a Web Chat re-render which will wipe the adaptive card state
const { target = { tagName: '' } } = event;
if ((target as HTMLElement).tagName === 'INPUT') {
return;
}
const { activityId } = (event.currentTarget as any).dataset;
this.updateSelectedActivity(activityId);
};
Expand All @@ -262,6 +263,12 @@ export class Chat extends Component<ChatProps, ChatState> {
if (event.key !== ' ' && event.key !== 'Enter') {
return;
}
// if we type inside of an input within an adaptive card, we want to avoid selecting the activity
// on spacebar because it will cause a Web Chat re-render which will wipe the adaptive card state
const { target = { tagName: '' } } = event;
if (event.key === ' ' && (target as HTMLElement).tagName === 'INPUT') {
return;
}
const { activityId } = (event.currentTarget as any).dataset;
this.updateSelectedActivity(activityId);
};
Expand Down