Skip to content

Update ProductOptionSelector props #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 21, 2020
Merged
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
8 changes: 1 addition & 7 deletions .storybook/stories/ProductOptionSelector.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,6 @@ export const basic = () => {
const [color, setColor] = useState(colors[0])

return (
<ProductOptionSelector
options={colors}
optionProps={{
selectedOption: color,
onSelectedOptionChange: color => setColor(color),
}}
/>
<ProductOptionSelector options={colors} value={color} onChange={color => setColor(color)} />
)
}
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-storefront",
"version": "7.0.0",
"version": "7.1.0",
"description": "Build and deploy e-commerce progressive web apps (PWAs) in record time.",
"module": "./index.js",
"license": "Apache-2.0",
Expand Down
21 changes: 21 additions & 0 deletions src/option/ProductOptionSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export default function ProductOptionSelector({
classes,
optionProps,
skeleton,
value,
onChange,
variant,
OptionComponent,
}) {
Expand All @@ -40,11 +42,19 @@ export default function ProductOptionSelector({

if (!options) return null

const onSelectedOptionChange = newValue => {
if (onChange) {
onChange(newValue)
}
}

return (
<div data-id="ProductOptionSelector" className={classes.root}>
{options.map((option, i) => {
return (
<OptionComponent
selectedOption={value}
onSelectedOptionChange={onSelectedOptionChange}
{...optionProps}
variant={variant || (option.image || option.color ? 'swatch' : 'text')}
name={name}
Expand Down Expand Up @@ -77,6 +87,12 @@ ProductOptionSelector.propTypes = {
*/
name: PropTypes.string,

/**
* Function to call when a new option is selected. Called with the new selected
* option or `null` when a selected option is deselected.
*/
onChange: PropTypes.func,

/**
* Props to apply to each `SwatchProductOption` or `TextProductOption` element.
*/
Expand All @@ -88,6 +104,11 @@ ProductOptionSelector.propTypes = {
*/
skeleton: PropTypes.number,

/**
* Current selected value among provided options or `null` when no option is selected.
*/
value: PropTypes.object,

/**
* Allows you to override the default component which is used to render a product option.
*/
Expand Down
97 changes: 97 additions & 0 deletions test/option/ProductOptionsSelector.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React, { useState } from 'react'
import { mount } from 'enzyme'
import ProductOptionSelector from 'react-storefront/option/ProductOptionSelector'
import ProductOption from 'react-storefront/option/ProductOption'
import PWAContext from 'react-storefront/PWAContext'

describe('ProductOptionSelector', () => {
let colors
let sizes
let wrapper

beforeEach(() => {
colors = [
{
text: 'Color1',
id: 'color1',
image: {
src: 'src1',
alt: 'alt1',
},
},
]
sizes = [{ id: 'sm', text: 'sm' }]
})

afterEach(() => {
try {
wrapper.unmount()
} catch (e) {}
})

it('should render the right variant depending on options', () => {
const Test = () => {
return (
<>
<ProductOptionSelector options={colors} />
<ProductOptionSelector options={sizes} />
</>
)
}

wrapper = mount(<Test />)

expect(
wrapper
.find(ProductOption)
.first()
.props().variant,
).toBe('swatch')
expect(
wrapper
.find(ProductOption)
.last()
.props().variant,
).toBe('text')
})

it('should call onChange on click', () => {
const onChangeSpy = jest.fn()

const Test = () => {
const [color, setColor] = useState(null)
const updateColor = value => {
setColor(value)
onChangeSpy(value)
}

return <ProductOptionSelector value={color} onChange={updateColor} options={colors} />
}

wrapper = mount(<Test />)

wrapper.find('button').simulate('click')
expect(onChangeSpy).toHaveBeenCalledWith(colors[0])

wrapper.find('button').simulate('click')
expect(onChangeSpy).toHaveBeenCalledWith(null)
})

it('should return null when options are undefined', () => {
wrapper = mount(<ProductOptionSelector />)

expect(wrapper.find(ProductOptionSelector).isEmptyRender()).toBe(true)
})

it('should render a skeleton with swatches', () => {
wrapper = mount(<ProductOptionSelector variant="swatch" skeleton={4} />)

expect(wrapper.find(ProductOptionSelector).isEmptyRender()).toBe(false)
})

it('should render a skeleton with text', () => {
wrapper = mount(<ProductOptionSelector variant="text" skeleton={4} />)

expect(wrapper.find(ProductOptionSelector).isEmptyRender()).toBe(false)
})
})