Commit 6edb2492 authored by Stefan Probst's avatar Stefan Probst
Browse files

fix: subscribe to field array value in workflow steps form screen

parent 59bc6785
Pipeline #289956 passed with stages
in 11 minutes and 48 seconds
......@@ -53,7 +53,65 @@ describe('Create workflow page', () => {
cy.get('h1').contains('Create Workflow steps')
})
it.only('should submit workflow with recommended fields and added steps', () => {
it('should go back to workflow from workflow steps view via button', () => {
cy.get('input[name="label"]').type('The workflow')
cy.get('textarea[name="description"]').type('The description')
cy.findByRole('button', { name: 'Next' }).realClick()
cy.findByRole('button', { name: 'Workflow' }).realClick()
cy.get('h1').should('have.text', 'Create Workflow')
cy.get('input[name="label"]').clear()
cy.findByRole('button', { name: 'Workflow steps' }).realClick()
cy.get('h1').should('have.text', 'Create Workflow')
cy.get('input[name="label"]').type('The workflow')
cy.findByRole('button', { name: 'Workflow steps' }).realClick()
cy.get('h1').should('have.text', 'Create Workflow steps')
})
it('should submit minimal workflow', () => {
cy.get('input[name="label"]').type('The workflow')
cy.get('textarea[name="description"]').type('The description')
cy.findByRole('button', { name: 'Next' }).realClick()
cy.findByRole('button', { name: 'Add step' }).realClick()
cy.get('input[name="composedOf[0].label"]').type('The first step')
cy.get('textarea[name="composedOf[0].description"]').type('The description')
cy.findByRole('button', { name: 'Relation type Please select an option' }).click()
cy.findByRole('option', { name: 'Relates to' }).click({ force: true })
cy.findByRole('combobox', { name: 'Related item' }).type('{downarrow}{downarrow}{enter}')
cy.findByRole('button', { name: 'Add Related item' }).click()
cy.findByRole('button', { name: 'Relation type Please select an option' }).click()
cy.findByRole('option', { name: 'Relates to' }).click({ force: true })
cy.findByRole('button', { name: 'Save' }).realClick()
cy.intercept({ method: 'POST', pathname: '/api/workflows' }).as('create-workflow')
cy.intercept({ method: 'POST', pathname: '/api/workflows/*/steps' }).as(
'create-workflow-step',
)
cy.findByRole('button', { name: 'Submit' }).realClick()
cy.findByRole('status').contains('Successfully suggested new Workflow.')
cy.location('pathname').should('equal', '/success')
cy.wait('@create-workflow').then((interception) => {
assert.deepEqual(interception.request.body, {
label: 'The workflow',
description: 'The description',
accessibleAt: [],
contributors: [],
externalIds: [],
properties: [],
relatedItems: [],
})
})
cy.wait('@create-workflow-step').then((interception) => {
assert.deepEqual(interception.request.body, {
label: 'The first step',
description: 'The description',
relatedItems: [{ persistentId: 'ArOAJD', relation: { code: 'relates-to' } }],
stepNo: 1,
})
})
})
it('should submit workflow with recommended fields and added steps', () => {
cy.get('input[name="label"]').type('The workflow')
cy.get('input[name="version"]').type('2.0')
cy.get('textarea[name="description"]').type('The description')
......@@ -92,14 +150,32 @@ describe('Create workflow page', () => {
.type('{downarrow}{downarrow}{downarrow}{enter}')
cy.findByRole('button', { name: 'Next' }).realClick()
cy.findByRole('button', { name: 'Add step' }).realClick()
cy.get('input[name="composedOf[0].label"]').type('The first step')
cy.get('textarea[name="composedOf[0].description"]').type('The description')
cy.findByRole('button', { name: 'Save' }).realClick()
cy.findByRole('button', { name: 'Add step' }).realClick()
cy.get('input[name="composedOf[1].label"]').type('The second step')
cy.get('textarea[name="composedOf[1].description"]').type('The description')
cy.findByRole('button', { name: 'Save' }).realClick()
cy.findByRole('button', { name: 'Move down' }).realClick()
cy.findByRole('button', { name: 'Move down' }).realClick()
cy.findByRole('button', { name: 'Move down' }).realClick()
cy.get('input[name="composedOf[0]label"]').type('The first step')
cy.get('textarea[name="composedOf[0]description"]').type('The description')
cy.findByRole('button', { name: 'Edit step 1' }).realClick()
cy.get('input[name="composedOf[0].label"]').clear().type('The edited step')
cy.findByRole('button', { name: 'Save' }).realClick()
cy.intercept({ method: 'POST', pathname: '/api/workflows' }).as('create-workflow')
cy.intercept({ method: 'POST', pathname: '/api/workflows/*/steps' }).as(
'create-workflow-step',
)
cy.findByRole('button', { name: 'Submit' }).realClick()
cy.findByRole('status').contains('Successfully suggested new Workflow.')
cy.location('pathname').should('equal', '/success')
cy.wait('@create-workflow').then((interception) => {
assert.deepEqual(interception.request.body, {
label: 'The workflow',
......@@ -144,273 +220,26 @@ describe('Create workflow page', () => {
],
})
})
})
it('should submit form when required fields are not empty on submit, and redirect to success page', () => {
cy.get('input[name="label"').focus().type('The label').blur()
cy.get('textarea[name="description"]').focus().type('The description').blur()
cy.findByRole('button', { name: 'Submit' }).realClick()
cy.findByRole('status').contains('Successfully suggested new Workflow.')
cy.location('pathname').should('equal', '/success')
})
it('should dispatch filled out form as payload on submit', () => {
cy.get('input[name="label"]').type('The label')
cy.get('input[name="version"]').type('2.0')
cy.get('textarea[name="description"]').type('The description')
cy.get('input[name="accessibleAt[0]"]').type('https://first.com')
cy.findByRole('button', { name: 'Add Accessible at URL' }).click()
cy.get('input[name="accessibleAt[1]"]').type('https://second.com')
cy.findByRole('button', { name: 'ID Service Please select an option' }).click()
cy.findByRole('option', { name: 'Wikidata' }).click({ force: true })
cy.get('input[name="externalIds[0].identifier"]').type('abcdef')
cy.findByRole('button', { name: 'Add External ID' }).click()
cy.findByRole('button', { name: 'ID Service Please select an option' }).click()
cy.findByRole('option', { name: 'GitHub' }).click({ force: true })
cy.get('input[name="externalIds[1].identifier"]').type('123')
cy.findByRole('button', { name: 'Role Please select an option' }).click()
cy.findByRole('option', { name: 'Contributor' }).click({ force: true })
cy.findByRole('combobox', { name: 'Name' }).type('{downarrow}{downarrow}{enter}')
cy.findByRole('button', { name: 'Add Actor' }).click()
cy.findByRole('button', { name: 'Role Please select an option' }).click()
cy.findByRole('option', { name: 'Contact' }).click({ force: true })
cy.findAllByRole('combobox', { name: 'Name' })
.last()
.type('{downarrow}{downarrow}{downarrow}{enter}')
// cy.findAllByRole('combobox', { name: 'Concept' })
// .first()
// .type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[0].concept.uri"]').type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[1].value"]').type('123')
cy.get('input[name="properties[2].concept.uri"]').type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[3].concept.uri"]').type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[4].value"]').type('http://see-also.com')
cy.get('input[name="properties[5].concept.uri"]').type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[6].value"]').type('2022')
cy.intercept({ pathname: '/api/workflows', method: 'POST' }).as('create-workflow')
cy.findByRole('button', { name: 'Submit' }).realClick()
cy.findByRole('status').contains('Successfully suggested new Workflow.')
cy.location('pathname').should('equal', '/success')
cy.wait('@create-workflow').then((interception) => {
cy.wait('@create-workflow-step').then((interception) => {
assert.deepEqual(interception.request.body, {
label: 'The label',
version: '2.0',
label: 'The edited step',
description: 'The description',
accessibleAt: ['https://first.com', 'https://second.com'],
contributors: [
{ actor: { id: 1 }, role: { code: 'contributor' } },
{ actor: { id: 2 }, role: { code: 'contact' } },
],
properties: [
{
type: { code: 'activity', type: 'concept' },
concept: {
uri: 'http://dcu.gr/ontologies/scholarlyontology/instances/ActivityType-Collecting',
},
},
{
type: { code: 'keyword', type: 'string' },
value: '123',
},
{
type: { code: 'language', type: 'concept' },
concept: { uri: 'http://iso639-3.sil.org/code/eng' },
},
{
type: { code: 'object-format', type: 'concept' },
concept: { uri: 'http://www.iana.org/assignments/media-types/image/tiff' },
},
{
type: { code: 'see-also', type: 'url' },
value: 'http://see-also.com',
},
{
type: { code: 'license', type: 'concept' },
concept: { uri: 'http://spdx.org/licenses/Entessa' },
},
{
type: { code: 'year', type: 'int' },
value: '2022',
},
],
externalIds: [
{ identifier: 'abcdef', identifierService: { code: 'Wikidata' } },
{ identifier: '123', identifierService: { code: 'GitHub' } },
],
relatedItems: [],
stepNo: 1,
})
})
})
it('should dispatch filled out form as draft payload when saving as draft', () => {
cy.get('input[name="label"]').type('The label')
cy.get('input[name="version"]').type('2.0')
cy.get('textarea[name="description"]').type('The description')
cy.get('input[name="accessibleAt[0]"]').type('https://first.com')
cy.findByRole('button', { name: 'Add Accessible at URL' }).click()
cy.get('input[name="accessibleAt[1]"]').type('https://second.com')
// FIXME: backend throws 500 when updating external ids
// @see https://gitlab.gwdg.de/sshoc/sshoc-marketplace-backend/-/issues/166
// cy.findByRole('button', { name: 'ID Service Please select an option' }).click()
// cy.findByRole('option', { name: 'Wikidata' }).click({ force: true })
// cy.get('input[name="externalIds[0].identifier"]').type('abcdef')
// cy.findByRole('button', { name: 'Add External ID' }).click()
// cy.findByRole('button', { name: 'ID Service Please select an option' }).click()
// cy.findByRole('option', { name: 'GitHub' }).click({ force: true })
// cy.get('input[name="externalIds[1].identifier"]').type('123')
cy.findByRole('button', { name: 'Role Please select an option' }).click()
cy.findByRole('option', { name: 'Contributor' }).click({ force: true })
cy.findByRole('combobox', { name: 'Name' }).type('{downarrow}{downarrow}{enter}')
cy.findByRole('button', { name: 'Add Actor' }).click()
cy.findByRole('button', { name: 'Role Please select an option' }).click()
cy.findByRole('option', { name: 'Contact' }).click({ force: true })
cy.findAllByRole('combobox', { name: 'Name' })
.last()
.type('{downarrow}{downarrow}{downarrow}{enter}')
// cy.findAllByRole('combobox', { name: 'Concept' })
// .first()
// .type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[0].concept.uri"]').type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[1].value"]').type('123')
cy.get('input[name="properties[2].concept.uri"]').type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[3].concept.uri"]').type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[4].value"]').type('http://see-also.com')
cy.get('input[name="properties[5].concept.uri"]').type('{downarrow}{downarrow}{enter}')
cy.get('input[name="properties[6].value"]').type('2022')
cy.intercept({ pathname: '/api/workflows', query: { draft: 'true' }, method: 'POST' }).as(
'create-draft-workflow',
)
cy.findByRole('button', { name: 'Save as draft' }).realClick()
cy.findByRole('status').contains('Successfully saved Workflow draft.')
cy.location('pathname').should('equal', '/workflow/new')
cy.wait('@create-draft-workflow').then((interception) => {
cy.wait('@create-workflow-step').then((interception) => {
assert.deepEqual(interception.request.body, {
label: 'The label',
version: '2.0',
label: 'The first step',
description: 'The description',
accessibleAt: ['https://first.com', 'https://second.com'],
contributors: [
{ actor: { id: 1 }, role: { code: 'contributor' } },
{ actor: { id: 2 }, role: { code: 'contact' } },
],
properties: [
{
type: { code: 'activity', type: 'concept' },
concept: {
uri: 'http://dcu.gr/ontologies/scholarlyontology/instances/ActivityType-Collecting',
},
},
{
type: { code: 'keyword', type: 'string' },
value: '123',
},
{
type: { code: 'language', type: 'concept' },
concept: { uri: 'http://iso639-3.sil.org/code/eng' },
},
{
type: { code: 'object-format', type: 'concept' },
concept: { uri: 'http://www.iana.org/assignments/media-types/image/tiff' },
},
{
type: { code: 'see-also', type: 'url' },
value: 'http://see-also.com',
},
{
type: { code: 'license', type: 'concept' },
concept: { uri: 'http://spdx.org/licenses/Entessa' },
},
{
type: { code: 'year', type: 'int' },
value: '2022',
},
],
// FIXME: backend throws 500 when updating external ids:
// @see https://gitlab.gwdg.de/sshoc/sshoc-marketplace-backend/-/issues/166
externalIds: [],
// externalIds: [
// { identifier: 'abcdef', identifierService: { code: 'Wikidata' } },
// { identifier: '123', identifierService: { code: 'GitHub' } },
// ],
relatedItems: [],
stepNo: 2,
})
})
})
cy.intercept({ pathname: '/api/workflows/*', query: { draft: 'true' }, method: 'PUT' }).as(
'update-draft-workflow',
)
cy.get('input[name="label"]').clear().type('The updated label')
cy.findByRole('button', { name: 'Save as draft' }).realClick()
cy.findAllByRole('status').last().contains('Successfully saved Workflow draft.')
cy.location('pathname').should('equal', '/workflow/new')
cy.wait('@update-draft-workflow').then((interception) => {
assert.equal(interception.request.body.label, 'The updated label')
})
cy.findAllByRole('button', { name: 'Remove Property' }).first().realClick()
cy.intercept({ pathname: '/api/workflows/*/commit', method: 'POST' }).as(
'commit-draft-workflow',
)
cy.findByRole('button', { name: 'Submit' }).realClick()
cy.findAllByRole('status').last().contains('Successfully suggested new Workflow.')
cy.location('pathname').should('equal', '/success')
cy.wait('@update-draft-workflow').then((interception) => {
assert.deepEqual(interception.request.body, {
label: 'The updated label',
version: '2.0',
description: 'The description',
accessibleAt: ['https://first.com', 'https://second.com'],
contributors: [
{ actor: { id: 1 }, role: { code: 'contributor' } },
{ actor: { id: 2 }, role: { code: 'contact' } },
],
properties: [
{
type: { code: 'keyword', type: 'string' },
value: '123',
},
{
type: { code: 'language', type: 'concept' },
concept: { uri: 'http://iso639-3.sil.org/code/eng' },
},
{
type: { code: 'object-format', type: 'concept' },
concept: { uri: 'http://www.iana.org/assignments/media-types/image/tiff' },
},
{
type: { code: 'see-also', type: 'url' },
value: 'http://see-also.com',
},
{
type: { code: 'license', type: 'concept' },
concept: { uri: 'http://spdx.org/licenses/Entessa' },
},
{
type: { code: 'year', type: 'int' },
value: '2022',
},
],
// FIXME: backend throws 500 when updating external ids:
// @see https://gitlab.gwdg.de/sshoc/sshoc-marketplace-backend/-/issues/166
externalIds: [],
// externalIds: [
// { identifier: 'abcdef', identifierService: { code: 'Wikidata' } },
// { identifier: '123', identifierService: { code: 'GitHub' } },
// ],
relatedItems: [],
})
})
cy.wait('@commit-draft-workflow')
it.only('should dispatch filled out form as draft payload when saving as draft', () => {
// TODO:
})
})
......@@ -433,6 +262,7 @@ describe('Create workflow page', () => {
it('should submit form when required fields are not empty on submit, and redirect to item detail page', () => {
cy.get('input[name="label"').focus().type('The label').blur()
cy.get('textarea[name="description"]').focus().type('The description').blur()
cy.findByRole('button', { name: 'Next' }).realClick()
cy.findByRole('button', { name: 'Publish' }).realClick()
cy.findByRole('status').contains('Successfully created new Workflow.')
cy.location('pathname').should('have.string', '/workflow')
......
......@@ -22,6 +22,7 @@ import type { ItemFormFields } from '@/components/item-form/useItemFormFields'
import { useWorkflowFormFields } from '@/components/item-form/useWorkflowFormFields'
import type { WorkflowFormPage } from '@/components/item-form/useWorkflowFormPage'
import { useWorkflowStepFormFields } from '@/components/item-form/useWorkflowStepFormFields'
import { useWorkflowStepFormRecommendedFields } from '@/components/item-form/useWorkflowStepFormRecommendedFields'
import { WorkflowFormNavigation } from '@/components/item-form/WorkflowFormNavigation'
import { WorkflowStepPreview } from '@/components/item-form/WorkflowStepPreview'
import { WorkflowTitle } from '@/components/item-form/WorkflowTitle'
......@@ -193,8 +194,10 @@ function WorkflowStepsFormSection(props: WorkflowStepsFormSectionProps): JSX.Ele
const { t } = useI18n<'authenticated' | 'common'>()
const fieldArray = useFieldArray<UndefinedLeaves<WorkflowStepInput> | WorkflowStepInput>(
'composedOf',
{ subscription: {} },
{ subscription: { value: true } },
)
const recommendedFields =
useWorkflowStepFormRecommendedFields() as UndefinedLeaves<WorkflowStepInput>
function onAdd() {
const index = fieldArray.fields.length ?? 0
......@@ -205,7 +208,7 @@ function WorkflowStepsFormSection(props: WorkflowStepsFormSectionProps): JSX.Ele
fieldArray.fields.remove(index)
},
})
fieldArray.fields.push({ label: undefined, description: undefined })
fieldArray.fields.push({ ...recommendedFields, label: undefined, description: undefined })
}
return (
......
......@@ -24,6 +24,7 @@ import type { ItemFormFields } from '@/components/item-form/useItemFormFields'
import { useWorkflowFormFields } from '@/components/item-form/useWorkflowFormFields'
import type { WorkflowFormPage } from '@/components/item-form/useWorkflowFormPage'
import { useWorkflowStepFormFields } from '@/components/item-form/useWorkflowStepFormFields'
import { useWorkflowStepFormRecommendedFields } from '@/components/item-form/useWorkflowStepFormRecommendedFields'
import { WorkflowFormNavigation } from '@/components/item-form/WorkflowFormNavigation'
import { WorkflowStepPreview } from '@/components/item-form/WorkflowStepPreview'
import { WorkflowTitle } from '@/components/item-form/WorkflowTitle'
......@@ -204,8 +205,10 @@ function WorkflowStepsFormSection(props: WorkflowStepsFormSectionProps): JSX.Ele
const { t } = useI18n<'authenticated' | 'common'>()
const fieldArray = useFieldArray<UndefinedLeaves<WorkflowStepInput> | WorkflowStepInput>(
'composedOf',
{ subscription: {} },
{ subscription: { value: true } },
)
const recommendedFields =
useWorkflowStepFormRecommendedFields() as UndefinedLeaves<WorkflowStepInput>
function onAdd() {
const index = fieldArray.fields.length ?? 0
......@@ -216,7 +219,7 @@ function WorkflowStepsFormSection(props: WorkflowStepsFormSectionProps): JSX.Ele
fieldArray.fields.remove(index)
},
})
fieldArray.fields.push({ label: undefined, description: undefined })
fieldArray.fields.push({ ...recommendedFields, label: undefined, description: undefined })
}
return (
......@@ -225,6 +228,7 @@ function WorkflowStepsFormSection(props: WorkflowStepsFormSectionProps): JSX.Ele
<FormFieldList>
{fieldArray.fields.map((name, index) => {
function onEdit() {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const value = fieldArray.fields.value[index]!
setPage({
type: 'step',
......
......@@ -74,6 +74,13 @@ export function removeEmptyItemFields<T extends ItemInput>(values: T): T {
break
}
case 'composedOf': {
if (Array.isArray(value)) {
item[key] = value.map(removeEmptyItemFields)
}
break
}
default: {
item[key] = value
break
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment