Skip to content

Commit 8e89c38

Browse files
authored
Merge pull request #196 from dirtyredz/BetterPressPage
Better press page
2 parents 183df39 + cc2c97d commit 8e89c38

File tree

28 files changed

+828
-54
lines changed

28 files changed

+828
-54
lines changed

common/styles/globalStyles.css

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ body {
2828
line-height: 1.5;
2929
hyphens: none;
3030
margin: 0;
31+
min-width: 300px;
3132
}
3233

3334
h1,
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* eslint-env jest */
2+
import { getPropsStartingWith, getDataAttributes, getAriaAttributes } from '../prop-utils';
3+
4+
describe('getPropsStartingWith', () => {
5+
test('should return the props that start with the given string', () => {
6+
const props = {
7+
'test-1': 'test',
8+
'test-2': 'test 2',
9+
'another-prop': 'test 3',
10+
};
11+
12+
const result = getPropsStartingWith('test-', props);
13+
expect(result).toEqual({
14+
'test-1': 'test',
15+
'test-2': 'test 2',
16+
});
17+
});
18+
});
19+
20+
describe('getDataAttributes', () => {
21+
test('should return only the props that start with `data-`', () => {
22+
const props = {
23+
'data-ci': 'ci',
24+
'data-gtm': 'gtm',
25+
children: 'test children',
26+
};
27+
28+
const result = getDataAttributes(props);
29+
30+
expect(result).toEqual({
31+
'data-ci': 'ci',
32+
'data-gtm': 'gtm',
33+
});
34+
});
35+
});
36+
37+
describe('getAriaAttributes', () => {
38+
test('should return only the props that start with `aria-`', () => {
39+
const props = {
40+
'aria-label': 'a11y rocks!',
41+
'aria-checked': 'true',
42+
children: 'test children',
43+
};
44+
45+
const result = getAriaAttributes(props);
46+
47+
expect(result).toEqual({
48+
'aria-label': 'a11y rocks!',
49+
'aria-checked': 'true',
50+
});
51+
});
52+
});

common/utils/prop-utils.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// General utilities for dealing with component prop types
2+
import pickBy from 'lodash/pickBy';
3+
4+
export function getPropsStartingWith(string, props) {
5+
return pickBy(props, (value, key) => key.startsWith(string));
6+
}
7+
8+
export function getDataAttributes(props) {
9+
return getPropsStartingWith('data-', props);
10+
}
11+
12+
export function getAriaAttributes(props) {
13+
return getPropsStartingWith('aria-', props);
14+
}

components/Cards/ImageCard/__tests__/__snapshots__/ImageCard.test.js.snap

