Skip to content

Commit

Permalink
Update YourStats to callout to Eras instead of Zoo-stats-graphql (#5963)
Browse files Browse the repository at this point in the history
* update your stats with proper fetch callout to eras. remove unused statsClient

* remove importing and stubbing statsClient from Recents and Notifications spec

* update stats test

* update specs that referenced stats Graphql client

* Refactor stats fetch

* Refactor tests for YourStats stats request changes

* Apply suggestions from code review

Co-authored-by: Jim O'Donnell <[email protected]>

* Refactor fetchDailyStats stubs

* Add node-fetch comment

---------

Co-authored-by: Mark Bouslog <[email protected]>
Co-authored-by: Jim O'Donnell <[email protected]>
  • Loading branch information
3 people authored Apr 18, 2024
1 parent e34ad00 commit 3bc4629
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 64 deletions.
4 changes: 2 additions & 2 deletions packages/app-project/stores/User/Recents/Recents.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ describe('Stores > Recents', function () {
collections: []
}
}))
sinon.stub(statsClient, 'request').callsFake(() => Promise.resolve(null))
sinon.stub(statsClient, 'fetchDailyStats').callsFake(() => Promise.resolve(null))
})

after(function () {
console.error.restore()
rootStore.client.panoptes.get.restore()
statsClient.request.restore()
statsClient.fetchDailyStats.restore()
})

