Skip to content

Commit

Permalink
Merge branch 'develop' into PWA-471
Browse files Browse the repository at this point in the history
  • Loading branch information
davemacaulay committed Jun 10, 2020
2 parents 3c999d1 + 77d97c6 commit 9998446
Show file tree
Hide file tree
Showing 9 changed files with 535 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

exports[`returns empty array if no available regions 1`] = `
Object {
"loading": false,
"regions": Array [],
}
`;

exports[`returns formatted regions 1`] = `
Object {
"loading": false,
"regions": Array [
Object {
"disabled": true,
Expand All @@ -31,6 +33,7 @@ Object {

exports[`returns formatted regions with id as the key 1`] = `
Object {
"loading": false,
"regions": Array [
Object {
"disabled": true,
Expand All @@ -51,3 +54,15 @@ Object {
],
}
`;

exports[`returns placeholder option while loading 1`] = `
Object {
"loading": true,
"regions": Array [
Object {
"label": "Loading Regions...",
"value": "",
},
],
}
`;
59 changes: 55 additions & 4 deletions packages/peregrine/lib/talons/Region/__tests__/useRegion.spec.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import React from 'react';
import { act } from 'react-test-renderer';
import { useQuery } from '@apollo/react-hooks';
import { useFieldApi, useFieldState } from 'informed';

import createTestInstance from '../../../util/createTestInstance';
import { useRegion } from '../useRegion';

jest.mock('informed', () => {
const useFieldState = jest.fn().mockReturnValue({
value: 'US'
});
const useFieldApi = jest.fn();

return { useFieldState };
return { useFieldApi, useFieldState };
});

jest.mock('@apollo/react-hooks', () => ({
Expand All @@ -25,17 +30,43 @@ jest.mock('@apollo/react-hooks', () => ({
})
}));

const Component = props => {
const talonProps = useRegion(props);
return <i talonProps={talonProps} />;
};

const props = {
queries: {}
};

test('returns placeholder option while loading', () => {
useQuery.mockReturnValueOnce({
error: false,
loading: true
});

const tree = createTestInstance(<Component {...props} />);
const { root } = tree;
const { talonProps } = root.findByType('i').props;

expect(talonProps).toMatchSnapshot();
});

test('returns formatted regions', () => {
const talonProps = useRegion(props);
const tree = createTestInstance(<Component {...props} />);
const { root } = tree;
const { talonProps } = root.findByType('i').props;

expect(talonProps).toMatchSnapshot();
});

test('returns formatted regions with id as the key', () => {
const talonProps = useRegion({ ...props, optionValueKey: 'id' });
const tree = createTestInstance(
<Component {...props} optionValueKey={'id'} />
);
const { root } = tree;
const { talonProps } = root.findByType('i').props;

expect(talonProps).toMatchSnapshot();
});

Expand All @@ -50,6 +81,26 @@ test('returns empty array if no available regions', () => {
loading: false
});

const talonProps = useRegion(props);
const tree = createTestInstance(<Component {...props} />);
const { root } = tree;
const { talonProps } = root.findByType('i').props;

expect(talonProps).toMatchSnapshot();
});

test('resets value on country change', () => {
const mockReset = jest.fn();

useFieldState.mockReturnValueOnce({ value: 'FR' });
useFieldApi.mockReturnValue({ reset: mockReset });

const tree = createTestInstance(<Component {...props} />);

expect(mockReset).not.toHaveBeenCalled();

act(() => {
tree.update(<Component {...props} />);
});

expect(mockReset).toHaveBeenCalled();
});
23 changes: 21 additions & 2 deletions packages/peregrine/lib/talons/Region/useRegion.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
import { useEffect, useRef } from 'react';
import { useQuery } from '@apollo/react-hooks';
import { useFieldState } from 'informed';
import { useFieldApi, useFieldState } from 'informed';

export const useRegion = props => {
const {
countryCodeField = 'country',
field = 'region',
optionValueKey = 'code',
queries: { getRegionsQuery }
} = props;

const hasInitialized = useRef(false);
const countryFieldState = useFieldState(countryCodeField);
const { value: country } = countryFieldState;
const regionFieldApi = useFieldApi(field);

// Reset region value when country changes. Because of how Informed sets initialValues,
// we want to skip the first state change of the value being initialized.
useEffect(() => {
if (country) {
if (hasInitialized.current) {
regionFieldApi.reset();
} else {
hasInitialized.current = true;
}
}
}, [country, regionFieldApi]);

const { data, error, loading } = useQuery(getRegionsQuery, {
variables: { countryCode: country }
});

let formattedRegionsData = [];
let formattedRegionsData = [{ label: 'Loading Regions...', value: '' }];
if (!loading && !error) {
const { country } = data;
const { available_regions: availableRegions } = country;
Expand All @@ -31,10 +47,13 @@ export const useRegion = props => {
label: '',
value: ''
});
} else {
formattedRegionsData = [];
}
}

return {
loading,
regions: formattedRegionsData
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders a disabled dropdown while loading 1`] = `
<div
className="root"
>
<label
className="label"
htmlFor="country"
>
Country
</label>
<span
className="root"
style={
Object {
"--iconsAfter": 1,
"--iconsBefore": 0,
}
}
>
<span
className="input"
>
<select
className="input"
disabled={true}
name="country"
onBlur={[Function]}
onChange={[Function]}
value="US"
/>
</span>
<span
className="before"
/>
<span
className="after"
>
<span
className="root"
>
<svg
className="icon"
fill="none"
height={18}
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
width={18}
xmlns="http://www.w3.org/2000/svg"
>
<polyline
points="6 9 12 15 18 9"
/>
</svg>
</span>
</span>
</span>
<p
className="root"
/>
</div>
`;

exports[`renders dropdown with country data 1`] = `
<div
className="root"
>
<label
className="label"
htmlFor="country"
>
Country
</label>
<span
className="root"
style={
Object {
"--iconsAfter": 1,
"--iconsBefore": 0,
}
}
>
<span
className="input"
>
<select
className="input"
disabled={false}
name="country"
onBlur={[Function]}
onChange={[Function]}
value="US"
>
<option
disabled={null}
hidden={null}
value="US"
>
United State
</option>
<option
disabled={null}
hidden={null}
value="FR"
>
France
</option>
</select>
</span>
<span
className="before"
/>
<span
className="after"
>
<span
className="root"
>
<svg
className="icon"
fill="none"
height={18}
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
width={18}
xmlns="http://www.w3.org/2000/svg"
>
<polyline
points="6 9 12 15 18 9"
/>
</svg>
</span>
</span>
</span>
<p
className="root"
/>
</div>
`;
40 changes: 40 additions & 0 deletions packages/venia-ui/lib/components/Country/__tests__/country.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { createTestInstance } from '@magento/peregrine';
import { useCountry } from '@magento/peregrine/lib/talons/Country/useCountry';

import Country from '../country';

jest.mock('@magento/peregrine/lib/talons/Country/useCountry');
jest.mock('../../../classify');

const mockProps = {
field: 'country',
initialValue: 'US',
label: 'Country',
validate: jest.fn()
};

test('renders a disabled dropdown while loading', () => {
useCountry.mockReturnValueOnce({
countries: [],
loading: true
});

const tree = createTestInstance(<Country {...mockProps} />);

expect(tree.toJSON()).toMatchSnapshot();
});

test('renders dropdown with country data', () => {
useCountry.mockReturnValueOnce({
countries: [
{ label: 'United State', value: 'US' },
{ label: 'France', value: 'FR' }
],
loading: false
});

const tree = createTestInstance(<Country {...mockProps} />);

expect(tree.toJSON()).toMatchSnapshot();
});
11 changes: 1 addition & 10 deletions packages/venia-ui/lib/components/Country/country.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,14 @@ const Country = props => {
}
});
const { countries, loading } = talonProps;
const {
classes: propClasses,
field,
label,
validate,
initialValue,
...inputProps
} = props;
const { classes: propClasses, field, label, ...inputProps } = props;

const classes = mergeClasses(defaultClasses, propClasses);
const selectProps = {
classes,
disabled: loading,
field,
items: countries,
validate,
initialValue,
...inputProps
};

Expand Down
Loading

0 comments on commit 9998446

Please sign in to comment.