Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit

Permalink
4646 // Resource view should sort correctly after text search cleared
Browse files Browse the repository at this point in the history
Signed-off-by: Dinika Saxena <dinikasaxenas@gmail.com>
  • Loading branch information
Dinika committed Jan 24, 2024
1 parent 6572a57 commit ea7a647
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 6 deletions.
102 changes: 102 additions & 0 deletions src/__mocks__/handlers/ResourceListContainerHandlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { rest } from 'msw';
import { deltaPath } from '__mocks__/handlers/handlers';
import { Resource } from '@bbp/nexus-sdk';

export const resourcesHandler = rest.get(
deltaPath(`resources/bbp/agents`),
(_, res, ctx) => {
const mockResponse = {
'@context': ['https://bluebrain.github.io/nexus/contexts/metadata.json'],
_total: 3,
_results: [
getMockResource('1'),
getMockResource('2'),
getMockResource('3'),
],
};

return res(ctx.status(200), ctx.json(mockResponse));
}
);

export const searchHitsHandler = rest.post(
deltaPath(
'/views/bbp/agents/https%3A%2F%2Fbluebrain.github.io%2Fnexus%2Fvocabulary%2FdefaultElasticSearchIndex/_search'
),
(_, res, ctx) => {
const filteredByDeprecation = {
buckets: [getMockBucket('1'), getMockBucket('2'), getMockBucket('3')],
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
};
const mockResponse = {
aggregations: {
schemas: {
doc_count: 3,
filteredByDeprecation: { ...filteredByDeprecation },
},
types: {
doc_count: 8,
filteredByDeprecation: { ...filteredByDeprecation },
},
},
hits: {
hits: [
getMockSearchHit('1'),
getMockSearchHit('2'),
getMockSearchHit('3'),
],
max_score: 123,
total: { relation: 'eq', value: 11 },
},
timed_out: false,
took: 0,
_shards: { failed: 0, skipped: 0, successful: 1, total: 1 },
};

return res(
// Respond with a 200 status code
ctx.status(200),
ctx.json(mockResponse)
);
}
);

const getMockResource = (id: string, extra?: Partial<Resource>) => ({
'@id': id,
'@type': ['View'],
description: 'Test description',
name: 'Test name',
_constrainedBy: 'https://bluebrain.github.io/nexus/schemas/views.json',
_createdAt: '2024-01-19T11:40:24.804553Z',
_createdBy: 'https://bbp.epfl.ch/nexus/v1/realms/bbp/users/mockuser',
_deprecated: false,
_incoming: 'test',
_outgoing: 'test',
_project: 'https://dev.nise.bbp.epfl.ch/nexus/v1/projects/bbp/agents',
_rev: 1,
_self: id,
_updatedAt: '2024-01-19T11:40:24.804553Z',
_updatedBy: 'https://bbp.epfl.ch/nexus/v1/realms/bbp/users/mockuser',
_uuid: id,
...extra,
});

const getMockSearchHit = (id: string, extra?: Partial<Resource>) => {
const resource = getMockResource(id, extra);
return {
_id: id,
_index: `delta_${id}`,
_score: 123,
_source: {
...resource,
_original_source: JSON.stringify(resource),
},
_type: '_doc',
};
};

