diff --git a/packages/api/src/services/library_item.ts b/packages/api/src/services/library_item.ts index f9f8d5cb7..0fcf6940e 100644 --- a/packages/api/src/services/library_item.ts +++ b/packages/api/src/services/library_item.ts @@ -293,7 +293,7 @@ const buildWhereClause = ( args.rangeFilters.forEach((filter, i) => { const param = `range_${filter.field}_${i}` queryBuilder.andWhere( - `library_item.${filter.field} ${filter.operator} ${param}`, + `library_item.${filter.field} ${filter.operator} :${param}`, { [param]: filter.value, } diff --git a/packages/api/src/utils/search.ts b/packages/api/src/utils/search.ts index c3af64881..357875449 100644 --- a/packages/api/src/utils/search.ts +++ b/packages/api/src/utils/search.ts @@ -275,7 +275,10 @@ const parseRangeFilter = ( switch (field.toUpperCase()) { case 'WORDSCOUNT': - field = 'wordCount' + field = 'word_count' + break + case 'READPOSITION': + field = 'reading_progress_bottom_percent' break default: return undefined @@ -410,7 +413,8 @@ export const parseSearchQuery = (query: string | undefined): SearchFilter => { 'site', 'note', 'rss', - 'wordCount', + 'wordsCount', + 'readPosition', ], tokenize: true, }) @@ -507,7 +511,8 @@ export const parseSearchQuery = (query: string | undefined): SearchFilter => { case 'mode': // mode is ignored and used only by the frontend break - case 'wordCount': { + case 'readPosition': + case 'wordsCount': { const rangeFilter = parseRangeFilter(keyword.keyword, keyword.value) rangeFilter && result.rangeFilters.push(rangeFilter) break diff --git a/packages/api/test/resolvers/article.test.ts b/packages/api/test/resolvers/article.test.ts index 85b788f90..d8c2545d9 100644 --- a/packages/api/test/resolvers/article.test.ts +++ b/packages/api/test/resolvers/article.test.ts @@ -1272,6 +1272,104 @@ describe('Article API', () => { expect(res.body.data.search.edges[0].node.id).to.eq(items[0].id) }) }) + + context('when readPosition:>20 readPosition:<50 is in the query', () => { + let items: LibraryItem[] = [] + + before(async () => { + keyword = 'readPosition:>20 readPosition:<50' + // Create some test items + items = await createLibraryItems( + [ + { + user, + title: 'test title 1', + readableContent: '
test 1
', + slug: 'test slug 1', + originalUrl: `${url}/test1`, + readingProgressBottomPercent: 40, + }, + { + user, + title: 'test title 2', + readableContent: 'test 2
', + slug: 'test slug 2', + originalUrl: `${url}/test2`, + readingProgressBottomPercent: 10, + }, + { + user, + title: 'test title 3', + readableContent: 'test 3
', + slug: 'test slug 3', + originalUrl: `${url}/test3`, + readingProgressBottomPercent: 100, + }, + ], + user.id + ) + }) + + after(async () => { + await deleteLibraryItems(items, user.id) + }) + + it('returns items with reading progress between 20% and 50% exclusively', async () => { + const res = await graphqlRequest(query, authToken).expect(200) + + expect(res.body.data.search.pageInfo.totalCount).to.eq(1) + expect(res.body.data.search.edges[0].node.id).to.eq(items[0].id) + }) + }) + + context('when wordsCount:>=10000 wordsCount:<=20000 is in the query', () => { + let items: LibraryItem[] = [] + + before(async () => { + keyword = 'wordsCount:>=10000 wordsCount:<=20000' + // Create some test items + items = await createLibraryItems( + [ + { + user, + title: 'test title 1', + readableContent: 'test 1
', + slug: 'test slug 1', + originalUrl: `${url}/test1`, + wordCount: 10000, + }, + { + user, + title: 'test title 2', + readableContent: 'test 2
', + slug: 'test slug 2', + originalUrl: `${url}/test2`, + wordCount: 8000, + }, + { + user, + title: 'test title 3', + readableContent: 'test 3
', + slug: 'test slug 3', + originalUrl: `${url}/test3`, + wordCount: 100000, + }, + ], + user.id + ) + }) + + after(async () => { + await deleteLibraryItems(items, user.id) + }) + + it('returns items with words count between 10000 and 20000 inclusively', async () => { + const res = await graphqlRequest(query, authToken).expect(200) + + expect(res.body.data.search.pageInfo.totalCount).to.eq(1) + expect(res.body.data.search.edges[0].node.id).to.eq(items[0].id) + }) + }) }) describe('TypeaheadSearch API', () => {