Skip to content

Commit

Permalink
Adds FeaturedProductAttributes component
Browse files Browse the repository at this point in the history
  • Loading branch information
rabidkitten committed May 2, 2023
1 parent b19bf91 commit 341f535
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 3 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ parts and could be harmful to younger children.

![Choking Hazard component](docs/components/choking-hazard.png)

### Featured Product Attributes

The Featured Product Attributes component displays a subset of product
attributes that consumers would be more interested in.

![Product Attributes component](docs/components/featured-product-attributes.png)

### Low Stock

The Low Stock component displays a message when a product is low on quantity.
Expand Down
Binary file added docs/components/featured-product-attributes.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 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": "@ditus/react-web-retail",
"version": "1.0.10",
"version": "1.0.11",
"description": "A set of reusable React web components based on Material UI for retail applications.",
"private": false,
"main": "dist/index.js",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// Copyright (c) DITUS INC. All rights reserved. See LICENSE file in the project
// root for details.
//
import React from 'react';
import PropTypes from 'prop-types';
import ProductAttributes from '../product-attributes/product-attributes';

/**
* Represents a list of attributes for a product that are designated as featured
* attributes, that is a select number of attributes that should be highlighted
* to a customer.
* @param {*} props The properties of the component.
* @returns {HTMLElement} An HTML element representing the component.
*/
function FeaturedProductAttributes(props) {
const {
attributes,
} = props;

if (!attributes || attributes.length === 0) {
return null;
}

const featured = attributes.filter((x) => x.isFeatured);
if (!featured || featured.length === 0) {
return null;
}

return (
<ProductAttributes attributes={featured} />
);
}

export default FeaturedProductAttributes;

FeaturedProductAttributes.propTypes = {
/**
* Specifies an array of attributes.
*/
attributes: PropTypes.arrayOf(PropTypes.shape),
};

FeaturedProductAttributes.defaultProps = {
attributes: [],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* @jest-environment jsdom
*/

//
// Copyright (c) DITUS INC. All rights reserved. See LICENSE file in the project
// root for details.
//
import React from 'react';
import { render } from '@testing-library/react';
import FeaturedProductAttributes from './featured-product-attributes';
import ProductAttributes from '../product-attributes/product-attributes';

// eslint-disable-next-line react/jsx-props-no-spreading
jest.mock('../product-attributes/product-attributes', () => jest.fn((props) => (<div {...props} />)));

describe('FeaturedProductAttributes', () => {
it('does not display if no attributes are specified.', async () => {
const { container, rerender } = render(
<FeaturedProductAttributes />,
);

expect(container).toBeEmptyDOMElement();

rerender(
<FeaturedProductAttributes attributes={[]} />,
);

expect(container).toBeEmptyDOMElement();
});

it('does not display if no attributes are marked as featured.', async () => {
const { container } = render(
<FeaturedProductAttributes
attributes={
[
{
isFeatured: false,
name: 'Color',
value: 'Red',
},
]
}
/>,
);

expect(container).toBeEmptyDOMElement();
});

it('displays featured attributes.', async () => {
const attributes = [
{
isFeatured: true,
name: 'Color',
value: 'Red',
},
];

const { container } = render(
<FeaturedProductAttributes
attributes={attributes}
/>,
);

expect(container).not.toBeEmptyDOMElement();

expect(ProductAttributes).toHaveBeenCalledTimes(1);
expect(ProductAttributes).toHaveBeenCalledWith({ attributes: [{ isFeatured: true, name: 'Color', value: 'Red' }] }, {});
});

it('does not display non-featured attributes.', async () => {
const attributes = [
{
isFeatured: false,
name: 'Material',
value: 'Cotton',
},
{
isFeatured: true,
name: 'Color',
value: 'Red',
},
];

const { container } = render(
<FeaturedProductAttributes
attributes={attributes}
/>,
);

expect(container).not.toBeEmptyDOMElement();
expect(ProductAttributes).toHaveBeenCalledWith({ attributes: [{ isFeatured: true, name: 'Color', value: 'Red' }] }, {});
});
});
1 change: 1 addition & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable import/prefer-default-export */
export { default as ChokingHazard } from './choking-hazard/choking-hazard';
export { default as FeaturedProductAttributes } from './featured-product-attributes/featured-product-attributes';
export { default as LowStock } from './low-stock/low-stock';
export { default as Price } from './price/price';
export { default as ProductAttribute } from './product-attribute/product-attribute';
Expand Down
46 changes: 46 additions & 0 deletions src/stories/FeaturedProductAttributes.stories.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable jsdoc/require-jsdoc */
/* eslint-disable react/jsx-props-no-spreading */
import React from 'react';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { CssBaseline, Grid } from '@mui/material';
import FeaturedProductAttributes from '../components/featured-product-attributes/featured-product-attributes';

export default {
title: 'Components/FeaturedProductAttributes',
component: FeaturedProductAttributes,
argTypes: {
attributes: {
control: 'object',
},
},
};

const theme = createTheme({
});

function Template(args) {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Grid container>
<FeaturedProductAttributes {...args} />
</Grid>
</ThemeProvider>
);
}

export const Primary = Template.bind({});
Primary.args = {
attributes: [
{
isFeatured: false,
name: 'Color',
value: 'Red',
},
{
isFeatured: true,
name: 'Material',
value: '100% Cotton',
},
],
};

0 comments on commit 341f535

Please sign in to comment.