diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js index ffa1557d2b54ed..075628d94a8267 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js @@ -108,6 +108,55 @@ describe('switch', () => { expectObservable(fn(context, args)).toBe('(0|)', [result]) ); }); + + it('should support partial results', () => { + testScheduler.run(({ cold, expectObservable }) => { + const context = 'foo'; + const case1 = cold('--ab-c-', { + a: { + type: 'case', + matches: false, + result: 1, + }, + b: { + type: 'case', + matches: true, + result: 2, + }, + c: { + type: 'case', + matches: false, + result: 3, + }, + }); + const case2 = cold('-a--bc-', { + a: { + type: 'case', + matches: true, + result: 4, + }, + b: { + type: 'case', + matches: true, + result: 5, + }, + c: { + type: 'case', + matches: true, + result: 6, + }, + }); + const expected = ' --abc(de)-'; + const args = { case: [() => case1, () => case2] }; + expectObservable(fn(context, args)).toBe(expected, { + a: 4, + b: 2, + c: 2, + d: 5, + e: 6, + }); + }); + }); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts index f4e6c92c91cb60..31e9d46341869d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { Observable, defer, from, of } from 'rxjs'; -import { concatMap, filter, merge, pluck, take } from 'rxjs/operators'; +import { Observable, combineLatest, defer, of } from 'rxjs'; +import { concatMap } from 'rxjs/operators'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { Case } from '../../../types'; import { getFunctionHelp } from '../../../i18n'; @@ -43,12 +43,16 @@ export function switchFn(): ExpressionFunctionDefinition< }, }, fn(input, args) { - return from(args.case ?? []).pipe( - concatMap((item) => item()), - filter(({ matches }) => matches), - pluck('result'), - merge(defer(() => args.default?.() ?? of(input))), - take(1) + const cases = args.case?.map((item) => defer(() => item())) ?? []; + const cases$ = cases.length ? combineLatest(cases) : of([]); + + return cases$.pipe( + concatMap((items) => { + const item = items.find(({ matches }) => matches); + const item$ = item && of(item.result); + + return item$ ?? args.default?.() ?? of(input); + }) ); }, };