From 31c1d4f5137f50d66bf8b2181563a38c0b975d2d Mon Sep 17 00:00:00 2001 From: Simon Backx Date: Thu, 31 Mar 2022 17:03:29 +0200 Subject: [PATCH] Renamed stats endpoint to /stats/member-count and added totals metadata refs https://ghost.slack.com/archives/C02G9E68C/p1648737467414789?thread_ts=1648644801.253699&cid=C02G9E68C - Anything in the API should use snakeCase - Reduce amount of nesting in endpoint name - Added totals metadata --- .../services/stats/lib/members-stats-service.js | 6 ++++-- core/server/web/api/canary/admin/routes.js | 2 +- test/e2e-api/admin/__snapshots__/stats.test.js.snap | 7 ++++++- test/e2e-api/admin/stats.test.js | 2 +- .../services/stats/members-stats-service.test.js | 12 ++++++++---- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/core/server/services/stats/lib/members-stats-service.js b/core/server/services/stats/lib/members-stats-service.js index 653284f9fc..0f3c51ad74 100644 --- a/core/server/services/stats/lib/members-stats-service.js +++ b/core/server/services/stats/lib/members-stats-service.js @@ -66,7 +66,8 @@ class MembersStatsService { const rows = await this.fetchAllStatusDeltas(); // Fetch current total amounts and start counting from there - let {paid, free, comped} = await this.getCount(); + const totals = await this.getCount(); + let {paid, free, comped} = totals; // Get today in UTC (default timezone for Luxon) const today = DateTime.local().toISODate(); @@ -120,7 +121,8 @@ class MembersStatsService { total: cumulativeResults.length, next: null, prev: null - } + }, + totals } }; } diff --git a/core/server/web/api/canary/admin/routes.js b/core/server/web/api/canary/admin/routes.js index 48c550d44f..413ab5b30b 100644 --- a/core/server/web/api/canary/admin/routes.js +++ b/core/server/web/api/canary/admin/routes.js @@ -138,7 +138,7 @@ module.exports = function apiRoutes() { router.get('/members/:id/signin_urls', mw.authAdminApi, http(api.memberSigninUrls.read)); // ## Stats - router.get('/stats/members/count-history', mw.authAdminApi, http(api.stats.memberCountHistory)); + router.get('/stats/member-count', mw.authAdminApi, http(api.stats.memberCountHistory)); // ## Labels router.get('/labels', mw.authAdminApi, http(api.labels.browse)); diff --git a/test/e2e-api/admin/__snapshots__/stats.test.js.snap b/test/e2e-api/admin/__snapshots__/stats.test.js.snap index f8edc8c8fb..250888d5f7 100644 --- a/test/e2e-api/admin/__snapshots__/stats.test.js.snap +++ b/test/e2e-api/admin/__snapshots__/stats.test.js.snap @@ -11,6 +11,11 @@ Object { "prev": null, "total": 1, }, + "totals": Object { + "comped": 0, + "free": 3, + "paid": 5, + }, }, "stats": Array [ Object { @@ -29,7 +34,7 @@ exports[`Stats API Can fetch member count history 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "191", + "content-length": "231", "content-type": "application/json; charset=utf-8", "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "vary": "Origin, Accept-Encoding", diff --git a/test/e2e-api/admin/stats.test.js b/test/e2e-api/admin/stats.test.js index 0c15d4263a..4219c24774 100644 --- a/test/e2e-api/admin/stats.test.js +++ b/test/e2e-api/admin/stats.test.js @@ -12,7 +12,7 @@ describe('Stats API', function () { it('Can fetch member count history', async function () { await agent - .get(`/stats/members/count-history`) + .get(`/stats/member-count`) .expectStatus(200) .matchBodySnapshot({ stats: [{ diff --git a/test/unit/server/services/stats/members-stats-service.test.js b/test/unit/server/services/stats/members-stats-service.test.js index 2941e8f168..55845fcca9 100644 --- a/test/unit/server/services/stats/members-stats-service.test.js +++ b/test/unit/server/services/stats/members-stats-service.test.js @@ -43,7 +43,7 @@ describe('MembersStatsService', function () { currentCounts.free = 2; currentCounts.comped = 3; - const {data: results} = await membersStatsService.getCountHistory(); + const {data: results, meta} = await membersStatsService.getCountHistory(); results.length.should.eql(1); results[0].should.eql({ date: today, @@ -53,6 +53,7 @@ describe('MembersStatsService', function () { paid_subscribed: 0, paid_canceled: 0 }); + meta.totals.should.eql(currentCounts); fakeStatuses.calledOnce.should.eql(true); fakeTotal.calledOnce.should.eql(true); @@ -73,7 +74,7 @@ describe('MembersStatsService', function () { currentCounts.free = 2; currentCounts.comped = 3; - const {data: results} = await membersStatsService.getCountHistory(); + const {data: results, meta} = await membersStatsService.getCountHistory(); results.length.should.eql(1); results[0].should.eql({ date: today, @@ -83,6 +84,7 @@ describe('MembersStatsService', function () { paid_subscribed: 4, paid_canceled: 3 }); + meta.totals.should.eql(currentCounts); fakeStatuses.calledOnce.should.eql(true); fakeTotal.calledOnce.should.eql(true); @@ -112,7 +114,7 @@ describe('MembersStatsService', function () { currentCounts.free = 3; currentCounts.comped = 4; - const {data: results} = await membersStatsService.getCountHistory(); + const {data: results, meta} = await membersStatsService.getCountHistory(); results.should.eql([ { date: yesterday, @@ -131,6 +133,7 @@ describe('MembersStatsService', function () { paid_canceled: 3 } ]); + meta.totals.should.eql(currentCounts); fakeStatuses.calledOnce.should.eql(true); fakeTotal.calledOnce.should.eql(true); }); @@ -166,7 +169,7 @@ describe('MembersStatsService', function () { currentCounts.free = 2; currentCounts.comped = 3; - const {data: results} = await membersStatsService.getCountHistory(); + const {data: results, meta} = await membersStatsService.getCountHistory(); results.should.eql([ { date: yesterday, @@ -185,6 +188,7 @@ describe('MembersStatsService', function () { paid_canceled: 3 } ]); + meta.totals.should.eql(currentCounts); fakeStatuses.calledOnce.should.eql(true); fakeTotal.calledOnce.should.eql(true); });