diff --git a/frontend/src/pages/RunList.test.tsx b/frontend/src/pages/RunList.test.tsx index 3cee3842b9f..5f524e48b0d 100644 --- a/frontend/src/pages/RunList.test.tsx +++ b/frontend/src/pages/RunList.test.tsx @@ -381,6 +381,50 @@ describe('RunList', () => { expect(Apis.runServiceApi.getRun).toHaveBeenCalledWith('run2'); }); + it('loads given and filtered list of runs only', async () => { + mockNRuns(5, {}); + const props = generateProps(); + props.runIdListMask = ['filterRun1', 'filterRun2', 'notincluded']; + tree = shallow(); + await (tree.instance() as RunListTest)._loadRuns({ + filter: encodeURIComponent( + JSON.stringify({ + predicates: [{ key: 'name', op: PredicateOp.ISSUBSTRING, string_value: 'filterRun' }], + }), + ), + }); + expect(tree.state('runs')).toMatchObject([ + { + run: { name: 'run with id: filterRun1' }, + }, + { + run: { name: 'run with id: filterRun2' }, + }, + ]); + }); + + it('loads given and filtered list of runs only through multiple filters', async () => { + mockNRuns(5, {}); + const props = generateProps(); + props.runIdListMask = ['filterRun1', 'filterRun2', 'notincluded1']; + tree = shallow(); + await (tree.instance() as RunListTest)._loadRuns({ + filter: encodeURIComponent( + JSON.stringify({ + predicates: [ + { key: 'name', op: PredicateOp.ISSUBSTRING, string_value: 'filterRun' }, + { key: 'name', op: PredicateOp.ISSUBSTRING, string_value: '1' }, + ], + }), + ), + }); + expect(tree.state('runs')).toMatchObject([ + { + run: { name: 'run with id: filterRun1' }, + }, + ]); + }); + it('adds metrics columns', async () => { mockNRuns(2, { run: { diff --git a/frontend/src/pages/RunList.tsx b/frontend/src/pages/RunList.tsx index a2dc8b45f0b..753c89863ff 100644 --- a/frontend/src/pages/RunList.tsx +++ b/frontend/src/pages/RunList.tsx @@ -331,9 +331,24 @@ class RunList extends React.PureComponent { if (Array.isArray(this.props.runIdListMask)) { displayRuns = this.props.runIdListMask.map(id => ({ run: { id } })); - // listRuns doesn't currently support batching by IDs, so in this case we retrieve each run - // individually. + const filter = JSON.parse( + decodeURIComponent(request.filter || '{"predicates": []}'), + ) as ApiFilter; + // listRuns doesn't currently support batching by IDs, so in this case we retrieve and filter + // each run individually. await this._getAndSetRuns(displayRuns); + const predicates = filter.predicates?.filter( + p => p.key === 'name' && p.op === PredicateOp.ISSUBSTRING, + ); + const substrings = predicates?.map(p => p.string_value?.toLowerCase() || '') || []; + displayRuns = displayRuns.filter(runDetail => { + for (const sub of substrings) { + if (!runDetail?.run?.name?.toLowerCase().includes(sub)) { + return false; + } + } + return true; + }); } else { // Load all runs if (this.props.storageState) {