Skip to content

Commit

Permalink
Merge pull request #455 from audioverse-org/av-448
Browse files Browse the repository at this point in the history
AV-448
  • Loading branch information
narthur authored Aug 10, 2023
2 parents 1bb87b6 + 1ab0e47 commit ecdda31
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 111 deletions.
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 14 additions & 29 deletions src/components/organisms/searchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { FormattedMessage, useIntl } from 'react-intl';

import LineHeading from '~components/atoms/lineHeading';
import Button from '~components/molecules/button';
import { CardRecordingFragment } from '~components/molecules/card/__generated__/recording';
import CardInferred, {
InferrableEntity,
} from '~components/molecules/card/inferred';
Expand Down Expand Up @@ -110,14 +109,16 @@ function Section({
const normalize = (s: string) =>
s.replace(/[\p{P}\p{S}\s]/gu, '').toLowerCase();

const isRecording = (e: InferrableEntity): e is CardRecordingFragment =>
e.__typename === 'Recording';
const getTitle = (e: InferrableEntity) =>
e.__typename === 'Person' ? e.name : e.title;

function hasExactMatch(term: string, sections: AugmentedFilter[]): boolean {
return !!sections
.find((s) => s.id === 'teachings')
?.nodes.slice(0, 3)
.find((e) => isRecording(e) && normalize(e.title) === normalize(term));
function sortSections(term: string, sections: AugmentedFilter[]) {
const t = normalize(term);
const a = sections.filter((s) =>
s.nodes.slice(0, 3).map(getTitle).map(normalize).includes(t)
);
const b = sections.filter((s) => !a.find((hs) => hs.id === s.id));
return [...a, ...b];
}

export default function Search({
Expand All @@ -134,8 +135,7 @@ export default function Search({
const { visible, loadMore, isLoading } = useSearch(entityType, t);
const endRef = useRef<HTMLDivElement>(null);
const endReached = useOnScreen(endRef);
const hasExactTeaching = hasExactMatch(t, visible);
const shouldHoistTeachings = hasExactTeaching && entityType === 'all';
const sections = sortSections(t, visible);

useEffect(() => {
if (entityType !== 'all' && endReached && !isLoading) loadMore();
Expand All @@ -149,29 +149,14 @@ export default function Search({
<LoadingCards />
) : (
<>
{shouldHoistTeachings && (
{sections.map((s) => (
<Section
key="teachings"
section={
visible.find((s) => s.id === 'teachings') as AugmentedFilter
}
key={s.id}
section={s}
entityType={entityType}
onEntityTypeChange={onEntityTypeChange}
/>
)}
{visible.map((s) => {
if (s.id === 'teachings' && shouldHoistTeachings) {
return null;
}
return (
<Section
key={s.id}
section={s}
entityType={entityType}
onEntityTypeChange={onEntityTypeChange}
/>
);
})}
))}
<div ref={endRef} />
</>
)}
Expand Down
121 changes: 112 additions & 9 deletions src/components/templates/andNavigation.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,25 @@ import { CardPersonFragment } from '~components/molecules/card/__generated__/per
import { CardRecordingFragment } from '~components/molecules/card/__generated__/recording';
import {
GetSearchAudiobooksDocument,
GetSearchPersonsDocument,
GetSearchRecordingsDocument,
} from '~components/organisms/__generated__/searchResults';
import { fetchApi } from '~lib/api/fetchApi';
import { SequenceContentType } from '~src/__generated__/graphql';
import {
buildGetSearchPersonsLoader,
buildGetSearchRecordingsLoader,
buildGetSearchSeriesLoader,
} from '~src/__generated__/loaders';

import { buildLoader } from '../../lib/test/buildLoader';
import { buildRenderer } from '../../lib/test/buildRenderer';
import { CardSequenceFragment } from '../molecules/card/__generated__/sequence';
import AndNavigation from './andNavigation';

const renderTemplate = buildRenderer(AndNavigation);

const teaching: CardRecordingFragment = {
__typename: 'Recording',
title: 'test',
title: 'the_teaching_title',
canonicalPath: '',
sequenceIndex: null,
id: '',
Expand All @@ -36,7 +41,7 @@ const teaching: CardRecordingFragment = {

const person: CardPersonFragment = {
__typename: 'Person',
name: 'test',
name: 'the_person_title',
recordings: {
aggregate: {
count: 0,
Expand All @@ -47,7 +52,30 @@ const person: CardPersonFragment = {
image: null,
};

const loadTeachings = buildLoader(GetSearchRecordingsDocument, {
const series: CardSequenceFragment = {
__typename: 'Sequence',
title: 'the_series_title',
canonicalPath: '',
id: '',
contentType: SequenceContentType.Series,
duration: 0,
summary: '',
speakers: {
nodes: [],
},
sequenceWriters: {
nodes: [],
},
allRecordings: {
aggregate: {
count: 0,
},
nodes: [],
},
collection: null,
};

const loadTeachings = buildGetSearchRecordingsLoader({
sermons: {
aggregate: {
count: 1,
Expand All @@ -59,7 +87,8 @@ const loadTeachings = buildLoader(GetSearchRecordingsDocument, {
},
},
});
const loadPresenters = buildLoader(GetSearchPersonsDocument, {

const loadPresenters = buildGetSearchPersonsLoader({
persons: {
aggregate: {
count: 1,
Expand All @@ -72,10 +101,24 @@ const loadPresenters = buildLoader(GetSearchPersonsDocument, {
},
});

const loadSeries = buildGetSearchSeriesLoader({
serieses: {
aggregate: {
count: 1,
},
nodes: [series],
pageInfo: {
hasNextPage: false,
endCursor: null,
},
},
});

describe('AndNavigation', () => {
beforeEach(() => {
loadTeachings();
loadPresenters();
loadSeries();
});

it('hoists teachings on exact match', async () => {
Expand All @@ -84,7 +127,7 @@ describe('AndNavigation', () => {
const searchInputs = screen.getAllByPlaceholderText('Search');
const search = searchInputs[0];

await userEvent.type(search, 'test');
await userEvent.type(search, 'the_teaching_title');

const teachingsHeading = await screen.findByRole('heading', {
name: 'Teachings',
Expand All @@ -102,7 +145,7 @@ describe('AndNavigation', () => {
const searchInputs = screen.getAllByPlaceholderText('Search');
const search = searchInputs[0];

await userEvent.type(search, 'Test');
await userEvent.type(search, 'The_Teaching_Title');

const teachingsHeading = await screen.findByRole('heading', {
name: 'Teachings',
Expand All @@ -120,7 +163,7 @@ describe('AndNavigation', () => {
const searchInputs = screen.getAllByPlaceholderText('Search');
const search = searchInputs[0];

await userEvent.type(search, 'test!');
await userEvent.type(search, 'the_teaching_title!');

const teachingsHeading = await screen.findByRole('heading', {
name: 'Teachings',
Expand Down Expand Up @@ -212,4 +255,64 @@ describe('AndNavigation', () => {
})
);
});

it('hoists series on exact match', async () => {
await renderTemplate();

const searchInputs = screen.getAllByPlaceholderText('Search');
const search = searchInputs[0];

await userEvent.type(search, 'the_series_title');

const seriesHeading = (
await screen.findAllByRole('heading', {
name: 'Series',
})
)[0];
const presentersHeading = await screen.findByRole('heading', {
name: 'Presenters',
});

expect(seriesHeading).toAppearBefore(presentersHeading);
});

it('only checks first three entities in section when hoisting', async () => {
loadTeachings({
sermons: {
aggregate: {
count: 4,
},
nodes: [
{ ...teaching, id: '1' },
{ ...teaching, id: '2' },
{ ...teaching, id: '3' },
{
...teaching,
id: '4',
title: 'the_teaching_title_2',
},
],
pageInfo: {
hasNextPage: false,
endCursor: null,
},
},
});

await renderTemplate();

const searchInputs = screen.getAllByPlaceholderText('Search');
const search = searchInputs[0];

await userEvent.type(search, 'the_teaching_title_2');

const teachingsHeading = await screen.findByRole('heading', {
name: 'Teachings',
});
const presentersHeading = await screen.findByRole('heading', {
name: 'Presenters',
});

expect(presentersHeading).toAppearBefore(teachingsHeading);
});
});
Loading

1 comment on commit ecdda31

@vercel
Copy link

@vercel vercel bot commented on ecdda31 Aug 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.