diff --git a/.sizelimit.json b/.sizelimit.json index 03263051..2c87d676 100644 --- a/.sizelimit.json +++ b/.sizelimit.json @@ -1,7 +1,7 @@ { "limits": { "total": 550000, - "totalGzip": 200000, + "totalGzip": 250000, "css": 150000, "cssGzip": 25000, "maxChunkSize": 50000, diff --git a/example/src/Onboarding.tsx b/example/src/Onboarding.tsx index 3fd2b48f..f14cd3e9 100644 --- a/example/src/Onboarding.tsx +++ b/example/src/Onboarding.tsx @@ -265,6 +265,9 @@ const OnboardingWithProps = ({ externalId={externalId} options={{ features: ['onboarding_reserves'], + jsonSchemaVersion: { + employment_basic_information: 'latest', + }, jsonSchemaVersionByCountry: { DEU: { contract_details: 1, diff --git a/src/flows/Onboarding/api.ts b/src/flows/Onboarding/api.ts index dc9c57d8..5d7abcbb 100644 --- a/src/flows/Onboarding/api.ts +++ b/src/flows/Onboarding/api.ts @@ -32,7 +32,11 @@ import { JSONSchemaFormType, FlowOptions, } from '@/src/flows/types'; -import { getContractDetailsSchemaVersion } from '@/src/flows/Onboarding/utils'; +import { + getContractDetailsSchemaVersion, + getBasicInformationSchemaVersion, + getBenefitOffersSchemaVersion, +} from '@/src/flows/Onboarding/utils'; import { createHeadlessForm } from '@/src/common/createHeadlessForm'; import { countriesOptions } from '@/src/common/api/countries'; @@ -232,14 +236,11 @@ export const useBenefitOffersSchema = ( fieldValues: FieldValues, options: OnboardingFlowProps['options'], ) => { - const jsonSchemaQueryParam = options?.jsonSchemaVersion - ?.benefit_offers_form_schema - ? { - json_schema_version: - options.jsonSchemaVersion.benefit_offers_form_schema, - } - : {}; const { client } = useClient(); + const jsonSchemaQueryParam = { + json_schema_version: getBenefitOffersSchemaVersion(options), + }; + return useQuery({ queryKey: ['benefit-offers-schema', employmentId], retry: false, @@ -274,11 +275,12 @@ export const useBenefitOffersSchema = ( * Use this hook to create an employment * @returns */ -export const useCreateEmployment = () => { +export const useCreateEmployment = ( + options?: OnboardingFlowProps['options'], +) => { const { client } = useClient(); - // TODO: setting 1 as basic_information only supports v1 for now in the API const jsonSchemaQueryParam = { - json_schema_version: 1, + json_schema_version: getBasicInformationSchemaVersion(options), }; return useMutation({ mutationFn: (payload: EmploymentCreateParams) => { @@ -302,8 +304,8 @@ export const useUpdateEmployment = ( ) => { const { client } = useClient(); const jsonSchemaQueryParams = { - // TODO: setting 1 as basic_information only supports v1 for now in the API - employment_basic_information_json_schema_version: 1, + employment_basic_information_json_schema_version: + getBasicInformationSchemaVersion(options), contract_details_json_schema_version: getContractDetailsSchemaVersion(options, countryCode) || 1, }; @@ -342,22 +344,17 @@ export const useUpdateBenefitsOffers = ( }: UnifiedEmploymentUpsertBenefitOffersRequest & { employmentId: string; }) => { - const jsonSchemaQueryParam = options?.jsonSchemaVersion - ?.benefit_offers_form_schema - ? { - json_schema_version: - options.jsonSchemaVersion.benefit_offers_form_schema, - } - : {}; + const jsonSchemaQueryParam = { + json_schema_version: getBenefitOffersSchemaVersion(options), + }; + return putUpdateBenefitOffer({ client: client as Client, body: payload, path: { employment_id: employmentId, }, - query: { - ...jsonSchemaQueryParam, - }, + query: jsonSchemaQueryParam, }); }, }); diff --git a/src/flows/Onboarding/hooks.tsx b/src/flows/Onboarding/hooks.tsx index 21c88464..b44115c5 100644 --- a/src/flows/Onboarding/hooks.tsx +++ b/src/flows/Onboarding/hooks.tsx @@ -9,6 +9,7 @@ import { useStepState, Step } from '@/src/flows/useStepState'; import { disabledInviteButtonEmploymentStatus, getContractDetailsSchemaVersion, + getBasicInformationSchemaVersion, reviewStepAllowedEmploymentStatus, STEPS, STEPS_WITHOUT_SELECT_COUNTRY, @@ -233,7 +234,7 @@ export const useOnboarding = ({ }, }); - const createEmploymentMutation = useCreateEmployment(); + const createEmploymentMutation = useCreateEmployment(options); const updateEmploymentMutation = useUpdateEmployment( internalCountryCode as string, options, @@ -328,7 +329,7 @@ export const useOnboarding = ({ enabled: isBasicInformationDetailsEnabled, }, }, - jsonSchemaVersion: 1, + jsonSchemaVersion: getBasicInformationSchemaVersion(options), }); const annualGrossSalaryField = diff --git a/src/flows/Onboarding/tests/useOnboardingJsonSchemaVersion.test.tsx b/src/flows/Onboarding/tests/useOnboardingJsonSchemaVersion.test.tsx index ad34fd7c..db1a296b 100644 --- a/src/flows/Onboarding/tests/useOnboardingJsonSchemaVersion.test.tsx +++ b/src/flows/Onboarding/tests/useOnboardingJsonSchemaVersion.test.tsx @@ -12,6 +12,7 @@ const mockGetShowSchema = vi.fn(); const mockPostCreateEmployment2 = vi.fn(); const mockPatchUpdateEmployment2 = vi.fn(); const mockPutUpdateBenefitOffer = vi.fn(); +const mockPostCreateContractEligibility = vi.fn(); // Mock the client functions vi.mock('@/src/client', () => ({ @@ -23,6 +24,8 @@ vi.mock('@/src/client', () => ({ mockPatchUpdateEmployment2(...args), putUpdateBenefitOffer: (...args: $TSFixMe[]) => mockPutUpdateBenefitOffer(...args), + postCreateContractEligibility: (...args: $TSFixMe[]) => + mockPostCreateContractEligibility(...args), })); const queryClient = new QueryClient({ @@ -73,6 +76,10 @@ describe('useOnboarding jsonSchemaVersion', () => { data: { data: { success: true } }, }); + mockPostCreateContractEligibility.mockResolvedValue({ + data: { data: { status: 'ok' } }, + }); + // Mock server responses server.use( http.get('*/v1/companies/:companyId', () => { @@ -199,6 +206,73 @@ describe('useOnboarding jsonSchemaVersion', () => { }); }); }); + + it('should pass custom jsonSchemaVersion to basic information form', async () => { + const options = { + jsonSchemaVersion: { + employment_basic_information: 2, + }, + }; + const { result } = renderHook( + () => + useOnboarding({ + companyId: 'test-company-id', + countryCode: 'PRT', + employmentId: 'test-employment-id', + skipSteps: ['select_country'], + options, + }), + { wrapper: TestProviders }, + ); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + await waitFor(() => { + expect(mockGetShowFormCountry).toHaveBeenCalled(); + }); + const call = mockGetShowFormCountry.mock.calls[0][0]; + expect(call.path).toEqual({ + country_code: 'PRT', + form: 'employment_basic_information', + }); + expect(call.query).toEqual({ + skip_benefits: true, + json_schema_version: 2, + }); + }); + + it('should pass custom benefit_offers_form_schema version to getShowSchema', async () => { + const options = { + jsonSchemaVersion: { + benefit_offers_form_schema: 2, + }, + }; + const { result } = renderHook( + () => + useOnboarding({ + companyId: 'test-company-id', + countryCode: 'PRT', + employmentId: 'test-employment-id', + skipSteps: ['select_country'], + options, + }), + { wrapper: TestProviders }, + ); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + // Navigate to benefits step + act(() => { + result.current.goTo('benefits'); + }); + await waitFor(() => { + expect(mockGetShowSchema).toHaveBeenCalled(); + }); + const call = mockGetShowSchema.mock.calls[0][0]; + expect(call.query).toEqual({ + json_schema_version: 2, + }); + }); }); describe('useUpdateEmployment calls', () => { @@ -294,5 +368,117 @@ describe('useOnboarding jsonSchemaVersion', () => { contract_details_json_schema_version: 2, }); }); + + it('should call patchUpdateEmployment2 with custom employment_basic_information_json_schema_version when submitting basic_information', async () => { + const { result } = renderHook( + () => + useOnboarding({ + employmentId: 'existing-employment-id', + companyId: 'test-company-id', + countryCode: 'ARG', + skipSteps: ['select_country'], + options: { + jsonSchemaVersion: { + employment_basic_information: 3, // ← Test this! + }, + }, + }), + { wrapper: TestProviders }, + ); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + // Submit basic_information form (first step) + await act(async () => { + await result.current.onSubmit({ + name: 'John Doe', + email: 'john@example.com', + }); + }); + await waitFor(() => { + expect(mockPatchUpdateEmployment2).toHaveBeenCalled(); + }); + const call = mockPatchUpdateEmployment2.mock.calls[0][0]; + expect(call.query).toEqual({ + skip_benefits: true, + employment_basic_information_json_schema_version: 3, // ← Assert this + contract_details_json_schema_version: 1, // default + }); + }); + }); + + describe('useCreateEmployment calls', () => { + it('should call postCreateEmployment2 with default json_schema_version when creating new employment', async () => { + const { result } = renderHook( + () => + useOnboarding({ + // No employmentId = create new + companyId: 'test-company-id', + countryCode: 'PRT', + skipSteps: ['select_country'], + }), + { wrapper: TestProviders }, + ); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + // Submit basic_information to create employment + await act(async () => { + await result.current.onSubmit({ + name: 'John Doe', + email: 'john@example.com', + }); + }); + + await waitFor(() => { + expect(mockPostCreateEmployment2).toHaveBeenCalled(); + }); + + const call = mockPostCreateEmployment2.mock.calls[0][0]; + + expect(call.query).toEqual({ + json_schema_version: 1, + }); + }); + + it('should call postCreateEmployment2 with custom employment_basic_information_json_schema_version', async () => { + const { result } = renderHook( + () => + useOnboarding({ + companyId: 'test-company-id', + countryCode: 'ARG', + skipSteps: ['select_country'], + options: { + jsonSchemaVersion: { + employment_basic_information: 3, + }, + }, + }), + { wrapper: TestProviders }, + ); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + await act(async () => { + await result.current.onSubmit({ + name: 'John Doe', + email: 'john@example.com', + }); + }); + + await waitFor(() => { + expect(mockPostCreateEmployment2).toHaveBeenCalled(); + }); + + const call = mockPostCreateEmployment2.mock.calls[0][0]; + + expect(call.query).toEqual({ + json_schema_version: 3, + }); + }); }); }); diff --git a/src/flows/Onboarding/tests/utils.test.ts b/src/flows/Onboarding/tests/utils.test.ts index a6f66e9e..0fc83c12 100644 --- a/src/flows/Onboarding/tests/utils.test.ts +++ b/src/flows/Onboarding/tests/utils.test.ts @@ -1,4 +1,8 @@ -import { getContractDetailsSchemaVersion } from '../utils'; +import { + getBasicInformationSchemaVersion, + getBenefitOffersSchemaVersion, + getContractDetailsSchemaVersion, +} from '../utils'; describe('getContractDetailsSchemaVersion', () => { it('should return version 1 for all countries', () => { @@ -12,7 +16,6 @@ describe('getContractDetailsSchemaVersion', () => { jsonSchemaVersionByCountry: { DEU: { contract_details: 2, - employment_basic_information: 2, }, }, }; @@ -22,3 +25,43 @@ describe('getContractDetailsSchemaVersion', () => { expect(result).toEqual(2); }); }); + +describe('getBenefitOffersSchemaVersion', () => { + it('should return version 1 for all countries', () => { + const result = getBenefitOffersSchemaVersion(undefined); + + expect(result).toEqual(1); + }); + + it('should override external jsonSchemaVersion with version 2', () => { + const options = { + jsonSchemaVersion: { + benefit_offers_form_schema: 2, + }, + }; + + const result = getBenefitOffersSchemaVersion(options); + + expect(result).toEqual(2); + }); +}); + +describe('getBasicInformationSchemaVersion', () => { + it('should return version 1 for all countries', () => { + const result = getBasicInformationSchemaVersion(undefined); + + expect(result).toEqual(1); + }); + + it('should override external jsonSchemaVersion with version 2', () => { + const options = { + jsonSchemaVersion: { + employment_basic_information: 2, + }, + }; + + const result = getBasicInformationSchemaVersion(options); + + expect(result).toEqual(2); + }); +}); diff --git a/src/flows/Onboarding/types.ts b/src/flows/Onboarding/types.ts index 7355ad0c..14d87b7d 100644 --- a/src/flows/Onboarding/types.ts +++ b/src/flows/Onboarding/types.ts @@ -51,6 +51,26 @@ export type OnboardingRenderProps = { type OnboardingFeatures = 'onboarding_reserves'; +/** + * JSON schema version configuration for a specific country + */ +type CountryJsonSchemaVersion = { + /** + * @deprecated Use `jsonSchemaVersion.employment_basic_information` instead for global configuration. + * This country-specific override is no longer recommended. + * + * The json schema version to use for the basic information step by country. + * The default value is 1. + */ + employment_basic_information?: number; + /** + * The json schema version to use for the contract details step by country. + * This is used to override the json schema version for the contract details step by country. + * The default value is 1. + */ + contract_details?: number | 'latest'; +}; + export type OnboardingFlowProps = { /** * The country code to use for the onboarding. @@ -86,23 +106,40 @@ export type OnboardingFlowProps = { /** * The options to use for the onboarding. */ - options?: Omit & { + options?: Omit & { jsfModify?: { select_country?: JSFModify; basic_information?: JSFModify; contract_details?: JSFModify; benefits?: JSFModify; }; + /** + * The json schema version to use for the onboarding. + * These versions apply globally to all countries. + * For country-specific overrides (e.g., contract_details), use jsonSchemaVersionByCountry instead. + * The default value is 1. + */ + jsonSchemaVersion?: { + /** + * The json schema version to use for the basic information step. + * Applies globally to all countries. + * The default value is 1. + */ + employment_basic_information?: number | 'latest'; + /** + * The json schema version to use for the benefit offers step. + * This is used to override the json schema version for the benefit offers step. + * The default value is 1. + */ + benefit_offers_form_schema?: number | 'latest'; + }; /** * The json schema version to use for the onboarding by country. * This is used to override the json schema version for the onboarding by country. - * the old jsonSchemaVersion is not working well at the moment, don't use it for now. + * Current use case is to support contract_details */ jsonSchemaVersionByCountry?: { - [countryCode: string]: { - employment_basic_information?: number; - contract_details?: number | 'latest'; - }; + [countryCode: string]: CountryJsonSchemaVersion; }; /** * The features to use for the onboarding. diff --git a/src/flows/Onboarding/utils.ts b/src/flows/Onboarding/utils.ts index 6f5c5a11..4cf726e7 100644 --- a/src/flows/Onboarding/utils.ts +++ b/src/flows/Onboarding/utils.ts @@ -77,3 +77,29 @@ export const getContractDetailsSchemaVersion = ( return requestedVersion; }; + +/** + * Gets the basic information schema version from options + * @param options - The flow options containing version configurations + * @returns The jsonSchemaVersion for basic information or default + */ +export const getBasicInformationSchemaVersion = ( + options: OnboardingFlowProps['options'], +): number | 'latest' => { + return ( + options?.jsonSchemaVersion?.employment_basic_information || DEFAULT_VERSION + ); +}; + +/** + * Gets the benefit offers schema version from options + * @param options - The flow options containing version configurations + * @returns The jsonSchemaVersion for benefit offers or undefined if not set + */ +export const getBenefitOffersSchemaVersion = ( + options: OnboardingFlowProps['options'], +): number | 'latest' => { + return ( + options?.jsonSchemaVersion?.benefit_offers_form_schema || DEFAULT_VERSION + ); +}; diff --git a/src/flows/types.ts b/src/flows/types.ts index c1f5c438..1df9f668 100644 --- a/src/flows/types.ts +++ b/src/flows/types.ts @@ -97,6 +97,7 @@ export type FlowOptions = { }; benefit_offers_form_schema?: number; contractor_contract_details_form_schema?: number; + employment_basic_information?: number | 'latest'; }; };