From e7f0cd28f3493443485eb5f9a723ed1f1382b121 Mon Sep 17 00:00:00 2001 From: Jai Bhagat Date: Mon, 26 Jul 2021 17:23:21 -0400 Subject: [PATCH] edit fuzzy search callback logic Namespaces are set-up in Nomad to be an object that has an id property. However, namespaces actually don't have that shape. Our search was expecting a namespace object, but we actually don't have a namespace assigned to jobs in our config and namespace is set to null. Normally, these namespaces would be set to default, but that would require us to refactor our Mirage config if we wanted to assert that namespaces are 'default' and not null. So this is a bandaid solution. --- ui/app/components/global-search/control.js | 77 ++++++++++++++-------- ui/mirage/config.js | 4 +- ui/tests/acceptance/search-test.js | 50 ++++++++++---- 3 files changed, 88 insertions(+), 43 deletions(-) diff --git a/ui/app/components/global-search/control.js b/ui/app/components/global-search/control.js index 5a100ded4..653617cdd 100644 --- a/ui/app/components/global-search/control.js +++ b/ui/app/components/global-search/control.js @@ -58,32 +58,40 @@ export default class GlobalSearchControl extends Component { const allTaskGroupResults = results.Matches.groups || []; const allCSIPluginResults = results.Matches.plugins || []; - const jobResults = allJobResults.slice(0, MAXIMUM_RESULTS).map(({ ID: name, Scope: [ namespace, id ]}) => ({ - type: 'job', - id, - namespace, - label: `${name} @ ${namespace}`, - })); + const jobResults = allJobResults + .slice(0, MAXIMUM_RESULTS) + .map(({ ID: name, Scope: [namespace, id] }) => ({ + type: 'job', + id, + namespace, + label: `${name} > ${namespace}`, + })); - const nodeResults = allNodeResults.slice(0, MAXIMUM_RESULTS).map(({ ID: name, Scope: [ id ]}) => ({ - type: 'node', - id, - label: name, - })); + const nodeResults = allNodeResults + .slice(0, MAXIMUM_RESULTS) + .map(({ ID: name, Scope: [id] }) => ({ + type: 'node', + id, + label: name, + })); - const allocationResults = allAllocationResults.slice(0, MAXIMUM_RESULTS).map(({ ID: name, Scope: [ namespace, id ]}) => ({ - type: 'allocation', - id, - label: `${name} @ ${namespace}`, - })); + const allocationResults = allAllocationResults + .slice(0, MAXIMUM_RESULTS) + .map(({ ID: name, Scope: [namespace, id] }) => ({ + type: 'allocation', + id, + label: `${name} > ${namespace}`, + })); - const taskGroupResults = allTaskGroupResults.slice(0, MAXIMUM_RESULTS).map(({ ID: id, Scope: [ namespace, jobId ]}) => ({ - type: 'task-group', - id, - namespace, - jobId, - label: id, - })); + const taskGroupResults = allTaskGroupResults + .slice(0, MAXIMUM_RESULTS) + .map(({ ID: id, Scope: [namespace, jobId] }) => ({ + type: 'task-group', + id, + namespace, + jobId, + label: id, + })); const csiPluginResults = allCSIPluginResults.slice(0, MAXIMUM_RESULTS).map(({ ID: id }) => ({ type: 'plugin', @@ -109,17 +117,32 @@ export default class GlobalSearchControl extends Component { options: nodeResults, }, { - groupName: resultsGroupLabel('Allocations', allocationResults, allAllocationResults, allocationsTruncated), + groupName: resultsGroupLabel( + 'Allocations', + allocationResults, + allAllocationResults, + allocationsTruncated + ), options: allocationResults, }, { - groupName: resultsGroupLabel('Task Groups', taskGroupResults, allTaskGroupResults, taskGroupsTruncated), + groupName: resultsGroupLabel( + 'Task Groups', + taskGroupResults, + allTaskGroupResults, + taskGroupsTruncated + ), options: taskGroupResults, }, { - groupName: resultsGroupLabel('CSI Plugins', csiPluginResults, allCSIPluginResults, csiPluginsTruncated), + groupName: resultsGroupLabel( + 'CSI Plugins', + csiPluginResults, + allCSIPluginResults, + csiPluginsTruncated + ), options: csiPluginResults, - } + }, ]; }) search; diff --git a/ui/mirage/config.js b/ui/mirage/config.js index 3e26e3bf2..e1ce1847c 100644 --- a/ui/mirage/config.js +++ b/ui/mirage/config.js @@ -612,7 +612,7 @@ export default function() { const transformedAllocs = matchedAllocs.models.map(alloc => ({ ID: alloc.name, - Scope: [(alloc.namespace || {}).id, alloc.id], + Scope: [alloc.namespace || 'default', alloc.id], })); const transformedGroups = matchedGroups.models.map(group => ({ @@ -622,7 +622,7 @@ export default function() { const transformedJobs = matchedJobs.models.map(job => ({ ID: job.name, - Scope: [job.namespace, job.id], + Scope: [job.namespace || 'default', job.id], })); const transformedNodes = matchedNodes.models.map(node => ({ diff --git a/ui/tests/acceptance/search-test.js b/ui/tests/acceptance/search-test.js index c1380f218..45238e954 100644 --- a/ui/tests/acceptance/search-test.js +++ b/ui/tests/acceptance/search-test.js @@ -16,8 +16,19 @@ module('Acceptance | search', function(hooks) { server.create('node', { name: 'xyz' }); const otherNode = server.create('node', { name: 'ghi' }); - server.create('job', { id: 'vwxyz', namespaceId: 'default', groupsCount: 1, groupTaskCount: 1 }); - server.create('job', { id: 'xyz', name: 'xyz job', namespaceId: 'default', groupsCount: 1, groupTaskCount: 1 }); + server.create('job', { + id: 'vwxyz', + namespaceId: 'default', + groupsCount: 1, + groupTaskCount: 1, + }); + server.create('job', { + id: 'xyz', + name: 'xyz job', + namespaceId: 'default', + groupsCount: 1, + groupTaskCount: 1, + }); server.create('job', { id: 'abc', namespaceId: 'default', groupsCount: 1, groupTaskCount: 1 }); const firstAllocation = server.schema.allocations.all().models[0]; @@ -35,8 +46,8 @@ module('Acceptance | search', function(hooks) { search.groups[0].as(jobs => { assert.equal(jobs.name, 'Jobs (2)'); assert.equal(jobs.options.length, 2); - assert.equal(jobs.options[0].text, 'vwxyz @ default'); - assert.equal(jobs.options[1].text, 'xyz job @ default'); + assert.equal(jobs.options[0].text, 'vwxyz > default'); + assert.equal(jobs.options[1].text, 'xyz job > default'); }); search.groups[1].as(clients => { @@ -70,7 +81,10 @@ module('Acceptance | search', function(hooks) { assert.equal(currentURL(), `/clients/${otherNode.id}`); await selectSearch(Layout.navbar.search.scope, firstAllocation.name); - assert.equal(Layout.navbar.search.groups[2].options[0].text, `${firstAllocation.name} @ ${firstAllocation.namespace}`); + assert.equal( + Layout.navbar.search.groups[2].options[0].text, + `${firstAllocation.name} > ${firstAllocation.namespace}` + ); await Layout.navbar.search.groups[2].options[0].click(); assert.equal(currentURL(), `/allocations/${firstAllocation.id}`); @@ -83,20 +97,24 @@ module('Acceptance | search', function(hooks) { await Layout.navbar.search.groups[4].options[0].click(); assert.equal(currentURL(), '/csi/plugins/xyz-plugin'); - const fuzzySearchQueries = server.pretender.handledRequests - .filterBy('url', '/v1/search/fuzzy'); + const fuzzySearchQueries = server.pretender.handledRequests.filterBy('url', '/v1/search/fuzzy'); - const featureDetectionQueries = fuzzySearchQueries - .filter(request => request.requestBody.includes('feature-detection-query')); + const featureDetectionQueries = fuzzySearchQueries.filter(request => + request.requestBody.includes('feature-detection-query') + ); - assert.ok(featureDetectionQueries.length, 1, 'expect the feature detection query to only run once'); + assert.ok( + featureDetectionQueries.length, + 1, + 'expect the feature detection query to only run once' + ); const realFuzzySearchQuery = fuzzySearchQueries[1]; assert.deepEqual(JSON.parse(realFuzzySearchQuery.requestBody), { - 'Context': 'all', - 'Namespace': '*', - 'Text': 'xy' + Context: 'all', + Namespace: '*', + Text: 'xy', }); }); @@ -106,7 +124,11 @@ module('Acceptance | search', function(hooks) { await selectSearch(Layout.navbar.search.scope, 'q'); assert.ok(Layout.navbar.search.noOptionsShown); - assert.equal(server.pretender.handledRequests.filterBy('url', '/v1/search/fuzzy').length, 1, 'expect the feature detection query'); + assert.equal( + server.pretender.handledRequests.filterBy('url', '/v1/search/fuzzy').length, + 1, + 'expect the feature detection query' + ); }); test('when fuzzy search is disabled on the server, the search control is hidden', async function(assert) {