+2
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ exports[`ImageCard should render properly with some props assigned 1`] = `
4343
}
4444
}
4545
className=""
46+
datum=""
4647
disabled={false}
4748
fullWidth={false}
4849
href="https://www.testlink.com"
50+
onClick={[Function]}
4951
tabIndex={0}
5052
theme="primary"
5153
type="button"

components/Press/CivicXBadge/CivicXBadge.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ CivicXBadge.defaultProps = {
1111
sourceUrl: 'http://cvcx.org/veterans-solutions-lab/',
1212
};
1313

14-
function CivicXBadge({ sourceUrl = 'http://cvcx.org/veterans-solutions-lab/' }) {
14+
function CivicXBadge({ sourceUrl }) {
1515
return (
1616
<div>
1717
<OutboundLink
18+
hasIcon={false}
1819
href={sourceUrl}
1920
analyticsEventLabel={`[CivicX Accelerator Badge] ${sourceUrl}`}
2021
>

components/Press/CivicXBadge/__tests__/__snapshots__/CivicXBadge.test.js.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ exports[`CivicXBadge it should render properly no props 1`] = `
55
<OutboundLink
66
analyticsEventLabel="[CivicX Accelerator Badge] http://cvcx.org/veterans-solutions-lab/"
77
className=""
8-
hasIcon={true}
8+
hasIcon={false}
99
href="http://cvcx.org/veterans-solutions-lab/"
1010
>
1111
<img
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.articlesGroup > h2 {
2+
text-align: center;
3+
}
4+
5+
.articlesGroup {
6+
max-width: 375px;
7+
padding-top: 15px;
8+
}
9+
10+
.articlesGroup .areAllLinksVisibleButton {
11+
min-width: 100px;
12+
line-height: 0.5;
13+
font-size: 0.9rem;
14+
margin: auto;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import React, { Component } from 'react';
2+
import PropTypes from 'prop-types';
3+
import OutboundLink from 'components/_common_/OutboundLink/OutboundLink';
4+
import Button from 'components/_common_/Button/Button';
5+
import styles from './ArticleGroup.css';
6+
7+
class ArticleGroup extends Component {
8+
static propTypes = {
9+
articles: PropTypes.arrayOf(
10+
PropTypes.shape({
11+
title: PropTypes.string.isRequired,
12+
url: PropTypes.string.isRequired,
13+
}),
14+
).isRequired,
15+
numberOfInitiallyVisibleLinks: PropTypes.number.isRequired,
16+
region: PropTypes.string.isRequired,
17+
};
18+
19+
state = {
20+
areAllLinksVisible: false,
21+
};
22+
23+
clickHandler = () => {
24+
this.setState(prevState => ({ areAllLinksVisible: !prevState.areAllLinksVisible }));
25+
};
26+
27+
render() {
28+
const { areAllLinksVisible } = this.state;
29+
const { articles, region, numberOfInitiallyVisibleLinks } = this.props;
30+
return (
31+
<div className={styles.articlesGroup}>
32+
<h2>{region}</h2>
33+
<ul>
34+
{articles.map((link, index) => {
35+
const isArticleVisible = areAllLinksVisible || index < numberOfInitiallyVisibleLinks;
36+
37+
return isArticleVisible ? (
38+
<li key={`GroupLink_${link.url}`}>
39+
<OutboundLink
40+
href={link.url}
41+
analyticsEventLabel="Press Article"
42+
>
43+
{link.title}
44+
</OutboundLink>
45+
</li>
46+
) : null;
47+
})}
48+
</ul>
49+
{articles.length > numberOfInitiallyVisibleLinks && (
50+
<Button
51+
aria-pressed={areAllLinksVisible}
52+
className={styles.areAllLinksVisibleButton}
53+
theme={areAllLinksVisible ? 'slate' : 'primary'}
54+
onClick={this.clickHandler}
55+
>
56+
{areAllLinksVisible ? 'Show Less' : 'Show All'}
57+
</Button>
58+
)}
59+
</div>
60+
);
61+
}
62+
}
63+
64+
export default ArticleGroup;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import React from 'react';
2+
import createShallowSnapshotTest from 'test-utils/createShallowSnapshotTest';
3+
import { mount, shallow } from 'enzyme';
4+
5+
import ArticleGroup from '../ArticleGroup';
6+
7+
describe('ArticleGroup', () => {
8+
test('should render properly with required props', () =>
9+
createShallowSnapshotTest(
10+
<ArticleGroup
11+
region="test"
12+
articles={[{ title: 'Example', url: 'https://example.com' }]}
13+
numberOfInitiallyVisibleLinks={1}
14+
/>,
15+
));
16+
17+
test('should render properly with required props and 3 links and a button', () =>
18+
createShallowSnapshotTest(
19+
<ArticleGroup
20+
region="test"
21+
articles={[
22+
{ title: 'Example', url: 'https://example.com' },
23+
{ title: 'Example', url: 'https://example.com' },
24+
{ title: 'Example', url: 'https://example.com' },
25+
]}
26+
numberOfInitiallyVisibleLinks={1}
27+
/>,
28+
));
29+
30+
test('should setState when clicking Show All button', () => {
31+
const ArticleGroupShallowInstance = shallow(
32+
<ArticleGroup
33+
region="test"
34+
articles={[
35+
{ title: 'Example', url: 'https://example.com' },
36+
{ title: 'Example', url: 'https://example.com' },
37+
{ title: 'Example', url: 'https://example.com' },
38+
]}
39+
numberOfInitiallyVisibleLinks={1}
40+
/>,
41+
);
42+
43+
ArticleGroupShallowInstance.instance().clickHandler();
44+
45+
expect(ArticleGroupShallowInstance.state().areAllLinksVisible).toEqual(true);
46+
});
47+
48+
test('should not create a button if not enough links', () => {
49+
const wrap = mount(
50+
<ArticleGroup
51+
region="test"
52+
articles={[{ title: 'Example', url: 'https://example.com' }]}
53+
numberOfInitiallyVisibleLinks={5}
54+
/>,
55+
);
56+
57+
expect(wrap.find('button').exists()).toEqual(false);
58+
});
59+
60+
test('should create a button if enough links are available', () => {
61+
const wrap = mount(
62+
<ArticleGroup
63+
region="test"
64+
articles={[
65+
{ title: 'Example', url: 'https://example.com' },
66+
{ title: 'Example', url: 'https://example.com' },
67+
{ title: 'Example', url: 'https://example.com' },
68+
]}
69+
numberOfInitiallyVisibleLinks={1}
70+
/>,
71+
);
72+
73+
expect(wrap.find('button').exists()).toEqual(true);
74+
});
75+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`ArticleGroup should render properly with required props 1`] = `
4+
<div
5+
className="articlesGroup"
6+
>
7+
<h2>
8+
test
9+
</h2>
10+
<ul>
11+
<li>
12+
<OutboundLink
13+
analyticsEventLabel="Press Article"
14+
className=""
15+
hasIcon={true}
16+
href="https://example.com"
17+
>
18+
Example
19+
</OutboundLink>
20+
</li>
21+
</ul>
22+
</div>
23+
`;
24+
25+
exports[`ArticleGroup should render properly with required props and 3 links and a button 1`] = `
26+
<div
27+
className="articlesGroup"
28+
>
29+
<h2>
30+
test
31+
</h2>
32+
<ul>
33+
<li>
34+
<OutboundLink
35+
analyticsEventLabel="Press Article"
36+
className=""
37+
hasIcon={true}
38+
href="https://example.com"
39+
>
40+
Example
41+
</OutboundLink>
42+
</li>
43+
</ul>
44+
<Button
45+
analyticsObject={
46+
Object {
47+
"action": "Button Selected",
48+
"category": "Interactions",
49+
}
50+
}
51+
aria-pressed={false}
52+
className="areAllLinksVisibleButton"
53+
datum=""
54+
disabled={false}
55+
fullWidth={false}
56+
onClick={[Function]}
57+
tabIndex={0}
58+
theme="primary"
59+
type="button"
60+
>
61+
Show All
62+
</Button>
63+
</div>
64+
`;

0 commit comments

Comments
 (0)