it('should exist', function () {
Expand Down
11 changes: 6 additions & 5 deletions packages/app-project/stores/User/User.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import * as client from '@zooniverse/panoptes-js'
import { expect } from 'chai'
import { when } from 'mobx'
import nock from 'nock'
import sinon from 'sinon'

import { statsClient } from './UserPersonalization/YourStats'

import Store from '@stores/Store'

Expand All @@ -16,6 +19,8 @@ describe('stores > User', function () {
let userStore

beforeEach(function () {
sinon.stub(statsClient, 'fetchDailyStats')

nock('https://panoptes-staging.zooniverse.org/api')
.persist()
.get('/users/1/recents')
Expand Down Expand Up @@ -57,11 +62,6 @@ describe('stores > User', function () {
.query(true)
.reply(200, { notifications: [] })

nock('https://graphql-stats.zooniverse.org')
.persist()
.post('/graphql')
.reply(200, { data: { statsCount: [] }})

rootStore = Store.create({ project: {
id: '1',
loadingState: asyncStates.success
Expand All @@ -70,6 +70,7 @@ describe('stores > User', function () {
})

afterEach(function () {
statsClient.fetchDailyStats.restore()
nock.cleanAll()
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ describe('Stores > Notifications', function () {
}

before(function () {
sinon.stub(statsClient, 'request')
sinon.stub(statsClient, 'fetchDailyStats')
sinon.stub(sugarClient, 'subscribeTo')
sinon.stub(sugarClient, 'on')
sinon.stub(sugarClient, 'unsubscribeFrom')
})

after(function () {
statsClient.request.restore()
statsClient.fetchDailyStats.restore()
sugarClient.subscribeTo.restore()
sugarClient.on.restore()
sugarClient.unsubscribeFrom.restore()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ describe('Stores > UserPersonalization', function () {

rootStore = initStore(true, { project })
sinon.spy(rootStore.client.panoptes, 'get')
sinon.stub(statsClient, 'request').callsFake(() => Promise.resolve({ statsCount: MOCK_DAILY_COUNTS }))
sinon.stub(statsClient, 'fetchDailyStats').callsFake(({ projectId, userId }) => (projectId === '2' && userId === '123') ?
Promise.resolve({ data: MOCK_DAILY_COUNTS }) :
Promise.reject(new Error(`Unable to fetch stats for project ${projectId} and user ${userId}`)))
sinon.stub(talkAPI, 'get').callsFake(() => Promise.resolve(undefined))
})

after(function () {
console.error.restore()
rootStore.client.panoptes.get.restore()
statsClient.request.restore()
statsClient.fetchDailyStats.restore()
talkAPI.get.restore()
nock.cleanAll()
})
Expand Down Expand Up @@ -97,19 +99,7 @@ describe('Stores > UserPersonalization', function () {
})

it('should trigger the child YourStats node to request user statistics', function () {
const query = `{
statsCount(
eventType: "classification",
interval: "1 Day",
window: "1 Week",
projectId: "2",
userId: "123"
){
period,
count
}
}`
expect(statsClient.request).to.have.been.calledOnceWith(query.replace(/\s+/g, ' '))
expect(statsClient.fetchDailyStats).to.have.been.calledOnceWith({ projectId: '2', userId: '123' })
})

it('should trigger the child Notifications store to request unread notifications', function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { statsClient } from '../YourStats'
import UserProjectPreferences, { Settings } from './UserProjectPreferences'
import { expect } from 'chai'


describe('Stores > UserProjectPreferences', function () {
const project = {
id: '2',
Expand Down Expand Up @@ -71,12 +72,12 @@ describe('Stores > UserProjectPreferences', function () {
}

before(function () {
sinon.stub(statsClient, 'request')
sinon.stub(statsClient, 'fetchDailyStats')
sinon.stub(talkAPI, 'get').resolves([])
})

after(function () {
statsClient.request.restore()
statsClient.fetchDailyStats.restore()
talkAPI.get.restore()
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
import asyncStates from '@zooniverse/async-states'
import { GraphQLClient } from 'graphql-request'
import { flow, getRoot, types } from 'mobx-state-tree'
import auth from 'panoptes-client/lib/auth'
import { env } from '@zooniverse/panoptes-js'

export const statsClient = new GraphQLClient('https://graphql-stats.zooniverse.org/graphql')
function statsHost(env) {
switch (env) {
case 'production':
return 'https://eras.zooniverse.org'
default:
return 'https://eras-staging.zooniverse.org'
}
}

export const statsClient = {
async fetchDailyStats({ projectId, userId }) {
const token = await auth.checkBearerToken()
const Authorization = `Bearer ${token}`
const stats = statsHost(env)
const queryParams = new URLSearchParams({
period: 'day',
project_id: projectId
}).toString()

const response = await fetch(`${stats}/classifications/users/${userId}?${queryParams}`, { headers: { Authorization } })
const jsonResponse = await response.json()
return jsonResponse
}
}

// https://stackoverflow.com/a/51918448/10951669
function firstDayOfWeek (dateObject, firstDayOfWeekIndex) {
Expand Down Expand Up @@ -67,25 +90,8 @@ const YourStats = types
self.setLoadingState(asyncStates.loading)
let dailyCounts
try {
const token = yield auth.checkBearerToken()
const Authorization = `Bearer ${token}`
statsClient.setHeaders({
Authorization
})
const query = `{
statsCount(
eventType: "classification",
interval: "1 Day",
window: "1 Week",
projectId: "${project.id}",
userId: "${user.id}"
){
period,
count
}
}`
const response = yield statsClient.request(query.replace(/\s+/g, ' '))
dailyCounts = response.statsCount
const statsData = yield statsClient.fetchDailyStats({ projectId: project.id, userId: user.id })
dailyCounts = statsData.data
self.setLoadingState(asyncStates.success)
} catch (error) {
self.handleError(error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe('Stores > YourStats', function () {
{ count: 8, period: '2019-10-05' },
{ count: 15, period: '2019-10-06' }
]

nockScope = nock('https://panoptes-staging.zooniverse.org/api')
.persist()
.get('/project_preferences')
Expand All @@ -45,13 +46,15 @@ describe('Stores > YourStats', function () {
.query(true)
.reply(200)
rootStore = initStore(true, { project })
sinon.stub(statsClient, 'request').callsFake(() => Promise.resolve({ statsCount: MOCK_DAILY_COUNTS }))
sinon.stub(statsClient, 'fetchDailyStats').callsFake(({ projectId, userId }) => (projectId === '2' && userId === '123') ?
Promise.resolve({ data: MOCK_DAILY_COUNTS }) :
Promise.reject(new Error(`Unable to fetch stats for project ${projectId} and user ${userId}`)))
sinon.stub(talkAPI, 'get')
})

after(function () {
console.error.restore()
statsClient.request.restore()
statsClient.fetchDailyStats.restore()
talkAPI.get.restore()
nock.cleanAll()
})
Expand All @@ -78,25 +81,12 @@ describe('Stores > YourStats', function () {
})

it('should request user statistics', function () {
const query = `{
statsCount(
eventType: "classification",
interval: "1 Day",
window: "1 Week",
projectId: "2",
userId: "123"
){
period,
count
}
}`

expect(statsClient.request).to.have.been.calledOnceWith(query.replace(/\s+/g, ' '))
expect(statsClient.fetchDailyStats).to.have.been.calledOnceWith({ projectId: '2', userId: '123' })
})

describe('weekly classification stats', function () {
it('should be created', function () {
expect(rootStore.user.personalization.stats.thisWeek.length).to.equal(7)
expect(getSnapshot(rootStore.user.personalization.stats.thisWeek).length).to.equal(7)
})

it('should start on Monday', function () {
Expand Down
1 change: 1 addition & 0 deletions packages/app-project/test/create-global-document.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Creates a global document object using jsdom to allow the use of the
// `mount` method in enzyme.
import { JSDOM } from 'jsdom'
// importing fetch from node-fetch and attaching it to the global object so that fetch can be tested with nock.
import fetch from 'node-fetch'
import nock from 'nock'

Expand Down

0 comments on commit 3bc4629

Please sign in to comment.