import { UniDriver } from '@wix/wix-ui-test-utils/unidriver'; import { baseUniDriverFactory, isSled2, isSled3 } from '../../unidriver'; import { CustomFieldType } from '@wix/bex-core'; import { CheckboxUniDriver, DropdownUniDriver, FormFieldUniDriver, InputAreaUniDriver, InputUniDriver, NumberInputUniDriver, TimeInputUniDriver, } from '@wix/design-system/dist/testkit/unidriver'; import { dataHooks } from '../dataHooks'; import { DatePickerUniDriver } from '../../unidriver/DatePicker.uni.driver'; export default (base: UniDriver, body: UniDriver) => { const fieldType = () => base.attr('data-field-type') as Promise; const inputBase = (suffix = '') => base.$(`[data-hook="${dataHooks.Input}${suffix}"]`); const dropdown = () => DropdownUniDriver(inputBase(), body); const checkbox = () => CheckboxUniDriver(inputBase(), body); const formField = () => FormFieldUniDriver(base.$(`[data-hook="${dataHooks.Label}"]`), body); return { /** * Gets field label */ getLabel: async () => { const type = await fieldType(); if (type === 'checkbox') { return checkbox().getLabel(); } const element = await formField().getLabel(); return element?.textContent; }, /** * Gets field value */ getValue: async () => { const type = await fieldType(); switch (type) { case 'url': case 'shortText': return InputUniDriver(inputBase(), body).getValue(); case 'date': return ( await DatePickerUniDriver(inputBase(), body) ).inputDriver.getValue(); case 'dateTime': const date = await ( await DatePickerUniDriver(inputBase('-date'), body) ).inputDriver.getValue(); const format = Intl.DateTimeFormat([], { hour: 'numeric', minute: 'numeric', }); const time = await TimeInputUniDriver( inputBase('-time'), body, ).getValue(); if (isNaN(time.getTime())) { return date; } return `${date} ${format.format(time)}`; case 'checkbox': return checkbox().isChecked(); case 'longText': return InputAreaUniDriver(inputBase(), body).getValue(); case 'dropdown': return dropdown().inputDriver.getValue(); case 'integer': case 'decimal': return NumberInputUniDriver(inputBase(), body).getValue(); default: throw new Error(`Driver for type '${type}' not found.`); } }, /** * Gets field status message */ getStatusMessage: async () => { const type = await fieldType(); switch (type) { case 'shortText': case 'url': return FormFieldUniDriver(base, body).getStatusMessage(); case 'date': return ( await DatePickerUniDriver(inputBase(), body) ).inputDriver.getStatusMessage(); case 'dateTime': let dateStatusMessage; let timeStatusMessage; try { dateStatusMessage = await ( await DatePickerUniDriver(inputBase('-date'), body) ).inputDriver.getStatusMessage(); } catch {} try { timeStatusMessage = await TimeInputUniDriver( inputBase('-time'), body, ).getStatusMessage(); } catch {} return [dateStatusMessage, timeStatusMessage].join('\n').trim(); case 'longText': return InputAreaUniDriver(inputBase(), body).getStatusMessage(); case 'dropdown': return dropdown().inputDriver.getStatusMessage(); case 'integer': case 'decimal': return NumberInputUniDriver(inputBase(), body).getStatusMessage(); default: throw new Error(`Driver for type '${type}' not found.`); } }, /** * Enters field value, handles different value types based on field type */ enterValue: async ( value: any, { locale = 'en' }: { locale?: string } = {}, ) => { const type = await fieldType(); switch (type) { case 'url': const inputDriver = InputUniDriver(inputBase(), body); await inputDriver.enterText(value); const urlNative = await inputBase().getNative(); // jsdom-only: enterText doesn't dispatch blur, so we do it manually. // Skip for sled-2 / sled-3 (real browsers handle blur natively). if (!isSled2(urlNative) && !isSled3(urlNative)) { await inputDriver.blur(); } return; case 'shortText': return InputUniDriver(inputBase(), body).enterText(value); case 'date': const datePickerUniDriver = await DatePickerUniDriver( inputBase(), body, ); await datePickerUniDriver.inputDriver.enterText( typeof value === 'string' ? value : `${Intl.DateTimeFormat().format(value)}`, ); const dateNative = await inputBase().getNative(); // jsdom-only blur (see url case above). if (!isSled2(dateNative) && !isSled3(dateNative)) { await datePickerUniDriver.inputDriver.blur(); } return; case 'dateTime': let dateValue = ''; let timeValue = ''; if (typeof value === 'string') { const parts = value.split('T'); dateValue = parts[0]; timeValue = parts[1]; } else { dateValue = `${Intl.DateTimeFormat([locale]).format(value)}`; timeValue = Intl.DateTimeFormat([locale], { hour: 'numeric', minute: 'numeric', }).format(value); } const datetimePickerUniDriver = await DatePickerUniDriver( inputBase('-date'), body, ); await datetimePickerUniDriver.inputDriver.enterText(dateValue); const datetimeDateNative = await inputBase('-date').getNative(); // jsdom-only: we do it twice because of a bug when removing the // value in the first time, then blur to commit. Real browsers // (sled-2 / sled-3) don't have either issue. if ( !isSled2(datetimeDateNative) && !isSled3(datetimeDateNative) ) { await datetimePickerUniDriver.inputDriver.enterText(dateValue); await datetimePickerUniDriver.inputDriver.blur(); } const timeInput = TimeInputUniDriver(inputBase('-time'), body); await timeInput.setValue(timeValue); const datetimeTimeNative = await inputBase('-time').getNative(); if (!isSled2(datetimeTimeNative) && !isSled3(datetimeTimeNative)) { await timeInput.confirmValue(); } return; case 'checkbox': const checkboxDriver = checkbox(); const isChecked = await checkboxDriver.isChecked(); if (value && !isChecked) { await checkboxDriver.click(); } else if (isChecked && !value) { await checkboxDriver.click(); } return; case 'longText': return InputAreaUniDriver(inputBase(), body).enterText(value); case 'dropdown': const dropdownDriver = dropdown(); await dropdownDriver.dropdownLayoutDriver.click(); return dropdownDriver.dropdownLayoutDriver.clickAtOptionWithValue( value, ); case 'integer': case 'decimal': return NumberInputUniDriver(inputBase(), body).enterText(value); default: throw new Error(`Driver for type '${type}' not found.`); } }, /** * Returns available dropdown options */ getOptions: async () => { const type = await fieldType(); if (type !== 'dropdown') { throw new Error(`Field type '${type}' does not support this method.`); } return dropdown().dropdownLayoutDriver.optionsContent(); }, /** * Returns remaining chars count on fields with maxLength */ getLengthLeft: async () => { return formField().getLengthLeft(); }, ...baseUniDriverFactory(base), }; };