Skip to content

Commit

Permalink
feat(PostalCodeAndCity): deprecate country in favor of countryCode (
Browse files Browse the repository at this point in the history
  • Loading branch information
langz authored Feb 15, 2025
1 parent c546009 commit 8d0d980
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ export const SettingCountryBasedOnPath = () => {
<ComponentBox>
<Form.Handler>
<Form.Card>
<Field.SelectCountry path="/myCountry" defaultValue="NO" />
<Field.PostalCodeAndCity country="/myCountry" />
<Field.SelectCountry path="/country" defaultValue="NO" />
<Field.PostalCodeAndCity countryCode="/country" />
</Form.Card>
</Form.Handler>
</ComponentBox>
Expand All @@ -202,7 +202,7 @@ export const NonNorwegianPostalCode = () => {
}}
>
<Field.PostalCodeAndCity
country="DE"
countryCode="DE"
postalCode={{
pattern: '^[0-9]{5}$',
onBlurValidator: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ showTabs: true
## Description

`Field.SelectCountry` is a wrapper component for the [selection component](/uilib/extensions/forms/base-fields/Selection), with options built in for selecting a country.
When selecting a country, the value returned is the selected country's [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) like `NO` for Norway.
When selecting a country, the value returned is the selected country's [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) (country code) like `NO` for Norway.

```jsx
import { Field } from '@dnb/eufemia/extensions/forms'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,18 @@ export type Props = Pick<
* You can also use the value of another field to define the country, by using a path value i.e. `/myCountryPath`.
* Default: `NO`
*/
/**
* @deprecated – use countryCode instead. Will be removed in v11.
*/
country?: Path | string

/**
* Defines which country the postal code and city is for.
* Setting it to anything other than `no` will remove the default norwegian postal code pattern.
* You can also use the value of another field to define the countryCode, by using a path value i.e. `/myCountryCodePath`.
* Default: `NO`
*/
countryCode?: Path | string
help?: HelpProps
}

Expand All @@ -33,17 +44,18 @@ function PostalCodeAndCity(props: Props) {
city = {},
help,
width = 'large',
country = defaultCountry,
country,
countryCode = defaultCountry,
...fieldBlockProps
} = props

const countryValue = getSourceValue(country)
const countryCodeValue = getSourceValue(country || countryCode)

const handleCityDefaults = useCallback(
(city: StringFieldProps) => {
const props: StringFieldProps = {}

switch (countryValue) {
switch (countryCodeValue) {
case defaultCountry: {
props.pattern = '^[A-Za-zÆØÅæøå -]+$'
break
Expand All @@ -52,7 +64,7 @@ function PostalCodeAndCity(props: Props) {

return { ...props, ...city }
},
[countryValue]
[countryCodeValue]
)

const {
Expand All @@ -67,7 +79,7 @@ function PostalCodeAndCity(props: Props) {
(postalCode: StringFieldProps) => {
const props: StringFieldProps = {}

switch (countryValue) {
switch (countryCodeValue) {
case defaultCountry:
case 'DK':
case 'CH': {
Expand All @@ -83,7 +95,7 @@ function PostalCodeAndCity(props: Props) {

return { ...props, ...postalCode }
},
[countryValue]
[countryCodeValue]
)

const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { PropertiesTableProps } from '../../../../shared/types'
import { FieldProperties } from '../FieldDocs'

export const PostalCodeAndCityProperties: PropertiesTableProps = {
country: {
countryCode: {
doc:
'Defines which country the postal code and city is for, based on the ISO 3166-1 alpha-2 format i.e. `NO`, `DE` etc. ' +
'Setting it to anything other than `NO` will remove the default norwegian postal code pattern. ' +
'You can also use the value of another field to define the country, by using a path value i.e. `/myCountryPath`. ' +
'You can also use the value of another field to define the countryCode, by using a path value i.e. `/myCountryCodePath`. ' +
'Defaults to `NO`',
type: ['Path', 'string'],
status: 'optional',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ describe('Field.PostalCodeAndCity', () => {
expect(city2).toHaveValue('Bergen')
})

// Deprecated – country is replaced with countryCode - can be removed in v11
describe('country', () => {
it('should not use Norwegian postal code validation rules if `country` is set to something other than `NO`', async () => {
render(<Field.PostalCodeAndCity country="DE" />)
Expand Down Expand Up @@ -294,6 +295,138 @@ describe('Field.PostalCodeAndCity', () => {
})
})

describe('countryCode', () => {
it('should not use Norwegian postal code validation rules if `countryCode` is set to something other than `NO`', async () => {
render(<Field.PostalCodeAndCity countryCode="DE" />)

const postalCodeInput = document.querySelector(
'.dnb-forms-field-postal-code-and-city__postal-code .dnb-input__input'
) as HTMLInputElement

expect(postalCodeInput).not.toHaveAttribute('placeholder')

await userEvent.type(postalCodeInput, '123456')

expect(postalCodeInput).toHaveValue('123456')
})

it('should not use Norwegian city validation rules if `countryCode` is set to something other than `NO`', async () => {
const { rerender } = render(<Field.PostalCodeAndCity />)

const city = document.querySelector(
'.dnb-forms-field-postal-code-and-city__city .dnb-input__input'
) as HTMLInputElement

expect(city).not.toHaveAttribute('placeholder')

await userEvent.type(city, 'äöü')
fireEvent.blur(city)

expect(city).toHaveValue('äöü')
expect(screen.queryByRole('alert')).toBeInTheDocument()

rerender(<Field.PostalCodeAndCity countryCode="DE" />)

await userEvent.type(city, 'äöü')
fireEvent.blur(city)

expect(city).toHaveValue('äöüäöü')
expect(screen.queryByRole('alert')).not.toBeInTheDocument()
})

it('should support custom postal code validation', async () => {
render(
<Field.PostalCodeAndCity
countryCode="DE"
postalCode={{
pattern: '^[0-9]{5}$',
mask: [/\d/, /\d/, /\d/, /\d/, /\d/],
placeholder: '00000',
validateInitially: true,
}}
city={{
validateInitially: true,
pattern: '^[a-zA-ZäöüÄÖÜß -]+$',
}}
/>
)

const [postalCode, city] = Array.from(
document.querySelectorAll('input')
)

expect(postalCode).toHaveAttribute('aria-placeholder', '00000')
await userEvent.type(postalCode, 'abcs123456')

expect(postalCode).toHaveValue('12345')

await userEvent.type(city, 'München')

expect(city).toHaveValue('München')
expect(screen.queryByRole('alert')).not.toBeInTheDocument()
})

it('should be able to use a path to set the countryCode value', async () => {
const { rerender } = render(
<Form.Handler data={{ countryCode: 'DE' }}>
<Field.PostalCodeAndCity countryCode="/countryCode" />
</Form.Handler>
)

const postalCodeDe = document.querySelector(
'.dnb-forms-field-postal-code-and-city input'
)

await userEvent.type(postalCodeDe, '123456')
expect(postalCodeDe).toHaveValue('123456')
expect(postalCodeDe).not.toHaveAttribute('aria-placeholder')

rerender(
<Form.Handler data={{ countryCode: 'NO' }}>
<Field.PostalCodeAndCity countryCode="/countryCode" />
</Form.Handler>
)

const postalCodeNo = document.querySelector(
'.dnb-forms-field-postal-code-and-city input'
)

await userEvent.type(postalCodeNo, '{Backspace>4}987654')
expect(postalCodeNo).toHaveValue('9876')
expect(postalCodeNo).toHaveAttribute('aria-placeholder', '0000')
})

it('should use value from countryCode inside iterate', async () => {
render(
<Form.Handler
defaultData={{
items: [{ countryCode: 'NO' }, { countryCode: 'DE' }],
}}
>
<Iterate.Array path="/items">
<Field.PostalCodeAndCity countryCode="/countryCode" />
</Iterate.Array>
</Form.Handler>
)

const [norway, germany] = Array.from(
document.querySelectorAll('.dnb-forms-field-postal-code-and-city')
)

await userEvent.type(
norway.querySelector('input'),
'{Backspace>4}987654'
)
expect(norway.querySelector('input').value).toBe('9876')

await userEvent.type(
germany.querySelector('input'),
'{Backspace>4}987654'
)
expect(germany.querySelector('input').value).toBe('987654')
})
})

describe('ARIA', () => {
const props = {
postalCode: { required: true, validateInitially: true },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function PostalCodeAndCityCountryCodeSelection() {
<Field.Option value="DE" label="Germany" />
</Field.Selection>
<Field.PostalCodeAndCity
country="/country"
countryCode="/country"
postalCode={{ path: '/postalCode' }}
city={{ path: '/city' }}
/>
Expand Down

0 comments on commit 8d0d980

Please sign in to comment.