-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f7761db
commit bda9b4d
Showing
9 changed files
with
430 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { buildErrorList } from '~/src/common/helpers/build-error-details.js' | ||
|
||
/** | ||
* @param {FormMetadata} metadata | ||
* @param {ValidationFailure<FormMetadataInput>} [validation] | ||
*/ | ||
export function submissionGuidanceViewModel(metadata, validation) { | ||
const pageTitle = 'Tell users what happens after they submit their form' | ||
const { formValues, formErrors } = validation ?? {} | ||
|
||
return { | ||
form: metadata, | ||
backLink: { | ||
text: 'Back', | ||
href: `/library/${metadata.slug}` | ||
}, | ||
pageTitle, | ||
errorList: buildErrorList(formErrors), | ||
formErrors: validation?.formErrors, | ||
formValues: validation?.formValues, | ||
field: { | ||
id: 'submissionGuidance', | ||
name: 'submissionGuidance', | ||
label: { | ||
text: 'What will happen after a user submits a form?' | ||
}, | ||
value: formValues?.submissionGuidance ?? metadata.submissionGuidance | ||
}, | ||
buttonText: 'Save and continue' | ||
} | ||
} | ||
|
||
/** | ||
* @import { FormMetadata, FormMetadataInput } from '@defra/forms-model' | ||
* @import { ValidationFailure } from '~/src/common/helpers/types.js' | ||
*/ |
48 changes: 48 additions & 0 deletions
48
designer/server/src/models/forms/submission-guidance.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { submissionGuidanceViewModel } from '~/src/models/forms/submission-guidance.js' | ||
|
||
describe('edit - model - submission - guidance', () => { | ||
const now = new Date() | ||
const authorId = 'f50ceeed-b7a4-47cf-a498-094efc99f8bc' | ||
const authorDisplayName = 'Enrique Chase' | ||
|
||
/** | ||
* @satisfies {FormMetadataAuthor} | ||
*/ | ||
const author = { | ||
id: authorId, | ||
displayName: authorDisplayName | ||
} | ||
|
||
/** | ||
* @satisfies {FormMetadata} | ||
*/ | ||
const formMetadata = { | ||
id: '661e4ca5039739ef2902b214', | ||
slug: 'my-form-slug', | ||
title: 'Test form', | ||
organisation: 'Defra', | ||
teamName: 'Defra Forms', | ||
teamEmail: '[email protected]', | ||
submissionGuidance: 'We’ll send you an email to let you know the outcome.', | ||
createdAt: now, | ||
createdBy: author, | ||
updatedAt: now, | ||
updatedBy: author | ||
} | ||
|
||
it('should test submission guidance view model', () => { | ||
const result = submissionGuidanceViewModel(formMetadata) | ||
expect(result.pageTitle).toBe( | ||
'Tell users what happens after they submit their form' | ||
) | ||
expect(result.field.id).toBe('submissionGuidance') | ||
expect(result.field.name).toBe('submissionGuidance') | ||
expect(result.field.value).toBe( | ||
'We’ll send you an email to let you know the outcome.' | ||
) | ||
}) | ||
}) | ||
|
||
/** | ||
* @import { FormMetadata, FormMetadataAuthor } from '@defra/forms-model' | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 116 additions & 0 deletions
116
designer/server/src/routes/forms/submission-guidance.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import { submissionGuidanceSchema } from '@defra/forms-model' | ||
import { StatusCodes } from 'http-status-codes' | ||
import Joi from 'joi' | ||
|
||
import * as scopes from '~/src/common/constants/scopes.js' | ||
import { sessionNames } from '~/src/common/constants/session-names.js' | ||
import { buildErrorDetails } from '~/src/common/helpers/build-error-details.js' | ||
import * as forms from '~/src/lib/forms.js' | ||
import { submissionGuidanceViewModel } from '~/src/models/forms/submission-guidance.js' | ||
|
||
export const ROUTE_PATH_EDIT_SUBMISSION_GUIDANCE = | ||
'/library/{slug}/edit/submission-guidance' | ||
|
||
export const schema = Joi.object().keys({ | ||
submissionGuidance: submissionGuidanceSchema.required().messages({ | ||
'string.empty': 'Enter what will happen after a user submits a form' | ||
}) | ||
}) | ||
|
||
export default [ | ||
/** | ||
* @satisfies {ServerRoute<{ Params: { slug: string } }>} | ||
*/ | ||
({ | ||
method: 'GET', | ||
path: ROUTE_PATH_EDIT_SUBMISSION_GUIDANCE, | ||
async handler(request, h) { | ||
const { auth, params, yar } = request | ||
const { slug } = params | ||
const { token } = auth.credentials | ||
|
||
const validation = yar.flash(sessionNames.validationFailure).at(0) | ||
|
||
// Retrieve form by slug | ||
const metadata = await forms.get(slug, token) | ||
|
||
// Create the submission guidance view model | ||
const model = submissionGuidanceViewModel(metadata, validation) | ||
|
||
return h.view('forms/submission-guidance', model) | ||
}, | ||
options: { | ||
auth: { | ||
mode: 'required', | ||
access: { | ||
entity: 'user', | ||
scope: [`+${scopes.SCOPE_WRITE}`] | ||
} | ||
} | ||
} | ||
}), | ||
|
||
/** | ||
* @satisfies {ServerRoute<{ Params: { slug: string }, Payload: { submissionGuidance: string } }>} | ||
*/ | ||
({ | ||
method: 'POST', | ||
path: ROUTE_PATH_EDIT_SUBMISSION_GUIDANCE, | ||
async handler(request, h) { | ||
const { auth, params, payload, yar } = request | ||
const { slug } = params | ||
const { submissionGuidance } = payload | ||
const { token } = auth.credentials | ||
|
||
// Retrieve form by slug | ||
const { id } = await forms.get(slug, token) | ||
|
||
// Update the metadata with the submission guidance text | ||
await forms.updateMetadata(id, { submissionGuidance }, token) | ||
|
||
yar.flash( | ||
sessionNames.successNotification, | ||
'What happens after users submit their form has been updated' | ||
) | ||
|
||
return h.redirect(`/library/${slug}`).code(StatusCodes.SEE_OTHER) | ||
}, | ||
options: { | ||
validate: { | ||
payload: schema, | ||
/** | ||
* @param {Request} request | ||
* @param {ResponseToolkit} h | ||
* @param {Error} [error] | ||
*/ | ||
failAction: (request, h, error) => { | ||
const { payload, yar, url } = request | ||
const { pathname: redirectTo } = url | ||
|
||
if (error && error instanceof Joi.ValidationError) { | ||
const formErrors = buildErrorDetails(error) | ||
|
||
yar.flash(sessionNames.validationFailure, { | ||
formErrors, | ||
formValues: payload | ||
}) | ||
} | ||
|
||
// Redirect POST to GET without resubmit on back button | ||
return h.redirect(redirectTo).code(StatusCodes.SEE_OTHER).takeover() | ||
} | ||
}, | ||
auth: { | ||
mode: 'required', | ||
access: { | ||
entity: 'user', | ||
scope: [`+${scopes.SCOPE_WRITE}`] | ||
} | ||
} | ||
} | ||
}) | ||
] | ||
|
||
/** | ||
* @import { Request, ResponseToolkit, ServerRoute } from '@hapi/hapi' | ||
*/ |
112 changes: 112 additions & 0 deletions
112
designer/server/src/routes/forms/submission-guidance.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import { StatusCodes } from 'http-status-codes' | ||
|
||
import { createServer } from '~/src/createServer.js' | ||
import * as forms from '~/src/lib/forms.js' | ||
import { auth } from '~/test/fixtures/auth.js' | ||
import { renderResponse } from '~/test/helpers/component-helpers.js' | ||
|
||
jest.mock('~/src/lib/forms.js') | ||
|
||
describe('Forms submission guidance', () => { | ||
/** @type {Server} */ | ||
let server | ||
|
||
beforeAll(async () => { | ||
server = await createServer() | ||
await server.initialize() | ||
}) | ||
|
||
const now = new Date() | ||
const authorId = 'f50ceeed-b7a4-47cf-a498-094efc99f8bc' | ||
const authorDisplayName = 'Enrique Chase' | ||
|
||
/** | ||
* @satisfies {FormMetadataAuthor} | ||
*/ | ||
const author = { | ||
id: authorId, | ||
displayName: authorDisplayName | ||
} | ||
|
||
/** | ||
* @satisfies {FormMetadata} | ||
*/ | ||
const formMetadata = { | ||
id: '661e4ca5039739ef2902b214', | ||
slug: 'my-form-slug', | ||
title: 'Test form', | ||
organisation: 'Defra', | ||
teamName: 'Defra Forms', | ||
teamEmail: '[email protected]', | ||
submissionGuidance: 'We’ll send you an email to let you know the outcome.', | ||
createdAt: now, | ||
createdBy: author, | ||
updatedAt: now, | ||
updatedBy: author | ||
} | ||
|
||
/** | ||
* @satisfies {FormDefinition} | ||
*/ | ||
const formDefinition = { | ||
name: 'Test form', | ||
pages: [], | ||
conditions: [], | ||
sections: [], | ||
lists: [] | ||
} | ||
|
||
test('GET - should check correct submission guidance is rendered in the view', async () => { | ||
jest.mocked(forms.get).mockResolvedValueOnce(formMetadata) | ||
jest | ||
.mocked(forms.getDraftFormDefinition) | ||
.mockResolvedValueOnce(formDefinition) | ||
|
||
const options = { | ||
method: 'get', | ||
url: '/library/my-form-slug/edit/submission-guidance', | ||
auth | ||
} | ||
|
||
const { document } = await renderResponse(server, options) | ||
|
||
const submissionGuidance = /** @satisfies {HTMLInputElement | null} */ ( | ||
document.querySelector('#submissionGuidance') | ||
) | ||
|
||
expect(submissionGuidance?.value).toBe( | ||
'We’ll send you an email to let you know the outcome.' | ||
) | ||
}) | ||
|
||
test('POST - should redirect to overviewpage after updating submission guidance', async () => { | ||
jest.mocked(forms.get).mockResolvedValueOnce(formMetadata) | ||
jest.mocked(forms.updateMetadata).mockResolvedValueOnce({ | ||
id: formMetadata.id, | ||
slug: 'my-form-slug', | ||
status: 'updated' | ||
}) | ||
|
||
const options = { | ||
method: 'post', | ||
url: '/library/my-form-slug/edit/submission-guidance', | ||
auth, | ||
payload: { | ||
submissionGuidance: | ||
'We’ll send you an email to let you know the outcome1.' | ||
} | ||
} | ||
|
||
const { | ||
response: { headers, statusCode } | ||
} = await renderResponse(server, options) | ||
|
||
expect(statusCode).toBe(StatusCodes.SEE_OTHER) | ||
expect(headers.location).toBe('/library/my-form-slug') | ||
}) | ||
}) | ||
|
||
/** | ||
* @import { FormDefinition, FormMetadata, FormMetadataAuthor } from '@defra/forms-model' | ||
* @import { Server } from '@hapi/hapi' | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.