From bf655ee95ce79a67ea34dbd69467a016a1bfbb9c Mon Sep 17 00:00:00 2001 From: Jim O'Donnell Date: Mon, 22 Feb 2021 11:07:44 +0000 Subject: [PATCH] Split code path for grouped workflows Only use the Cellect API for grouped workflows. Return a default set of workflow data otherwise. Remove included subject sets from the workflow request and request them separately, based on the Cellect response. Update tests to test for grouped and non-grouped workflows. Update mocks to represent Cellect responses without the grouped attribute. --- .../fetchWorkflowsHelper.js | 85 ++++-- .../fetchWorkflowsHelper.spec.js | 91 +++--- .../getDefaultPageProps.spec.js | 278 +++++++++++------- .../getStaticPageProps.spec.js | 274 ++++++++++------- 4 files changed, 442 insertions(+), 286 deletions(-) diff --git a/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.js b/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.js index d4a8581a3ab..b5ca5b16ed3 100644 --- a/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.js +++ b/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.js @@ -2,18 +2,32 @@ import { panoptes } from '@zooniverse/panoptes-js' import fetch from 'node-fetch' async function fetchWorkflowData (activeWorkflows, env) { - const response = await panoptes - .get('/workflows', { - complete: false, + const query = { + complete: false, + env, + fields: 'completeness,display_name,grouped', + id: activeWorkflows.join(','), + include: 'subject_sets' + } + const response = await panoptes.get('/workflows', query) + const { workflows } = response.body + return workflows +} + +async function fetchSubjectSetData(subjectSetIDs, env) { + let subject_sets = [] + try { + const query = { env, - fields: 'completeness,grouped', - id: activeWorkflows.join(','), - include: 'subject_sets' - }) - const { workflows, linked } = response.body - const subjectSets = linked ? linked.subject_sets : [] - await Promise.allSettled(subjectSets.map(subjectSet => fetchPreviewImage(subjectSet, env))) - return { subjectSets, workflows } + id: subjectSetIDs.join(',') + } + const response = await panoptes.get('/subject_sets', query) + subject_sets = response.body.subject_sets + await Promise.allSettled(subject_sets.map(subjectSet => fetchPreviewImage(subjectSet, env))) + } catch (error) { + console.error(error) + } + return subject_sets } function fetchDisplayNames (language, activeWorkflows, env) { @@ -30,10 +44,17 @@ function fetchDisplayNames (language, activeWorkflows, env) { } async function fetchWorkflowCellectStatus(workflow) { - const workflowURL = `https://cellect.zooniverse.org/workflows/${workflow.id}/status` - const response = await fetch(workflowURL) - const body = await response.json() - const { groups } = body ?? {} + let groups = {} + if (workflow.grouped) { + try { + const workflowURL = `https://cellect.zooniverse.org/workflows/${workflow.id}/status` + const response = await fetch(workflowURL) + const body = await response.json() + groups = body.groups ?? {} + } catch (error) { + console.error(error) + } + } return groups } @@ -49,38 +70,44 @@ async function fetchPreviewImage (subjectSet, env) { subjectSet.subjects = linked.subjects } -async function buildWorkflow(workflow, displayName, subjectSets, isDefault) { +async function workflowSubjectSets(workflow, env) { const subjectSetCounts = await fetchWorkflowCellectStatus(workflow) - const workflowSubjectSets = workflow.links.subject_sets - .map(subjectSetID => { - const subjectSet = subjectSets.find(subjectSet => subjectSet.id === subjectSetID) - subjectSet.availableSubjects = subjectSetCounts[subjectSetID] - return subjectSet - }) - .filter(Boolean) + const subjectSetIDs = Object.keys(subjectSetCounts) + const subjectSets = await fetchSubjectSetData(subjectSetIDs, env) + subjectSets.forEach(subjectSet => { + subjectSet.availableSubjects = subjectSetCounts[subjectSet.id] + }) + return subjectSets +} - return { +async function buildWorkflow(workflow, displayName, isDefault, env) { + const workflowData = { completeness: workflow.completeness || 0, default: isDefault, displayName, grouped: workflow.grouped, id: workflow.id, - subjectSets: workflowSubjectSets + subjectSets: [] + } + if (workflow.grouped) { + workflowData.subjectSets = await workflowSubjectSets(workflow, env) } + + return workflowData } async function fetchWorkflowsHelper (language = 'en', activeWorkflows, defaultWorkflow, env) { - const { subjectSets, workflows } = await fetchWorkflowData(activeWorkflows, env) + const workflows = await fetchWorkflowData(activeWorkflows, env) const workflowIds = workflows.map(workflow => workflow.id) const displayNames = await fetchDisplayNames(language, workflowIds, env) const awaitWorkflows = workflows.map(workflow => { const isDefault = workflows.length === 1 || workflow.id === defaultWorkflow - const displayName = displayNames[workflow.id] - return buildWorkflow(workflow, displayName, subjectSets, isDefault) + const displayName = displayNames[workflow.id] || workflow.display_name + return buildWorkflow(workflow, displayName, isDefault, env) }) const workflowStatuses = await Promise.allSettled(awaitWorkflows) - const workflowsWithSubjectSets = workflowStatuses.map(result => result.value) + const workflowsWithSubjectSets = workflowStatuses.map(result => result.value || result.reason) return workflowsWithSubjectSets } diff --git a/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.spec.js b/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.spec.js index fa7f5dfb27a..5271be2cedc 100644 --- a/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.spec.js +++ b/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.spec.js @@ -15,7 +15,7 @@ describe('Helpers > fetchWorkflowsHelper', function () { { id: '2', completeness: 0.7, - grouped: false, + grouped: true, links: { subject_sets: ['1', '2', '3'] } @@ -56,9 +56,7 @@ describe('Helpers > fetchWorkflowsHelper', function () { const cellect = nock('https://cellect.zooniverse.org') .persist() .get('/workflows/1/status') - .reply(200, { - groups: availableSubjects - }) + .reply(200, {}) .get('/workflows/2/status') .reply(200, { groups: availableSubjects @@ -79,14 +77,16 @@ describe('Helpers > fetchWorkflowsHelper', function () { .get('/workflows') .query(true) .reply(200, { - workflows: WORKFLOWS.slice(0, 1), - linked: { - subject_sets: [ - subjectSet('1'), - subjectSet('2'), - subjectSet('3') - ] - } + workflows: WORKFLOWS.slice(0, 1) + }) + .get('/subject_sets') + .query(query => query.id === '1,2,3') + .reply(200, { + subject_sets: [ + subjectSet('1'), + subjectSet('2'), + subjectSet('3') + ] }) const result = await fetchWorkflowsHelper('en', ['1']) @@ -98,11 +98,7 @@ describe('Helpers > fetchWorkflowsHelper', function () { grouped: false, id: '1', displayName: 'Foo', - subjectSets: [ - Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), - Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), - Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) - ] + subjectSets: [] } ]) }) @@ -117,14 +113,16 @@ describe('Helpers > fetchWorkflowsHelper', function () { .get('/workflows') .query(true) .reply(200, { - workflows: WORKFLOWS, - linked: { - subject_sets: [ - subjectSet('1'), - subjectSet('2'), - subjectSet('3') - ] - } + workflows: WORKFLOWS + }) + .get('/subject_sets') + .query(true) + .reply(200, { + subject_sets: [ + subjectSet('1'), + subjectSet('2'), + subjectSet('3') + ] }) const result = await fetchWorkflowsHelper('en', ['1', '2']) @@ -135,16 +133,12 @@ describe('Helpers > fetchWorkflowsHelper', function () { grouped: false, id: '1', displayName: 'Foo', - subjectSets: [ - Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), - Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), - Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) - ] + subjectSets: [] }, { completeness: 0.7, default: false, - grouped: false, + grouped: true, id: '2', displayName: 'Bar', subjectSets: [ @@ -167,14 +161,16 @@ describe('Helpers > fetchWorkflowsHelper', function () { .get('/workflows') .query(true) .reply(200, { - workflows: WORKFLOWS, - linked: { - subject_sets: [ - subjectSet('1'), - subjectSet('2'), - subjectSet('3') - ] - } + workflows: WORKFLOWS + }) + .get('/subject_sets') + .query(true) + .reply(200, { + subject_sets: [ + subjectSet('1'), + subjectSet('2'), + subjectSet('3') + ] }) const result = await fetchWorkflowsHelper('en', ['1', '2'], '2') @@ -185,16 +181,12 @@ describe('Helpers > fetchWorkflowsHelper', function () { grouped: false, id: '1', displayName: 'Foo', - subjectSets: [ - Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), - Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), - Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) - ] + subjectSets: [] }, { completeness: 0.7, default: true, - grouped: false, + grouped: true, id: '2', displayName: 'Bar', subjectSets: [ @@ -238,14 +230,7 @@ describe('Helpers > fetchWorkflowsHelper', function () { .get('/workflows') .query(true) .reply(200, { - workflows: WORKFLOWS, - linked: { - subject_sets: [ - subjectSet('1'), - subjectSet('2'), - subjectSet('3') - ] - } + workflows: WORKFLOWS }) try { diff --git a/packages/app-project/src/helpers/getDefaultPageProps/getDefaultPageProps.spec.js b/packages/app-project/src/helpers/getDefaultPageProps/getDefaultPageProps.spec.js index f85aa7627e4..64ad08c086e 100644 --- a/packages/app-project/src/helpers/getDefaultPageProps/getDefaultPageProps.spec.js +++ b/packages/app-project/src/helpers/getDefaultPageProps/getDefaultPageProps.spec.js @@ -13,6 +13,16 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { } } + const GROUPED_PROJECT = { + id: '2', + default_workflow: '2', + primary_language: 'en', + slug: 'test-owner/grouped-project', + links: { + active_workflows: ['2'] + } + } + const TRANSLATION = { translated_id: 1, strings: { @@ -20,6 +30,13 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { } } + const GROUPED_TRANSLATION = { + translated_id: 2, + strings: { + display_name: 'Bar' + } + } + const WORKFLOW = { id: '1', completeness: 0.4, @@ -29,6 +46,15 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { } } + const GROUPED_WORKFLOW = { + id: '2', + completeness: 0.4, + grouped: true, + links: { + subject_sets: ['1', '2', '3'] + } + } + const availableSubjects = { 1: 4, 2: 10, @@ -43,53 +69,77 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { } } - describe('with the staging API', function () { - before(function () { - const slug = 'test-owner/test-project' - const cellect = nock('https://cellect.zooniverse.org') + function mockAPI(panoptesHost) { + const cellect = nock('https://cellect.zooniverse.org') + .persist() + .get('/workflows/2/status') + .reply(200, { + groups: availableSubjects + }) + const scope = nock(panoptesHost) .persist() - .get('/workflows/1/status') + .get('/projects') + .query(query => query.slug === 'test-owner/test-project') .reply(200, { - groups: availableSubjects + projects: [PROJECT] }) - const scope = nock('https://panoptes-staging.zooniverse.org/api') - .persist() - .get('/projects') - .query(query => query.slug === slug) - .reply(200, { - projects: [PROJECT] - }) - .get('/projects') - .query(query => query.slug !== slug) - .reply(200, { - projects: [] - }) - .get('/translations') - .query(query => { - return query.translated_type === 'workflow' - && query.translated_id === '1' - && query.language === 'en' - }) - .reply(200, { - translations: [TRANSLATION] - }) - .get('/workflows') - .query(query => query.id === '1') - .reply(200, { - workflows: [WORKFLOW], - linked: { - subject_sets: [ - subjectSet('1'), - subjectSet('2'), - subjectSet('3') - ] - } - }) - .get('/workflows') - .query(query => query.id !== '1') - .reply(200, { - workflows: [] - }) + .get('/projects') + .query(query => query.slug === 'test-owner/grouped-project') + .reply(200, { + projects: [GROUPED_PROJECT] + }) + .get('/projects') + .query(query => query.slug === 'test-owner/test-wrong-project') + .reply(200, { + projects: [] + }) + .get('/translations') + .query(query => { + return query.translated_type === 'workflow' + && query.translated_id === '1' + && query.language === 'en' + }) + .reply(200, { + translations: [TRANSLATION] + }) + .get('/translations') + .query(query => { + return query.translated_type === 'workflow' + && query.translated_id === '2' + && query.language === 'en' + }) + .reply(200, { + translations: [GROUPED_TRANSLATION] + }) + .get('/subject_sets') + .query(query => query.id === '1,2,3') + .reply(200, { + subject_sets: [ + subjectSet('1'), + subjectSet('2'), + subjectSet('3') + ] + }) + .get('/workflows') + .query(query => query.id === '1') + .reply(200, { + workflows: [WORKFLOW] + }) + .get('/workflows') + .query(query => query.id === '2') + .reply(200, { + workflows: [GROUPED_WORKFLOW] + }) + .get('/workflows') + .query(query => parseInt(query.id) > 2) + .reply(200, { + workflows: [] + }) + } + + describe('with the staging API', function () { + before(function () { + mockAPI('https://panoptes-staging.zooniverse.org/api') }) after(function () { @@ -122,11 +172,7 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { grouped: false, id: '1', displayName: 'Foo', - subjectSets: [ - Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), - Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), - Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) - ] + subjectSets: [] } ]) }) @@ -169,6 +215,43 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { }) }) + describe('with a grouped workflow', function () { + it('should return the project\'s active workflows with subject sets', async function () { + const params = { + owner: 'test-owner', + project: 'grouped-project', + workflowID: '2' + } + const query = { + env: 'staging' + } + const req = { + connection: { + encrypted: true + }, + headers: { + host: 'www.zooniverse.org' + } + } + const res = {} + const { props } = await getDefaultPageProps({ params, query, req, res }) + expect(props.workflows).to.deep.equal([ + { + completeness: 0.4, + default: true, + grouped: true, + id: '2', + displayName: 'Bar', + subjectSets: [ + Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), + Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), + Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) + ] + } + ]) + }) + }) + describe('with an invalid workflow ID', function () { let props let res = {} @@ -177,7 +260,7 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { const params = { owner: 'test-owner', project: 'test-project', - workflowID: '2' + workflowID: '3' } const query = { env: 'staging' @@ -203,58 +286,14 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { }) it('should pass an error message to the error page', function () { - expect(props.title).to.equal('Workflow 2 was not found') + expect(props.title).to.equal('Workflow 3 was not found') }) }) }) describe('with the production API', function () { before(function () { - const slug = 'test-owner/test-project' - const cellect = nock('https://cellect.zooniverse.org') - .persist() - .get('/workflows/1/status') - .reply(200, { - groups: availableSubjects - }) - const scope = nock('https://www.zooniverse.org/api') - .persist() - .get('/projects') - .query(query => query.slug === slug) - .reply(200, { - projects: [PROJECT] - }) - .get('/projects') - .query(query => query.slug !== slug) - .reply(200, { - projects: [] - }) - .get('/translations') - .query(query => { - return query.translated_type === 'workflow' - && query.translated_id === '1' - && query.language === 'en' - }) - .reply(200, { - translations: [TRANSLATION] - }) - .get('/workflows') - .query(query => query.id === '1') - .reply(200, { - workflows: [WORKFLOW], - linked: { - subject_sets: [ - subjectSet('1'), - subjectSet('2'), - subjectSet('3') - ] - } - }) - .get('/workflows') - .query(query => query.id !== '1') - .reply(200, { - workflows: [] - }) + mockAPI('https://www.zooniverse.org/api') }) after(function () { @@ -287,11 +326,7 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { grouped: false, id: '1', displayName: 'Foo', - subjectSets: [ - Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), - Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), - Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) - ] + subjectSets: [] } ]) }) @@ -334,6 +369,43 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { }) }) + describe('with a grouped workflow', function () { + it('should return the project\'s active workflows with subject sets', async function () { + const params = { + owner: 'test-owner', + project: 'grouped-project', + workflowID: '2' + } + const query = { + env: 'production' + } + const req = { + connection: { + encrypted: true + }, + headers: { + host: 'www.zooniverse.org' + } + } + const res = {} + const { props } = await getDefaultPageProps({ params, query, req, res }) + expect(props.workflows).to.deep.equal([ + { + completeness: 0.4, + default: true, + grouped: true, + id: '2', + displayName: 'Bar', + subjectSets: [ + Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), + Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), + Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) + ] + } + ]) + }) + }) + describe('with an invalid workflow ID', function () { let props let res = {} @@ -342,7 +414,7 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { const params = { owner: 'test-owner', project: 'test-project', - workflowID: '2' + workflowID: '3' } const query = { env: 'production' @@ -368,7 +440,7 @@ describe('Components > ProjectHomePage > getDefaultPageProps', function () { }) it('should pass an error message to the error page', function () { - expect(props.title).to.equal('Workflow 2 was not found') + expect(props.title).to.equal('Workflow 3 was not found') }) }) }) diff --git a/packages/app-project/src/helpers/getStaticPageProps/getStaticPageProps.spec.js b/packages/app-project/src/helpers/getStaticPageProps/getStaticPageProps.spec.js index a4a4d4dfceb..c74bfd6dabc 100644 --- a/packages/app-project/src/helpers/getStaticPageProps/getStaticPageProps.spec.js +++ b/packages/app-project/src/helpers/getStaticPageProps/getStaticPageProps.spec.js @@ -13,6 +13,16 @@ describe('Helpers > getStaticPageProps', function () { } } + const GROUPED_PROJECT = { + id: '2', + default_workflow: '2', + primary_language: 'en', + slug: 'test-owner/grouped-project', + links: { + active_workflows: ['2'] + } + } + const TRANSLATION = { translated_id: 1, strings: { @@ -20,6 +30,13 @@ describe('Helpers > getStaticPageProps', function () { } } + const GROUPED_TRANSLATION = { + translated_id: 2, + strings: { + display_name: 'Bar' + } + } + const WORKFLOW = { id: '1', completeness: 0.4, @@ -29,6 +46,15 @@ describe('Helpers > getStaticPageProps', function () { } } + const GROUPED_WORKFLOW = { + id: '2', + completeness: 0.4, + grouped: true, + links: { + subject_sets: ['1', '2', '3'] + } + } + const availableSubjects = { 1: 4, 2: 10, @@ -43,53 +69,77 @@ describe('Helpers > getStaticPageProps', function () { } } - describe('with the staging API', function () { - before(function () { - const slug = 'test-owner/test-project' - const cellect = nock('https://cellect.zooniverse.org') + function mockAPI(panoptesHost) { + const cellect = nock('https://cellect.zooniverse.org') + .persist() + .get('/workflows/2/status') + .reply(200, { + groups: availableSubjects + }) + const scope = nock(panoptesHost) .persist() - .get('/workflows/1/status') + .get('/projects') + .query(query => query.slug === 'test-owner/test-project') .reply(200, { - groups: availableSubjects + projects: [PROJECT] }) - const scope = nock('https://panoptes-staging.zooniverse.org/api') - .persist() - .get('/projects') - .query(query => query.slug === slug) - .reply(200, { - projects: [PROJECT] - }) - .get('/projects') - .query(query => query.slug !== slug) - .reply(200, { - projects: [] - }) - .get('/translations') - .query(query => { - return query.translated_type === 'workflow' - && query.translated_id === '1' - && query.language === 'en' - }) - .reply(200, { - translations: [TRANSLATION] - }) - .get('/workflows') - .query(query => query.id === '1') - .reply(200, { - workflows: [WORKFLOW], - linked: { - subject_sets: [ - subjectSet('1'), - subjectSet('2'), - subjectSet('3') - ] - } - }) - .get('/workflows') - .query(query => query.id !== '1') - .reply(200, { - workflows: [] - }) + .get('/projects') + .query(query => query.slug === 'test-owner/grouped-project') + .reply(200, { + projects: [GROUPED_PROJECT] + }) + .get('/projects') + .query(query => query.slug === 'test-owner/test-wrong-project') + .reply(200, { + projects: [] + }) + .get('/translations') + .query(query => { + return query.translated_type === 'workflow' + && query.translated_id === '1' + && query.language === 'en' + }) + .reply(200, { + translations: [TRANSLATION] + }) + .get('/translations') + .query(query => { + return query.translated_type === 'workflow' + && query.translated_id === '2' + && query.language === 'en' + }) + .reply(200, { + translations: [GROUPED_TRANSLATION] + }) + .get('/subject_sets') + .query(query => query.id === '1,2,3') + .reply(200, { + subject_sets: [ + subjectSet('1'), + subjectSet('2'), + subjectSet('3') + ] + }) + .get('/workflows') + .query(query => query.id === '1') + .reply(200, { + workflows: [WORKFLOW] + }) + .get('/workflows') + .query(query => query.id === '2') + .reply(200, { + workflows: [GROUPED_WORKFLOW] + }) + .get('/workflows') + .query(query => parseInt(query.id) > 2) + .reply(200, { + workflows: [] + }) + } + + describe('with the staging API', function () { + before(function () { + mockAPI('https://panoptes-staging.zooniverse.org/api') }) after(function () { @@ -113,11 +163,7 @@ describe('Helpers > getStaticPageProps', function () { grouped: false, id: '1', displayName: 'Foo', - subjectSets: [ - Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), - Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), - Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) - ] + subjectSets: [] } ]) }) @@ -147,6 +193,43 @@ describe('Helpers > getStaticPageProps', function () { }) }) + describe('with a grouped workflow', function () { + it('should return the project\'s active workflows with subject sets', async function () { + const params = { + owner: 'test-owner', + project: 'grouped-project', + workflowID: '2' + } + const query = { + env: 'staging' + } + const req = { + connection: { + encrypted: true + }, + headers: { + host: 'www.zooniverse.org' + } + } + const res = {} + const { props } = await getStaticPageProps({ params, query }) + expect(props.workflows).to.deep.equal([ + { + completeness: 0.4, + default: true, + grouped: true, + id: '2', + displayName: 'Bar', + subjectSets: [ + Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), + Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), + Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) + ] + } + ]) + }) + }) + describe('with an invalid workflow ID', function () { let props @@ -154,7 +237,7 @@ describe('Helpers > getStaticPageProps', function () { const params = { owner: 'test-owner', project: 'test-project', - workflowID: '2' + workflowID: '3' } const query = { env: 'staging' @@ -168,58 +251,14 @@ describe('Helpers > getStaticPageProps', function () { }) it('should return a workflow error message', function () { - expect(props.title).to.equal('Workflow 2 was not found') + expect(props.title).to.equal('Workflow 3 was not found') }) }) }) describe('with the production API', function () { before(function () { - const slug = 'test-owner/test-project' - const cellect = nock('https://cellect.zooniverse.org') - .persist() - .get('/workflows/1/status') - .reply(200, { - groups: availableSubjects - }) - const scope = nock('https://www.zooniverse.org/api') - .persist() - .get('/projects') - .query(query => query.slug === slug) - .reply(200, { - projects: [PROJECT] - }) - .get('/projects') - .query(query => query.slug !== slug) - .reply(200, { - projects: [] - }) - .get('/translations') - .query(query => { - return query.translated_type === 'workflow' - && query.translated_id === '1' - && query.language === 'en' - }) - .reply(200, { - translations: [TRANSLATION] - }) - .get('/workflows') - .query(query => query.id === '1') - .reply(200, { - workflows: [WORKFLOW], - linked: { - subject_sets: [ - subjectSet('1'), - subjectSet('2'), - subjectSet('3') - ] - } - }) - .get('/workflows') - .query(query => query.id !== '1') - .reply(200, { - workflows: [] - }) + mockAPI('https://www.zooniverse.org/api') }) after(function () { @@ -243,11 +282,7 @@ describe('Helpers > getStaticPageProps', function () { grouped: false, id: '1', displayName: 'Foo', - subjectSets: [ - Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), - Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), - Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) - ] + subjectSets: [] } ]) }) @@ -285,6 +320,43 @@ describe('Helpers > getStaticPageProps', function () { }) }) + describe('with a grouped workflow', function () { + it('should return the project\'s active workflows with subject sets', async function () { + const params = { + owner: 'test-owner', + project: 'grouped-project', + workflowID: '2' + } + const query = { + env: 'production' + } + const req = { + connection: { + encrypted: true + }, + headers: { + host: 'www.zooniverse.org' + } + } + const res = {} + const { props } = await getStaticPageProps({ params, query }) + expect(props.workflows).to.deep.equal([ + { + completeness: 0.4, + default: true, + grouped: true, + id: '2', + displayName: 'Bar', + subjectSets: [ + Object.assign(subjectSet('1'), { availableSubjects: availableSubjects[1]}), + Object.assign(subjectSet('2'), { availableSubjects: availableSubjects[2]}), + Object.assign(subjectSet('3'), { availableSubjects: availableSubjects[3]}) + ] + } + ]) + }) + }) + describe('with an invalid workflow ID', function () { let props