From f92626bca94f9943b3350ddee5054eb85b2107c5 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 | 84 ++++-- .../fetchWorkflowsHelper.spec.js | 91 +++--- .../getDefaultPageProps.spec.js | 278 +++++++++++------- .../getStaticPageProps.spec.js | 274 ++++++++++------- 4 files changed, 441 insertions(+), 286 deletions(-) diff --git a/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.js b/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.js index d4a8581a3a..0b6488ffd3 100644 --- a/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.js +++ b/packages/app-project/src/helpers/fetchWorkflowsHelper/fetchWorkflowsHelper.js @@ -2,18 +2,31 @@ 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(',') + } + 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 +43,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 +69,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 fa7f5dfb27..5271be2ced 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 f85aa7627e..64ad08c086 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 a4a4d4dfce..c74bfd6dab 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