Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/api/forms/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ export const makeFormLiveErrorMessages = {
missingTermsAndConditions:
'You must confirm you meet the terms and conditions before you make this form live.',
missingLivePaymentApiKey:
'You must add a valid live payment API key before you make this form live.'
'You must add a valid live payment API key before you make this form live.',
missingTranslations:
'You must finish translating the whole form into Welsh before making this form live.',
outOfSyncTranslations:
'You have made changes to the form that have affected Welsh translations. You must re-save the Welsh translations.'
}

export const removeFormErrorMessages = {
Expand Down
40 changes: 40 additions & 0 deletions src/api/forms/service/definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
Engine,
FormDefinitionRequestType,
FormStatus,
buildTranslationDataRows,
getErrorMessage,
isPaymentPage
} from '@defra/forms-model'
Expand Down Expand Up @@ -192,6 +193,43 @@ function missingTermsAndConditions(form) {
return !form.termsAndConditionsAgreed
}

/**
* @param {FormMetadata} form
* @param {FormDefinition} definition
*/
function checkForMissingTranslations(form, definition) {
// Ignore if no translations
// @ts-expect-error - dynamic language name
if (!definition.metadata?.translations?.cy) {
return
}

// @ts-expect-error - dynamic language name
const cy = definition.metadata.translations.cy

// Check if translation entries are in sync with form definition
const translations = buildTranslationDataRows(form, definition)
const combinedRows = translations.overviewRows.concat(translations.formRows)
const expectedKeys = new Set(combinedRows.map((row) => row.name))
const foundKeys = new Set(Object.keys(cy))

const added = [...foundKeys].filter((v) => !expectedKeys.has(v))
const removed = [...expectedKeys].filter((v) => !foundKeys.has(v))

if (added.length || removed.length || foundKeys.size !== expectedKeys.size) {
throw Boom.badRequest(makeFormLiveErrorMessages.outOfSyncTranslations)
}

// Check for any empty translations
const hasEmptyValues = Object.entries(
// @ts-expect-error - dynamic language name
definition.metadata.translations.cy
).some(([, value]) => !value)
if (hasEmptyValues) {
throw Boom.badRequest(makeFormLiveErrorMessages.missingTranslations)
}
}

/**
* Validates form and form definition for publishing to live
* @param {string} formId - ID of the form
Expand Down Expand Up @@ -251,6 +289,8 @@ function validateFormForPublishing(
if (!form.notificationEmail) {
throw Boom.badRequest(makeFormLiveErrorMessages.missingOutputEmail)
}

checkForMissingTranslations(form, draftFormDefinition)
}

/**
Expand Down
49 changes: 49 additions & 0 deletions src/api/forms/service/definition.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,55 @@
)
})

it('should fail to create a live state from existing draft form when the Welsh translations are out of sync', async () => {
jest.mocked(formMetadata.get).mockResolvedValue(formMetadataDocument)

jest.mocked(formDefinition.get).mockResolvedValueOnce(
/** @type {FormDefinition} */ ({
...definition,
metadata: {
translations: {
cy: {
'form.title': 'Welsh form title'
}
}
}
})
)

await expect(createLiveFromDraft(id, author)).rejects.toThrow(

Check failure on line 443 in src/api/forms/service/definition.test.js

View workflow job for this annotation

GitHub Actions / Unit tests

Forms service › createLiveFromDraft › should fail to create a live state from existing draft form when the Welsh translations are out of sync

expect(received).rejects.toThrow(expected) Expected message: "You have made changes to the form that have affected Welsh translations. You must re-save the Welsh translations." Received message: "(0 , _formsModel.buildTranslationDataRows) is not a function" 209 | 210 | // Check if translation entries are in sync with form definition > 211 | const translations = buildTranslationDataRows(form, definition) | ^ 212 | const combinedRows = translations.overviewRows.concat(translations.formRows) 213 | const expectedKeys = new Set(combinedRows.map((row) => row.name)) 214 | const foundKeys = new Set(Object.keys(cy)) at checkForMissingTranslations (src/api/forms/service/definition.js:211:48) at checkForMissingTranslations (src/api/forms/service/definition.js:293:3) at validateFormForPublishing (src/api/forms/service/definition.js:355:5) at Object.<anonymous> (src/api/forms/service/definition.test.js:443:7) at Object.toThrow (node_modules/expect/build/index.js:218:22) at Object.toThrow (src/api/forms/service/definition.test.js:443:61)
Boom.badRequest(makeFormLiveErrorMessages.outOfSyncTranslations)
)
})

it('should fail to create a live state from existing draft form when the Welsh translations are not fully completed', async () => {
jest.mocked(formMetadata.get).mockResolvedValue(formMetadataDocument)

jest.mocked(formDefinition.get).mockResolvedValueOnce(
/** @type {FormDefinition} */ ({
...definition,
metadata: {
translations: {
cy: {
'form.title': 'Welsh form title',
'form.contact.email.address': 'my-email@test.com',
'form.contact.email.responseTime': 'Welsh response time',
'form.contact.online.url': 'https://welsh-contact.org',
'form.contact.online.text': 'Welsh contact text',
'form.contact.phone': 'Welsh phone',
'form.submissionGuidance': 'Welsh submission guidance',
'form.privacyNoticeUrl': ''
}
}
}
})
)

await expect(createLiveFromDraft(id, author)).rejects.toThrow(

Check failure on line 471 in src/api/forms/service/definition.test.js

View workflow job for this annotation

GitHub Actions / Unit tests

Forms service › createLiveFromDraft › should fail to create a live state from existing draft form when the Welsh translations are not fully completed

expect(received).rejects.toThrow(expected) Expected message: "You must finish translating the whole form into Welsh before making this form live." Received message: "(0 , _formsModel.buildTranslationDataRows) is not a function" 209 | 210 | // Check if translation entries are in sync with form definition > 211 | const translations = buildTranslationDataRows(form, definition) | ^ 212 | const combinedRows = translations.overviewRows.concat(translations.formRows) 213 | const expectedKeys = new Set(combinedRows.map((row) => row.name)) 214 | const foundKeys = new Set(Object.keys(cy)) at checkForMissingTranslations (src/api/forms/service/definition.js:211:48) at checkForMissingTranslations (src/api/forms/service/definition.js:293:3) at validateFormForPublishing (src/api/forms/service/definition.js:355:5) at Object.<anonymous> (src/api/forms/service/definition.test.js:471:7) at Object.toThrow (node_modules/expect/build/index.js:218:22) at Object.toThrow (src/api/forms/service/definition.test.js:471:61)
Boom.badRequest(makeFormLiveErrorMessages.missingTranslations)
)
})

it('should succeed to create a live state from existing draft form when there is no start page when engine is V2', async () => {
const draftV2DefinitionNoStartPage = /** @type {FormDefinition} */ ({
...definition,
Expand Down
Loading