From 5facf5d91f860a85205370389a01a65a8e150790 Mon Sep 17 00:00:00 2001 From: MrOrz Date: Sun, 25 Feb 2018 01:15:31 +0800 Subject: [PATCH] Add author related filter input for ListArticles --- src/graphql/queries/ListArticles.js | 53 +++++++++++++++ .../queries/__fixtures__/ListArticles.js | 6 ++ src/graphql/queries/__tests__/ListArticles.js | 64 +++++++++++++++++++ .../__snapshots__/ListArticles.js.snap | 56 ++++++++++++++++ 4 files changed, 179 insertions(+) diff --git a/src/graphql/queries/ListArticles.js b/src/graphql/queries/ListArticles.js index 55acae40..45bcc17f 100644 --- a/src/graphql/queries/ListArticles.js +++ b/src/graphql/queries/ListArticles.js @@ -1,4 +1,5 @@ import { GraphQLInt, GraphQLString, GraphQLInputObjectType } from 'graphql'; +import client from 'util/client'; import { createFilterType, @@ -44,6 +45,23 @@ export default { description: 'List only the articles whose number of replies matches the criteria.', }, + appId: { + type: GraphQLString, + description: + 'Use with userId to show only articles from a specific user.', + }, + userId: { + type: GraphQLString, + description: + 'Use with appId to show only articles from a specific user.', + }, + fromUserOfArticleId: { + type: GraphQLString, + description: ` + Specify an articleId here to show only articles from the sender of that specified article. + When specified, it overrides the settings of appId and userId. + `, + }, }), }, orderBy: { @@ -70,6 +88,41 @@ export default { const mustQueries = []; // Affects scores const filterQueries = []; // Not affects scores + if (filter.fromUserOfArticleId) { + let specifiedArticle; + try { + specifiedArticle = (await client.get({ + index: 'articles', + type: 'doc', + id: filter.fromUserOfArticleId, + _source: ['userId', 'appId'], + }))._source; + } catch (e) { + if (e.statusCode && e.statusCode === 404) { + throw new Error( + 'fromUserOfArticleId does not match any existing articles' + ); + } + + // Re-throw unknown error + throw e; + } + + // Overriding filter's userId and appId, as indicated in the description + // + filter.userId = specifiedArticle.userId; + filter.appId = specifiedArticle.appId; + } + + if (filter.appId && filter.userId) { + filterQueries.push( + { term: { appId: filter.appId } }, + { term: { userId: filter.userId } } + ); + } else if (filter.appId || filter.userId) { + throw new Error('Both appId and userId must be specified at once'); + } + if (filter.moreLikeThis) { mustQueries.push({ // Ref: http://stackoverflow.com/a/8831494/1582110 diff --git a/src/graphql/queries/__fixtures__/ListArticles.js b/src/graphql/queries/__fixtures__/ListArticles.js index 0ee9f938..cd5bbb16 100644 --- a/src/graphql/queries/__fixtures__/ListArticles.js +++ b/src/graphql/queries/__fixtures__/ListArticles.js @@ -1,5 +1,7 @@ export default { '/articles/doc/listArticleTest1': { + userId: 'user1', + appId: 'app1', replyRequestCount: 2, normalArticleReplyCount: 2, updatedAt: 1, @@ -10,6 +12,8 @@ export default { `, }, '/articles/doc/listArticleTest2': { + userId: 'user1', + appId: 'app1', replyRequestCount: 1, normalArticleReplyCount: 1, updatedAt: 2, @@ -17,6 +21,8 @@ export default { '臣亮言:先帝創業未半,而中道崩殂。今天下三分,益州 疲弊,此誠危急存亡之秋也。', }, '/articles/doc/listArticleTest3': { + userId: 'user2', + appId: 'app1', replyRequestCount: 0, normalArticleReplyCount: 0, updatedAt: 3, diff --git a/src/graphql/queries/__tests__/ListArticles.js b/src/graphql/queries/__tests__/ListArticles.js index 78fb090c..6e80701f 100644 --- a/src/graphql/queries/__tests__/ListArticles.js +++ b/src/graphql/queries/__tests__/ListArticles.js @@ -137,6 +137,70 @@ describe('ListArticles', () => { ).toMatchSnapshot(); }); + it('filters by userId, appId and fromUserOfArticleId', async () => { + // Lists only articles by userId & appId + expect( + await gql` + { + ListArticles(filter: { userId: "user1", appId: "app1" }) { + edges { + node { + id + } + } + totalCount + } + } + `() + ).toMatchSnapshot(); + + // Lists only articles by fromUserOfArticleId + expect( + await gql` + { + ListArticles(filter: { fromUserOfArticleId: "listArticleTest1" }) { + edges { + node { + id + } + } + totalCount + } + } + `() + ).toMatchSnapshot(); + }); + + it('throws error when author filter is not set correctly', async () => { + const { errors: noUserIdError } = await gql` + { + ListArticles(filter: { appId: "specified-but-no-user-id" }) { + edges { + node { + id + } + } + totalCount + } + } + `(); + expect(noUserIdError).toMatchSnapshot(); + + const { errors: notExistError } = await gql` + { + ListArticles(filter: { fromUserOfArticleId: "not-exist" }) { + edges { + node { + id + } + } + totalCount + } + } + `(); + expect(notExistError).toMatchSnapshot(); + }); + it('supports after', async () => { expect( await gql` diff --git a/src/graphql/queries/__tests__/__snapshots__/ListArticles.js.snap b/src/graphql/queries/__tests__/__snapshots__/ListArticles.js.snap index 9fb69a9c..b188f06b 100644 --- a/src/graphql/queries/__tests__/__snapshots__/ListArticles.js.snap +++ b/src/graphql/queries/__tests__/__snapshots__/ListArticles.js.snap @@ -79,6 +79,50 @@ Object { } `; +exports[`ListArticles filters by userId, appId and fromUserOfArticleId 1`] = ` +Object { + "data": Object { + "ListArticles": Object { + "edges": Array [ + Object { + "node": Object { + "id": "listArticleTest2", + }, + }, + Object { + "node": Object { + "id": "listArticleTest1", + }, + }, + ], + "totalCount": 2, + }, + }, +} +`; + +exports[`ListArticles filters by userId, appId and fromUserOfArticleId 2`] = ` +Object { + "data": Object { + "ListArticles": Object { + "edges": Array [ + Object { + "node": Object { + "id": "listArticleTest2", + }, + }, + Object { + "node": Object { + "id": "listArticleTest1", + }, + }, + ], + "totalCount": 2, + }, + }, +} +`; + exports[`ListArticles lists all articles 1`] = ` Object { "data": Object { @@ -216,3 +260,15 @@ Object { }, } `; + +exports[`ListArticles throws error when author filter is not set correctly 1`] = ` +Array [ + [GraphQLError: Both appId and userId must be specified at once], +] +`; + +exports[`ListArticles throws error when author filter is not set correctly 2`] = ` +Array [ + [GraphQLError: fromUserOfArticleId does not match any existing articles], +] +`;