Skip to content

Commit

Permalink
edit fuzzy search callback logic
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ChaiWithJai committed Jul 26, 2021
1 parent d3bf103 commit 2649d19
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 46 deletions.
83 changes: 53 additions & 30 deletions ui/app/components/global-search/control.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 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 taskGroupResults = allTaskGroupResults.slice(0, MAXIMUM_RESULTS).map(({ ID: id, Scope: [ namespace, jobId ]}) => ({
type: 'task-group',
id,
namespace,
jobId,
label: id,
}));
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 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 csiPluginResults = allCSIPluginResults.slice(0, MAXIMUM_RESULTS).map(({ ID: id }) => ({
type: 'plugin',
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions ui/mirage/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 => ({
Expand All @@ -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 => ({
Expand Down
50 changes: 36 additions & 14 deletions ui/tests/acceptance/search-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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 => {
Expand Down Expand Up @@ -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}`);

Expand All @@ -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',
});
});

Expand All @@ -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) {
Expand Down

0 comments on commit 2649d19

Please sign in to comment.