Skip to content

Commit

Permalink
refactor: migrate snippet-callbacks to vue 2.7 (#1431)
Browse files Browse the repository at this point in the history
  • Loading branch information
CachedaCodes authored Mar 19, 2024
1 parent d10dc88 commit 168ff1d
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 63 deletions.
17 changes: 16 additions & 1 deletion packages/x-components/src/__tests__/bus.dummy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Dictionary } from '@empathyco/x-utils';
import { EmittedData, EventPayload, XPriorityBus } from '@empathyco/x-bus';
import { EmittedData, EventPayload, SubjectPayload, XPriorityBus } from '@empathyco/x-bus';
import { Subject } from 'rxjs';
import { WireMetadata, XEventsTypes } from '../wiring';

export class XDummyBus<
Expand All @@ -22,3 +23,17 @@ export class XDummyBus<
return Promise.resolve({ event, ...emittedPayload });
}
}

/**
* Dummy function to create an emitter for a given event.
*
* @param event - The event to create the emitter for.
*/
export function dummyCreateEmitter<SomeEvent extends keyof XEventsTypes>(
this: XPriorityBus<any, any>,
event: SomeEvent
): void {
this.emitters[event] = new Subject<
SubjectPayload<EventPayload<XEventsTypes, SomeEvent>, WireMetadata>
>();
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import { mount, Wrapper } from '@vue/test-utils';
import { installNewXPlugin } from '../../__tests__/utils';
import { baseSnippetConfig } from '../../views/base-config';
import { XEventListeners } from '../../x-installer/api/api.types';
import SnippetCallbacks from '../snippet-callbacks.vue';
import { bus } from '../../plugins/x-bus';
import { dummyCreateEmitter } from '../../__tests__/bus.dummy';

// Making bus not repeat subjects
jest.spyOn(bus, 'createEmitter' as any).mockImplementation(dummyCreateEmitter.bind(bus) as any);

function renderSnippetCallbacks({
callbacks = {}
}: RenderSnippetCallbacksOptions = {}): RenderSnippetCallbacksAPI {
const [, localVue] = installNewXPlugin();
const wrapper = mount(SnippetCallbacks, {
provide: {
snippetConfig: localVue.observable({ ...baseSnippetConfig, callbacks })
},
localVue
snippetConfig: { ...baseSnippetConfig, callbacks }
}
});

return {
wrapper
};
}