const getMockBucket = (key: string, docCount: number = 1) => ({
key,
doc_count: docCount,
});
2 changes: 1 addition & 1 deletion src/shared/components/ResourceList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ const ResourceListComponent: React.FunctionComponent<{
onChange={handleUpdate}
size="small"
/>
<div className="count">
<div className="count" data-testid="resource-count">
{!!total &&
`${total.toLocaleString()} result${total > 1 ? 's' : ''}`}
</div>
Expand Down
103 changes: 103 additions & 0 deletions src/shared/containers/ResourceListBoardContainer.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { deltaPath } from '__mocks__/handlers/handlers';
import { setupServer } from 'msw/node';
import { QueryClient, QueryClientProvider } from 'react-query';
import { cleanup, render, screen, waitFor } from '../../utils/testUtil';
import { createNexusClient, ResourceListOptions } from '@bbp/nexus-sdk';
import { NexusProvider } from '@bbp/react-nexus';
import '@testing-library/jest-dom';
import { createMemoryHistory } from 'history';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import {
resourcesHandler,
searchHitsHandler,
} from '__mocks__/handlers/ResourceListContainerHandlers';
import ResourceListBoardContainer from './ResourceListBoardContainer';
import { UserEvent } from '@testing-library/user-event/dist/types/setup/setup';
import configureStore from '../store';
import userEvent from '@testing-library/user-event';

describe('ResourceListBoardContainer', () => {
const queryClient = new QueryClient();
let user: UserEvent;
let server: ReturnType<typeof setupServer>;
let spy: jasmine.Spy;

beforeAll(() => {
server = setupServer(resourcesHandler, searchHitsHandler);
server.listen();
});

beforeEach(async () => {
const history = createMemoryHistory({});
const nexus = createNexusClient({
fetch,
uri: deltaPath(),
});
const store = configureStore(history, { nexus }, {});

const resourceListBoardContainer = (
<Provider store={store}>
<Router history={history}>
<QueryClientProvider client={queryClient}>
<NexusProvider nexusClient={nexus}>
<ResourceListBoardContainer
orgLabel="bbp"
projectLabel="agents"
refreshLists={false}
/>
</NexusProvider>
</QueryClientProvider>
</Router>
</Provider>
);

spy = spyOn(nexus.Resource, 'list').and.callThrough();
await waitFor(() => {
renderContainer(resourceListBoardContainer);
});
await screen.findByText('3 results');
});

const renderContainer = (containerToRender: JSX.Element) => {
render(containerToRender);
user = userEvent.setup();
};

afterEach(() => {
cleanup();
queryClient.clear();
localStorage.clear();
});

afterAll(() => {
server.resetHandlers();
server.close();
});

const querySentToApi = (): ResourceListOptions =>
spy.calls.mostRecent().args.at(-1);

const defaultSortCriteria = '-_createdAt';

it('sends sort without search text by default', async () => {
const defaultQuery = querySentToApi();
expect(defaultQuery.q).toBeUndefined();
expect(defaultQuery.sort).toEqual(defaultSortCriteria);
});

it('preserves sorting critria after search text is cleared', async () => {
const searchInput = screen.getByPlaceholderText('Search...');
await user.type(searchInput, 'something');

const queryWithSearchText = querySentToApi();
expect(queryWithSearchText.q).toEqual('something');
expect(queryWithSearchText.sort).toBeUndefined();

await user.clear(searchInput);

const queryWithoutSearchText = querySentToApi();
expect(queryWithoutSearchText.q).toEqual('');
expect(queryWithoutSearchText.sort).toEqual('-_createdAt');
});
});
11 changes: 6 additions & 5 deletions src/shared/containers/ResourceListContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,6 @@ const ResourceListContainer: React.FunctionComponent<{
size: pageSize,
};

if (searchValue) {
query.sort = undefined;
}

if (searchValue !== list.query.q) {
return setList({
...list,
Expand Down Expand Up @@ -174,8 +170,13 @@ const ResourceListContainer: React.FunctionComponent<{
size: 10,
}
),
nexus.Resource.list(orgLabel, projectLabel, list.query),
nexus.Resource.list(
orgLabel,
projectLabel,
list.query.q ? { ...list.query, sort: undefined } : { ...list.query }
),
]);

if (resourcesByIdOrSelf.status === 'fulfilled') {
const resultsLength = resourcesByIdOrSelf.value.hits.hits.length;
const hits = resourcesByIdOrSelf.value.hits.hits;
Expand Down

0 comments on commit ea7a647

Please sign in to comment.