diff --git a/README.md b/README.md index 4f4b5831a8..9d76257d75 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ Be sure to check out the above migrations before embarking on a new component. | Elements | Collections | Views | Modules | Behaviors | |-----------------|-----------------|-----------------|-----------------|--------------------| | x Button | x Breadcrumb | _ Advertisement | x Accordion | x Form Validation | -| x Container | x Form | _ Card | x Checkbox | *API (NA)* | +| x Container | x Form | x Card | x Checkbox | *API (NA)* | | x Divider | x Grid | _ Comment | _ Dimmer | *Visibility (NA)* | | x Flag | x Menu | x Feed | x Dropdown | | | x Header | x Message | x Item | _ Embed | | diff --git a/docs/app/Examples/views/Card/Content/ContentBlock.js b/docs/app/Examples/views/Card/Content/ContentBlock.js new file mode 100644 index 0000000000..ccc9d7c22c --- /dev/null +++ b/docs/app/Examples/views/Card/Content/ContentBlock.js @@ -0,0 +1,46 @@ +import React from 'react' +import { Card, Feed } from 'stardust' + +const ContentBlock = () => ( + + + + Recent Activity + + + + + + + + + + You added Jenny Hess to your coworker group. + + + + + + + + + + You added Molly Malone as a friend. + + + + + + + + + You added Elliot Baker to your musicians group. + + + + + + +) + +export default ContentBlock diff --git a/docs/app/Examples/views/Card/Content/ExtraContent.js b/docs/app/Examples/views/Card/Content/ExtraContent.js new file mode 100644 index 0000000000..1cb4cdccc7 --- /dev/null +++ b/docs/app/Examples/views/Card/Content/ExtraContent.js @@ -0,0 +1,24 @@ +import React from 'react' +import { Card, Icon } from 'stardust' + +const description = [ + 'Amy is a violinist with 2 years experience in the wedding industry.', + 'She enjoys the outdoors and currently resides in upstate New York.', +].join(' ') + +const ExtraContent = () => ( + + + + About Amy + + + + + + 4 Friends + + +) + +export default ExtraContent diff --git a/docs/app/Examples/views/Card/Content/HeaderCard.js b/docs/app/Examples/views/Card/Content/HeaderCard.js new file mode 100644 index 0000000000..fbfd6e1a84 --- /dev/null +++ b/docs/app/Examples/views/Card/Content/HeaderCard.js @@ -0,0 +1,38 @@ +import React from 'react' +import { Card } from 'stardust' + +const HeaderCards = () => ( + + + + + Matthew Harris + + + Co-Worker + + + Matthew is a pianist living in Nashville. + + + + + + + + + + + + + + + + +) + +export default HeaderCards diff --git a/docs/app/Examples/views/Card/Content/ImageCard.js b/docs/app/Examples/views/Card/Content/ImageCard.js new file mode 100644 index 0000000000..5034c92015 --- /dev/null +++ b/docs/app/Examples/views/Card/Content/ImageCard.js @@ -0,0 +1,29 @@ +import React from 'react' +import { Card, Icon, Image } from 'stardust' + +const ImageCard = () => ( + + + + + Daniel + + + + Joined in 2016 + + + + Daniel is a comedian living in Nashville. + + + + + + 10 Friends + + + +) + +export default ImageCard diff --git a/docs/app/Examples/views/Card/Content/LinkCard.js b/docs/app/Examples/views/Card/Content/LinkCard.js new file mode 100644 index 0000000000..e07f23909a --- /dev/null +++ b/docs/app/Examples/views/Card/Content/LinkCard.js @@ -0,0 +1,13 @@ +import React from 'react' +import { Card } from 'stardust' + +const LinkCard = () => ( + +) + +export default LinkCard diff --git a/docs/app/Examples/views/Card/Content/index.js b/docs/app/Examples/views/Card/Content/index.js new file mode 100644 index 0000000000..32c8062e67 --- /dev/null +++ b/docs/app/Examples/views/Card/Content/index.js @@ -0,0 +1,36 @@ +import React from 'react' + +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const Content = () => ( + + + + + + + +) + +export default Content diff --git a/docs/app/Examples/views/Card/Types/GroupByProps.js b/docs/app/Examples/views/Card/Types/GroupByProps.js new file mode 100644 index 0000000000..a192ef0b6f --- /dev/null +++ b/docs/app/Examples/views/Card/Types/GroupByProps.js @@ -0,0 +1,26 @@ +import React from 'react' +import { Card } from 'stardust' + +const items = [ + { + header: 'Project Report - April', + description: 'Leverage agile frameworks to provide a robust synopsis for high level overviews.', + meta: 'ROI: 30%', + }, + { + header: 'Project Report - May', + description: 'Bring to the table win-win survival strategies to ensure proactive domination.', + meta: 'ROI: 34%', + }, + { + header: 'Project Report - June', + description: 'Capitalise on low hanging fruit to identify a ballpark value added activity to beta test.', + meta: 'ROI: 27%', + }, +] + +const GroupByProps = () => ( + +) + +export default GroupByProps diff --git a/docs/app/Examples/views/Card/Types/Groups.js b/docs/app/Examples/views/Card/Types/Groups.js new file mode 100644 index 0000000000..64e140b19c --- /dev/null +++ b/docs/app/Examples/views/Card/Types/Groups.js @@ -0,0 +1,69 @@ +import React from 'react' +import { Button, Card, Image } from 'stardust' + +const Groups = () => ( + + + + + + Steve Sanders + + + Friends of Elliot + + + Steve wants to add you to the group best friends + + + +
+ + +
+
+
+ + + + + Molly Thomas + + + New User + + + Molly wants to add you to the group musicians + + + +
+ + +
+
+
+ + + + + Jenny Lawrence + + + New User + + + Jenny requested permission to view your contact details + + + +
+ + +
+
+
+
+) + +export default Groups diff --git a/docs/app/Examples/views/Card/Types/IndividualCard.js b/docs/app/Examples/views/Card/Types/IndividualCard.js new file mode 100644 index 0000000000..9768d98b14 --- /dev/null +++ b/docs/app/Examples/views/Card/Types/IndividualCard.js @@ -0,0 +1,29 @@ +import React from 'react' +import { Card, Icon, Image } from 'stardust' + +const IndividualCard = () => ( + + + + + Matthew + + + + Joined in 2015 + + + + Matthew is a musician living in Nashville. + + + + + + 22 Friends + + + +) + +export default IndividualCard diff --git a/docs/app/Examples/views/Card/Types/IndividualCardByProps.js b/docs/app/Examples/views/Card/Types/IndividualCardByProps.js new file mode 100644 index 0000000000..82ea032bed --- /dev/null +++ b/docs/app/Examples/views/Card/Types/IndividualCardByProps.js @@ -0,0 +1,21 @@ +import React from 'react' +import { Card, Icon } from 'stardust' + +const extra = ( + + + 16 Friends + +) + +const IndividualCardByProps = () => ( + +) + +export default IndividualCardByProps diff --git a/docs/app/Examples/views/Card/Types/index.js b/docs/app/Examples/views/Card/Types/index.js new file mode 100644 index 0000000000..b1e635cd62 --- /dev/null +++ b/docs/app/Examples/views/Card/Types/index.js @@ -0,0 +1,29 @@ +import React from 'react' + +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const Types = () => ( + + + + + + +) + +export default Types diff --git a/docs/app/Examples/views/Card/Variations/Colored.js b/docs/app/Examples/views/Card/Variations/Colored.js new file mode 100644 index 0000000000..1d1575d846 --- /dev/null +++ b/docs/app/Examples/views/Card/Variations/Colored.js @@ -0,0 +1,23 @@ +import React from 'react' +import { Card } from 'stardust' + +const src = 'http://semantic-ui.com/images/wireframe/white-image.png' + +const ColoredCards = () => ( + + + + + + + + + + + + + + +) + +export default ColoredCards diff --git a/docs/app/Examples/views/Card/Variations/ColumnCount.js b/docs/app/Examples/views/Card/Variations/ColumnCount.js new file mode 100644 index 0000000000..97e1d0409a --- /dev/null +++ b/docs/app/Examples/views/Card/Variations/ColumnCount.js @@ -0,0 +1,23 @@ +import React from 'react' +import { Card } from 'stardust' + +const src = 'http://semantic-ui.com/images/wireframe/image.png' + +const ColumnCountCards = () => ( + + + + + + + + + + + + + + +) + +export default ColumnCountCards diff --git a/docs/app/Examples/views/Card/Variations/Fluid.js b/docs/app/Examples/views/Card/Variations/Fluid.js new file mode 100644 index 0000000000..8e93e24896 --- /dev/null +++ b/docs/app/Examples/views/Card/Variations/Fluid.js @@ -0,0 +1,18 @@ +import React from 'react' +import { Card } from 'stardust' + +const FluidCards = () => ( + + + + + + + + + + + +) + +export default FluidCards diff --git a/docs/app/Examples/views/Card/Variations/index.js b/docs/app/Examples/views/Card/Variations/index.js new file mode 100644 index 0000000000..c4349a76ca --- /dev/null +++ b/docs/app/Examples/views/Card/Variations/index.js @@ -0,0 +1,26 @@ +import React from 'react' + +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const Variations = () => ( + + + + + +) + +export default Variations diff --git a/docs/app/Examples/views/Card/index.js b/docs/app/Examples/views/Card/index.js new file mode 100644 index 0000000000..916ed13bb4 --- /dev/null +++ b/docs/app/Examples/views/Card/index.js @@ -0,0 +1,15 @@ +import React from 'react' + +import Content from './Content' +import Types from './Types' +import Variations from './Variations' + +const CardExamples = () => ( +
+ + + +
+) + +export default CardExamples diff --git a/src/views/Card/Card.js b/src/views/Card/Card.js new file mode 100644 index 0000000000..5ae1c2c979 --- /dev/null +++ b/src/views/Card/Card.js @@ -0,0 +1,142 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getUnhandledProps, + META, + SUI, + useKeyOnly, +} from '../../lib' +import { createImage } from '../../factories' +import CardContent from './CardContent' +import CardDescription from './CardDescription' +import CardGroup from './CardGroup' +import CardHeader from './CardHeader' +import CardMeta from './CardMeta' + +function Card(props) { + const { + centered, + children, + className, + color, + description, + extra, + fluid, + header, + href, + image, + meta, + onClick, + raised, + } = props + + const classes = cx('ui', + useKeyOnly(centered, 'centered'), + useKeyOnly(fluid, 'fluid'), + useKeyOnly(raised, 'raised'), + color, + 'card', + className, + ) + const rest = getUnhandledProps(Card, props) + + const handleClick = (e) => { + if (onClick) onClick(e) + } + const CardComponent = href || onClick ? 'a' : 'div' + + if (children) { + return ( + + {children} + + ) + } + + return ( + + {createImage(image)} + {(description || header || meta) && ( + + )} + {extra && {extra}} + + ) +} + +Card._meta = { + name: 'Card', + type: META.TYPES.VIEW, + props: { + color: SUI.COLORS, + }, +} + +Card.propTypes = { + /** A Card can center itself inside its container. */ + centered: PropTypes.bool, + + /** Primary content of the Card. */ + children: customPropTypes.every([ + customPropTypes.disallow(['description', 'header', 'image', 'meta']), + PropTypes.node, + ]), + + /** Classes that will be added to the Card className. */ + className: PropTypes.string, + + /** A Card can be formatted to display different colors. */ + color: PropTypes.oneOf(Card._meta.props.color), + + /** Shorthand prop for CardDescription. Mutually exclusive with children. */ + description: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.node, + ]), + + /** Shorthand prop for CardContent containing extra prop. Mutually exclusive with children. */ + extra: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.node, + ]), + + /** A Card can be formatted to take up the width of its container. */ + fluid: PropTypes.bool, + + /** Shorthand prop for CardHeader. Mutually exclusive with children. */ + header: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.node, + ]), + + /** Render as an `a` tag instead of a `div` and adds the href attribute. */ + href: PropTypes.string, + + /** A card can contain an Image component. */ + image: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.node, + ]), + + /** Shorthand prop for CardMeta. Mutually exclusive with children. */ + meta: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.node, + ]), + + /** Render as an `a` tag instead of a `div` and called with event on Card click. */ + onClick: PropTypes.func, + + /** A Card can be formatted to raise above the page. */ + raised: PropTypes.bool, +} + +Card.Content = CardContent +Card.Description = CardDescription +Card.Group = CardGroup +Card.Header = CardHeader +Card.Meta = CardMeta + +export default Card diff --git a/src/views/Card/CardContent.js b/src/views/Card/CardContent.js new file mode 100644 index 0000000000..2c6f9b701c --- /dev/null +++ b/src/views/Card/CardContent.js @@ -0,0 +1,83 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getUnhandledProps, + META, + useKeyOnly, +} from '../../lib' +import CardDescription from './CardDescription' +import CardHeader from './CardHeader' +import CardMeta from './CardMeta' + +function CardContent(props) { + const { className, children, description, extra, header, meta } = props + const classes = cx( + className, + useKeyOnly(extra, 'extra'), + 'content', + ) + const rest = getUnhandledProps(CardContent, props) + + if (children) { + return
{children}
+ } + + return ( +
+ {header && } + {meta && } + {description && } +
+ ) +} + +CardContent._meta = { + name: 'CardContent', + parent: 'Card', + type: META.TYPES.VIEW, +} + +CardContent.propTypes = { + /** Primary content of the CardContent. Mutually exclusive with all shorthand props. */ + children: customPropTypes.every([ + customPropTypes.disallow(['description', 'header', 'meta']), + PropTypes.node, + ]), + + /** Classes that will be added to the CardContent className */ + className: PropTypes.string, + + /** Shorthand prop for CardDescription. Mutually exclusive with children. */ + description: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]), + ]), + + /** A card can contain extra content meant to be formatted separately from the main content */ + extra: PropTypes.bool, + + /** Shorthand prop for CardHeader. Mutually exclusive with children. */ + header: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]), + ]), + + /** Shorthand prop for CardMeta. Mutually exclusive with children. */ + meta: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]), + ]), +} + +export default CardContent diff --git a/src/views/Card/CardDescription.js b/src/views/Card/CardDescription.js new file mode 100644 index 0000000000..f49e737246 --- /dev/null +++ b/src/views/Card/CardDescription.js @@ -0,0 +1,44 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getUnhandledProps, + META, +} from '../../lib' + +function CardDescription(props) { + const { className, children, content } = props + const classes = cx(className, 'description') + const rest = getUnhandledProps(CardDescription, props) + + return
{ children || content }
+} + +CardDescription._meta = { + name: 'CardDescription', + parent: 'Card', + type: META.TYPES.VIEW, +} + +CardDescription.propTypes = { + /** Primary content of the CardDescription. Mutually exclusive with content. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** Classes that will be added to the CardDescription className. */ + className: PropTypes.string, + + /** Primary content of the CardDescription. Mutually exclusive with children. */ + content: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]), + ]), +} + +export default CardDescription diff --git a/src/views/Card/CardGroup.js b/src/views/Card/CardGroup.js new file mode 100644 index 0000000000..cf04cb38f9 --- /dev/null +++ b/src/views/Card/CardGroup.js @@ -0,0 +1,73 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getUnhandledProps, + META, + numberToWord, + SUI, + useKeyOnly, +} from '../../lib' +import Card from './Card' + +function CardGroup(props) { + const { className, children, doubling, items, itemsPerRow, stackable } = props + const classes = cx('ui', + numberToWord(itemsPerRow), + useKeyOnly(doubling, 'doubling'), + useKeyOnly(stackable, 'stackable'), + className, + 'cards', + ) + const rest = getUnhandledProps(CardGroup, props) + + const content = !items ? children : items.map(item => { + const key = item.key || [item.header, item.description].join('-') + return + }) + + return
{content}
+} + +CardGroup._meta = { + name: 'CardGroup', + parent: 'Card', + props: { + itemsPerRow: SUI.WIDTHS, + }, + type: META.TYPES.VIEW, +} + +CardGroup.propTypes = { + /** A group of Card components. Mutually exclusive with items. */ + children: customPropTypes.every([ + customPropTypes.disallow(['items']), + PropTypes.node, + ]), + + /** Classes that will be added to the CardGroup className */ + className: PropTypes.string, + + /** A group of cards can double its column width for mobile */ + doubling: PropTypes.bool, + + /** Shorthand prop for children. Mutually exclusive with children. */ + items: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.arrayOf(PropTypes.shape({ + description: PropTypes.node, + meta: PropTypes.node, + key: PropTypes.string, + header: PropTypes.node, + })), + ]), + + /** A group of cards can set how many cards should exist in a row */ + itemsPerRow: PropTypes.oneOf(CardGroup._meta.props.itemsPerRow), + + /** A group of cards can automatically stack rows to a single columns on mobile devices */ + stackable: PropTypes.bool, +} + +export default CardGroup diff --git a/src/views/Card/CardHeader.js b/src/views/Card/CardHeader.js new file mode 100644 index 0000000000..ba18584e32 --- /dev/null +++ b/src/views/Card/CardHeader.js @@ -0,0 +1,44 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getUnhandledProps, + META, +} from '../../lib' + +function CardHeader(props) { + const { className, children, content } = props + const classes = cx(className, 'header') + const rest = getUnhandledProps(CardHeader, props) + + return
{children || content}
+} + +CardHeader._meta = { + name: 'CardHeader', + parent: 'Card', + type: META.TYPES.VIEW, +} + +CardHeader.propTypes = { + /** Primary content of the CardHeader. Mutually exclusive with content. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** Classes that will be added to the CardHeader className */ + className: PropTypes.string, + + /** Primary content of the CardHeader. Mutually exclusive with children. */ + content: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]), + ]), +} + +export default CardHeader diff --git a/src/views/Card/CardMeta.js b/src/views/Card/CardMeta.js new file mode 100644 index 0000000000..c464d823ae --- /dev/null +++ b/src/views/Card/CardMeta.js @@ -0,0 +1,44 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getUnhandledProps, + META, +} from '../../lib' + +function CardMeta(props) { + const { className, children, content } = props + const classes = cx(className, 'meta') + const rest = getUnhandledProps(CardMeta, props) + + return
{children || content}
+} + +CardMeta._meta = { + name: 'CardMeta', + parent: 'Card', + type: META.TYPES.VIEW, +} + +CardMeta.propTypes = { + /** Primary content of the CardMeta. Mutually exclusive with content. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** Classes that will be added to the CardMeta className */ + className: PropTypes.string, + + /** Primary content of the CardMeta. Mutually exclusive with children. */ + content: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]), + ]), +} + +export default CardMeta diff --git a/src/views/index.js b/src/views/index.js index 2a89872908..46fed01d3f 100644 --- a/src/views/index.js +++ b/src/views/index.js @@ -1,3 +1,4 @@ +export { default as Card } from './Card/Card' export { default as Feed } from './Feed/Feed' export { default as Item } from './Item/Item' export { default as Statistic } from './Statistic/Statistic' diff --git a/test/specs/views/Card/Card-test.js b/test/specs/views/Card/Card-test.js new file mode 100644 index 0000000000..ea2f0b11dc --- /dev/null +++ b/test/specs/views/Card/Card-test.js @@ -0,0 +1,67 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import { sandbox } from 'test/utils' +import Card from 'src/views/Card/Card' +import CardContent from 'src/views/Card/CardContent' +import CardDescription from 'src/views/Card/CardDescription' +import CardGroup from 'src/views/Card/CardGroup' +import CardHeader from 'src/views/Card/CardHeader' +import CardMeta from 'src/views/Card/CardMeta' + +describe('Card', () => { + common.isConformant(Card) + common.hasUIClassName(Card) + common.hasSubComponents(Card, [CardContent, CardDescription, CardGroup, CardHeader, CardMeta]) + common.propKeyOnlyToClassName(Card, 'centered') + common.propKeyOnlyToClassName(Card, 'fluid') + common.propKeyOnlyToClassName(Card, 'raised') + common.rendersChildren(Card) + + it('renders a
by default', () => { + shallow().should.have.tagName('div') + }) + + describe('href prop', () => { + it('renders an with an href attr', () => { + const url = faker.internet.url() + const wrapper = shallow() + + wrapper.should.have.tagName('a') + wrapper.should.have.attr('href', url) + }) + }) + + describe('onClick prop', () => { + it('can be omitted', () => { + const click = () => mount({faker.hacker.phrase()}).simulate('click') + expect(click).to.not.throw() + }) + + it('renders instead of
', () => { + const handleClick = sandbox.spy() + const wrapper = shallow() + + wrapper.should.have.tagName('a') + }) + + it('is called with (event) on click', () => { + const handleClick = sandbox.spy() + const wrapper = mount() + + wrapper.simulate('click') + + handleClick.should.have.been.calledOnce() + handleClick.should.have.been.calledWithMatch({}) + }) + }) + + describe('extra prop', () => { + it('renders an CardContent component', () => { + const wrapper = shallow() + + wrapper.should.have.descendants('CardContent') + }) + }) +}) diff --git a/test/specs/views/Card/CardContent-test.js b/test/specs/views/Card/CardContent-test.js new file mode 100644 index 0000000000..940bdcd604 --- /dev/null +++ b/test/specs/views/Card/CardContent-test.js @@ -0,0 +1,41 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import CardContent from 'src/views/Card/CardContent' +import CardDescription from 'src/views/Card/CardDescription' +import CardHeader from 'src/views/Card/CardHeader' +import CardMeta from 'src/views/Card/CardMeta' + +describe('CardContent', () => { + common.isConformant(CardContent) + common.propKeyOnlyToClassName(CardContent, 'extra') + common.rendersChildren(CardContent) + + describe('description prop', () => { + it('renders description component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) + + describe('header prop', () => { + it('renders header component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) + + describe('meta prop', () => { + it('renders meta component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) +}) diff --git a/test/specs/views/Card/CardDescription-test.js b/test/specs/views/Card/CardDescription-test.js new file mode 100644 index 0000000000..004ac4db9d --- /dev/null +++ b/test/specs/views/Card/CardDescription-test.js @@ -0,0 +1,26 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import CardDescription from 'src/views/Card/CardDescription' + +describe('CardDescription', () => { + common.isConformant(CardDescription) + common.rendersChildren(CardDescription) + + describe('description prop', () => { + it('renders child text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + + it('renders child node', () => { + const child =
+ + shallow() + .should.contain(child) + }) + }) +}) diff --git a/test/specs/views/Card/CardGroup-test.js b/test/specs/views/Card/CardGroup-test.js new file mode 100644 index 0000000000..90126db732 --- /dev/null +++ b/test/specs/views/Card/CardGroup-test.js @@ -0,0 +1,30 @@ +import faker from 'faker' +import React from 'react' +import * as common from 'test/specs/commonTests' +import CardGroup from 'src/views/Card/CardGroup' + +describe('CardGroup', () => { + common.isConformant(CardGroup) + common.hasUIClassName(CardGroup) + common.propKeyOnlyToClassName(CardGroup, 'doubling') + common.propKeyOnlyToClassName(CardGroup, 'stackable') + common.implementsNumberToWordProp(CardGroup, 'itemsPerRow') + common.rendersChildren(CardGroup) + + describe('renders children', () => { + const firstText = faker.hacker.phrase() + const secondText = faker.hacker.phrase() + + it('with `items` prop', () => { + const items = [ + { header: firstText }, + { header: secondText }, + ] + + const wrapper = mount().find('Card') + + wrapper.first().find('CardHeader').should.contain.text(firstText) + wrapper.last().find('CardHeader').should.contain.text(secondText) + }) + }) +}) diff --git a/test/specs/views/Card/CardHeader-test.js b/test/specs/views/Card/CardHeader-test.js new file mode 100644 index 0000000000..30ab01ca53 --- /dev/null +++ b/test/specs/views/Card/CardHeader-test.js @@ -0,0 +1,26 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import CardHeader from 'src/views/Card/CardHeader' + +describe('CardHeader', () => { + common.isConformant(CardHeader) + common.rendersChildren(CardHeader) + + describe('description prop', () => { + it('renders child text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + + it('renders child node', () => { + const child =
+ + shallow() + .should.contain(child) + }) + }) +}) diff --git a/test/specs/views/Card/CardMeta-test.js b/test/specs/views/Card/CardMeta-test.js new file mode 100644 index 0000000000..ce675b90a4 --- /dev/null +++ b/test/specs/views/Card/CardMeta-test.js @@ -0,0 +1,26 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import CardMeta from 'src/views/Card/CardMeta' + +describe('CardMeta', () => { + common.isConformant(CardMeta) + common.rendersChildren(CardMeta) + + describe('description prop', () => { + it('renders child text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + + it('renders child node', () => { + const child =
+ + shallow() + .should.contain(child) + }) + }) +})