From 036f4952f959e3eedb8e0c88a5043dd2448ad6ca Mon Sep 17 00:00:00 2001 From: AJ Ancheta <7781450+ancheetah@users.noreply.github.com> Date: Wed, 3 Sep 2025 00:01:02 -0400 Subject: [PATCH] feat(davinci-client): support prefilled phone field --- .changeset/shiny-crabs-wish.md | 5 + e2e/davinci-app/components/object-value.ts | 5 +- e2e/davinci-suites/src/form-fields.test.ts | 10 +- .../src/phone-number-field.test.ts | 197 +++++++++--------- .../davinci-client/src/lib/collector.types.ts | 2 +- .../src/lib/collector.utils.test.ts | 177 +++++++++++++++- .../davinci-client/src/lib/collector.utils.ts | 17 +- .../davinci-client/src/lib/davinci.types.ts | 3 +- .../davinci-client/src/lib/node.reducer.ts | 5 +- 9 files changed, 295 insertions(+), 126 deletions(-) create mode 100644 .changeset/shiny-crabs-wish.md diff --git a/.changeset/shiny-crabs-wish.md b/.changeset/shiny-crabs-wish.md new file mode 100644 index 0000000000..97637eea48 --- /dev/null +++ b/.changeset/shiny-crabs-wish.md @@ -0,0 +1,5 @@ +--- +'@forgerock/davinci-client': minor +--- + +Added support for pre-filled phone number and country code diff --git a/e2e/davinci-app/components/object-value.ts b/e2e/davinci-app/components/object-value.ts index 71eed4873a..4c847a6bd6 100644 --- a/e2e/davinci-app/components/object-value.ts +++ b/e2e/davinci-app/components/object-value.ts @@ -81,7 +81,10 @@ export default function objectValueComponent( return; } - updater({ phoneNumber: selectedValue, countryCode: collector.input.value.countryCode }); + updater({ + phoneNumber: selectedValue, + countryCode: collector.output.value?.countryCode || '', + }); }); formEl.appendChild(phoneLabel); diff --git a/e2e/davinci-suites/src/form-fields.test.ts b/e2e/davinci-suites/src/form-fields.test.ts index ddddbd4c63..0ad89d3e21 100644 --- a/e2e/davinci-suites/src/form-fields.test.ts +++ b/e2e/davinci-suites/src/form-fields.test.ts @@ -8,9 +8,7 @@ import { expect, test } from '@playwright/test'; import { asyncEvents } from './utils/async-events.js'; -// This test is failing due to a new phone number feature flag for pre-filling country codes. -// A fix will be addressed in https://pingidentity.atlassian.net/browse/SDKS-4200 -test.skip('Should render form fields', async ({ page }) => { +test('Should render form fields', async ({ page }) => { const { navigate } = asyncEvents(page); await navigate('/?clientId=60de77d5-dd2c-41ef-8c40-f8bb2381a359'); @@ -33,6 +31,8 @@ test.skip('Should render form fields', async ({ page }) => { await page.locator('#combobox-field-key-3').check(); await page.locator('#combobox-field-key-2').uncheck(); + await page.locator('#phone-number-input').fill('1234567890'); + await expect(page.getByRole('button', { name: 'Flow Button' })).toBeVisible(); await expect(page.getByRole('button', { name: 'Flow Link' })).toBeVisible(); @@ -52,6 +52,10 @@ test.skip('Should render form fields', async ({ page }) => { 'dropdown-field-key': 'dropdown-option2-value', 'radio-group-key': 'option2 value', 'combobox-field-key': ['option1 value', 'option3 value'], + 'phone-field': { + phoneNumber: '1234567890', + countryCode: 'GB', + }, }); }); diff --git a/e2e/davinci-suites/src/phone-number-field.test.ts b/e2e/davinci-suites/src/phone-number-field.test.ts index e7105a6430..77617e2b72 100644 --- a/e2e/davinci-suites/src/phone-number-field.test.ts +++ b/e2e/davinci-suites/src/phone-number-field.test.ts @@ -7,115 +7,106 @@ import { expect, test } from '@playwright/test'; import { password } from './utils/demo-user.js'; -test('Login - add email device - authenticate with email device', async ({ page }) => { - /** Go to page */ - await page.goto('/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); +test.describe('Device registration tests', () => { + const username = 'fakeemail@user.com'; - expect(page.url()).toContain( - 'http://localhost:5829/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e', - ); - /** - * Register a new user - */ - await page.goto('http://localhost:5829/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); - await expect(page.getByRole('button', { name: 'USER_REGISTRATION' })).toBeVisible(); - await page.getByRole('button', { name: 'USER_REGISTRATION' }).click(); - await page.getByRole('textbox', { name: 'Email' }).click(); - await page.getByRole('textbox', { name: 'Email' }).fill('fakeemail@user.com'); - await page.getByRole('textbox', { name: 'Password' }).fill('U.QPDWEN47ZMyJhCDmhGLK*nr'); - await page.getByRole('textbox', { name: 'Given Name' }).fill('demouser'); - await page.getByRole('textbox', { name: 'Family Name' }).fill('demouser'); - expect(await page.getByRole('button', { name: 'Continue' })).toBeVisible(); - await page.getByRole('button', { name: 'Continue' }).click(); - await expect(page.getByRole('heading', { name: 'Registration Complete' })).toBeVisible(); - await page.getByRole('button').click(); - await page.getByRole('button', { name: 'Logout' }).click(); - /*** - * Login with the new user - **/ - await page.goto('http://localhost:5829/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); - await page.getByRole('button', { name: 'USER_LOGIN' }).click(); - await page.getByText('SDK Automation - Sign On'); - await page.getByRole('textbox', { name: 'Username' }).fill('fakeemail@user.com'); - await page.getByRole('textbox', { name: 'Password' }).fill(password); - await page.getByRole('button', { name: 'Sign On' }).click(); + test.afterEach(async ({ page }) => { + await page.goto('/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); - /** Register a device */ - await page.getByText('Select Test Form'); - await page.getByRole('button', { name: 'DEVICE_REGISTRATION' }).click(); - await page.getByText('SDK Automation - Device Registration'); - await page.getByRole('button', { name: 'Email' }).click(); - await page.getByText('SDK Automation - Device Registration'); - await page.getByRole('textbox', { name: 'Email Address' }).fill('test+my_fake_user@example.com'); - await page.getByRole('button', { name: 'Submit' }).click(); - await expect(page.getByText('EMAIL MFA Registered')).toBeVisible(); - await page.getByRole('button').click(); + await page.getByRole('button', { name: 'USER_LOGIN' }).click(); + await page.getByRole('textbox', { name: 'Username' }).fill(username); + await page.getByRole('textbox', { name: 'Password' }).fill(password); + await page.getByRole('button', { name: 'Sign On' }).click(); - /** Authenticate with the Device */ - await page.getByRole('button', { name: 'DEVICE_AUTHENTICATION' }).click(); - await page.getByText('SDK Automation - Device Authentication'); - await page.getByRole('button', { name: 'Email' }).click(); - await page.getByRole('button', { name: 'USER_DELETE' }).click(); - await page.getByRole('heading', { name: 'Success' }); - await page.getByRole('button', { name: 'Start over' }).click(); -}); + await page.getByRole('button', { name: 'USER_DELETE' }).click(); + await expect(page.getByRole('heading', { name: 'Success' })).toBeVisible(); + }); + + test('Login - add email device - authenticate with email device', async ({ page }) => { + /** Go to page */ + await page.goto('/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); + + expect(page.url()).toContain( + 'http://localhost:5829/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e', + ); + await expect(page.getByText('Select Test Form')).toBeVisible(); + + /** + * Register a new user + */ + await page.getByRole('button', { name: 'USER_REGISTRATION' }).click(); + await page.getByRole('textbox', { name: 'Email' }).fill(username); + await page.getByRole('textbox', { name: 'Password' }).fill(password); + await page.getByRole('textbox', { name: 'Given Name' }).fill('demouser'); + await page.getByRole('textbox', { name: 'Family Name' }).fill('demouser'); + await page.getByRole('button', { name: 'Continue' }).click(); + await expect(page.getByRole('heading', { name: 'Registration Complete' })).toBeVisible(); + await page.getByRole('button', { name: 'Continue' }).click(); + await page.getByRole('button', { name: 'Logout' }).click(); + + /*** + * Login with the new user + **/ + await page.goto('/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); + await page.getByRole('button', { name: 'USER_LOGIN' }).click(); + await expect(page.getByText('SDK Automation - Sign On')).toBeVisible(); + await page.getByRole('textbox', { name: 'Username' }).fill(username); + await page.getByRole('textbox', { name: 'Password' }).fill(password); + await page.getByRole('button', { name: 'Sign On' }).click(); -// This test is failing due to a new phone number feature flag for pre-filling country codes. -// A fix will be addressed in https://pingidentity.atlassian.net/browse/SDKS-4200 -test.skip('Login - add phone device - authenticate with phone device', async ({ page }) => { - await page.goto('/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); - /*** - * Go to page - ***/ - expect(page.url()).toContain( - 'http://localhost:5829/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0', - ); + /** Register a device */ + await expect(page.getByText('Select Test Form')).toBeVisible(); + await page.getByRole('button', { name: 'DEVICE_REGISTRATION' }).click(); + await expect(page.getByText('SDK Automation - Device Registration')).toBeVisible(); + await page.getByRole('button', { name: 'Email' }).click(); + await page + .getByRole('textbox', { name: 'Email Address' }) + .fill('test+my_fake_user@example.com'); + await page.getByRole('button', { name: 'Submit' }).click(); + await expect(page.getByText('EMAIL MFA Registered')).toBeVisible(); + await page.getByRole('button', { name: 'Continue' }).click(); + }); - /** - * Register a new user - **/ - await page.goto('http://localhost:5829/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); - await expect(page.getByRole('button', { name: 'USER_REGISTRATION' })).toBeVisible(); - await page.getByRole('button', { name: 'USER_REGISTRATION' }).click(); - await page.getByRole('textbox', { name: 'Email' }).click(); - await page.getByRole('textbox', { name: 'Email' }).fill('fakeemail2@user.com'); - await page.getByRole('textbox', { name: 'Password' }).fill('U.QPDWEN47ZMyJhCDmhGLK*nr'); - await page.getByRole('textbox', { name: 'Given Name' }).fill('demouser'); - await page.getByRole('textbox', { name: 'Family Name' }).fill('demouser'); - expect(await page.getByRole('button', { name: 'Continue' })).toBeVisible(); - await page.getByRole('button', { name: 'Continue' }).click(); - await expect(page.getByRole('heading', { name: 'Registration Complete' })).toBeVisible(); - await page.getByRole('button').click(); - await page.getByRole('button', { name: 'Logout' }).click(); - await page.goto('http://localhost:5829/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); + test('Login - add phone device - authenticate with phone device', async ({ page }) => { + /** Go to page */ + await page.goto('/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); + expect(page.url()).toContain( + 'http://localhost:5829/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0', + ); - /** - * Login with the new user - **/ - await page.getByRole('button', { name: 'USER_LOGIN' }).click(); - await page.getByText('SDK Automation - Sign On'); - await page.getByRole('textbox', { name: 'Username' }).fill('fakeemail2@user.com'); - await page.getByRole('textbox', { name: 'Password' }).fill(password); - await page.getByRole('button', { name: 'Sign On' }).click(); + /** + * Register a new user + **/ + await expect(page.getByText('Select Test Form')).toBeVisible(); + await page.getByRole('button', { name: 'USER_REGISTRATION' }).click(); + await page.getByRole('textbox', { name: 'Email' }).fill(username); + await page.getByRole('textbox', { name: 'Password' }).fill(password); + await page.getByRole('textbox', { name: 'Given Name' }).fill('demouser'); + await page.getByRole('textbox', { name: 'Family Name' }).fill('demouser'); + await page.getByRole('button', { name: 'Continue' }).click(); + await expect(page.getByRole('heading', { name: 'Registration Complete' })).toBeVisible(); + await page.getByRole('button', { name: 'Continue' }).click(); + await page.getByRole('button', { name: 'Logout' }).click(); - /** Register a Device */ - await page.getByText('Select Test Form'); - await page.getByRole('button', { name: 'DEVICE_REGISTRATION' }).click(); - await page.getByText('SDK Automation - Device Registration'); - await page.getByRole('button', { name: 'Text Message' }).click(); - await expect(page.getByText('SDK Automation - Enter Phone Number')).toBeVisible(); - await expect(page.locator('#countryCode')).toBeVisible(); - await page.locator('#countryCode').selectOption('1'); - await page.getByRole('textbox', { name: 'Enter Phone Number' }).fill('3035550100'); - await page.getByRole('button', { name: 'Submit' }).click(); - await expect(page.getByText('SMS/Voice MFA Registered')).toBeVisible(); - await page.getByRole('button').click(); + /** + * Login with the new user + **/ + await page.goto('/?clientId=20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0'); + await page.getByRole('button', { name: 'USER_LOGIN' }).click(); + await expect(page.getByText('SDK Automation - Sign On')).toBeVisible(); + await page.getByRole('textbox', { name: 'Username' }).fill(username); + await page.getByRole('textbox', { name: 'Password' }).fill(password); + await page.getByRole('button', { name: 'Sign On' }).click(); - /** Authenticate with the Device */ - await page.getByRole('button', { name: 'DEVICE_AUTHENTICATION' }).click(); - await page.getByText('SDK Automation - Device Authentication'); - await page.getByRole('button', { name: 'Text Message' }).click(); - await page.getByRole('button', { name: 'USER_DELETE' }).click(); - await page.getByRole('heading', { name: 'Success' }); - await page.getByRole('button', { name: 'Start over' }).click(); + /** Register a Device */ + await expect(page.getByText('Select Test Form')).toBeVisible(); + await page.getByRole('button', { name: 'DEVICE_REGISTRATION' }).click(); + await expect(page.getByText('SDK Automation - Device Registration')).toBeVisible(); + await page.getByRole('button', { name: 'Text Message' }).click(); + await expect(page.getByText('SDK Automation - Enter Phone Number')).toBeVisible(); + await page.getByRole('textbox', { name: 'Enter Phone Number' }).fill('3035550100'); + await page.getByRole('button', { name: 'Submit' }).click(); + await expect(page.getByText('SMS/Voice MFA Registered')).toBeVisible(); + await page.getByRole('button', { name: 'Continue' }).click(); + }); }); diff --git a/packages/davinci-client/src/lib/collector.types.ts b/packages/davinci-client/src/lib/collector.types.ts index e7a47b10c9..eca12e7696 100644 --- a/packages/davinci-client/src/lib/collector.types.ts +++ b/packages/davinci-client/src/lib/collector.types.ts @@ -290,7 +290,7 @@ export interface PhoneNumberInputValue { phoneNumber: string; } -interface PhoneNumberOutputValue { +export interface PhoneNumberOutputValue { countryCode?: string; phoneNumber?: string; } diff --git a/packages/davinci-client/src/lib/collector.utils.test.ts b/packages/davinci-client/src/lib/collector.utils.test.ts index 49dbabd5c4..7fa13d5629 100644 --- a/packages/davinci-client/src/lib/collector.utils.test.ts +++ b/packages/davinci-client/src/lib/collector.utils.test.ts @@ -30,7 +30,7 @@ import type { RedirectField, StandardField, } from './davinci.types.js'; -import { ValidatedTextCollector } from './collector.types.js'; +import { PhoneNumberOutputValue, ValidatedTextCollector } from './collector.types.js'; describe('Action Collectors', () => { describe('returnFlowCollector', () => { @@ -537,16 +537,17 @@ describe('Object value collectors', () => { }); describe('returnPhoneNumberCollector', () => { - const mockField: PhoneNumberField = { - key: 'phone-number-key', - defaultCountryCode: null, - label: 'Phone Number', - type: 'PHONE_NUMBER', - required: true, - }; + it('input value is empty when no prefill or default country code', () => { + const mockField: PhoneNumberField = { + key: 'phone-number-key', + defaultCountryCode: null, + label: 'Phone Number', + type: 'PHONE_NUMBER', + required: true, + validatePhoneNumber: true, + }; - it('should create a phone number collector', () => { - const result = returnObjectValueCollector(mockField, 1); + const result = returnObjectValueCollector(mockField, 1, {}); expect(result).toEqual({ category: 'ObjectValueCollector', error: null, @@ -572,6 +573,162 @@ describe('returnPhoneNumberCollector', () => { }, }); }); + + it('default country code is set on collector when not prefilled', () => { + const mockField: PhoneNumberField = { + key: 'phone-number-key', + defaultCountryCode: 'US', + label: 'Phone Number', + type: 'PHONE_NUMBER', + required: true, + validatePhoneNumber: true, + }; + const result = returnObjectValueCollector(mockField, 1, {}); + expect(result).toEqual({ + category: 'ObjectValueCollector', + error: null, + type: 'PhoneNumberCollector', + id: 'phone-number-key-1', + name: 'phone-number-key', + input: { + key: mockField.key, + value: { + countryCode: mockField.defaultCountryCode, + phoneNumber: '', + }, + type: mockField.type, + }, + output: { + key: mockField.key, + label: mockField.label, + type: mockField.type, + value: { + countryCode: mockField.defaultCountryCode, + phoneNumber: '', + }, + }, + }); + }); + + it('prefilled country code is set on collector', () => { + const mockField: PhoneNumberField = { + key: 'phone-number-key', + defaultCountryCode: 'US', + label: 'Phone Number', + type: 'PHONE_NUMBER', + required: true, + validatePhoneNumber: true, + }; + const prefillMock: PhoneNumberOutputValue = { + countryCode: 'CA', + }; + const result = returnObjectValueCollector(mockField, 1, prefillMock); + expect(result).toEqual({ + category: 'ObjectValueCollector', + error: null, + type: 'PhoneNumberCollector', + id: 'phone-number-key-1', + name: 'phone-number-key', + input: { + key: mockField.key, + value: { + countryCode: prefillMock.countryCode, + phoneNumber: '', + }, + type: mockField.type, + }, + output: { + key: mockField.key, + label: mockField.label, + type: mockField.type, + value: { + countryCode: prefillMock.countryCode, + phoneNumber: '', + }, + }, + }); + expect(result.input.value.countryCode).not.toEqual(mockField.defaultCountryCode); + expect(result.output.value?.countryCode).not.toEqual(mockField.defaultCountryCode); + }); + + it('prefilled phone number is set on collector', () => { + const mockField: PhoneNumberField = { + key: 'phone-number-key', + defaultCountryCode: null, + label: 'Phone Number', + type: 'PHONE_NUMBER', + required: true, + validatePhoneNumber: true, + }; + const prefillMock: PhoneNumberOutputValue = { + phoneNumber: '1234567890', + }; + const result = returnObjectValueCollector(mockField, 1, prefillMock); + expect(result).toEqual({ + category: 'ObjectValueCollector', + error: null, + type: 'PhoneNumberCollector', + id: 'phone-number-key-1', + name: 'phone-number-key', + input: { + key: mockField.key, + value: { + countryCode: '', + phoneNumber: prefillMock.phoneNumber, + }, + type: mockField.type, + }, + output: { + key: mockField.key, + label: mockField.label, + type: mockField.type, + value: { + countryCode: '', + phoneNumber: prefillMock.phoneNumber, + }, + }, + }); + }); + + it('prefilled values are set on collector', () => { + const mockField: PhoneNumberField = { + key: 'phone-number-key', + defaultCountryCode: 'US', + label: 'Phone Number', + type: 'PHONE_NUMBER', + required: true, + validatePhoneNumber: true, + }; + const prefillMock: PhoneNumberOutputValue = { + countryCode: 'CA', + phoneNumber: '1234567890', + }; + const result = returnObjectValueCollector(mockField, 1, prefillMock); + expect(result).toEqual({ + category: 'ObjectValueCollector', + error: null, + type: 'PhoneNumberCollector', + id: 'phone-number-key-1', + name: 'phone-number-key', + input: { + key: mockField.key, + value: { + countryCode: prefillMock.countryCode, + phoneNumber: prefillMock.phoneNumber, + }, + type: mockField.type, + }, + output: { + key: mockField.key, + label: mockField.label, + type: mockField.type, + value: { + countryCode: prefillMock.countryCode, + phoneNumber: prefillMock.phoneNumber, + }, + }, + }); + }); }); describe('No Value Collectors', () => { diff --git a/packages/davinci-client/src/lib/collector.utils.ts b/packages/davinci-client/src/lib/collector.utils.ts index 83ab01c89c..1a542c4c29 100644 --- a/packages/davinci-client/src/lib/collector.utils.ts +++ b/packages/davinci-client/src/lib/collector.utils.ts @@ -24,6 +24,7 @@ import type { AutoCollectorTypes, UnknownCollector, InferAutoCollectorType, + PhoneNumberOutputValue, } from './collector.types.js'; import type { DeviceAuthenticationField, @@ -422,7 +423,7 @@ export function returnMultiSelectCollector(field: MultiSelectField, idx: number, export function returnObjectCollector< Field extends DeviceAuthenticationField | DeviceRegistrationField | PhoneNumberField, CollectorType extends ObjectValueCollectorTypes = 'ObjectValueCollector', ->(field: Field, idx: number, collectorType: CollectorType) { +>(field: Field, idx: number, collectorType: CollectorType, prefillData?: PhoneNumberOutputValue) { let error = ''; if (!('key' in field)) { error = `${error}Key is not found in the field object. `; @@ -481,9 +482,11 @@ export function returnObjectCollector< key: `${device.type}-${idx}`, })); } else if (field.type === 'PHONE_NUMBER') { + const prefilledCountryCode = prefillData?.countryCode; + const prefilledPhone = prefillData?.phoneNumber; defaultValue = { - countryCode: field.defaultCountryCode || '', - phoneNumber: '', + countryCode: prefilledCountryCode ? prefilledCountryCode : field.defaultCountryCode || '', + phoneNumber: prefilledPhone || '', }; } @@ -527,8 +530,12 @@ export function returnObjectSelectCollector( ); } -export function returnObjectValueCollector(field: PhoneNumberField, idx: number) { - return returnObjectCollector(field, idx, 'PhoneNumberCollector'); +export function returnObjectValueCollector( + field: PhoneNumberField, + idx: number, + prefillData: PhoneNumberOutputValue, +) { + return returnObjectCollector(field, idx, 'PhoneNumberCollector', prefillData); } /** diff --git a/packages/davinci-client/src/lib/davinci.types.ts b/packages/davinci-client/src/lib/davinci.types.ts index 17dfabdbd1..f4a363fbe5 100644 --- a/packages/davinci-client/src/lib/davinci.types.ts +++ b/packages/davinci-client/src/lib/davinci.types.ts @@ -149,7 +149,8 @@ export type PhoneNumberField = { key: string; label: string; defaultCountryCode: string | null; - required: boolean; + required: boolean; // TODO: add to phone collector + validatePhoneNumber: boolean; // TODO: add to phone collector }; export type ProtectField = { diff --git a/packages/davinci-client/src/lib/node.reducer.ts b/packages/davinci-client/src/lib/node.reducer.ts index 018012d1e7..4e1d7a3058 100644 --- a/packages/davinci-client/src/lib/node.reducer.ts +++ b/packages/davinci-client/src/lib/node.reducer.ts @@ -44,6 +44,7 @@ import { DeviceRegistrationCollector, PhoneNumberCollector, PhoneNumberInputValue, + PhoneNumberOutputValue, UnknownCollector, ProtectCollector, } from './collector.types.js'; @@ -147,8 +148,8 @@ export const nodeCollectorReducer = createReducer(initialCollectorValues, (build return returnPasswordCollector(field, idx); } case 'PHONE_NUMBER': { - // No data to send - return returnObjectValueCollector(field, idx); + const prefillData = data as PhoneNumberOutputValue; + return returnObjectValueCollector(field, idx, prefillData); } case 'TEXT': { const str = data as string;