diff --git a/common/styles/globalStyles.css b/common/styles/globalStyles.css index 8235db7d2..7db8d3d29 100644 --- a/common/styles/globalStyles.css +++ b/common/styles/globalStyles.css @@ -28,6 +28,7 @@ body { line-height: 1.5; hyphens: none; margin: 0; + min-width: 300px; } h1, diff --git a/common/utils/__tests__/prop-utils.test.js b/common/utils/__tests__/prop-utils.test.js new file mode 100644 index 000000000..5c5e21365 --- /dev/null +++ b/common/utils/__tests__/prop-utils.test.js @@ -0,0 +1,52 @@ +/* eslint-env jest */ +import { getPropsStartingWith, getDataAttributes, getAriaAttributes } from '../prop-utils'; + +describe('getPropsStartingWith', () => { + test('should return the props that start with the given string', () => { + const props = { + 'test-1': 'test', + 'test-2': 'test 2', + 'another-prop': 'test 3', + }; + + const result = getPropsStartingWith('test-', props); + expect(result).toEqual({ + 'test-1': 'test', + 'test-2': 'test 2', + }); + }); +}); + +describe('getDataAttributes', () => { + test('should return only the props that start with `data-`', () => { + const props = { + 'data-ci': 'ci', + 'data-gtm': 'gtm', + children: 'test children', + }; + + const result = getDataAttributes(props); + + expect(result).toEqual({ + 'data-ci': 'ci', + 'data-gtm': 'gtm', + }); + }); +}); + +describe('getAriaAttributes', () => { + test('should return only the props that start with `aria-`', () => { + const props = { + 'aria-label': 'a11y rocks!', + 'aria-checked': 'true', + children: 'test children', + }; + + const result = getAriaAttributes(props); + + expect(result).toEqual({ + 'aria-label': 'a11y rocks!', + 'aria-checked': 'true', + }); + }); +}); diff --git a/common/utils/prop-utils.js b/common/utils/prop-utils.js new file mode 100644 index 000000000..4313dd0fe --- /dev/null +++ b/common/utils/prop-utils.js @@ -0,0 +1,14 @@ +// General utilities for dealing with component prop types +import pickBy from 'lodash/pickBy'; + +export function getPropsStartingWith(string, props) { + return pickBy(props, (value, key) => key.startsWith(string)); +} + +export function getDataAttributes(props) { + return getPropsStartingWith('data-', props); +} + +export function getAriaAttributes(props) { + return getPropsStartingWith('aria-', props); +} diff --git a/components/Cards/ImageCard/__tests__/__snapshots__/ImageCard.test.js.snap b/components/Cards/ImageCard/__tests__/__snapshots__/ImageCard.test.js.snap index e902876ee..9674e2a80 100644 --- a/components/Cards/ImageCard/__tests__/__snapshots__/ImageCard.test.js.snap +++ b/components/Cards/ImageCard/__tests__/__snapshots__/ImageCard.test.js.snap @@ -43,9 +43,11 @@ exports[`ImageCard should render properly with some props assigned 1`] = ` } } className="" + datum="" disabled={false} fullWidth={false} href="https://www.testlink.com" + onClick={[Function]} tabIndex={0} theme="primary" type="button" diff --git a/components/Press/CivicXBadge/CivicXBadge.js b/components/Press/CivicXBadge/CivicXBadge.js index 029db9e67..d4cb42fe7 100644 --- a/components/Press/CivicXBadge/CivicXBadge.js +++ b/components/Press/CivicXBadge/CivicXBadge.js @@ -11,10 +11,11 @@ CivicXBadge.defaultProps = { sourceUrl: 'http://cvcx.org/veterans-solutions-lab/', }; -function CivicXBadge({ sourceUrl = 'http://cvcx.org/veterans-solutions-lab/' }) { +function CivicXBadge({ sourceUrl }) { return (
diff --git a/components/Press/CivicXBadge/__tests__/__snapshots__/CivicXBadge.test.js.snap b/components/Press/CivicXBadge/__tests__/__snapshots__/CivicXBadge.test.js.snap index 1c6728818..de178224c 100644 --- a/components/Press/CivicXBadge/__tests__/__snapshots__/CivicXBadge.test.js.snap +++ b/components/Press/CivicXBadge/__tests__/__snapshots__/CivicXBadge.test.js.snap @@ -5,7 +5,7 @@ exports[`CivicXBadge it should render properly no props 1`] = ` h2 { + text-align: center; +} + +.articlesGroup { + max-width: 375px; + padding-top: 15px; +} + +.articlesGroup .areAllLinksVisibleButton { + min-width: 100px; + line-height: 0.5; + font-size: 0.9rem; + margin: auto; +} diff --git a/components/Press/PressLinks/ArticleGroup/ArticleGroup.js b/components/Press/PressLinks/ArticleGroup/ArticleGroup.js new file mode 100644 index 000000000..f598ec0d6 --- /dev/null +++ b/components/Press/PressLinks/ArticleGroup/ArticleGroup.js @@ -0,0 +1,64 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import OutboundLink from 'components/_common_/OutboundLink/OutboundLink'; +import Button from 'components/_common_/Button/Button'; +import styles from './ArticleGroup.css'; + +class ArticleGroup extends Component { + static propTypes = { + articles: PropTypes.arrayOf( + PropTypes.shape({ + title: PropTypes.string.isRequired, + url: PropTypes.string.isRequired, + }), + ).isRequired, + numberOfInitiallyVisibleLinks: PropTypes.number.isRequired, + region: PropTypes.string.isRequired, + }; + + state = { + areAllLinksVisible: false, + }; + + clickHandler = () => { + this.setState(prevState => ({ areAllLinksVisible: !prevState.areAllLinksVisible })); + }; + + render() { + const { areAllLinksVisible } = this.state; + const { articles, region, numberOfInitiallyVisibleLinks } = this.props; + return ( +
+

{region}

+
    + {articles.map((link, index) => { + const isArticleVisible = areAllLinksVisible || index < numberOfInitiallyVisibleLinks; + + return isArticleVisible ? ( +
  • + + {link.title} + +
  • + ) : null; + })} +
+ {articles.length > numberOfInitiallyVisibleLinks && ( + + )} +
+ ); + } +} + +export default ArticleGroup; diff --git a/components/Press/PressLinks/ArticleGroup/__tests__/ArticleGroup.test.js b/components/Press/PressLinks/ArticleGroup/__tests__/ArticleGroup.test.js new file mode 100644 index 000000000..d0d1618c4 --- /dev/null +++ b/components/Press/PressLinks/ArticleGroup/__tests__/ArticleGroup.test.js @@ -0,0 +1,75 @@ +import React from 'react'; +import createShallowSnapshotTest from 'test-utils/createShallowSnapshotTest'; +import { mount, shallow } from 'enzyme'; + +import ArticleGroup from '../ArticleGroup'; + +describe('ArticleGroup', () => { + test('should render properly with required props', () => + createShallowSnapshotTest( + , + )); + + test('should render properly with required props and 3 links and a button', () => + createShallowSnapshotTest( + , + )); + + test('should setState when clicking Show All button', () => { + const ArticleGroupShallowInstance = shallow( + , + ); + + ArticleGroupShallowInstance.instance().clickHandler(); + + expect(ArticleGroupShallowInstance.state().areAllLinksVisible).toEqual(true); + }); + + test('should not create a button if not enough links', () => { + const wrap = mount( + , + ); + + expect(wrap.find('button').exists()).toEqual(false); + }); + + test('should create a button if enough links are available', () => { + const wrap = mount( + , + ); + + expect(wrap.find('button').exists()).toEqual(true); + }); +}); diff --git a/components/Press/PressLinks/ArticleGroup/__tests__/__snapshots__/ArticleGroup.test.js.snap b/components/Press/PressLinks/ArticleGroup/__tests__/__snapshots__/ArticleGroup.test.js.snap new file mode 100644 index 000000000..458a90fb7 --- /dev/null +++ b/components/Press/PressLinks/ArticleGroup/__tests__/__snapshots__/ArticleGroup.test.js.snap @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ArticleGroup should render properly with required props 1`] = ` +
+

+ test +

+
    +
  • + + Example + +
  • +
+
+`; + +exports[`ArticleGroup should render properly with required props and 3 links and a button 1`] = ` +
+

+ test +

+
    +
  • + + Example + +
  • +
+ +
+`; diff --git a/components/Press/PressLinks/Articles.js b/components/Press/PressLinks/Articles.js new file mode 100644 index 000000000..603f6d680 --- /dev/null +++ b/components/Press/PressLinks/Articles.js @@ -0,0 +1,211 @@ +const Boston = [ + { + title: 'How Tech Pros Can Volunteer in Fun Ways', + url: 'https://insights.dice.com/2017/01/11/tech-pros-volunteer-fun-ways/', + }, + { + title: 'MassChallenge Finalists: Finnest, Operation Code, Sunrise Health', + url: + 'https://www.necn.com/news/business/MassChallenge-Finnest_-Operation-Code_-Sunrise-Health_NECN-441063423.html', + }, + { + title: 'TechBreakfast at Microsoft NERD', + url: 'http://www.wickedbandwidth.com/02072017-techbreakfast-microsoft-nerd/', + }, + { + title: 'Operation Code - #BNT80 Boston New Technology Startup Demo', + url: 'https://www.youtube.com/watch?v=YGaG_HL3oEQ', + }, + { + title: 'MassChallenge Finalist | Operation Code | Conrad Hollomon', + url: 'https://www.youtube.com/watch?v=GcvVsVsH-Gg', + }, + { + title: 'Operation Code – Creating a Coding Community with Veterans and Citizens', + url: + 'https://venturefizz.com/stories/boston/operation-code-creating-coding-community-veterans-and-citizens', + }, + { + title: 'Innovation Spotlight: Operation Code', + url: 'https://www.deepcoredata.com/innovation-spotlight-veterans-mission-operation-code/', + }, + { + title: 'tech4vets Masschallenge Veterans', + url: 'https://blogs.microsoft.com/newengland/2017/11/10/tech4vets-masschallenge-veterans/', + }, +]; + +const General = [ + { + title: 'TechHire Educator Spotlight: Operation Code', + url: + 'https://blog.opportunityatwork.org/techhire-educator-spotlight-operation-code-debd0a796f9d', + }, + { + title: 'Why Veterans Will Make Excellent Programmers', + url: 'https://www.switchup.org/blog/why-veterans-will-make-excellent-programmers', + }, + { + title: 'THOUSANDS OF VETERANS WANT TO LEARN TO CODE — BUT CAN’T', + url: 'https://www.wired.com/story/thousands-of-veterans-want-to-learn-to-code-but-cant/', + }, + { + title: 'Hacking Entrepreneurship — An Interview with David Molina of Operation Code', + url: + 'https://medium.com/the-hum/hacking-entrepreneurship-an-interview-with-david-molina-of-operation-code-12a7e199e4e0', + }, + { + title: 'A Marine Vet’s Path into Coding Brings Him Back Home', + url: + 'https://medium.com/operation-code/a-marine-vets-path-into-coding-brings-him-back-home-4fcf5645d740', + }, + { + title: 'Operation Code: Connecting Veterans with Code Skills', + url: 'http://blog.teamtreehouse.com/operation-code-connecting-veterans-with-code', + }, + { + title: 'Operation Code: connecting tech and veterans', + url: 'https://blog.github.com/2016-11-11-operation-code-connecting-tech-and-veterans/', + }, + { + title: + 'When the call of duty is technology, veterans rally to support each other through Operation Code', // eslint-disable-line + url: + 'https://www.geekwire.com/2016/call-duty-technology-veterans-rally-support-operation-code/', + }, + { + title: 'Get Coding Now with Operation Code Army Veteran and Founder David Molina', + url: 'https://www.youtube.com/watch?v=qoy7scC2SHk', + }, + { + title: 'The New Developer - Operation Code - GitHub Universe 2016', + url: 'https://www.youtube.com/watch?v=xN7yMoe38xc', + }, + { + title: 'What happens when military veterans learn to code - CodeConf 2016', + url: 'https://www.youtube.com/watch?v=-wSwlLeKFdE', + }, + { + title: 'How Operation Code helps veterans learn programming skills', + url: 'https://opensource.com/article/17/4/operation-code-mentors-veterans', + }, + { + title: 'Helping Veterans Learn to Code with David Molina', + url: + 'https://softwareengineeringdaily.com/2016/03/20/helping-veterans-learn-code-david-molina/', + }, + { + title: 'Podcast: a developing story as told by developers', + url: 'https://developingstory.netlify.com/tds-66-david-molina-from-operation-code', + }, + { + title: 'Instagram: David Molina', + url: 'https://www.instagram.com/p/21p5bFxUjd/?taken-by=davidcmolina', + }, + { + title: 'From Aviation Electrician to Back End Engineering: Bret Funk’s Operation Code story', + url: + 'http://blog.teamtreehouse.com/from-aviation-electrician-to-back-end-engineering-bret-funk-operation-code-story', + }, + { + title: 'Navy Veteran to Software Developer: Geno Guerrero’s Operation Code Story', + url: + 'http://blog.teamtreehouse.com/navy-veteran-to-software-developer-geno-guerreros-operation-code-story', + }, + { + title: 'From Marine Corps Veteran to Front End Developer: Billy Le’s Operation Code Story', + url: 'http://blog.teamtreehouse.com/marine-corps-veteran-front-end-developer-billy-le', + }, + { + title: 'Few Options For Veterans Looking To Enter Tech', + url: 'https://techcrunch.com/2015/11/11/few-options-for-veterans-looking-to-enter-tech/', + }, + { + title: "Coding Boot Camps Go After Veterans To Take Silicon Valley's Vacant Tech Jobs", + url: + 'https://www.ibtimes.com/coding-boot-camps-go-after-veterans-take-silicon-valleys-vacant-tech-jobs-2174421', + }, + { + title: '20 Diversity and Inclusion Leaders to Follow in 2018', + url: 'https://www.makeschool.com/blog/20-diversity-and-inclusion-leaders-to-follow-in-2018', + }, + { + title: 'Tech innovation meets military service: GeekWire’s Memorial Day remembrance and update', + url: + 'http://bitshare.cm/news/tech-innovation-meets-military-service-geekwires-memorial-day-remembrance-and-update/', + }, + { + title: "MAP HOSTS CONGRESSIONAL BRIEFING ON VETERANS' READINESS IN TECH CAREERS", + url: 'https://www.millennialaction.org/press-archives/vetstechpr', + }, + { + title: "Analytics Pros, Inc. Hosts Training for Veterans and Veterans' Spouses", + url: + 'https://www.advfn.com/news_Analytics-Pros-Inc-Hosts-Training-for-Veterans-a_72657464.html', + }, + { + title: 'Episode 36 – How to pick a programming language to learn for new developers – Part 2', + url: + 'http://mentoringdevelopers.com/episode-36-how-to-pick-a-programming-language-to-learn-for-new-developers-part-2/', + }, + { + title: 'How to “upskill” Veterans’ training for technology jobs', + url: 'https://www.blogs.va.gov/VAntage/33028/upskill-veterans-training-technology-jobs/', + }, + { + title: 'Instagram: Operation Code made the front cover of Oregon Veterans News Magazine', + url: 'https://www.instagram.com/p/BbZT3Q-BBDC/', + }, + { + title: 'Jameel: From Marines to SoftwareEngineer', + url: 'https://blog.sabio.la/jameel-from-jarhead-to-softwareengineer-9130702da5c1', + }, + { + title: 'Seattle coding-school tuition to be covered by GI Bill', + url: + 'https://www.seattletimes.com/business/technology/seattles-code-fellows-wins-approval-under-gi-bill/', + }, + { + title: 'Veteran: GI Bill should cover code school', + url: + 'https://www.koin.com/news/veteran-gi-bill-should-cover-code-school_20180208085618706/960235415', + }, + { + title: + 'Patriot Boot Camp And Operation Code Join Forces To Help Military Veterans Become Technology Entrepreneurs', // eslint-disable-line + url: 'http://patriotbootcamp.org/blog/operation-code', + }, + { + title: 'Operation Code wants veterans to work in tech', + url: 'http://www.maswired.com/operation-code-wants-veterans-to-work-in-tech/', + }, + { + title: 'Coding Bootcamps Accepts GI Bill', + url: 'http://diversemilitary.net/2017/06/27/coding-bootcamps-accepts-gi-bill/', + }, + { + title: 'Operation Code Looks to Help Veterans Land IT Careers', + url: + 'https://news.clearancejobs.com/2017/07/17/operation-code-looks-help-veterans-land-careers/', + }, +]; + +const NYC = [ + { + title: 'New program aims to help veterans land jobs in tech industry', + url: + 'https://wtkr.com/2018/05/16/new-program-aims-to-help-veterans-land-jobs-in-tech-industry/', + }, + { + title: 'Veterans in Residence', + url: + 'http://www.wdtv.com/content/news/Veterans-in-Residence-program-helping-veterans-grow-businesses-482707221.html', + }, + { + title: 'After Flying Solo, Veterans Find Others Who Have Their Backs', + url: + 'https://www.wework.com/blog/posts/after-flying-solo-veterans-find-others-who-have-their-back', + }, +]; + +export { NYC, Boston, General }; diff --git a/components/Press/PressLinks/PressLinks.css b/components/Press/PressLinks/PressLinks.css new file mode 100644 index 000000000..cdd729881 --- /dev/null +++ b/components/Press/PressLinks/PressLinks.css @@ -0,0 +1,12 @@ +.logos a { + color: #249cbc; + text-decoration: none; +} + +.logos .flexContainer { + width: 100%; + display: flex; + flex-flow: row wrap; + justify-content: space-around; + padding: 15px 0 0 0; +} diff --git a/components/Press/PressLinks/PressLinks.js b/components/Press/PressLinks/PressLinks.js new file mode 100644 index 000000000..f1fed54ec --- /dev/null +++ b/components/Press/PressLinks/PressLinks.js @@ -0,0 +1,32 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styles from './PressLinks.css'; +import * as Articles from './Articles'; +import ArticleGroup from './ArticleGroup/ArticleGroup'; + +PressLinks.propTypes = { + numberOfInitiallyVisibleLinks: PropTypes.number, +}; + +PressLinks.defaultProps = { + numberOfInitiallyVisibleLinks: 5, +}; + +function PressLinks({ numberOfInitiallyVisibleLinks }) { + return ( +
+
+ {Object.keys(Articles).map(region => ( + + ))} +
+
+ ); +} + +export default PressLinks; diff --git a/components/Press/PressLinks/__tests__/PressLinks.test.js b/components/Press/PressLinks/__tests__/PressLinks.test.js new file mode 100644 index 000000000..10f6a9334 --- /dev/null +++ b/components/Press/PressLinks/__tests__/PressLinks.test.js @@ -0,0 +1,8 @@ +import React from 'react'; +import createShallowSnapshotTest from 'test-utils/createShallowSnapshotTest'; + +import PressLinks from '../PressLinks'; + +describe('PressLinks', () => { + test('it should render properly no props', () => createShallowSnapshotTest()); +}); diff --git a/components/Press/PressLinks/__tests__/__snapshots__/PressLinks.test.js.snap b/components/Press/PressLinks/__tests__/__snapshots__/PressLinks.test.js.snap new file mode 100644 index 000000000..9ca681fcc --- /dev/null +++ b/components/Press/PressLinks/__tests__/__snapshots__/PressLinks.test.js.snap @@ -0,0 +1,216 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PressLinks it should render properly no props 1`] = ` +
+
+ + + +
+
+`; diff --git a/components/Press/PressPhotos/PressPhotos.css b/components/Press/PressPhotos/PressPhotos.css index 9e13ea10d..83227f96f 100644 --- a/components/Press/PressPhotos/PressPhotos.css +++ b/components/Press/PressPhotos/PressPhotos.css @@ -7,18 +7,13 @@ } .photos > img { + max-width: 350px; width: auto; - max-height: 368px; + padding: 0.75rem; } -@media screen and (min-width: 415px) and (max-width: 1280px) { +@media screen and (max-width: 499px) { .photos > img { - width: 350px; - } -} - -@media screen and (max-width: 414px) { - .photos > img { - width: 300px; + width: 100%; } } diff --git a/components/Press/PressVideos/PressVideos.css b/components/Press/PressVideos/PressVideos.css index 00a868a6a..a336a8663 100644 --- a/components/Press/PressVideos/PressVideos.css +++ b/components/Press/PressVideos/PressVideos.css @@ -13,21 +13,19 @@ /* Video iFrame Media Queries */ @media screen and (max-width: 960px) { .pressVideos iframe { - width: 666px; + width: 100%; height: 375px; } } @media screen and (max-width: 720px) { .pressVideos iframe { - width: 444px; height: 250px; } } @media screen and (max-width: 480px) { .pressVideos iframe { - width: 333px; height: 187.5px; } } diff --git a/components/Press/index.js b/components/Press/index.js index d2ea20b03..8a480c698 100644 --- a/components/Press/index.js +++ b/components/Press/index.js @@ -1,5 +1,6 @@ import CivicXBadge from './CivicXBadge/CivicXBadge'; import Photos from './PressPhotos/PressPhotos'; import Videos from './PressVideos/PressVideos'; +import Links from './PressLinks/PressLinks'; -export { CivicXBadge, Photos, Videos }; +export { CivicXBadge, Photos, Videos, Links }; diff --git a/components/ReusableSections/DonateSection/__tests__/__snapshots__/DonateSection.test.js.snap b/components/ReusableSections/DonateSection/__tests__/__snapshots__/DonateSection.test.js.snap index 6ae56b30e..0065e9a9e 100644 --- a/components/ReusableSections/DonateSection/__tests__/__snapshots__/DonateSection.test.js.snap +++ b/components/ReusableSections/DonateSection/__tests__/__snapshots__/DonateSection.test.js.snap @@ -32,8 +32,10 @@ exports[`DonateSection should render properly with no props 1`] = ` } } className="" + datum="" disabled={false} fullWidth={false} + onClick={[Function]} tabIndex={0} theme="primary" type="button" diff --git a/components/ReusableSections/JoinSection/__tests__/__snapshots__/JoinSection.test.js.snap b/components/ReusableSections/JoinSection/__tests__/__snapshots__/JoinSection.test.js.snap index 3c11ac58d..eaa1da125 100644 --- a/components/ReusableSections/JoinSection/__tests__/__snapshots__/JoinSection.test.js.snap +++ b/components/ReusableSections/JoinSection/__tests__/__snapshots__/JoinSection.test.js.snap @@ -31,8 +31,10 @@ exports[`JoinSection it should render properly with no props 1`] = ` } } className="" + datum="" disabled={false} fullWidth={false} + onClick={[Function]} tabIndex={0} theme="secondary" type="button" diff --git a/components/ReusableSections/SignUpSection/__tests__/__snapshots__/SignUpSection.test.js.snap b/components/ReusableSections/SignUpSection/__tests__/__snapshots__/SignUpSection.test.js.snap index 6d310a595..2766f0fef 100644 --- a/components/ReusableSections/SignUpSection/__tests__/__snapshots__/SignUpSection.test.js.snap +++ b/components/ReusableSections/SignUpSection/__tests__/__snapshots__/SignUpSection.test.js.snap @@ -21,8 +21,10 @@ exports[`SignUpSection it should render properly with no props 1`] = ` } } className="" + datum="" disabled={false} fullWidth={false} + onClick={[Function]} tabIndex={0} theme="secondary" type="button" diff --git a/components/_common_/Button/Button.js b/components/_common_/Button/Button.js index 8e8942207..f93b9d912 100644 --- a/components/_common_/Button/Button.js +++ b/components/_common_/Button/Button.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import ReactGA from 'react-ga'; import { googleAnalyticsEventPropType } from 'common/constants/custom-props'; +import { getDataAttributes, getAriaAttributes } from 'common/utils/prop-utils'; import styles from './Button.css'; class Button extends Component { @@ -16,17 +17,19 @@ class Button extends Component { tabIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), theme: PropTypes.oneOf(['primary', 'secondary', 'slate']), type: PropTypes.oneOf(['button', 'reset', 'submit']), + datum: PropTypes.any, // eslint-disable-line react/forbid-prop-types }; static defaultProps = { analyticsObject: { - category: 'Interactions', action: 'Button Selected', + category: 'Interactions', }, className: '', + datum: '', disabled: false, fullWidth: false, - onClick: undefined, + onClick: () => {}, tabIndex: 0, theme: 'primary', type: 'button', @@ -41,13 +44,13 @@ class Button extends Component { // eslint-disable-next-line no-console console.log('Analytics Disabled', props.analyticsObject); } - - return props.onClick; + props.onClick(); }; render() { const { props } = this; - + const customDataAttributes = getDataAttributes(props); + const ariaAttributes = getAriaAttributes(props); /* eslint-disable react/button-has-type */ return ( , ); }); + test('should spread data and aria props', () => { + const wrapper = shallow( + , + ); + expect(wrapper.prop('aria-label')).toEqual('test'); + expect(wrapper.prop('data-attr')).toEqual('test'); + }); + test('should render without a generated span when children is PropTypes.node', () => { const testText = 'Testing No Span'; @@ -64,6 +68,14 @@ describe('Button', () => { /* eslint-enable no-console */ }); + test('call props.onClick when button is clicked', () => { + const onClickMock = jest.fn(); + const ButtonShallowInstance = shallow(); + ButtonShallowInstance.instance().clickHandler(); + + expect(onClickMock).toHaveBeenCalledTimes(1); + }); + test('should call ReactGA when in prod environment', () => { /* eslint-disable no-console */ ReactGA.initialize('foo', { testMode: true }); diff --git a/components/_common_/Form/FormSelect/__tests__/FormSelect.test.js b/components/_common_/Form/FormSelect/__tests__/FormSelect.test.js index 680456012..23913374b 100644 --- a/components/_common_/Form/FormSelect/__tests__/FormSelect.test.js +++ b/components/_common_/Form/FormSelect/__tests__/FormSelect.test.js @@ -7,32 +7,22 @@ import FormSelect from '../FormSelect'; describe('FormSelect', () => { let options; - + beforeEach(() => { options = [{ label: 'test 1', value: 'TEST1' }, { label: 'test 2', value: 'TEST2' }]; }); - + test('should render with just required props passed', () => { createSnapshotTest(); }); - + test('should render when passed a prompt and options', () => { - createSnapshotTest( - , - ); + createSnapshotTest(); }); test('should call onChange from props after onChange', () => { const onChangeMock = jest.fn(); - const wrap = mount( - , - ); + const wrap = mount(); wrap.find('select').simulate('change', { target: { value: 'TEST1' }, }); @@ -48,7 +38,7 @@ describe('FormSelect', () => { e.target.value === 'TEST3'} - options={[ ...options, { label: 'test 3', value: 'TEST3' }]} + options={[...options, { label: 'test 3', value: 'TEST3' }]} />, ); wrap.find('select').simulate('change', { diff --git a/components/_common_/Form/FormTextArea/__tests__/FormTextArea.test.js b/components/_common_/Form/FormTextArea/__tests__/FormTextArea.test.js index 1d9fedb55..88f12fc18 100644 --- a/components/_common_/Form/FormTextArea/__tests__/FormTextArea.test.js +++ b/components/_common_/Form/FormTextArea/__tests__/FormTextArea.test.js @@ -9,7 +9,7 @@ describe('FormTextArea', () => { test('should render with just required props passed', () => { createSnapshotTest(); }); - + test('should render when passed a placeholder', () => { createSnapshotTest(); }); diff --git a/jest.config.js b/jest.config.js index 823a41bf7..c959b797c 100644 --- a/jest.config.js +++ b/jest.config.js @@ -44,6 +44,7 @@ module.exports = { '/common/utils/api-utils.js', '/components/FAQ/questions.js', '/components/ZipRecruiterJobs/ZipRecruiterJobs.js', + '/components/Press/PressLinks/Articles.js', // Ignore Next.js files '/components/head.js', diff --git a/pages/press.js b/pages/press.js index 8f12bfabf..012f2f66c 100644 --- a/pages/press.js +++ b/pages/press.js @@ -2,7 +2,7 @@ import React from 'react'; import Link from 'next/link'; import Head from 'components/head'; import Section from 'components/_common_/Section/Section'; -import { Videos, Photos, CivicXBadge } from 'components/Press'; +import { Videos, Photos, CivicXBadge, Links } from 'components/Press'; import styles from './styles/press.css'; export default () => ( @@ -77,21 +77,25 @@ export default () => (
-
+
-
+
-
+
+ +
+ +
View Our Branding
-
+
Operation Code is a graduate of the following startup accelerators:
diff --git a/pages/styles/press.css b/pages/styles/press.css index 527053e41..9aca78ddc 100644 --- a/pages/styles/press.css +++ b/pages/styles/press.css @@ -43,12 +43,7 @@ } .customContent { - display: -ms-flexbox; - display: flex; - flex-flow: column; - justify-content: space-between; align-items: center; - width: 80%; } .logos {