From 4fa43a514c067d857d7dd66024fc9628b059e277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rebecca=20K=C3=B6nig?= Date: Fri, 17 Mar 2023 15:11:15 +0100 Subject: [PATCH] fix: convert multiple filter values to a string (#1776) --- lib/create-contentful-api.ts | 9 +- lib/types/query/equality.ts | 16 +- lib/types/query/location.ts | 46 ++--- lib/types/query/query.ts | 19 +- lib/types/query/range.ts | 9 +- lib/types/query/search.ts | 10 +- lib/types/query/subset.ts | 10 +- lib/types/query/util.ts | 11 +- lib/utils/normalize-search-parameters.ts | 18 ++ test/integration/getTags.test.ts | 4 +- test/integration/tests.test.ts | 4 +- test/types/mocks.ts | 21 +- test/types/queries/asset-queries.test-d.ts | 130 ++++++++++++- test/types/queries/entry-queries.test-d.ts | 179 +++++++++++++++--- test/types/queries/tag-queries.test-d.ts | 120 ++++++++++-- test/types/query-integer.test-d.ts | 51 ----- test/types/query-types/boolean.test-d.ts | 62 +++--- test/types/query-types/date.test-d.ts | 71 ++++--- test/types/query-types/integer.test-d.ts | 64 +++---- test/types/query-types/location.test-d.ts | 121 +++--------- test/types/query-types/number.test-d.ts | 67 ++++--- test/types/query-types/object.test-d.ts | 61 ++---- test/types/query-types/richtext.test-d.ts | 62 +++--- test/types/query-types/symbol.test-d.ts | 63 +++--- test/types/query-types/tagName.test-d.ts | 62 ++---- test/types/query-types/text.test-d.ts | 63 +++--- test/types/query.test-d.ts | 28 ++- .../utils/normalize-search-parameters.test.ts | 24 +++ 28 files changed, 802 insertions(+), 603 deletions(-) create mode 100644 lib/utils/normalize-search-parameters.ts delete mode 100644 test/types/query-integer.test-d.ts create mode 100644 test/unit/utils/normalize-search-parameters.test.ts diff --git a/lib/create-contentful-api.ts b/lib/create-contentful-api.ts index 5ff63457d..9e193bc5d 100644 --- a/lib/create-contentful-api.ts +++ b/lib/create-contentful-api.ts @@ -28,7 +28,8 @@ import { SyncOptions, } from './types' import { EntryQueries, LocaleOption, TagQueries } from './types/query/query' -import { FieldsType } from './types' +import { FieldsType } from './types/query/util' +import normalizeSearchParameters from './utils/normalize-search-parameters' import normalizeSelect from './utils/normalize-select' import resolveCircular from './utils/resolve-circular' import validateTimestamp from './utils/validate-timestamp' @@ -457,7 +458,7 @@ export default function createContentfulApi( const entries = await get({ context: 'environment', path: 'entries', - config: createRequestConfig({ query: normalizeSelect(query) }), + config: createRequestConfig({ query: normalizeSearchParameters(normalizeSelect(query)) }), }) return resolveCircular(entries, { @@ -534,7 +535,7 @@ export default function createContentfulApi( return get({ context: 'environment', path: 'assets', - config: createRequestConfig({ query: normalizeSelect(query) }), + config: createRequestConfig({ query: normalizeSearchParameters(normalizeSelect(query)) }), }) } catch (error) { errorHandler(error as AxiosError) @@ -552,7 +553,7 @@ export default function createContentfulApi( return get({ context: 'environment', path: 'tags', - config: createRequestConfig({ query: normalizeSelect(query) }), + config: createRequestConfig({ query: normalizeSearchParameters(normalizeSelect(query)) }), }) } diff --git a/lib/types/query/equality.ts b/lib/types/query/equality.ts index 572d5ee7a..7fbc9c522 100644 --- a/lib/types/query/equality.ts +++ b/lib/types/query/equality.ts @@ -1,5 +1,5 @@ import { EntryFields } from '../entry' -import { ConditionalQueries, NonEmpty } from './util' +import { ConditionalQueries } from './util' type SupportedTypes = | EntryFields.Symbol @@ -14,14 +14,20 @@ type SupportedTypes = * @desc equality - search for exact matches * @see [Documentation]{@link https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters/equality-operator} */ -export type EqualityFilter = NonEmpty< - ConditionalQueries +export type EqualityFilter = ConditionalQueries< + Fields, + SupportedTypes, + Prefix, + '' > /** * @desc inequality - exclude matching items * @see [Documentation]{@link https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters/inequality-operator} */ -export type InequalityFilter = NonEmpty< - ConditionalQueries +export type InequalityFilter = ConditionalQueries< + Fields, + SupportedTypes, + Prefix, + '[ne]' > diff --git a/lib/types/query/location.ts b/lib/types/query/location.ts index b22013ede..6ae54db18 100644 --- a/lib/types/query/location.ts +++ b/lib/types/query/location.ts @@ -1,12 +1,11 @@ import { ConditionalPick } from 'type-fest' import { EntryFields } from '../entry' -import { NonEmpty } from './util' type Types = EntryFields.Location | undefined -export type ProximitySearchFilterInput = [number, number] | undefined -export type BoundingBoxSearchFilterInput = [number, number, number, number] | undefined -export type BoundingCircleSearchFilterInput = [number, number, number] | undefined +export type ProximitySearchFilterInput = [number, number] +export type BoundingBoxSearchFilterInput = [number, number, number, number] +export type BoundingCircleSearchFilterInput = [number, number, number] type BaseLocationFilter< Fields, @@ -14,12 +13,10 @@ type BaseLocationFilter< ValueType, Prefix extends string, QueryFilter extends string = '' -> = NonEmpty< - NonNullable<{ - [FieldName in keyof ConditionalPick as `${Prefix}.${string & - FieldName}[${QueryFilter}]`]?: ValueType - }> -> +> = NonNullable<{ + [FieldName in keyof ConditionalPick as `${Prefix}.${string & + FieldName}[${QueryFilter}]`]?: ValueType +}> /** * @desc near - location proximity search @@ -34,24 +31,13 @@ export type ProximitySearchFilter = BaseLocationF > /** - * @desc within - location in a bounding rectangle - * @see [Documentation]{@link https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters/locations-in-a-bounding-object} - */ -type BoundingBoxSearchFilter = BaseLocationFilter< - Fields, - Types, - BoundingBoxSearchFilterInput, - Prefix, - 'within' -> -/** - * @desc within - location in a bounding circle + * @desc within - location in a bounding object * @see [Documentation]{@link https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters/locations-in-a-bounding-object} */ -type BoundingCircleSearchFilter = BaseLocationFilter< +type BoundingObjectSearchFilter = BaseLocationFilter< Fields, Types, - BoundingCircleSearchFilterInput, + BoundingCircleSearchFilterInput | BoundingBoxSearchFilterInput, Prefix, 'within' > @@ -59,10 +45,10 @@ type BoundingCircleSearchFilter = BaseLocationFil /** * @desc location search * @see [proximity]{@link ProximitySearchFilter} - * @see [bounding rectangle]{@link BoundingBoxSearchFilter} - * @see [bounding circle]{@link BoundingCircleSearchFilter} + * @see [bounding object]{@link BoundingObjectSearchFilter} */ -export type LocationSearchFilters = - | ProximitySearchFilter - | BoundingBoxSearchFilter - | BoundingCircleSearchFilter +export type LocationSearchFilters = ProximitySearchFilter< + Fields, + Prefix +> & + BoundingObjectSearchFilter diff --git a/lib/types/query/query.ts b/lib/types/query/query.ts index 0bad20e13..b25595076 100644 --- a/lib/types/query/query.ts +++ b/lib/types/query/query.ts @@ -57,14 +57,13 @@ export type EntriesQueries = export type EntryQueries = Omit -export type AssetFieldsQueries = - | (ExistenceFilter & - EqualityFilter & - InequalityFilter & - FullTextSearchFilters & - AssetSelectFilter) - | RangeFilters - | SubsetFilters +export type AssetFieldsQueries = ExistenceFilter & + EqualityFilter & + InequalityFilter & + FullTextSearchFilters & + AssetSelectFilter & + RangeFilters & + SubsetFilters export type AssetQueries = AssetFieldsQueries & SysQueries> & @@ -76,8 +75,8 @@ export type TagNameFilters = { name?: string 'name[ne]'?: string 'name[match]'?: string - 'name[in]'?: string - 'name[nin]'?: string + 'name[in]'?: string[] + 'name[nin]'?: string[] } export type TagQueries = TagNameFilters & diff --git a/lib/types/query/range.ts b/lib/types/query/range.ts index 2c5d35b3d..f1a0b8e59 100644 --- a/lib/types/query/range.ts +++ b/lib/types/query/range.ts @@ -1,5 +1,5 @@ import { EntryFields } from '../entry' -import { ConditionalQueries, NonEmpty } from './util' +import { ConditionalQueries } from './util' type RangeFilterTypes = 'lt' | 'lte' | 'gt' | 'gte' @@ -13,6 +13,9 @@ type SupportedTypes = EntryFields.Date | EntryFields.Number | EntryFields.Intege * {string} gte: Greater than or equal to. * @see [Documentation]{@link https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters/select-operator} */ -export type RangeFilters = NonEmpty< - ConditionalQueries +export type RangeFilters = ConditionalQueries< + Fields, + SupportedTypes, + Prefix, + `[${RangeFilterTypes}]` > diff --git a/lib/types/query/search.ts b/lib/types/query/search.ts index f0a9d9649..4522044f8 100644 --- a/lib/types/query/search.ts +++ b/lib/types/query/search.ts @@ -1,5 +1,5 @@ import { EntryFields } from '../entry' -import { ConditionalFixedQueries, NonEmpty } from './util' +import { ConditionalFixedQueries } from './util' type SupportedTypes = | EntryFields.Text @@ -12,6 +12,10 @@ type SupportedTypes = * @desc match - full text search * @see [documentation]{@link https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters/full-text-search} */ -export type FullTextSearchFilters = NonEmpty< - ConditionalFixedQueries +export type FullTextSearchFilters = ConditionalFixedQueries< + Fields, + SupportedTypes, + string, + Prefix, + '[match]' > diff --git a/lib/types/query/subset.ts b/lib/types/query/subset.ts index 65a3e0dee..99a0cd85a 100644 --- a/lib/types/query/subset.ts +++ b/lib/types/query/subset.ts @@ -1,9 +1,10 @@ import { EntryFields } from '..' -import { ConditionalQueries, NonEmpty } from './util' +import { ConditionalListQueries } from './util' type SubsetFilterTypes = 'in' | 'nin' type SupportedTypes = | EntryFields.Symbol + | EntryFields.Symbol[] | EntryFields.Text | EntryFields.Integer | EntryFields.Number @@ -19,6 +20,9 @@ type SupportedTypes = * // {'fields.myField', 'singleValue'} * // {'fields.myField', 'firstValue,secondValue'} */ -export type SubsetFilters = NonEmpty< - NonNullable> +export type SubsetFilters = ConditionalListQueries< + Fields, + SupportedTypes, + Prefix, + `[${SubsetFilterTypes}]` > diff --git a/lib/types/query/util.ts b/lib/types/query/util.ts index e4da9c197..9c36c7d04 100644 --- a/lib/types/query/util.ts +++ b/lib/types/query/util.ts @@ -6,7 +6,6 @@ export type BaseOrArrayType = T extends Array ? U : T export type NonEmpty = T extends Record ? never : T -//TODO: should we also allow ValueType[] for array types export type ConditionalFixedQueries< Fields, SupportedTypes, @@ -18,6 +17,16 @@ export type ConditionalFixedQueries< FieldName}${QueryFilter}`]?: ValueType } +export type ConditionalListQueries< + Fields, + SupportedTypes, + Prefix extends string, + QueryFilter extends string = '' +> = { + [FieldName in keyof ConditionalPick as `${Prefix}.${string & + FieldName}${QueryFilter}`]?: NonNullable>[] +} + export type ConditionalQueries< Fields, SupportedTypes, diff --git a/lib/utils/normalize-search-parameters.ts b/lib/utils/normalize-search-parameters.ts new file mode 100644 index 000000000..397d201a4 --- /dev/null +++ b/lib/utils/normalize-search-parameters.ts @@ -0,0 +1,18 @@ +export default function normalizeSearchParameters(query: Record): Record { + const convertedQuery = {} + let hasConverted = false + for (const key in query) { + // We allow multiple values to be passed as arrays + // which have to be converted to comma-separated strings before being sent to the API + if (Array.isArray(query[key])) { + convertedQuery[key] = query[key].join(',') + hasConverted = true + } + } + + if (hasConverted) { + return { ...query, ...convertedQuery } + } + + return query +} diff --git a/test/integration/getTags.test.ts b/test/integration/getTags.test.ts index bfaa8ab49..7f2d2b3a4 100644 --- a/test/integration/getTags.test.ts +++ b/test/integration/getTags.test.ts @@ -38,14 +38,14 @@ describe('getTags', () => { }) it('gets the tags with the name in the list of the provided value', async () => { - const response = await client.getTags({ 'name[in]': 'public tag,public tag 1' }) + const response = await client.getTags({ 'name[in]': ['public tag', 'public tag 1'] }) expect(response.items).toHaveLength(1) expect(response.items[0].name).toEqual('public tag 1') }) it('gets the tags with the name not in the list of the provided value', async () => { - const response = await client.getTags({ 'name[nin]': 'public tag,public tag 1' }) + const response = await client.getTags({ 'name[nin]': ['public tag', 'public tag 1'] }) expect(response.items).toHaveLength(0) expect(response.items).toEqual([]) diff --git a/test/integration/tests.test.ts b/test/integration/tests.test.ts index 0e5c8aea3..db0c49b8a 100644 --- a/test/integration/tests.test.ts +++ b/test/integration/tests.test.ts @@ -217,7 +217,7 @@ test('Gets entries with array inequality query', async () => { }) test('Gets entries with inclusion query', async () => { - const response = await client.getEntries({ 'sys.id[in]': 'finn,jake' }) + const response = await client.getEntries({ 'sys.id[in]': ['finn', 'jake'] }) expect(response.total).toBe(2) expect(response.items.filter((item) => item.sys.id === 'finn')).toHaveLength(1) @@ -296,7 +296,7 @@ test('Gets entries with full text search query on field', async () => { test('Gets entries with location proximity search', async () => { const response = await client.getEntries({ content_type: '1t9IbcfdCk6m04uISSsaIK', - 'fields.center[near]': '38,-122', + 'fields.center[near]': [38, -122], }) expect(response.items[0].fields.center.lat).toBeDefined() diff --git a/test/types/mocks.ts b/test/types/mocks.ts index bafc17a9d..be5b4780b 100644 --- a/test/types/mocks.ts +++ b/test/types/mocks.ts @@ -6,17 +6,34 @@ import { AssetLink, AssetSys, BaseEntry, + EntryFields, EntryLink, EntrySys, FieldsType, } from '../../lib' +import { + BoundingBoxSearchFilterInput, + BoundingCircleSearchFilterInput, + ProximitySearchFilterInput, +} from '../../lib/types/query/location' +export const anyValue = '' as any export const stringValue = '' +export const stringArrayValue = [stringValue] export const numberValue = 123 -export const booleanValue = true -export const dateValue = '2018-05-03T09:18:16.329Z' +export const numberArrayValue = [numberValue] + +export const booleanValue = true as boolean +export const booleanArrayValue = [booleanValue] +export const dateValue: EntryFields.Date = '2018-05-03T09:18:16.329Z' +export const dateArrayValue = [dateValue] export const locationValue = { lat: 55.01496234536782, lon: 38.75813066219786 } export const jsonValue = {} + +export const nearLocationValue: ProximitySearchFilterInput = [1, 0] +export const withinCircleLocationValue: BoundingCircleSearchFilterInput = [1, 0, 2] +export const withinBoxLocationValue: BoundingBoxSearchFilterInput = [1, 0, 2, 1] + export const metadataValue = { tags: [] } export const entryLink: EntryLink = { type: 'Link', diff --git a/test/types/queries/asset-queries.test-d.ts b/test/types/queries/asset-queries.test-d.ts index ba90b5915..7172db28f 100644 --- a/test/types/queries/asset-queries.test-d.ts +++ b/test/types/queries/asset-queries.test-d.ts @@ -1,16 +1,126 @@ import { expectAssignable, expectNotAssignable } from 'tsd' -import { AssetQueries } from '../../../lib' +import { AssetFields, AssetQueries } from '../../../lib' +// @ts-ignore +import * as mocks from '../mocks' -// select operator +type DefaultAssetQueries = AssetQueries + +// equality operator + +expectAssignable({ + 'fields.title': mocks.stringValue, + 'sys.updatedAt': mocks.dateValue, +}) +expectNotAssignable({ + 'fields.unknownField': mocks.anyValue, +}) +expectNotAssignable({ + 'sys.unknownProp': mocks.anyValue, +}) + +// exists operator (field is present) + +expectAssignable({ + 'fields.title[exists]': mocks.booleanValue, + 'sys.updatedAt[exists]': mocks.booleanValue, +}) +expectNotAssignable({ + 'fields.unknownField[exists]': mocks.anyValue, +}) +expectNotAssignable({ + 'sys.unknownProp[exists]': mocks.anyValue, +}) + +// gt operator (range) + +expectAssignable({ + 'sys.updatedAt[gt]': mocks.dateValue, +}) +expectNotAssignable({ + 'sys.unknownProp[gt]': mocks.anyValue, +}) + +// gte operator (range) + +expectAssignable({ + 'sys.updatedAt[gte]': mocks.dateValue, +}) +expectNotAssignable({ + 'sys.unknownProp[gte]': mocks.anyValue, +}) + +// in operator + +expectAssignable({ + 'fields.title[in]': mocks.stringArrayValue, + 'sys.updatedAt[in]': mocks.dateArrayValue, +}) +expectNotAssignable({ + 'fields.unknownField[in]': mocks.anyValue, +}) +expectNotAssignable({ + 'sys.unknownProp[in]': mocks.anyValue, +}) + +// lt operator (range) + +expectAssignable({ + 'sys.updatedAt[lt]': mocks.dateValue, +}) +expectNotAssignable({ + 'sys.unknownProp[lt]': mocks.anyValue, +}) + +// lte operator (range) -expectAssignable>({ select: ['sys'] }) -expectAssignable>({ select: ['sys.createdAt'] }) -expectNotAssignable>({ select: ['sys.unknownProperty'] }) +expectAssignable({ + 'sys.updatedAt[lte]': mocks.dateValue, +}) +expectNotAssignable({ + 'sys.unknownProp[lte]': mocks.anyValue, +}) + +// match operator (full-text search) -expectAssignable>({ select: ['fields'] }) -expectAssignable>({ - select: ['fields.someField'], +expectAssignable({ + 'fields.title[match]': mocks.stringValue, }) -expectNotAssignable>({ - select: ['fields.unknownField'], +expectNotAssignable({ + 'fields.unknownField[match]': mocks.anyValue, +}) + +// ne operator (inequality) + +expectAssignable({ + 'fields.title[ne]': mocks.stringValue, + 'sys.updatedAt[ne]': mocks.dateValue, }) +expectNotAssignable({ + 'fields.unknownField[ne]': mocks.anyValue, +}) +expectNotAssignable({ + 'sys.unknownProp[ne]': mocks.anyValue, +}) + +// nin operator + +expectAssignable({ + 'fields.title[nin]': mocks.stringArrayValue, + 'sys.updatedAt[nin]': mocks.dateArrayValue, +}) +expectNotAssignable({ + 'fields.unknownField[nin]': mocks.anyValue, +}) +expectNotAssignable({ + 'sys.unknownProp[nin]': mocks.anyValue, +}) + +// select operator + +expectAssignable({ select: ['sys'] }) +expectAssignable({ select: ['sys.createdAt'] }) +expectNotAssignable({ select: ['sys.unknownProperty'] }) + +expectAssignable({ select: ['fields'] }) +expectAssignable({ select: ['fields.title'] }) +expectNotAssignable({ select: ['fields.unknownField'] }) diff --git a/test/types/queries/entry-queries.test-d.ts b/test/types/queries/entry-queries.test-d.ts index c379b9af5..97bc78f44 100644 --- a/test/types/queries/entry-queries.test-d.ts +++ b/test/types/queries/entry-queries.test-d.ts @@ -1,102 +1,227 @@ import { expectAssignable, expectNotAssignable } from 'tsd' import { EntryFields, EntriesQueries } from '../../../lib' +// @ts-ignore +import * as mocks from '../mocks' + +// equality + +expectAssignable>({ + 'sys.updatedAt': mocks.dateValue, +}) +expectNotAssignable>({ + 'fields.numberField': mocks.anyValue, +}) +expectAssignable>({ + content_type: 'id', + 'fields.someField': mocks.stringValue, + 'sys.updatedAt': mocks.dateValue, +}) +expectNotAssignable>({ + 'sys.unknownProp': mocks.anyValue, +}) +expectNotAssignable>({ + content_type: 'id', + 'fields.unknownField': mocks.anyValue, +}) // exists operator (field is present) +expectAssignable>({ + 'sys.updatedAt[exists]': mocks.booleanValue, +}) expectNotAssignable>({ - 'fields.numberField[exists]': true, + 'fields.numberField[exists]': mocks.anyValue, }) expectAssignable>({ content_type: 'id', - 'fields.someField[exists]': true, + 'fields.someField[exists]': mocks.booleanValue, + 'sys.updatedAt[exists]': mocks.booleanValue, +}) +expectNotAssignable>({ + 'sys.unknownProp[exists]': mocks.anyValue, }) expectNotAssignable>({ content_type: 'id', - 'fields.unknownField[exists]': true, + 'fields.unknownField[exists]': mocks.anyValue, }) // gt operator (range) +expectAssignable>({ + 'sys.updatedAt[gt]': mocks.dateValue, +}) expectNotAssignable>({ - 'fields.numberField[gt]': 3, + 'fields.numberField[gt]': mocks.anyValue, }) expectAssignable>({ content_type: 'id', - 'fields.numberField[gt]': 3, + 'fields.numberField[gt]': mocks.numberValue, + 'sys.updatedAt[gt]': mocks.dateValue, +}) +expectNotAssignable>({ + 'sys.unknownProp[gt]': mocks.anyValue, }) expectNotAssignable>({ content_type: 'id', - 'fields.unknownField[gt]': 3, + 'fields.unknownField[gt]': mocks.anyValue, }) // gte operator (range) +expectAssignable>({ + 'sys.updatedAt[gte]': mocks.dateValue, +}) expectNotAssignable>({ - 'fields.numberField[gte]': 3, + 'fields.numberField[gte]': mocks.anyValue, }) expectAssignable>({ content_type: 'id', - 'fields.numberField[gte]': 3, + 'fields.numberField[gte]': mocks.numberValue, + 'sys.updatedAt[gte]': mocks.dateValue, +}) +expectNotAssignable>({ + 'sys.unknownProp[gte]': mocks.anyValue, }) expectNotAssignable>({ content_type: 'id', - 'fields.unknownField[gte]': 3, + 'fields.unknownField[gte]': mocks.anyValue, +}) + +// in operator + +expectAssignable>({ + 'sys.updatedAt[in]': mocks.dateArrayValue, +}) +expectNotAssignable>({ + 'fields.numberField[in]': mocks.anyValue, + 'fields.stringArrayField[in]': mocks.anyValue, +}) +expectAssignable>({ + content_type: 'id', + 'fields.numberField[in]': mocks.numberArrayValue, + 'fields.stringArrayField[in]': mocks.stringArrayValue, + 'sys.updatedAt[in]': mocks.dateArrayValue, +}) +expectNotAssignable>({ + 'sys.unknownProp[in]': mocks.anyValue, +}) +expectNotAssignable>({ + content_type: 'id', + 'fields.unknownField[in]': mocks.anyValue, }) // lt operator (range) +expectAssignable>({ + 'sys.updatedAt[lt]': mocks.dateValue, +}) expectNotAssignable>({ - 'fields.numberField[lt]': 3, + 'fields.numberField[lt]': mocks.anyValue, }) expectAssignable>({ content_type: 'id', - 'fields.numberField[lt]': 3, + 'fields.numberField[lt]': mocks.numberValue, + 'sys.updatedAt[lt]': mocks.dateValue, +}) +expectNotAssignable>({ + 'sys.unknownProp[lt]': mocks.anyValue, }) expectNotAssignable>({ content_type: 'id', - 'fields.unknownField[lt]': 3, + 'fields.unknownField[lt]': mocks.anyValue, }) // lte operator (range) +expectAssignable>({ + 'sys.updatedAt[lte]': mocks.dateValue, +}) expectNotAssignable>({ - 'fields.numberField[lte]': 3, + 'fields.numberField[lte]': mocks.anyValue, }) expectAssignable>({ content_type: 'id', - 'fields.numberField[lte]': 3, + 'fields.numberField[lte]': mocks.numberValue, + 'sys.updatedAt[lte]': mocks.dateValue, +}) +expectNotAssignable>({ + 'sys.unknownProp[lte]': mocks.anyValue, }) expectNotAssignable>({ content_type: 'id', - 'fields.unknownField[lte]': 3, + 'fields.unknownField[lte]': mocks.anyValue, }) // match operator (full-text search) expectNotAssignable>({ - 'fields.textField[match]': 'value', + 'fields.textField[match]': mocks.anyValue, }) expectAssignable>({ content_type: 'id', - 'fields.textField[match]': 'value', + 'fields.textField[match]': mocks.stringValue, }) expectNotAssignable>({ content_type: 'id', - 'fields.unknownField[match]': 'value', + 'fields.unknownField[match]': mocks.anyValue, +}) + +// ne operator (inequality) + +expectAssignable>({ + 'sys.updatedAt[ne]': mocks.dateValue, +}) +expectNotAssignable>({ + 'fields.numberField[ne]': mocks.anyValue, +}) +expectAssignable>({ + content_type: 'id', + 'fields.someField[ne]': mocks.stringValue, + 'sys.updatedAt[ne]': mocks.dateValue, +}) +expectNotAssignable>({ + 'sys.unknownProp[ne]': mocks.anyValue, +}) +expectNotAssignable>({ + content_type: 'id', + 'fields.unknownField[ne]': mocks.anyValue, }) // near operator (full-text search) expectNotAssignable>({ - 'fields.locationField[near]': [0, 1], + 'fields.locationField[near]': mocks.anyValue, }) expectAssignable>({ content_type: 'id', - 'fields.locationField[near]': [0, 1], + 'fields.locationField[near]': mocks.nearLocationValue, }) expectNotAssignable>({ content_type: 'id', - 'fields.unknownField[near]': [0, 1], + 'fields.unknownField[near]': mocks.anyValue, +}) + +// nin operator + +expectAssignable>({ + 'sys.updatedAt[nin]': mocks.dateArrayValue, +}) +expectNotAssignable>({ + 'fields.numberField[nin]': mocks.anyValue, + 'fields.stringArrayField[nin]': mocks.anyValue, +}) +expectAssignable>({ + content_type: 'id', + 'fields.numberField[nin]': mocks.numberArrayValue, + 'fields.stringArrayField[nin]': mocks.stringArrayValue, + 'sys.updatedAt[nin]': mocks.dateArrayValue, +}) +expectNotAssignable>({ + 'sys.unknownProp[nin]': mocks.anyValue, +}) +expectNotAssignable>({ + content_type: 'id', + 'fields.unknownField[nin]': mocks.anyValue, }) // select operator @@ -119,29 +244,29 @@ expectNotAssignable>({ // within operator (bounding circle) expectNotAssignable>({ - 'fields.locationField[within]': [0, 1, 2], + 'fields.locationField[within]': mocks.anyValue, }) expectAssignable>({ content_type: 'id', - 'fields.locationField[within]': [0, 1, 2], + 'fields.locationField[within]': mocks.withinCircleLocationValue, }) expectNotAssignable>({ content_type: 'id', - ['fields.unknownField[within]']: [0, 1, 2], + 'fields.unknownField[within]': mocks.anyValue, }) // within operator (bounding rectangle) expectNotAssignable>({ - 'fields.locationField[within]': [0, 1, 2, 3], + 'fields.locationField[within]': mocks.anyValue, }) expectAssignable>({ content_type: 'id', - 'fields.locationField[within]': [0, 1, 2, 3], + 'fields.locationField[within]': mocks.withinBoxLocationValue, }) expectNotAssignable>({ content_type: 'id', - 'fields.unknownField[within]': [0, 1, 2, 3], + 'fields.unknownField[within]': mocks.anyValue, }) // search on references diff --git a/test/types/queries/tag-queries.test-d.ts b/test/types/queries/tag-queries.test-d.ts index bb2a1af42..857d6deee 100644 --- a/test/types/queries/tag-queries.test-d.ts +++ b/test/types/queries/tag-queries.test-d.ts @@ -1,35 +1,121 @@ import { expectAssignable, expectNotAssignable } from 'tsd' import { TagQueries } from '../../../lib' +// @ts-ignore +import * as mocks from '../mocks' -const dateFilter = '2023-03-03T09:18:16.329Z' -const tagId = 'tagId' -const userId = 'userId' +// equality operator -// Tag sys queries -expectAssignable({ 'sys.id': tagId }) +expectAssignable({ + 'sys.id': mocks.stringValue, + 'sys.createdAt': mocks.dateValue, + 'sys.updatedAt': mocks.dateValue, + 'sys.visibility': mocks.stringValue, + 'sys.type': mocks.stringValue, +}) +expectNotAssignable({ 'sys.createdBy': mocks.anyValue }) +expectNotAssignable({ 'sys.updatedBy': mocks.anyValue }) +expectNotAssignable({ 'sys.version': mocks.anyValue }) +expectNotAssignable({ 'sys.revision': mocks.anyValue }) -expectAssignable({ 'sys.createdAt': dateFilter }) +// gt operator (range) -expectAssignable({ 'sys.updatedAt': dateFilter }) +expectAssignable({ + 'sys.createdAt[gt]': mocks.dateValue, + 'sys.updatedAt[gt]': mocks.dateValue, +}) +expectNotAssignable({ 'sys.createdBy[gt]': mocks.anyValue }) +expectNotAssignable({ 'sys.id[gt]': mocks.anyValue }) +expectNotAssignable({ 'sys.revision[gt]': mocks.anyValue }) +expectNotAssignable({ 'sys.type[gt]': mocks.anyValue }) +expectNotAssignable({ 'sys.updatedBy[gt]': mocks.anyValue }) +expectNotAssignable({ 'sys.version[gt]': mocks.anyValue }) +expectNotAssignable({ 'sys.visibility[gt]': mocks.anyValue }) -expectAssignable({ 'sys.visibility': 'private' }) +// gte operator (range) -expectAssignable({ 'sys.type': 'Tag' }) +expectAssignable({ + 'sys.createdAt[gte]': mocks.dateValue, + 'sys.updatedAt[gte]': mocks.dateValue, +}) +expectNotAssignable({ 'sys.createdBy[gte]': mocks.anyValue }) +expectNotAssignable({ 'sys.id[gte]': mocks.anyValue }) +expectNotAssignable({ 'sys.revision[gte]': mocks.anyValue }) +expectNotAssignable({ 'sys.type[gte]': mocks.anyValue }) +expectNotAssignable({ 'sys.updatedBy[gte]': mocks.anyValue }) +expectNotAssignable({ 'sys.version[gte]': mocks.anyValue }) +expectNotAssignable({ 'sys.visibility[gte]': mocks.anyValue }) -expectNotAssignable({ 'sys.createdBy': userId }) +// in operator -expectNotAssignable({ 'sys.updatedBy': userId }) +expectAssignable({ + 'sys.id[in]': mocks.stringArrayValue, + 'sys.createdAt[in]': mocks.dateArrayValue, + 'sys.updatedAt[in]': mocks.dateArrayValue, + 'sys.visibility[in]': mocks.stringArrayValue, + 'sys.type[in]': mocks.stringArrayValue, +}) +expectNotAssignable({ 'sys.createdBy[in]': mocks.anyValue }) +expectNotAssignable({ 'sys.updatedBy[in]': mocks.anyValue }) +expectNotAssignable({ 'sys.version[in]': mocks.anyValue }) +expectNotAssignable({ 'sys.revision[in]': mocks.anyValue }) -expectNotAssignable({ 'sys.version': 2 }) +// lt operator (range) -expectNotAssignable({ 'sys.revision': 2 }) +expectAssignable({ + 'sys.createdAt[lt]': mocks.dateValue, + 'sys.updatedAt[lt]': mocks.dateValue, +}) +expectNotAssignable({ 'sys.createdBy[lt]': mocks.anyValue }) +expectNotAssignable({ 'sys.id[lt]': mocks.anyValue }) +expectNotAssignable({ 'sys.revision[lt]': mocks.anyValue }) +expectNotAssignable({ 'sys.type[lt]': mocks.anyValue }) +expectNotAssignable({ 'sys.updatedBy[lt]': mocks.anyValue }) +expectNotAssignable({ 'sys.version[lt]': mocks.anyValue }) +expectNotAssignable({ 'sys.visibility[lt]': mocks.anyValue }) -// Tag fixed Query filters +// lte operator (range) -expectAssignable({ skip: 1 }) +expectAssignable({ + 'sys.createdAt[lte]': mocks.dateValue, + 'sys.updatedAt[lte]': mocks.dateValue, +}) +expectNotAssignable({ 'sys.createdBy[lte]': mocks.anyValue }) +expectNotAssignable({ 'sys.id[lte]': mocks.anyValue }) +expectNotAssignable({ 'sys.revision[lte]': mocks.anyValue }) +expectNotAssignable({ 'sys.type[lte]': mocks.anyValue }) +expectNotAssignable({ 'sys.updatedBy[lte]': mocks.anyValue }) +expectNotAssignable({ 'sys.version[lte]': mocks.anyValue }) +expectNotAssignable({ 'sys.visibility[lte]': mocks.anyValue }) -expectAssignable({ limit: 1 }) +// ne operator (inequality) -expectAssignable({ order: 'sys.updatedAt' }) +expectAssignable({ + 'sys.id[ne]': mocks.stringValue, + 'sys.createdAt[ne]': mocks.dateValue, + 'sys.updatedAt[ne]': mocks.dateValue, + 'sys.visibility[ne]': mocks.stringValue, + 'sys.type[ne]': mocks.stringValue, +}) +expectNotAssignable({ 'sys.createdBy[ne]': mocks.anyValue }) +expectNotAssignable({ 'sys.updatedBy[ne]': mocks.anyValue }) +expectNotAssignable({ 'sys.version[ne]': mocks.anyValue }) +expectNotAssignable({ 'sys.revision[ne]': mocks.anyValue }) +// nin operator + +expectAssignable({ + 'sys.id[nin]': mocks.stringArrayValue, + 'sys.createdAt[nin]': mocks.dateArrayValue, + 'sys.updatedAt[nin]': mocks.dateArrayValue, + 'sys.visibility[nin]': mocks.stringArrayValue, + 'sys.type[nin]': mocks.stringArrayValue, +}) +expectNotAssignable({ 'sys.createdBy[nin]': mocks.anyValue }) +expectNotAssignable({ 'sys.updatedBy[nin]': mocks.anyValue }) +expectNotAssignable({ 'sys.version[nin]': mocks.anyValue }) +expectNotAssignable({ 'sys.revision[nin]': mocks.anyValue }) + +// Fixed query filters + +expectAssignable({ skip: 1, limit: 1, order: 'sys.updatedAt' }) expectNotAssignable({ locale: 'en' }) diff --git a/test/types/query-integer.test-d.ts b/test/types/query-integer.test-d.ts deleted file mode 100644 index 63eec7427..000000000 --- a/test/types/query-integer.test-d.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' -import { EntryFields } from '../../lib' -import { EqualityFilter, InequalityFilter } from '../../lib/types/query/equality' -import { ExistenceFilter } from '../../lib/types/query/existence' -import { LocationSearchFilters } from '../../lib/types/query/location' -import { RangeFilters } from '../../lib/types/query/range' -import { EntrySelectFilterWithFields } from '../../lib/types/query/select' -import { SubsetFilters } from '../../lib/types/query/subset' - -const numberValue = 1 -const booleanValue = true - -expectAssignable>({ - 'fields.testField': numberValue, -}) -expectAssignable>({ - 'fields.testField[ne]': numberValue, -}) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, -}) -expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Integer - }, - 'fields' - > ->({ - 'fields.testField[near]': numberValue, - 'fields.testField[within]': [0, 0, 0], -}) -expectAssignable>({ - 'fields.testField[lt]': numberValue, - 'fields.testField[lte]': numberValue, - 'fields.testField[gt]': numberValue, - 'fields.testField[gte]': numberValue, -}) - -// TODO: unskip this test -// expectNotAssignable>({ -// 'fields.testField[match]': stringValue, -// }) - -expectAssignable>({ - select: ['fields.testField'], -}) -expectAssignable>({ - 'fields.testField[in]': numberValue, - 'fields.testField[nin]': numberValue, -}) diff --git a/test/types/query-types/boolean.test-d.ts b/test/types/query-types/boolean.test-d.ts index b10c9789f..8f51d7b6b 100644 --- a/test/types/query-types/boolean.test-d.ts +++ b/test/types/query-types/boolean.test-d.ts @@ -1,4 +1,4 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' +import { expectAssignable, expectType } from 'tsd' import { EntryFields } from '../../../lib' import { EqualityFilter, InequalityFilter } from '../../../lib/types/query/equality' import { ExistenceFilter } from '../../../lib/types/query/existence' @@ -7,43 +7,37 @@ import { RangeFilters } from '../../../lib/types/query/range' import { FullTextSearchFilters } from '../../../lib/types/query/search' import { EntrySelectFilterWithFields } from '../../../lib/types/query/select' import { SubsetFilters } from '../../../lib/types/query/subset' +// @ts-ignore +import * as mocks from '../mocks' -const stringValue = '' -const booleanValue = true - -expectAssignable>({ - 'fields.testField': booleanValue, -}) -expectAssignable>({ - 'fields.testField[ne]': booleanValue, -}) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, +expectAssignable>({}) +expectType>>({ + 'fields.testField': mocks.booleanValue, }) -expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Boolean - }, - 'fields' - > ->({ - 'fields.testField[near]': booleanValue, - 'fields.testField[within]': [0, 0, 0], -}) -expectNotAssignable>({ - 'fields.testField[lt]': booleanValue, - 'fields.testField[lte]': booleanValue, - 'fields.testField[gt]': booleanValue, - 'fields.testField[gte]': booleanValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[ne]': mocks.booleanValue, }) -expectNotAssignable>({ - 'fields.testField[match]': stringValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[exists]': mocks.booleanValue, }) -expectAssignable>({ + +expectAssignable>>({}) + +expectAssignable>>({}) + +expectAssignable>>({}) + +expectAssignable>({}) +expectAssignable>>({ select: ['fields.testField'], }) -expectAssignable>({ - 'fields.testField[in]': booleanValue, - 'fields.testField[nin]': booleanValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[in]': mocks.booleanArrayValue, + 'fields.testField[nin]': mocks.booleanArrayValue, }) diff --git a/test/types/query-types/date.test-d.ts b/test/types/query-types/date.test-d.ts index 771af4f64..0a40b7d7b 100644 --- a/test/types/query-types/date.test-d.ts +++ b/test/types/query-types/date.test-d.ts @@ -1,4 +1,4 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' +import { expectAssignable, expectType } from 'tsd' import { EntryFields } from '../../../lib' import { EqualityFilter, InequalityFilter } from '../../../lib/types/query/equality' import { ExistenceFilter } from '../../../lib/types/query/existence' @@ -7,47 +7,46 @@ import { RangeFilters } from '../../../lib/types/query/range' import { FullTextSearchFilters } from '../../../lib/types/query/search' import { EntrySelectFilterWithFields } from '../../../lib/types/query/select' import { SubsetFilters } from '../../../lib/types/query/subset' +// @ts-ignore +import * as mocks from '../mocks' -export const dateValue: EntryFields.Date = '2018-05-03T09:18:16.329Z' -const stringValue = '' -const booleanValue = true - -expectAssignable>({ - 'fields.testField': dateValue, -}) -expectAssignable>({ - 'fields.testField[ne]': dateValue, -}) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, +expectAssignable>({}) +expectType>>({ + 'fields.testField': mocks.dateValue, }) -expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Date - }, - 'fields' - > ->({ - 'fields.testField[near]': dateValue, - 'fields.testField[within]': [0, 0, 0], + +expectAssignable>({}) +expectType>>({ + 'fields.testField[ne]': mocks.dateValue, }) -expectAssignable>({ - 'fields.testField[lt]': dateValue, - 'fields.testField[lte]': dateValue, - 'fields.testField[gt]': dateValue, - 'fields.testField[gte]': dateValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[exists]': mocks.booleanValue, }) -expectAssignable>({ - 'fields.testField[match]': stringValue, + +expectAssignable>>({}) + +expectAssignable>({}) +expectType>>({ + 'fields.testField[lt]': mocks.dateValue, + 'fields.testField[lte]': mocks.dateValue, + 'fields.testField[gt]': mocks.dateValue, + 'fields.testField[gte]': mocks.dateValue, }) -expectAssignable>({ - 'fields.testField[match]': dateValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[match]': mocks.stringValue, }) -expectAssignable>({ + +expectAssignable>({}) +expectAssignable>>({ select: ['fields.testField'], }) -expectAssignable>({ - 'fields.testField[in]': dateValue, - 'fields.testField[nin]': dateValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[in]': mocks.dateArrayValue, + 'fields.testField[nin]': mocks.dateArrayValue, }) diff --git a/test/types/query-types/integer.test-d.ts b/test/types/query-types/integer.test-d.ts index 09b58e25e..536fb15f0 100644 --- a/test/types/query-types/integer.test-d.ts +++ b/test/types/query-types/integer.test-d.ts @@ -1,52 +1,48 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' +import { expectAssignable, expectType } from 'tsd' import { EntryFields } from '../../../lib' import { EqualityFilter, InequalityFilter } from '../../../lib/types/query/equality' import { ExistenceFilter } from '../../../lib/types/query/existence' import { LocationSearchFilters } from '../../../lib/types/query/location' import { RangeFilters } from '../../../lib/types/query/range' import { FullTextSearchFilters } from '../../../lib/types/query/search' -import { EntrySelectFilter, EntrySelectFilterWithFields } from '../../../lib/types/query/select' +import { EntrySelectFilterWithFields } from '../../../lib/types/query/select' import { SubsetFilters } from '../../../lib/types/query/subset' +// @ts-ignore +import * as mocks from '../mocks' -const numberValue = 1 -const stringValue = '' -const booleanValue = true - -expectAssignable>({ - 'fields.testField': numberValue, -}) -expectAssignable>({ - 'fields.testField[ne]': numberValue, +expectAssignable>({}) +expectType>>({ + 'fields.testField': mocks.numberValue, }) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, -}) -expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Integer - }, - 'fields' - > ->({ - 'fields.testField[near]': numberValue, - 'fields.testField[within]': [0, 0, 0], + +expectAssignable>({}) +expectType>>({ + 'fields.testField[ne]': mocks.numberValue, }) -expectAssignable>({ - 'fields.testField[lt]': numberValue, - 'fields.testField[lte]': numberValue, - 'fields.testField[gt]': numberValue, - 'fields.testField[gte]': numberValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[exists]': mocks.booleanValue, }) -expectNotAssignable>({ - 'fields.testField[match]': stringValue, +expectAssignable>>({}) + +expectAssignable>({}) +expectType>>({ + 'fields.testField[lt]': mocks.numberValue, + 'fields.testField[lte]': mocks.numberValue, + 'fields.testField[gt]': mocks.numberValue, + 'fields.testField[gte]': mocks.numberValue, }) +expectAssignable>>({}) + expectAssignable>({ select: ['fields.testField'], }) -expectAssignable>({ - 'fields.testField[in]': numberValue, - 'fields.testField[nin]': numberValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[in]': mocks.numberArrayValue, + 'fields.testField[nin]': mocks.numberArrayValue, }) diff --git a/test/types/query-types/location.test-d.ts b/test/types/query-types/location.test-d.ts index 1cd179690..4f8f13ecc 100644 --- a/test/types/query-types/location.test-d.ts +++ b/test/types/query-types/location.test-d.ts @@ -1,108 +1,49 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' +import { expectAssignable, expectNotAssignable, expectType } from 'tsd' import { EntryFields } from '../../../lib' import { EqualityFilter, InequalityFilter } from '../../../lib/types/query/equality' import { ExistenceFilter } from '../../../lib/types/query/existence' -import { - BoundingBoxSearchFilterInput, - BoundingCircleSearchFilterInput, - LocationSearchFilters, - ProximitySearchFilterInput, -} from '../../../lib/types/query/location' +import { LocationSearchFilters } from '../../../lib/types/query/location' import { RangeFilters } from '../../../lib/types/query/range' import { FullTextSearchFilters } from '../../../lib/types/query/search' import { EntrySelectFilterWithFields } from '../../../lib/types/query/select' import { SubsetFilters } from '../../../lib/types/query/subset' +// @ts-ignore +import * as mocks from '../mocks' -const stringValue = '' -const booleanValue = true -const numberValue = 12.11 -export const nearLocationValue: ProximitySearchFilterInput = [1, 0] -export const withinCircleLocationValue: BoundingCircleSearchFilterInput = [1, 0, 2] -export const withinBoxLocationValue: BoundingBoxSearchFilterInput = [1, 0, 2, 1] +expectAssignable>>({}) -expectNotAssignable>({ - 'fields.testField': { lat: numberValue, lon: numberValue }, -}) -expectNotAssignable>({ - 'fields.testField[ne]': { lat: numberValue, lon: numberValue }, +expectAssignable>>({}) + +expectAssignable>({}) +expectType>>({ + 'fields.testField[exists]': mocks.booleanValue, }) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, + +expectAssignable>({}) +expectAssignable>>({ + 'fields.testField[near]': mocks.nearLocationValue, + 'fields.testField[within]': mocks.withinCircleLocationValue, }) -expectAssignable< - LocationSearchFilters< - { - testField: EntryFields.Location - }, - 'fields' - > ->({ - 'fields.testField[near]': nearLocationValue, +expectAssignable>>({ + 'fields.testField[near]': mocks.nearLocationValue, + 'fields.testField[within]': mocks.withinBoxLocationValue, }) expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Location - }, - 'fields' - > ->({ - 'fields.testField[within]': nearLocationValue, -}) -expectAssignable< - LocationSearchFilters< - { - testField: EntryFields.Location - }, - 'fields' - > ->({ - 'fields.testField[within]': withinCircleLocationValue, -}) + LocationSearchFilters<{ testField: EntryFields.Location }, 'fields'>['fields.testField[near]'] +>(mocks.withinCircleLocationValue) expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Location - }, - 'fields' - > ->({ - 'fields.testField[near]': withinCircleLocationValue, -}) - -expectAssignable< - LocationSearchFilters< - { - testField: EntryFields.Location - }, - 'fields' - > ->({ - 'fields.testField[within]': withinBoxLocationValue, -}) + LocationSearchFilters<{ testField: EntryFields.Location }, 'fields'>['fields.testField[near]'] +>(mocks.withinBoxLocationValue) expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Location - }, - 'fields' - > ->({ - 'fields.testField[near]': withinBoxLocationValue, -}) -expectNotAssignable>({ - 'fields.testField[lt]': nearLocationValue, - 'fields.testField[lte]': nearLocationValue, - 'fields.testField[gt]': nearLocationValue, - 'fields.testField[gte]': nearLocationValue, -}) -expectNotAssignable>({ - 'fields.testField[match]': stringValue, -}) + LocationSearchFilters<{ testField: EntryFields.Location }, 'fields'>['fields.testField[within]'] +>(mocks.nearLocationValue) + +expectAssignable>>({}) + +expectAssignable>>({}) + expectAssignable>({ select: ['fields.testField'], }) -expectNotAssignable>({ - 'fields.testField[in]': nearLocationValue, - 'fields.testField[nin]': nearLocationValue, -}) + +expectAssignable>>({}) diff --git a/test/types/query-types/number.test-d.ts b/test/types/query-types/number.test-d.ts index a799ebf18..22f5ee1bf 100644 --- a/test/types/query-types/number.test-d.ts +++ b/test/types/query-types/number.test-d.ts @@ -1,4 +1,4 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' +import { expectAssignable, expectType } from 'tsd' import { EntryFields } from '../../../lib' import { EqualityFilter, InequalityFilter } from '../../../lib/types/query/equality' import { ExistenceFilter } from '../../../lib/types/query/existence' @@ -7,44 +7,43 @@ import { RangeFilters } from '../../../lib/types/query/range' import { FullTextSearchFilters } from '../../../lib/types/query/search' import { EntrySelectFilterWithFields } from '../../../lib/types/query/select' import { SubsetFilters } from '../../../lib/types/query/subset' +// @ts-ignore +import * as mocks from '../mocks' -const numberValue = 1 -const stringValue = '' -const booleanValue = true - -expectAssignable>({ - 'fields.testField': numberValue, -}) -expectAssignable>({ - 'fields.testField[ne]': numberValue, -}) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, +expectAssignable>({}) +expectType>>({ + 'fields.testField': mocks.numberValue, }) -expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Number - }, - 'fields' - > ->({ - 'fields.testField[near]': numberValue, - 'fields.testField[within]': [0, 0, 0], + +expectAssignable>({}) +expectType>>({ + 'fields.testField[ne]': mocks.numberValue, }) -expectAssignable>({ - 'fields.testField[lt]': numberValue, - 'fields.testField[lte]': numberValue, - 'fields.testField[gt]': numberValue, - 'fields.testField[gte]': numberValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[exists]': mocks.booleanValue, }) -expectNotAssignable>({ - 'fields.testField[match]': stringValue, + +expectType>>({}) + +expectAssignable>({}) +expectType>>({ + 'fields.testField[lt]': mocks.numberValue, + 'fields.testField[lte]': mocks.numberValue, + 'fields.testField[gt]': mocks.numberValue, + 'fields.testField[gte]': mocks.numberValue, }) -expectAssignable>({ + +expectAssignable>>({}) + +expectAssignable>({}) +expectAssignable>>({ select: ['fields.testField'], }) -expectAssignable>({ - 'fields.testField[in]': numberValue, - 'fields.testField[nin]': numberValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[in]': mocks.numberArrayValue, + 'fields.testField[nin]': mocks.numberArrayValue, }) diff --git a/test/types/query-types/object.test-d.ts b/test/types/query-types/object.test-d.ts index c4d929df9..8c6ff3f0a 100644 --- a/test/types/query-types/object.test-d.ts +++ b/test/types/query-types/object.test-d.ts @@ -1,4 +1,4 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' +import { expectAssignable, expectType } from 'tsd' import { EntryFields } from '../../../lib' import { EqualityFilter, InequalityFilter } from '../../../lib/types/query/equality' import { ExistenceFilter } from '../../../lib/types/query/existence' @@ -7,48 +7,27 @@ import { RangeFilters } from '../../../lib/types/query/range' import { FullTextSearchFilters } from '../../../lib/types/query/search' import { EntrySelectFilterWithFields } from '../../../lib/types/query/select' import { SubsetFilters } from '../../../lib/types/query/subset' +// @ts-ignore +import * as mocks from '../mocks' -const stringValue = '' -const booleanValue = true -const objectValue = { hello: 'world' } +expectAssignable>>({}) -expectNotAssignable>({ - 'fields.testField': objectValue, -}) -expectNotAssignable>({ - 'fields.testField[ne]': objectValue, -}) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, -}) -expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Object - }, - 'fields' - > ->({ - 'fields.testField[near]': objectValue, - 'fields.testField[within]': [0, 0, 0], -}) -expectNotAssignable>({ - 'fields.testField[lt]': objectValue, - 'fields.testField[lte]': objectValue, - 'fields.testField[gt]': objectValue, - 'fields.testField[gte]': objectValue, -}) -expectNotAssignable>({ - 'fields.testField[match]': stringValue, +expectAssignable>>({}) + +expectAssignable>({}) +expectType>>({ + 'fields.testField[exists]': mocks.booleanValue, }) -expectAssignable>({ + +expectAssignable>>({}) + +expectAssignable>>({}) + +expectAssignable>>({}) + +expectAssignable>({}) +expectAssignable>>({ select: ['fields.testField'], }) -expectNotAssignable>({ - 'fields.testField[in]': objectValue, - 'fields.testField[nin]': objectValue, -}) -expectNotAssignable>({ - 'fields.testField[in]': stringValue, - 'fields.testField[nin]': stringValue, -}) + +expectAssignable>>({}) diff --git a/test/types/query-types/richtext.test-d.ts b/test/types/query-types/richtext.test-d.ts index c5bc86667..83ea0218e 100644 --- a/test/types/query-types/richtext.test-d.ts +++ b/test/types/query-types/richtext.test-d.ts @@ -1,50 +1,36 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' +import { expectAssignable, expectType } from 'tsd' import { EntryFields } from '../../../lib' -// import { EqualityFilter, InequalityFilter } from '../../lib/types/query/equality' +import { EqualityFilter, InequalityFilter } from '../../../lib/types/query/equality' import { ExistenceFilter } from '../../../lib/types/query/existence' import { LocationSearchFilters } from '../../../lib/types/query/location' import { RangeFilters } from '../../../lib/types/query/range' import { FullTextSearchFilters } from '../../../lib/types/query/search' import { EntrySelectFilterWithFields } from '../../../lib/types/query/select' import { SubsetFilters } from '../../../lib/types/query/subset' +// @ts-ignore +import * as mocks from '../mocks' -const stringValue = '' -const booleanValue = true - -// TODO fix tests -// expectNotAssignable>({ -// 'fields.testField': stringValue, -// }) -// expectNotAssignable>({ -// 'fields.testField[ne]': stringValue, -// }) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, -}) -expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.RichText - }, - 'fields' - > ->({ - 'fields.testField[near]': stringValue, - 'fields.testField[within]': [0, 0, 0], -}) -expectNotAssignable>({ - 'fields.testField[lt]': stringValue, - 'fields.testField[lte]': stringValue, - 'fields.testField[gt]': stringValue, - 'fields.testField[gte]': stringValue, +expectAssignable>>({}) + +expectAssignable>>({}) + +expectAssignable>({}) +expectType>>({ + 'fields.testField[exists]': mocks.booleanValue, }) -expectAssignable>({ - 'fields.testField[match]': stringValue, + +expectAssignable>>({}) + +expectType>>({}) + +expectAssignable>({}) +expectType>>({ + 'fields.testField[match]': mocks.stringValue, }) -expectAssignable>({ + +expectAssignable>({}) +expectAssignable>>({ select: ['fields.testField'], }) -expectNotAssignable>({ - 'fields.testField[in]': stringValue, - 'fields.testField[nin]': stringValue, -}) + +expectAssignable>>({}) diff --git a/test/types/query-types/symbol.test-d.ts b/test/types/query-types/symbol.test-d.ts index cc1fbd0b4..0ad413870 100644 --- a/test/types/query-types/symbol.test-d.ts +++ b/test/types/query-types/symbol.test-d.ts @@ -1,4 +1,4 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' +import { expectAssignable, expectType } from 'tsd' import { EntryFields } from '../../../lib' import { EqualityFilter, InequalityFilter } from '../../../lib/types/query/equality' import { ExistenceFilter } from '../../../lib/types/query/existence' @@ -7,43 +7,40 @@ import { RangeFilters } from '../../../lib/types/query/range' import { FullTextSearchFilters } from '../../../lib/types/query/search' import { EntrySelectFilterWithFields } from '../../../lib/types/query/select' import { SubsetFilters } from '../../../lib/types/query/subset' +// @ts-ignore +import * as mocks from '../mocks' -const stringValue = '' -const booleanValue = true - -expectAssignable>({ - 'fields.testField': stringValue, -}) -expectAssignable>({ - 'fields.testField[ne]': stringValue, -}) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, +expectAssignable>({}) +expectType>>({ + 'fields.testField': mocks.stringValue, }) -expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Symbol - }, - 'fields' - > ->({ - 'fields.testField[near]': stringValue, - 'fields.testField[within]': [0, 0, 0], + +expectAssignable>({}) +expectType>>({ + 'fields.testField[ne]': mocks.stringValue, }) -expectNotAssignable>({ - 'fields.testField[lt]': stringValue, - 'fields.testField[lte]': stringValue, - 'fields.testField[gt]': stringValue, - 'fields.testField[gte]': stringValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[exists]': mocks.booleanValue, }) -expectAssignable>({ - 'fields.testField[match]': stringValue, + +expectAssignable>>({}) + +expectAssignable>>({}) + +expectAssignable>({}) +expectType>>({ + 'fields.testField[match]': mocks.stringValue, }) -expectAssignable>({ + +expectAssignable>({}) +expectAssignable>>({ select: ['fields.testField'], }) -expectAssignable>({ - 'fields.testField[in]': stringValue, - 'fields.testField[nin]': stringValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[in]': mocks.stringArrayValue, + 'fields.testField[nin]': mocks.stringArrayValue, }) diff --git a/test/types/query-types/tagName.test-d.ts b/test/types/query-types/tagName.test-d.ts index dd0bd420a..387f2d2b3 100644 --- a/test/types/query-types/tagName.test-d.ts +++ b/test/types/query-types/tagName.test-d.ts @@ -1,49 +1,21 @@ import { expectAssignable, expectNotAssignable } from 'tsd' import { TagNameFilters } from '../../../lib/types/query/query' - -const booleanValue = false -const stringValue = '' -const rangeString = 'test1,test2' - -expectAssignable({ - 'name[exists]': booleanValue, -}) - -expectAssignable({ - name: stringValue, -}) - -expectAssignable({ - 'name[match]': stringValue, -}) - -expectAssignable({ - 'name[ne]': stringValue, -}) +// @ts-ignore +import * as mocks from '../mocks' expectAssignable({ - 'name[in]': rangeString, -}) - -expectAssignable({ - 'name[nin]': rangeString, -}) - -expectNotAssignable({ - 'name[near]': rangeString, -}) - -expectNotAssignable({ - 'name[within]': rangeString, -}) - -expectNotAssignable({ - select: ['name'], -}) - -expectNotAssignable({ - 'name[lt]': stringValue, - 'name[lte]': stringValue, - 'name[gt]': stringValue, - 'name[gte]': stringValue, -}) + 'name[exists]': mocks.booleanValue, + name: mocks.stringValue, + 'name[match]': mocks.stringValue, + 'name[ne]': mocks.stringValue, + 'name[in]': mocks.stringArrayValue, + 'name[nin]': mocks.stringArrayValue, +}) + +expectNotAssignable({ 'name[near]': mocks.anyValue }) +expectNotAssignable({ 'name[within]': mocks.anyValue }) +expectNotAssignable({ select: mocks.anyValue }) +expectNotAssignable({ 'name[lt]': mocks.anyValue }) +expectNotAssignable({ 'name[lte]': mocks.anyValue }) +expectNotAssignable({ 'name[gt]': mocks.anyValue }) +expectNotAssignable({ 'name[gte]': mocks.anyValue }) diff --git a/test/types/query-types/text.test-d.ts b/test/types/query-types/text.test-d.ts index d1e0553be..09826fee3 100644 --- a/test/types/query-types/text.test-d.ts +++ b/test/types/query-types/text.test-d.ts @@ -1,4 +1,4 @@ -import { expectAssignable, expectNotAssignable } from 'tsd' +import { expectAssignable, expectType } from 'tsd' import { EntryFields } from '../../../lib' import { EqualityFilter, InequalityFilter } from '../../../lib/types/query/equality' import { ExistenceFilter } from '../../../lib/types/query/existence' @@ -7,43 +7,40 @@ import { RangeFilters } from '../../../lib/types/query/range' import { FullTextSearchFilters } from '../../../lib/types/query/search' import { EntrySelectFilterWithFields } from '../../../lib/types/query/select' import { SubsetFilters } from '../../../lib/types/query/subset' +// @ts-ignore +import * as mocks from '../mocks' -const stringValue = '' -const booleanValue = true - -expectAssignable>({ - 'fields.testField': stringValue, -}) -expectAssignable>({ - 'fields.testField[ne]': stringValue, -}) -expectAssignable>({ - 'fields.testField[exists]': booleanValue, +expectAssignable>({}) +expectType>>({ + 'fields.testField': mocks.stringValue, }) -expectNotAssignable< - LocationSearchFilters< - { - testField: EntryFields.Text - }, - 'fields' - > ->({ - 'fields.testField[near]': stringValue, - 'fields.testField[within]': [0, 0, 0], + +expectAssignable>({}) +expectType>>({ + 'fields.testField[ne]': mocks.stringValue, }) -expectNotAssignable>({ - 'fields.testField[lt]': stringValue, - 'fields.testField[lte]': stringValue, - 'fields.testField[gt]': stringValue, - 'fields.testField[gte]': stringValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[exists]': mocks.booleanValue, }) -expectAssignable>({ - 'fields.testField[match]': stringValue, + +expectAssignable>>({}) + +expectAssignable>>({}) + +expectAssignable>({}) +expectType>>({ + 'fields.testField[match]': mocks.stringValue, }) -expectAssignable>({ + +expectAssignable>({}) +expectAssignable>>({ select: ['fields.testField'], }) -expectAssignable>({ - 'fields.testField[in]': stringValue, - 'fields.testField[nin]': stringValue, + +expectAssignable>({}) +expectType>>({ + 'fields.testField[in]': mocks.stringArrayValue, + 'fields.testField[nin]': mocks.stringArrayValue, }) diff --git a/test/types/query.test-d.ts b/test/types/query.test-d.ts index 716e28de2..dd04a0ea5 100644 --- a/test/types/query.test-d.ts +++ b/test/types/query.test-d.ts @@ -1,7 +1,6 @@ import { expectAssignable } from 'tsd' -import { EntriesQueries, EntryFields, EntryLink, FieldsType } from '../../lib' +import { EntriesQueries, EntryFields, FieldsType } from '../../lib' import { EntryFieldsQueries } from '../../lib/types/query/query' -import { BLOCKS } from '@contentful/rich-text-types' export const stringValue = '' export const numberValue = 123 @@ -10,9 +9,6 @@ export const booleanValue = true const symbolValue: EntryFields.Symbol = '' const dateValue: EntryFields.Date = '23-02-2023T00:00:00Z' -const locationValue: EntryFields.Location = { lat: 33, lon: 34 } -const richTextValue: EntryFields.RichText = { nodeType: BLOCKS.DOCUMENT, data: {}, content: [] } - /* * EntryFields: Type Text */ @@ -21,8 +17,8 @@ expectAssignable> 'fields.stringField[exists]': booleanValue, 'fields.stringField': stringValue, 'fields.stringField[ne]': stringValue, - 'fields.stringField[in]': stringValue, - 'fields.stringField[nin]': stringValue, + 'fields.stringField[in]': [stringValue], + 'fields.stringField[nin]': [stringValue], 'fields.stringField[match]': stringValue, }) @@ -34,8 +30,8 @@ expectAssignable>>( 'fields.dateField[exists]': booleanValue, 'fields.dateField': dateValue, 'fields.dateField[ne]': dateValue, - 'fields.dateField[in]': dateValue, - 'fields.dateField[nin]': dateValue, + 'fields.dateField[in]': [dateValue], + 'fields.dateField[nin]': [dateValue], 'fields.dateField[match]': dateValue, // Date is a string type so Typescript will allow the match filter on it. 'fields.dateField[lt]': dateValue, 'fields.dateField[lte]': dateValue, @@ -123,6 +119,8 @@ expectAssignable { + test('normalizeSearchParameters does nothing if all values are string values', () => { + const query = { + 'fields.stringParameter[in]': 'string1,string2', + 'fields.locationParameter[within]': '0,1,2,3', + } + const normalized = normalizeSearchParameters(query) + expect(normalized).toBe(query) + }) + + test('normalizeSelect converts array values into string values', () => { + const query = { + 'fields.stringParameter[in]': ['string1', 'string2'], + 'fields.locationParameter[within]': [0, 1, 2, 3], + } + const normalized = normalizeSearchParameters(query) + expect(normalized).toEqual({ + 'fields.stringParameter[in]': 'string1,string2', + 'fields.locationParameter[within]': '0,1,2,3', + }) + }) +})