diff --git a/package-lock.json b/package-lock.json index 587069b..e9f8c73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "@companieshouse/api-sdk-node": "^2.0.218", + "@companieshouse/api-sdk-node": "^2.0.219", "@companieshouse/ch-node-utils": "^1.3.13", "@companieshouse/node-session-handler": "^5.0.1", "@companieshouse/structured-logging-node": "^2.0.1", @@ -624,9 +624,9 @@ } }, "node_modules/@companieshouse/api-sdk-node": { - "version": "2.0.218", - "resolved": "https://registry.npmjs.org/@companieshouse/api-sdk-node/-/api-sdk-node-2.0.218.tgz", - "integrity": "sha512-RcchYeU0pwb1ToWiSmwKSfRcCEFYneKpBqlTkrWQDa4Brq3zGWaRAYBD7j4HNNyFGC0mH+v7SmQ1a/rF25QJ5w==", + "version": "2.0.219", + "resolved": "https://registry.npmjs.org/@companieshouse/api-sdk-node/-/api-sdk-node-2.0.219.tgz", + "integrity": "sha512-PDtiVamZTkNW/PiEcUZ833Ds4JOjDzK+7yrCzinJllqxb0oZWsoAJ+cswqCQyI1clkYvC/2yZe2kG/V3jp0W7w==", "dependencies": { "axios": "^1.7.4", "camelcase-keys": "~6.2.2", diff --git a/package.json b/package.json index 367344a..2cdc4ce 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "license": "MIT", "homepage": "https://github.com/companieshouse/limited-partnerships-web#readme", "dependencies": { - "@companieshouse/api-sdk-node": "^2.0.218", + "@companieshouse/api-sdk-node": "^2.0.219", "@companieshouse/ch-node-utils": "^1.3.13", "@companieshouse/node-session-handler": "^5.0.1", "@companieshouse/structured-logging-node": "^2.0.1", diff --git a/src/application/registration/Service.ts b/src/application/registration/Service.ts index e276162..c4a1875 100644 --- a/src/application/registration/Service.ts +++ b/src/application/registration/Service.ts @@ -12,8 +12,22 @@ class RegistrationService { this.registrationGateway = registrationGateway; } - getSubmissionById(id: string): Promise { - return this.registrationGateway.getSubmissionById(id); + async getLimitedPartnership( + opt: { access_token: string; refresh_token: string }, + transactionId: string, + submissionId: string + ): Promise { + try { + return await this.registrationGateway.getLimitedPartnership( + opt, + transactionId, + submissionId + ); + } catch (error: any) { + logger.error(`Error getting LimitedPartnership ${JSON.stringify(error)}`); + + throw error; + } } async createTransactionAndFirstSubmission( diff --git a/src/domain/IRegistrationGateway.ts b/src/domain/IRegistrationGateway.ts index f92c833..6d42d42 100644 --- a/src/domain/IRegistrationGateway.ts +++ b/src/domain/IRegistrationGateway.ts @@ -13,7 +13,11 @@ interface IRegistrationGateway { transactionId: string, data: Record ): Promise; - getSubmissionById(id: string): Promise; + getLimitedPartnership( + opt: { access_token: string; refresh_token: string }, + transactionId: string, + submissionId: string + ): Promise; sendPageData( opt: { access_token: string }, transactionId: string, diff --git a/src/infrastructure/gateway/registration/RegistrationGateway.ts b/src/infrastructure/gateway/registration/RegistrationGateway.ts index 0bfc6ea..1b779cb 100644 --- a/src/infrastructure/gateway/registration/RegistrationGateway.ts +++ b/src/infrastructure/gateway/registration/RegistrationGateway.ts @@ -96,8 +96,26 @@ class RegistrationGateway implements IRegistrationGateway { } } - async getSubmissionById(id: string): Promise { - throw new Error("Method not implemented."); + async getLimitedPartnership( + opt: { access_token: string; refresh_token: string }, + transactionId: string, + submissionId: string + ): Promise { + const apiCall = { + service: "limitedPartnershipsService", + method: "getLimitedPartnership", + args: [transactionId, submissionId], + }; + + const response = await makeApiCallWithRetry< + Resource | ApiErrorResponse + >(opt, apiCall); + + if (response.httpStatusCode !== 200) { + throw response; + } + + return (response as Resource)?.resource ?? {}; } } diff --git a/src/infrastructure/gateway/registration/RegistrationInMemoryGateway.ts b/src/infrastructure/gateway/registration/RegistrationInMemoryGateway.ts index 0b2104d..28eb7df 100644 --- a/src/infrastructure/gateway/registration/RegistrationInMemoryGateway.ts +++ b/src/infrastructure/gateway/registration/RegistrationInMemoryGateway.ts @@ -102,13 +102,29 @@ class RegistrationInMemoryGateway implements IRegistrationGateway { this.limitedPartnerships[index] = limitedPartnershipBuilder.build(); } - async getSubmissionById(id: string): Promise { + async getLimitedPartnership( + opt: { access_token: string; refresh_token: string }, + transactionId: string, + submissionId: string + ): Promise { + if ( + transactionId === ":transactionId" && + submissionId === ":submissionId" + ) { + return new LimitedPartnershipGatewayBuilder( + this.limitedPartnerships[0] + ).build(); + } + const limitedPartnerShip = this.limitedPartnerships.find( - (lp) => lp._id === id + (lp) => lp._id === submissionId ); if (!limitedPartnerShip) { - throw new CustomError("Limited partnership", `Not found: ${id}`); + throw new CustomError( + "Limited partnership", + `Not found: ${submissionId}` + ); } return new LimitedPartnershipGatewayBuilder(limitedPartnerShip).build(); diff --git a/src/presentation/controller/registration/Controller.ts b/src/presentation/controller/registration/Controller.ts index 0e2f5c7..2a43a73 100644 --- a/src/presentation/controller/registration/Controller.ts +++ b/src/presentation/controller/registration/Controller.ts @@ -30,6 +30,7 @@ class RegistrationController extends AbstractController { return async (request: Request, response: Response, next: NextFunction) => { try { const session = request.session as Session; + const tokens = this.extractTokens(request); const pageType = super.pageType(request.path); const { transactionId, submissionId } = this.extractIds(request); @@ -41,10 +42,21 @@ class RegistrationController extends AbstractController { submissionId ); + let limitedPartnership = {}; + if (transactionId && submissionId) { + limitedPartnership = + await this.registrationService.getLimitedPartnership( + tokens, + transactionId, + submissionId + ); + } + const cache = await this.cacheService.getDataFromCache(session); pageRouting.data = { ...pageRouting.data, + limitedPartnership, cache, }; diff --git a/src/presentation/controller/registration/Routing.ts b/src/presentation/controller/registration/Routing.ts index 901e99c..a6acf0b 100644 --- a/src/presentation/controller/registration/Routing.ts +++ b/src/presentation/controller/registration/Routing.ts @@ -1,8 +1,5 @@ import { PageRouting, PagesRouting } from "../PageRouting"; -import { - BASE_URL, - BASE_WITH_IDS_URL, -} from "../../../config/constants"; +import { BASE_URL, BASE_WITH_IDS_URL } from "../../../config/constants"; import RegistrationPageType from "./PageType"; import PageType from "../PageType"; @@ -13,14 +10,17 @@ export const NAME_TEMPLATE = RegistrationPageType.name; export const EMAIL_TEMPLATE = RegistrationPageType.email; export const GENERAL_PARTNERS_TEMPLATE = RegistrationPageType.generalPartners; export const LIMITED_PARTNERS_TEMPLATE = RegistrationPageType.limitedPartners; -export const GENERAL_PARTNER_CHOICE_TEMPLATE = RegistrationPageType.generalPartnerChoice; -export const LIMITED_PARTNER_CHOICE_TEMPLATE = RegistrationPageType.limitedPartnerChoice; +export const GENERAL_PARTNER_CHOICE_TEMPLATE = + RegistrationPageType.generalPartnerChoice; +export const LIMITED_PARTNER_CHOICE_TEMPLATE = + RegistrationPageType.limitedPartnerChoice; export const NEXT_TEMPLATE = RegistrationPageType.next; // URLs const START_URL = `${BASE_URL}/start`; export const WHICH_TYPE_URL = `${BASE_URL}/${WHICH_TYPE_TEMPLATE}`; export const NAME_URL = `${BASE_URL}/${NAME_TEMPLATE}`; +export const NAME_WITH_IDS_URL = `${BASE_WITH_IDS_URL}/${NAME_TEMPLATE}`; export const EMAIL_URL = `${BASE_WITH_IDS_URL}/${EMAIL_TEMPLATE}`; export const GENERAL_PARTNERS_URL = `${BASE_WITH_IDS_URL}/${GENERAL_PARTNERS_TEMPLATE}`; export const GENERAL_PARTNER_CHOICE_URL = `${BASE_WITH_IDS_URL}/${GENERAL_PARTNER_CHOICE_TEMPLATE}`; @@ -44,7 +44,7 @@ const registrationRoutingName = { }; const registrationRoutingEmail = { - previousUrl: NAME_URL, + previousUrl: NAME_WITH_IDS_URL, currentUrl: EMAIL_URL, nextUrl: GENERAL_PARTNERS_URL, pageType: RegistrationPageType.email, @@ -94,7 +94,6 @@ const list = [ registrationRoutingGeneralPartnerChoice, registrationRoutingLimitedPartnerChoice, registrationRoutingNext, - ]; export const registrationsRouting: PagesRouting = new Map< diff --git a/src/presentation/test/builder/LimitedPartnershipBuilder.ts b/src/presentation/test/builder/LimitedPartnershipBuilder.ts index 20083d8..53a3845 100644 --- a/src/presentation/test/builder/LimitedPartnershipBuilder.ts +++ b/src/presentation/test/builder/LimitedPartnershipBuilder.ts @@ -1,4 +1,7 @@ -import { NameEndingType } from "@companieshouse/api-sdk-node/dist/services/limited-partnerships"; +import { + NameEndingType, + PartnershipType, +} from "@companieshouse/api-sdk-node/dist/services/limited-partnerships"; import TransactionLimitedPartnership from "../../../domain/entities/TransactionLimitedPartnership"; class LimitedPartnershipBuilder { @@ -6,6 +9,8 @@ class LimitedPartnershipBuilder { data = { partnership_name: "partnership_name test", name_ending: NameEndingType.LIMITED_PARTNERSHIP, + partnership_type: PartnershipType.LP, + email: "test@email.com", }; withId(id: string) { @@ -23,6 +28,16 @@ class LimitedPartnershipBuilder { return this; } + withPartnershipType(partnershipType: PartnershipType) { + this.data.partnership_type = partnershipType; + return this; + } + + withEmail(email: string) { + this.data.email = email; + return this; + } + build(): TransactionLimitedPartnership { return { _id: this["_id"], diff --git a/src/presentation/test/integration/registration/email.test.ts b/src/presentation/test/integration/registration/email.test.ts index 8709fc8..95d40a0 100644 --- a/src/presentation/test/integration/registration/email.test.ts +++ b/src/presentation/test/integration/registration/email.test.ts @@ -12,6 +12,8 @@ import LimitedPartnershipBuilder from "../../builder/LimitedPartnershipBuilder"; describe("Email Page", () => { beforeEach(() => { setLocalesEnabled(false); + + appDevDependencies.registrationGateway.feedLimitedPartnerships([]); }); const setLocalesEnabled = (bool: boolean) => { @@ -46,6 +48,19 @@ describe("Email Page", () => { expect(res.text).toContain(cyTranslationText.emailPage.emailHint); expect(res.text).toContain(cyTranslationText.buttons.saveAndContinue); }); + + it("should load the name page with data from api", async () => { + const limitedPartnership = new LimitedPartnershipBuilder().build(); + + appDevDependencies.registrationGateway.feedLimitedPartnerships([ + limitedPartnership, + ]); + + const res = await request(app).get(EMAIL_URL); + + expect(res.status).toBe(200); + expect(res.text).toContain(limitedPartnership?.data?.email); + }); }); describe("Post email", () => { diff --git a/src/presentation/test/integration/registration/gateway.test.ts b/src/presentation/test/integration/registration/gateway.test.ts index e6c7d6f..e411de1 100644 --- a/src/presentation/test/integration/registration/gateway.test.ts +++ b/src/presentation/test/integration/registration/gateway.test.ts @@ -12,6 +12,7 @@ import { EMAIL_URL, NAME_URL } from "../../../controller/registration/Routing"; import RegistrationPageType from "../../../controller/registration/PageType"; import enTranslationText from "../../../../../locales/en/translations.json"; import { RefreshTokenService } from "@companieshouse/api-sdk-node/dist/services/refresh-token"; +import LimitedPartnershipBuilder from "../../builder/LimitedPartnershipBuilder"; jest.mock("@companieshouse/api-sdk-node"); @@ -37,6 +38,10 @@ const value = { httpStatusCode: 200, resource: {}, }), + getLimitedPartnership: () => ({ + httpStatusCode: 200, + resource: new LimitedPartnershipBuilder().build(), + }), }, refreshToken: { ...RefreshTokenService.prototype, @@ -51,12 +56,14 @@ const mockCreateApiClient = createApiClient as jest.Mock; mockCreateApiClient.mockReturnValue(value); describe("Gateway", () => { - describe("Create transaction and the first submission", () => { - beforeAll(() => { - appDevDependencies.registrationGateway.feedLimitedPartnerships([]); - appDevDependencies.registrationGateway.feedErrors([]); - }); + beforeEach(() => { + appDevDependencies.registrationGateway.feedLimitedPartnerships([]); + appDevDependencies.registrationGateway.feedErrors([]); + mockCreateApiClient.mockReturnValue(value); + }); + + describe("Create transaction and the first submission", () => { it("should create a transaction and the first submission", async () => { const url = appDevDependencies.registrationController.insertIdsInUrl( NAME_URL, @@ -167,4 +174,43 @@ describe("Gateway", () => { }); }); }); + + describe("Get Limited Parnership", () => { + it("should load the name page with data from api", async () => { + const url = appDevDependencies.registrationController.insertIdsInUrl( + EMAIL_URL, + appDevDependencies.registrationGateway.transactionId, + appDevDependencies.registrationGateway.submissionId + ); + + const res = await request(appRealDependencies).get(url); + + expect(res.status).toBe(200); + expect(res.text).toContain(enTranslationText.emailPage.whatIsEmail); + }); + + it("should load error page if submissionId is incorrect", async () => { + mockCreateApiClient.mockReturnValue({ + ...value, + limitedPartnershipsService: { + ...value.limitedPartnershipsService, + getLimitedPartnership: () => ({ + httpStatusCode: 404, + errors: ["Not Found"], + }), + }, + }); + + const url = appDevDependencies.registrationController.insertIdsInUrl( + EMAIL_URL, + appDevDependencies.registrationGateway.transactionId, + "wrong-id" + ); + + const res = await request(appRealDependencies).get(url); + + expect(res.status).toBe(500); + expect(res.text).toContain(enTranslationText.errorPage.title); + }); + }); }); diff --git a/src/presentation/test/integration/registration/name.test.ts b/src/presentation/test/integration/registration/name.test.ts index ddd6f5a..f988cc6 100644 --- a/src/presentation/test/integration/registration/name.test.ts +++ b/src/presentation/test/integration/registration/name.test.ts @@ -1,16 +1,24 @@ import request from "supertest"; import { LocalesService } from "@companieshouse/ch-node-utils"; +import { + NameEndingType, + PartnershipType, +} from "@companieshouse/api-sdk-node/dist/services/limited-partnerships"; + import * as config from "../../../../config/constants"; import enTranslationText from "../../../../../locales/en/translations.json"; import cyTranslationText from "../../../../../locales/cy/translations.json"; import app from "../app"; -import { NAME_URL } from "../../../controller/registration/Routing"; +import { + NAME_URL, + NAME_WITH_IDS_URL, +} from "../../../controller/registration/Routing"; import { appDevDependencies, APPLICATION_CACHE_KEY_PREFIX_REGISTRATION, } from "../../../../config"; import RegistrationPageType from "../../../controller/registration/PageType"; -import { PartnershipType } from "@companieshouse/api-sdk-node/dist/services/limited-partnerships"; +import LimitedPartnershipBuilder from "../../builder/LimitedPartnershipBuilder"; describe("Name Page", () => { beforeEach(() => { @@ -67,6 +75,29 @@ describe("Name Page", () => { expect(res.text).not.toContain("WELSH -"); }); + it("should load the name page with data from api", async () => { + const limitedPartnership = new LimitedPartnershipBuilder() + .withId(appDevDependencies.registrationGateway.submissionId) + .withNameEnding(NameEndingType.LIMITED_PARTNERSHIP) + .build(); + + appDevDependencies.registrationGateway.feedLimitedPartnerships([ + limitedPartnership, + ]); + + const url = appDevDependencies.registrationController.insertIdsInUrl( + NAME_WITH_IDS_URL, + appDevDependencies.registrationGateway.transactionId, + appDevDependencies.registrationGateway.submissionId + ); + + const res = await request(app).get(url); + + expect(res.status).toBe(200); + expect(res.text).toContain(limitedPartnership?.data?.partnership_name); + expect(res.text).toContain(limitedPartnership?.data?.name_ending); + }); + it("should load the private name page with Welsh text", async () => { setLocalesEnabled(true); diff --git a/src/presentation/test/unit/registration/getSubmission.spec.ts b/src/presentation/test/unit/registration/getSubmission.spec.ts index 3ac27bb..845b6a9 100644 --- a/src/presentation/test/unit/registration/getSubmission.spec.ts +++ b/src/presentation/test/unit/registration/getSubmission.spec.ts @@ -17,7 +17,9 @@ describe("Get Submission", () => { ]); const result = - await appDevDependencies.registrationService.getSubmissionById( + await appDevDependencies.registrationService.getLimitedPartnership( + { access_token: "access_token", refresh_token: "refresh_token" }, + "transaction_id", limitedPartnership["_id"] as string ); @@ -32,7 +34,11 @@ describe("Get Submission", () => { ]); await appDevDependencies.registrationService - .getSubmissionById("wrong-id") + .getLimitedPartnership( + { access_token: "access_token", refresh_token: "refresh_token" }, + "transaction_id", + "wrong-id" + ) .catch((error) => { expect(error).toEqual( new CustomError("Limited partnership", "Not found: wrong-id") diff --git a/src/routes/registration.ts b/src/routes/registration.ts index 6fb4266..c6d1f2b 100644 --- a/src/routes/registration.ts +++ b/src/routes/registration.ts @@ -13,6 +13,7 @@ import { GENERAL_PARTNERS_URL, GENERAL_PARTNER_CHOICE_URL, LIMITED_PARTNER_CHOICE_URL, + NAME_WITH_IDS_URL, } from "../presentation/controller/registration/Routing"; export const registrationEndpoints = ( @@ -29,6 +30,7 @@ export const registrationEndpoints = ( authentication, dependencies.registrationController.redirectAndCacheSelection() ); + router.get( NAME_URL, authentication, @@ -39,11 +41,19 @@ export const registrationEndpoints = ( authentication, dependencies.registrationController.createTransactionAndFirstSubmission() ); + + router.get( + NAME_WITH_IDS_URL, + authentication, + dependencies.registrationController.getPageRouting() + ); + router.get( GENERAL_PARTNERS_URL, authentication, dependencies.registrationController.getPageRouting() ); + router.get( EMAIL_URL, authentication, @@ -54,11 +64,13 @@ export const registrationEndpoints = ( authentication, dependencies.registrationController.sendPageData() ); + router.get( GENERAL_PARTNERS_URL, authentication, dependencies.registrationController.getPageRouting() ); + router.get( GENERAL_PARTNER_CHOICE_URL, authentication, @@ -70,6 +82,7 @@ export const registrationEndpoints = ( // to be changed - use different method dependencies.registrationController.redirectAndCacheSelection() ); + router.get( LIMITED_PARTNERS_URL, authentication, @@ -87,6 +100,7 @@ export const registrationEndpoints = ( // to be changed - use different method dependencies.registrationController.redirectAndCacheSelection() ); + router.get( NEXT_URL, authentication, diff --git a/src/views/email.njk b/src/views/email.njk index 21be281..ae606cf 100644 --- a/src/views/email.njk +++ b/src/views/email.njk @@ -21,7 +21,7 @@ }, id: "registered-email", name: "email", - value: props.data.limitedPartnership.email, + value: props.data.limitedPartnership.data.email, type: "email", attributes : { required : true diff --git a/src/views/name.njk b/src/views/name.njk index 572f4a7..7728c9b 100644 --- a/src/views/name.njk +++ b/src/views/name.njk @@ -114,6 +114,12 @@ const radioButtons = document.querySelectorAll('input[name="name_ending"]'); radioButtons.forEach(function(radioButton) { + // set value on loading + if (radioButton.checked) { + suffixDiv.textContent = radioButton.value; + } + + // set value on change radioButton.addEventListener('change', function() { if (radioButton.checked) { suffixDiv.textContent = radioButton.value; diff --git a/src/views/pages/name/options-with-or-without-welsh.njk b/src/views/pages/name/options-with-or-without-welsh.njk index 372644b..3058304 100644 --- a/src/views/pages/name/options-with-or-without-welsh.njk +++ b/src/views/pages/name/options-with-or-without-welsh.njk @@ -87,6 +87,7 @@ classes: "govuk-radios", idPrefix: "name_ending", name: "name_ending", + value: props.data.limitedPartnership.data.name_ending, fieldset: { legend: { isPageHeading: false,