diff --git a/client/.eslintrc.json b/client/.eslintrc.json index a935eaec6..1144f985d 100644 --- a/client/.eslintrc.json +++ b/client/.eslintrc.json @@ -18,6 +18,7 @@ ], "rules": { "react/jsx-uses-react": "error", - "react/jsx-uses-vars": "error" + "react/jsx-uses-vars": "error", + "no-console": ["warn", { "allow": ["warn", "error"] }] } } diff --git a/graph/loaders/metrics.js b/graph/loaders/metrics.js index a22cbb58f..2627d82d9 100644 --- a/graph/loaders/metrics.js +++ b/graph/loaders/metrics.js @@ -2,13 +2,12 @@ const _ = require('lodash'); const DataLoader = require('dataloader'); const {objectCacheKeyFn} = require('./util'); -const CommentModel = require('../../models/comment'); const ActionModel = require('../../models/action'); /** * Returns a list of assets with action metadata included on the models. */ -const getAssetMetrics = ({loaders: {Metrics, Assets}}, {from, to, sort, limit}) => { +const getAssetMetrics = ({loaders: {Metrics, Assets, Comments}}, {from, to, sort, limit}) => { let commentMetrics = {}; let assetMetrics = []; @@ -34,7 +33,7 @@ const getAssetMetrics = ({loaders: {Metrics, Assets}}, {from, to, sort, limit}) let commentIDs = Object.keys(commentMetrics); // Find those comments. - return Metrics.getSpecificComments.loadMany(commentIDs); + return Comments.get.loadMany(commentIDs); }) .then((comments) => { @@ -202,21 +201,8 @@ const getRecentActions = (context, {from, to}) => { ]); }; -const getSpecificComments = (context, ids) => { - return CommentModel.find({ - id: { - $in: ids - } - }) - .select({ - id: 1, - asset_id: 1 - }); -}; - module.exports = (context) => ({ Metrics: { - getSpecificComments: new DataLoader((ids) => getSpecificComments(context, ids)), getRecentActions: new DataLoader(([{from, to}]) => getRecentActions(context, {from, to}).then((as) => [as]), { batch: false, cacheKeyFn: objectCacheKeyFn('from', 'to') diff --git a/test/graph/loaders/metrics.js b/test/graph/loaders/metrics.js index 303b40897..032a59536 100644 --- a/test/graph/loaders/metrics.js +++ b/test/graph/loaders/metrics.js @@ -4,6 +4,7 @@ const {graphql} = require('graphql'); const schema = require('../../../graph/schema'); const Context = require('../../../graph/context'); const UserModel = require('../../../models/user'); +const AssetModel = require('../../../models/asset'); const SettingsService = require('../../../services/settings'); const ActionModel = require('../../../models/action'); const CommentModel = require('../../../models/comment'); @@ -26,7 +27,9 @@ describe('graph.loaders.Metrics', () => { describe('different comment states', () => { beforeEach(() => CommentModel.create([ - {id: '1', body: 'a new comment!'} + {id: '1', body: 'a new comment!'}, + {id: '2', body: 'a new comment!'}, + {id: '3', body: 'a new comment!'} ])); [ @@ -36,6 +39,12 @@ describe('graph.loaders.Metrics', () => { {liked: 1, flagged: 1, actions: [ {action_type: 'FLAG', item_id: '1', item_type: 'COMMENTS'}, {action_type: 'LIKE', item_id: '1', item_type: 'COMMENTS'} + ]}, + {liked: 3, flagged: 1, actions: [ + {action_type: 'LIKE', item_id: '1', item_type: 'COMMENTS'}, + {action_type: 'LIKE', item_id: '2', item_type: 'COMMENTS'}, + {action_type: 'LIKE', item_id: '3', item_type: 'COMMENTS'}, + {action_type: 'FLAG', item_id: '3', item_type: 'COMMENTS'} ]} ].forEach(({liked, flagged, actions}) => { @@ -63,4 +72,82 @@ describe('graph.loaders.Metrics', () => { }); }); + + describe('#Assets', () => { + const query = ` + fragment metrics on Asset { + id + action_summaries { + type: __typename + actionCount + actionableItemCount + } + } + + query Metrics($from: Date!, $to: Date!) { + assetsByFlag: assetMetrics(from: $from, to: $to, sort: FLAG) { + ...metrics + } + assetsByLike: assetMetrics(from: $from, to: $to, sort: LIKE) { + ...metrics + } + } + `; + + describe('different comment states', () => { + + beforeEach(() => Promise.all([ + AssetModel.create([ + {id: 'a1', url: 'http://localhost:3030/article/1'}, + {id: 'a2', url: 'http://localhost:3030/article/2'} + ]), + CommentModel.create([ + {id: 'c1', asset_id: 'a1', body: 'a new comment!'}, + {id: 'c2', asset_id: 'a1', body: 'a new comment!'}, + {id: 'c3', asset_id: 'a1', body: 'a new comment!'} + ]) + ])); + + [ + {liked: 0, flagged: 0, actions: []}, + {liked: 1, flagged: 0, actions: [{action_type: 'LIKE', item_id: 'c1', item_type: 'COMMENTS'}]}, + {liked: 0, flagged: 1, actions: [{action_type: 'FLAG', item_id: 'c1', item_type: 'COMMENTS'}]}, + {liked: 1, flagged: 1, actions: [ + {action_type: 'FLAG', item_id: 'c1', item_type: 'COMMENTS'}, + {action_type: 'LIKE', item_id: 'c1', item_type: 'COMMENTS'} + ]}, + {liked: 1, flagged: 1, actions: [ + {action_type: 'LIKE', item_id: 'c1', item_type: 'COMMENTS'}, + {action_type: 'LIKE', item_id: 'c2', item_type: 'COMMENTS'}, + {action_type: 'LIKE', item_id: 'c3', item_type: 'COMMENTS'}, + {action_type: 'FLAG', item_id: 'c3', item_type: 'COMMENTS'} + ]} + ].forEach(({liked, flagged, actions}) => { + + describe(`with actions=${actions.length}`, () => { + + beforeEach(() => ActionModel.create(actions)); + + it(`returns the correct amount of metrics liked=${liked} flagged=${flagged}`, () => { + const context = new Context({user: new UserModel({roles: ['ADMIN']})}); + + return graphql(schema, query, {}, context, { + from: (new Date()).setMinutes((new Date()).getMinutes() - 5), + to: (new Date()).setMinutes((new Date()).getMinutes() + 5) + }) + .then(({data, errors}) => { + console.log(JSON.stringify(errors, null, 2)); + + expect(errors).to.be.undefined; + expect(data.assetsByLike).to.have.length(liked); + expect(data.assetsByFlag).to.have.length(flagged); + }); + }); + + }); + + }); + + }); + }); });