Skip to content
Closed
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/components/form/fields/FieldSetField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,11 @@ export function FieldSetField({
};
}

if (field.isVisible === false || field.deprecated) {
if (
field.isVisible === false ||
field.deprecated ||
field.hidden
) {
return null; // Skip hidden or deprecated fields
}

Expand Down
7 changes: 5 additions & 2 deletions src/flows/Onboarding/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
getContractDetailsSchemaVersion,
getBasicInformationSchemaVersion,
getBenefitOffersSchemaVersion,
withJobTitleEligibilityRiskAcknowledgement,
} from '@/src/flows/Onboarding/utils';
// oxlint-disable-next-line no-restricted-imports -- TODO: move onto useHeadlessForm, see docs/USE_HEADLESS_FORM_ROLLOUT.md
import { createHeadlessForm } from '@/src/common/createHeadlessForm';
Expand Down Expand Up @@ -317,7 +318,8 @@ export const useLegacyContractDetailsSchema = ({
return response;
},
enabled: options?.queryOptions?.enabled,
select: ({ data }) => data?.data || {},
select: ({ data }) =>
withJobTitleEligibilityRiskAcknowledgement(data?.data || {}),
});

const { form } = useHeadlessForm({
Expand Down Expand Up @@ -385,7 +387,8 @@ export const useContractDetailsSchema = ({
return response;
},
enabled: options?.queryOptions?.enabled,
select: ({ data }) => data?.data,
select: ({ data }) =>
data?.data && withJobTitleEligibilityRiskAcknowledgement(data.data),
});

const { form, handleValidation, parseFormValues } = useHeadlessForm({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import {
contractDetailsSchemaV1JobTitleEligibility,
employmentDefaultResponse,
} from '@/src/flows/Onboarding/tests/fixtures';
import { OnboardingRenderProps } from '@/src/flows/Onboarding/types';
import {
OnboardingFlowProps,
OnboardingRenderProps,
} from '@/src/flows/Onboarding/types';
import { fillRadio, queryClient, TestProviders } from '@/src/tests/testHelpers';
import { server } from '@/src/tests/server';
import { $TSFixMe } from '@/src/types/remoteFlows';
Expand Down Expand Up @@ -114,13 +117,17 @@ describe.each(schemaPaths)(
vi.restoreAllMocks();
});

const renderContractDetailsStep = async () => {
const renderContractDetailsStep = async ({
features = ['job_title_eligibility'],
}: {
features?: NonNullable<OnboardingFlowProps['options']>['features'];
} = {}) => {
render(
<OnboardingFlow
companyId='test-company-id'
employmentId='test-employment-id'
skipSteps={['select_country']}
options={{ features: ['job_title_eligibility'] }}
options={{ features }}
render={mockRender}
/>,
{ wrapper: TestProviders },
Expand Down Expand Up @@ -148,6 +155,17 @@ describe.each(schemaPaths)(
await user.tab();
};

it('keeps the risk acknowledgement hidden when the check is not enabled', async () => {
await renderContractDetailsStep({ features: [] });

await fillRoleFields();

expect(jobTitleEligibilityCheckSpy).not.toHaveBeenCalled();
expect(
screen.queryByLabelText(/I acknowledge the risks/i),
).not.toBeInTheDocument();
});

it('calls the job title eligibility check once the role fields are filled and blurred', async () => {
await renderContractDetailsStep();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/**
* Trimmed down contract details schema exposing only the fields the job title
* eligibility check cares about: the role fields sent to the check, the hidden
* slug/result fields it fills, and the risk acknowledgement that the
* yes_with_ack result reveals. Served as jsf v1 and as jsf v0.
* Trimmed down contract details schema exposing only the Role Requirements
* fieldset, as the gateway serves it to API partners for DEU, ITA and PRT: the
* role fields sent to the job title eligibility check, the hidden slug field,
* and the risk acknowledgement. The server-owned check result field and the
* yes_with_ack conditional are withheld from the served schema, so the SDK has
* to add them. role_description drops its minLength to keep the tests short.
* Served as jsf v1 and as jsf v0.
*/
const jobTitleEligibilitySchema = {
additionalProperties: false,
Expand Down Expand Up @@ -64,34 +67,28 @@ const jobTitleEligibilitySchema = {
inputType: 'hidden',
},
},
additional_job_title_eligibility_check_result: {
type: ['string', 'null'],
'x-jsf-presentation': {
inputType: 'hidden',
},
},
},
allOf: [
{
if: {
properties: {
additional_job_title_eligibility_check_result: {
const: 'yes_with_ack',
},
},
required: ['additional_job_title_eligibility_check_result'],
},
then: {
required: ['employer_acknowledges_risk'],
},
else: {
properties: {
employer_acknowledges_risk: false,
},
},
},
],
required: ['role_description'],
type: 'object',
'x-jsf-order': [
'role_description',
'role_is_onsite',
'role_requires_license',
'employer_acknowledges_risk',
'additional_job_title_eligibility_check_slug',
],
'x-rmt-flatFieldsets': {
additional_job_title_eligibility_check: {
propertiesByName: [
'additional_job_title_eligibility_check_slug',
'role_description',
'role_is_onsite',
'role_requires_license',
'employer_acknowledges_risk',
],
title: 'Role Requirements',
},
},
};

export const contractDetailsSchemaV1JobTitleEligibility = {
Expand Down
55 changes: 55 additions & 0 deletions src/flows/Onboarding/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,61 @@ export const JOB_TITLE_ELIGIBILITY_SLUG_FIELD =
export const JOB_TITLE_ELIGIBILITY_RESULT_FIELD =
'additional_job_title_eligibility_check_result';

const EMPLOYER_ACKNOWLEDGES_RISK_FIELD = 'employer_acknowledges_risk';

type ContractDetailsJsonSchema = {
properties?: Record<string, unknown>;
allOf?: unknown[];
'x-jsf-order'?: string[];
};

export const withJobTitleEligibilityRiskAcknowledgement = <
T extends ContractDetailsJsonSchema,
>(
schema: T,
): T => {
const properties = schema.properties ?? {};
if (
!properties[JOB_TITLE_ELIGIBILITY_SLUG_FIELD] ||
!properties[EMPLOYER_ACKNOWLEDGES_RISK_FIELD] ||
properties[JOB_TITLE_ELIGIBILITY_RESULT_FIELD]
) {
return schema;
}

return {
...schema,
properties: {
...properties,
[JOB_TITLE_ELIGIBILITY_RESULT_FIELD]: {
type: ['string', 'null'],
'x-jsf-presentation': { inputType: 'hidden' },
},
},
allOf: [
...(schema.allOf ?? []),
{
if: {
properties: {
[JOB_TITLE_ELIGIBILITY_RESULT_FIELD]: { const: 'yes_with_ack' },
},
required: [JOB_TITLE_ELIGIBILITY_RESULT_FIELD],
},
then: { required: [EMPLOYER_ACKNOWLEDGES_RISK_FIELD] },
else: { properties: { [EMPLOYER_ACKNOWLEDGES_RISK_FIELD]: false } },
},
],
...(schema['x-jsf-order']
? {
'x-jsf-order': [
...schema['x-jsf-order'],
JOB_TITLE_ELIGIBILITY_RESULT_FIELD,
],
}
: {}),
};
};

const JOB_TITLE_ELIGIBILITY_PARAM_FIELDS = [
'role_description',
'role_is_onsite',
Expand Down
Loading