From e078010afe6a9e5a0f3d5254b976f28d1f971fb6 Mon Sep 17 00:00:00 2001 From: Inga <52715130+inga-lovinde@users.noreply.github.com> Date: Mon, 11 Dec 2023 02:34:44 +0000 Subject: [PATCH] support for case insensitive search --- src/app.module.spec.ts | 12 +++++++++ src/services/omdbEnrichedDataService.spec.ts | 13 ++++++++++ src/services/omdbEnrichedDataService.ts | 27 ++++++++++++++++---- src/utils/stringHelpers.spec.ts | 24 +++++++++++++++++ src/utils/stringHelpers.ts | 8 ++++++ 5 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 src/utils/stringHelpers.spec.ts create mode 100644 src/utils/stringHelpers.ts diff --git a/src/app.module.spec.ts b/src/app.module.spec.ts index aeeeee7..90944bc 100644 --- a/src/app.module.spec.ts +++ b/src/app.module.spec.ts @@ -90,4 +90,16 @@ describe('AppController (e2e)', () => { expect(response.body).toMatchObject([]); }); }); + + it('/api/movies?writers=gEoRgE lUcAs (GET)', () => { + return request(app.getHttpServer()) + .get('/api/movies?writers=gEoRgE lUcAs') + .expect(200) + .expect((response) => { + expect(response.body).toMatchObject([ + { title: 'Indiana Jones and the Last Crusade' }, + { title: 'Star Wars: Episode IV - A New Hope' }, + ]); + }); + }); }); diff --git a/src/services/omdbEnrichedDataService.spec.ts b/src/services/omdbEnrichedDataService.spec.ts index f9b7a5c..cbb99ae 100644 --- a/src/services/omdbEnrichedDataService.spec.ts +++ b/src/services/omdbEnrichedDataService.spec.ts @@ -304,4 +304,17 @@ describe('createOmdbEnrichedDataService', () => { expect(result).toMatchObject([]); }); + + it('returns correct search results for writer = gEoRgE lUcAs and actor = hArRiSoN fOrD', async () => { + const service = await servicePromise; + const result = service.getSearchResults({ + actors: 'hArRiSoN fOrD', + writers: 'gEoRgE lUcAs', + }); + + expect(result).toMatchObject([ + { title: 'Indiana Jones and the Last Crusade' }, + { title: 'Star Wars: Episode IV - A New Hope' }, + ]); + }); }); diff --git a/src/services/omdbEnrichedDataService.ts b/src/services/omdbEnrichedDataService.ts index dd87710..c9a9831 100644 --- a/src/services/omdbEnrichedDataService.ts +++ b/src/services/omdbEnrichedDataService.ts @@ -5,6 +5,7 @@ import type { OmdbProvider, SearchFilters, } from '../types'; +import { areStringsEqual } from '../utils/stringHelpers'; export const createOmdbEnrichedDataService = async ( internalProvider: InternalProvider, @@ -48,11 +49,27 @@ export const createOmdbEnrichedDataService = async ( const metadataValue = metadata[fieldName as keyof SearchFilters]; if (Array.isArray(metadataValue)) { - // filterValue here is filters[fieldName], and is not undefined (because it comes from nonEmptyFilters), - // so it's guaranteed to have a matching type because of SearchFilters / GenericSearchFilters definition, - // but this logic is too complicated for TS to prove it automatically. - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument - return metadataValue.includes(filterValue as any); + return metadataValue.some((singularValue) => { + if (typeof singularValue === 'string') { + return areStringsEqual( + singularValue, + // filterValue here is filters[fieldName], and is not undefined (because it comes from nonEmptyFilters), + // so it's guaranteed to have a matching type because of SearchFilters / GenericSearchFilters definition, + // but this logic is too complicated for TS to prove it automatically. + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument + filterValue as any, + ); + } else { + return singularValue === filterValue; + } + }); + } else if (typeof metadataValue === 'string') { + return areStringsEqual( + metadataValue, + // see comment above + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument + filterValue as any, + ); } else { return metadataValue === filterValue; } diff --git a/src/utils/stringHelpers.spec.ts b/src/utils/stringHelpers.spec.ts new file mode 100644 index 0000000..aa5c73c --- /dev/null +++ b/src/utils/stringHelpers.spec.ts @@ -0,0 +1,24 @@ +import { describe, it, expect } from '@jest/globals'; +import { areStringsEqual } from './stringHelpers'; + +describe('areStringsEqual', () => { + it('returns true for identical strings', () => { + expect(areStringsEqual('abc', 'abc')).toBe(true); + }); + + it('returns false for different strings', () => { + expect(areStringsEqual('abc', 'def')).toBe(false); + }); + + it('returns true for strings with different casing', () => { + expect(areStringsEqual('abc', 'ABC')).toBe(true); + }); + + it('returns true for strings with different variants', () => { + expect(areStringsEqual('Nürnberg', 'Nurnberg')).toBe(true); + }); + + it('returns true for strings with different casing (turkish I)', () => { + expect(areStringsEqual('İSMİNİZ.GIF', 'isminiz.gif')).toBe(true); + }); +}); diff --git a/src/utils/stringHelpers.ts b/src/utils/stringHelpers.ts new file mode 100644 index 0000000..4225ece --- /dev/null +++ b/src/utils/stringHelpers.ts @@ -0,0 +1,8 @@ +export const areStringsEqual = (a: string, b: string) => { + return ( + a.localeCompare(b, undefined, { + usage: 'search', + sensitivity: 'base', + }) === 0 + ); +};