// TODO: Refactor in EMP-3380
// eslint-disable-next-line jest/no-disabled-tests
describe.skip('testing SnippetCallbacks component', () => {
describe('testing SnippetCallbacks component', () => {
beforeAll(() => {
jest.useFakeTimers();
});

it('executes a callback injected from the snippetConfig', () => {
const acceptedAQueryCallback = jest.fn(payload => payload);
const clickedColumnPickerCallback = jest.fn(payload => payload);
Expand All @@ -33,43 +37,42 @@ describe.skip('testing SnippetCallbacks component', () => {
}
});

wrapper.vm.$x.emit('UserAcceptedAQuery', 'lego');
bus.emit('UserAcceptedAQuery', 'lego');
jest.runAllTimers();

expect(acceptedAQueryCallback).toHaveBeenCalledTimes(1);
expect(acceptedAQueryCallback).toHaveBeenCalledWith('lego', {
location: undefined,
moduleName: null,
replaceable: true
});
expect(acceptedAQueryCallback).toHaveBeenCalledWith('lego', expect.any(Object));

expect(clickedColumnPickerCallback).not.toHaveBeenCalled();

wrapper.vm.$x.emit('UserClickedColumnPicker', 1);
bus.emit('UserClickedColumnPicker', 1);
jest.runAllTimers();

expect(acceptedAQueryCallback).toHaveBeenCalledTimes(1);

expect(clickedColumnPickerCallback).toHaveBeenCalledTimes(1);
expect(clickedColumnPickerCallback).toHaveBeenCalledWith(1, {
location: undefined,
moduleName: null,
replaceable: true
});
expect(clickedColumnPickerCallback).toHaveBeenCalledWith(1, expect.any(Object));

// Force unsubscribing
wrapper.destroy();
});

it('emits a SnippetCallbackExecuted event when a callback is executed', () => {
const acceptedAQueryCallback = jest.fn((payload: string) => payload + '1');
const clickedColumnPickerCallback = jest.fn((payload: number) => payload + 1);
const { wrapper } = renderSnippetCallbacks({
renderSnippetCallbacks({
callbacks: {
UserAcceptedAQuery: acceptedAQueryCallback,
UserClickedColumnPicker: clickedColumnPickerCallback
}
});

const eventSpy = jest.fn();
wrapper.vm.$x.on('SnippetCallbackExecuted').subscribe(eventSpy);
bus.on('SnippetCallbackExecuted').subscribe(eventSpy);

bus.emit('UserAcceptedAQuery', 'playmobil');
jest.runAllTimers();

wrapper.vm.$x.emit('UserAcceptedAQuery', 'playmobil');
expect(eventSpy).toHaveBeenCalledTimes(1);
expect(eventSpy).toHaveBeenCalledWith({
event: 'UserAcceptedAQuery',
Expand All @@ -78,7 +81,9 @@ describe.skip('testing SnippetCallbacks component', () => {
metadata: expect.any(Object)
});

wrapper.vm.$x.emit('UserClickedColumnPicker', 3);
bus.emit('UserClickedColumnPicker', 3);
jest.runAllTimers();

expect(eventSpy).toHaveBeenCalledTimes(2);
expect(eventSpy).toHaveBeenCalledWith({
event: 'UserClickedColumnPicker',
Expand Down
82 changes: 44 additions & 38 deletions packages/x-components/src/components/snippet-callbacks.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

<script lang="ts">
import { map } from '@empathyco/x-utils';
import { Component, Inject } from 'vue-property-decorator';
import Vue from 'vue';
import { computed, defineComponent } from 'vue';
import { WireMetadata } from '../wiring';
import { SnippetConfig, XEventListeners } from '../x-installer/api/api.types';
import { useHybridInject } from '../composables';
import { useXBus } from '../composables/use-x-bus';
import GlobalXBus from './global-x-bus.vue';
/**
Expand All @@ -16,44 +17,49 @@
*
* @public
*/
@Component({
components: { GlobalXBus }
})
export default class SnippetCallbacks extends Vue {
/**
* Injects {@link SnippetConfig} provided by an ancestor as snippetConfig.
*
* @internal
*/
@Inject('snippetConfig')
public snippetConfig!: SnippetConfig;
export default defineComponent({
name: 'SnippetCallbacks',
components: { GlobalXBus },
setup() {
const xBus = useXBus();
/**
* It maps all the callbacks provided by the snippetConfig and adds an emit to each one.
*
* @returns The event listeners with the {@link XEventsTypes.SnippetCallbackExecuted} emit in
* the callback.
*
* @internal
*
*/
protected get eventListeners(): XEventListeners {
const { callbacks } = this.snippetConfig;
return callbacks
? map(callbacks, (eventName, callback) => {
return (payload: unknown, metadata: WireMetadata) => {
const callbackReturn = callback(payload as never, metadata);
this.$x.emit('SnippetCallbackExecuted', {
event: eventName,
callbackReturn,
payload: payload as never,
metadata
});
};
})
: ({} as XEventListeners);
/**
* Injects {@link SnippetConfig} provided by an ancestor as snippetConfig.
*
* @internal
*/
const snippetConfig = useHybridInject<SnippetConfig>('snippetConfig');
/**
* It maps all the callbacks provided by the snippetConfig and adds an emit to each one.
*
* @returns The event listeners with the {@link XEventsTypes.SnippetCallbackExecuted} emit in
* the callback.
*
* @internal
*
*/
const eventListeners = computed<XEventListeners>(() => {
const callbacks = snippetConfig?.callbacks;
return callbacks
? map(callbacks, (eventName, callback) => {
return (payload: unknown, metadata: WireMetadata) => {
const callbackReturn = callback(payload as never, metadata);
xBus.emit('SnippetCallbackExecuted', {
event: eventName,
callbackReturn,
payload: payload as never,
metadata
});
};
})
: ({} as XEventListeners);
});
return { eventListeners };
}
}
});
</script>

<docs lang="mdx">
Expand Down

0 comments on commit 168ff1d

Please sign in to comment.