diff --git a/src/views/Card/Card.js b/src/views/Card/Card.js
index ab4d58f494..ccd2d35721 100644
--- a/src/views/Card/Card.js
+++ b/src/views/Card/Card.js
@@ -2,9 +2,10 @@ import cx from 'classnames'
import React, { PropTypes } from 'react'
import {
+ customPropTypes,
+ getUnhandledProps,
META,
SUI,
- getUnhandledProps,
useKeyOnly,
} from '../../lib'
import CardContent from './CardContent'
@@ -19,8 +20,11 @@ function Card(props) {
children,
className,
color,
+ description,
fluid,
+ header,
href,
+ meta,
onClick,
raised,
} = props
@@ -47,7 +51,7 @@ function Card(props) {
href={href}
onClick={handleClick}
>
- {children}
+ {children || }
)
}
@@ -73,12 +77,30 @@ Card.propTypes = {
/** 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,
+ ]),
+
/** 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,
+ /** 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,
diff --git a/src/views/Card/CardGroup.js b/src/views/Card/CardGroup.js
index f8c9c54ea0..c7d0d86bd7 100644
--- a/src/views/Card/CardGroup.js
+++ b/src/views/Card/CardGroup.js
@@ -34,7 +34,7 @@ CardGroup._meta = {
name: 'CardGroup',
parent: 'Card',
props: {
- width: SUI.WIDTHS,
+ itemsPerRow: SUI.WIDTHS,
},
type: META.TYPES.VIEW,
}
@@ -47,7 +47,7 @@ CardGroup.propTypes = {
]),
doubling: PropTypes.bool,
items: customPropTypes.every([
- customPropTypes.disallow(['description', 'title']),
+ customPropTypes.disallow(['description', 'header']),
PropTypes.arrayOf(PropTypes.shape({
description: PropTypes.node,
meta: PropTypes.node,
diff --git a/test/specs/views/Card/Card-test.js b/test/specs/views/Card/Card-test.js
index 176115b1e6..d624cd649b 100644
--- a/test/specs/views/Card/Card-test.js
+++ b/test/specs/views/Card/Card-test.js
@@ -1,8 +1,53 @@
+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.rendersChildren(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)
+
+ describe('renders different elements', () => {
+ it('
by default', () => {
+ shallow(
).should.have.tagName('div')
+ })
+
+ it('
with `href` prop', () => {
+ 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 and handles click', () => {
+ const handleClick = sandbox.spy()
+ const wrapper = mount()
+
+ wrapper.should.have.tagName('a')
+ wrapper.simulate('click')
+
+ handleClick.should.have.been.calledOnce()
+ handleClick.should.have.been.calledWithMatch({})
+ })
+ })
+ })
})
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..2918f3ffc1
--- /dev/null
+++ b/test/specs/views/Card/CardGroup-test.js
@@ -0,0 +1,43 @@
+import faker from 'faker'
+import React from 'react'
+import * as common from 'test/specs/commonTests'
+import Card from 'src/views/Card/Card'
+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')
+
+ describe('renders children', () => {
+ const firstText = faker.hacker.phrase()
+ const secondText = faker.hacker.phrase()
+
+ it('with `children` prop', () => {
+ const wrapper = mount(
+
+ {firstText}
+ {secondText}
+
+ )
+ .find('Card')
+
+ wrapper.first().should.contain.text(firstText)
+ wrapper.last().should.contain.text(secondText)
+ })
+
+ 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)
+ })
+ })
+})