diff --git a/__tests__/Layout.test.js b/__tests__/Layout.test.js index a6d826b..b7a44fe 100644 --- a/__tests__/Layout.test.js +++ b/__tests__/Layout.test.js @@ -44,6 +44,7 @@ describe('Layout', () => { remaining: [patterns[1]], current: patterns[0] }, + intro: false, mode: 'light', js: 'es5' }); @@ -86,6 +87,7 @@ describe('Layout', () => { remaining: [patterns[1]], current: patterns[0] }, + intro: false, mode: 'dark', js: 'es5' }); diff --git a/__tests__/actions/actions.test.js b/__tests__/actions/actions.test.js index bd9ff0c..4b4a187 100644 --- a/__tests__/actions/actions.test.js +++ b/__tests__/actions/actions.test.js @@ -1,3 +1,4 @@ +import { start } from '../../src/actions/start'; import { restart } from '../../src/actions/restart'; import { submitAnswer } from '../../src/actions/submitAnswer'; import { toggle, toggleJS, toggleMode } from '../../src/actions/toggle'; @@ -6,10 +7,17 @@ import { TOGGLE, TOGGLE_JS, TOGGLE_MODE, + START, RESTART } from '../../src/static/constants/actions'; describe('Action Creators', () => { + it('should dispatch START action', () => { + expect(start('start')).toEqual({ + type: START, + payload: 'start' + }); + }); it('should dispatch RESTART action', () => { expect(restart('restart')).toEqual({ type: RESTART, diff --git a/__tests__/pages/Game.test.js b/__tests__/pages/Game.test.js index fd70fa6..9ae91c6 100644 --- a/__tests__/pages/Game.test.js +++ b/__tests__/pages/Game.test.js @@ -9,7 +9,7 @@ import { themeDark } from '../../src/styles/themes/theme.dark'; import styleLight from '../../src/styles/hljs/hljs.light'; import styleDark from '../../src/styles/hljs/hljs.dark'; import Game from '../../src/pages/Game'; -import { RESTART } from '../../src/static/constants/actions'; +import { START, RESTART } from '../../src/static/constants/actions'; const patterns = [ { @@ -43,6 +43,7 @@ const store = mockStore({ remaining: [patterns[1]], current: patterns[0] }, + intro: false, mode: 'light', js: 'es5' }); @@ -115,6 +116,41 @@ describe('Game page - GAME - DARK style', () => { }); }); +describe('Game page - INTRO', () => { + let tree; + const store = mockStore({ + patterns: patterns, + progress: { + answers: patterns, + remaining: [], + current: null + }, + intro: true, + mode: 'light', + js: 'es5' + }); + + beforeEach(() => { + tree = mount( + + + + + + ); + }); + + it('renders a component', () => { + expect(tree.find('Button')).toMatchSnapshot(); + }); + + it('reacts to button click', () => { + tree.find('button').simulate('click'); + const actions = store.getActions(); + expect(actions).toMatchObject([{ type: START }]); + }); +}); + describe('Game page - RESULTS', () => { let tree; const patterns = [ @@ -147,6 +183,7 @@ describe('Game page - RESULTS', () => { remaining: [], current: null }, + intro: false, mode: 'light', js: 'es5' }); diff --git a/__tests__/pages/__snapshots__/About.test.js.snap b/__tests__/pages/__snapshots__/About.test.js.snap index 330dda9..d2c9047 100644 --- a/__tests__/pages/__snapshots__/About.test.js.snap +++ b/__tests__/pages/__snapshots__/About.test.js.snap @@ -2,7 +2,7 @@ exports[`About page renders with a DARK theme 1`] = ` .c0 { - color: #F5F5F5; + color: #C8C8C8; } .c0 a { @@ -71,7 +71,7 @@ exports[`About page renders with a DARK theme 1`] = ` exports[`About page renders with a LIGHT theme 1`] = ` .c0 { - color: #0A000A; + color: #6F256F; } .c0 a { diff --git a/__tests__/pages/__snapshots__/Game.test.js.snap b/__tests__/pages/__snapshots__/Game.test.js.snap index f7d56cd..1b3ba8b 100644 --- a/__tests__/pages/__snapshots__/Game.test.js.snap +++ b/__tests__/pages/__snapshots__/Game.test.js.snap @@ -858,6 +858,119 @@ exports[`Game page - GAME - LIGHT style renders a component 1`] `; +exports[`Game page - INTRO renders a component 1`] = ` +.c0 { + background-color: #F2E8F2; + border: 1px solid #EDB8ED; + border-radius: 4px; + cursor: pointer; + font: 400 1rem 'Karla','sans-serif'; + height: 48px; + max-width: 240px; + outline: none; + padding: 0 1.5rem; + width: 37.5%; +} + +.c0 span { + color: #6F256F; +} + +.c0:hover { + background-color: #6F256F; + border-color: #6F256F; +} + +.c0:hover span { + color: #FFFFFF; +} + + + + + + + Start Game + + + + + +`; + exports[`Game page - RESULTS renders a component 1`] = ` .c0 { border: 4px solid red; @@ -958,7 +1071,7 @@ exports[`Game page - RESULTS renders a component 1`] = `null`; exports[`Game page - RESULTS renders a component 1`] = ` .c0 { - color: #0A000A; + color: #6F256F; margin: 3rem 0; text-align: center; } diff --git a/__tests__/reducers/reducers.test.js b/__tests__/reducers/reducers.test.js index a2ef218..7e9a6f1 100644 --- a/__tests__/reducers/reducers.test.js +++ b/__tests__/reducers/reducers.test.js @@ -4,6 +4,7 @@ import { TOGGLE, TOGGLE_JS, TOGGLE_MODE, + START, RESTART } from '../../src/static/constants/actions'; @@ -38,6 +39,7 @@ const initialState = { js: 'es5', mode: 'dark', patterns: answers, + intro: true, progress: { answers: [], remaining: answers, @@ -85,6 +87,17 @@ describe('Reducers', () => { }); }); + it('should toggle INTRO', () => { + const action = { + type: START + }; + + expect(reducer(initialState, action)).toEqual({ + ...initialState, + intro: false + }); + }); + it('should handle SUBMIT', () => { const action = { type: SUBMIT, diff --git a/__tests__/selectors/selectors.test.js b/__tests__/selectors/selectors.test.js index c28bf7b..2202ae4 100644 --- a/__tests__/selectors/selectors.test.js +++ b/__tests__/selectors/selectors.test.js @@ -4,7 +4,8 @@ import { getMode, getJS, getCurrent, - getAnswers + getAnswers, + getIntro } from '../../src/selectors'; describe('Selectors', () => { @@ -14,6 +15,7 @@ describe('Selectors', () => { state = { mode: 'dark', js: 'es6', + intro: true, patterns: [0, 1, 2, 3, 4, 5, 6], progress: { answers: [0, 1, 2], @@ -46,4 +48,8 @@ describe('Selectors', () => { it('should get the JS version', () => { expect(getJS(state)).toBe('es6'); }); + + it('should get the intro value', () => { + expect(getIntro(state)).toBe(true); + }); }); diff --git a/src/actions/start.js b/src/actions/start.js new file mode 100644 index 0000000..c50278f --- /dev/null +++ b/src/actions/start.js @@ -0,0 +1,6 @@ +import { START } from '../static/constants/actions'; + +export const start = payload => ({ + type: START, + payload +}); diff --git a/src/hoc/withThemeProvider.jsx b/src/hoc/withThemeProvider.jsx deleted file mode 100644 index b305ebd..0000000 --- a/src/hoc/withThemeProvider.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { compose } from 'redux'; -import { connect } from 'react-redux'; -import { ThemeProvider } from 'styled-components'; -import { themeLight } from '../styles/themes/theme.light'; -import { themeDark } from '../styles/themes/theme.dark'; - -const withThemeProvider = Component => { - const Sub = ({ mode, ...rest }) => ( - - - - ); - - Sub.propTypes = { - mode: PropTypes.string.isRequired - }; - - return Sub; -}; - -const mapStateToProps = ({ mode }) => ({ mode }); - -const composedWrapper = compose( - connect( - mapStateToProps, - null - ), - withThemeProvider -); - -export default composedWrapper; diff --git a/src/pages/Game.jsx b/src/pages/Game.jsx index b69f6c9..35b9939 100644 --- a/src/pages/Game.jsx +++ b/src/pages/Game.jsx @@ -2,8 +2,9 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; import { connect } from 'react-redux'; +import { start } from '../actions/start'; import { restart } from '../actions/restart'; -import { getCurrent, getAnswers } from '../selectors'; +import { getIntro, getCurrent, getAnswers } from '../selectors'; import ButtonContainer from '../components/ButtonContainer'; import ProgressBar from '../components/ProgressBar'; import Code from '../components/Code'; @@ -11,6 +12,19 @@ import Result from '../components/Result'; import Percentage from '../components/Percentage'; import Button from '../components/Button'; +const Intro = styled.div` + border: 1px solid ${props => props.theme.border}; + border-radius: 4px; + color: ${props => props.theme.text}; + margin: 2rem 0; + padding: 2rem 3rem; +`; + +const StartButtonContainer = styled.div` + margin: 3rem auto 1rem; + /* text-align: center; */ +`; + const Restart = styled.div` margin: 3rem 0; text-align: center; @@ -35,7 +49,7 @@ const ShareContainer = styled.p` text-align: center; `; -const Game = ({ current, answers, style, onRestart }) => { +const Game = ({ intro, current, answers, style, onStart, onRestart }) => { let correct; if (!current) { @@ -44,13 +58,29 @@ const Game = ({ current, answers, style, onRestart }) => { return ( - {current ? ( + {intro && ( + + + Each question contains a code snippet and four answer choices. + + Look carefully at the code and choose the one correct answer. + + After answering all 23 questions you'll be shown your results. + + + + + )} + + {!intro && current && ( - ) : ( + )} + + {!intro && !current && ( @@ -82,17 +112,21 @@ const Game = ({ current, answers, style, onRestart }) => { Game.propTypes = { style: PropTypes.object.isRequired, + onStart: PropTypes.func.isRequired, onRestart: PropTypes.func.isRequired, answers: PropTypes.array.isRequired, + intro: PropTypes.bool.isRequired, current: PropTypes.object }; export default connect( state => ({ + intro: getIntro(state), current: getCurrent(state), answers: getAnswers(state) }), { + onStart: () => start(), onRestart: () => restart() } )(Game); diff --git a/src/reducers/index.js b/src/reducers/index.js index aa12eff..67d9c35 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,4 +1,11 @@ -import { SUBMIT, TOGGLE, TOGGLE_JS, TOGGLE_MODE, RESTART } from '../static/constants/actions'; +import { + SUBMIT, + TOGGLE, + TOGGLE_JS, + TOGGLE_MODE, + START, + RESTART +} from '../static/constants/actions'; import { randomFromRange } from '../helpers/randomFromRange'; const rootReducer = (state, action) => { @@ -22,6 +29,8 @@ const rootReducer = (state, action) => { return { ...state, js: action.payload }; case TOGGLE_MODE: return { ...state, mode: action.payload }; + case START: + return { ...state, intro: false }; case RESTART: return { ...state, diff --git a/src/selectors/index.js b/src/selectors/index.js index c49930d..ba9e5ab 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -6,6 +6,8 @@ export const getMode = state => state.mode; export const getJS = state => state.js; +export const getIntro = state => state.intro; + export const getCurrent = state => state.progress.current; export const getAnswers = state => state.progress.answers; diff --git a/src/static/constants/actions.js b/src/static/constants/actions.js index e180e3c..7222394 100644 --- a/src/static/constants/actions.js +++ b/src/static/constants/actions.js @@ -2,4 +2,5 @@ export const SUBMIT = 'SUBMIT'; export const TOGGLE = 'TOGGLE'; export const TOGGLE_JS = 'TOGGLE_JS'; export const TOGGLE_MODE = 'TOGGLE_MODE'; +export const START = 'START'; export const RESTART = 'RESTART'; diff --git a/src/static/constants/colors.js b/src/static/constants/colors.js index 3f96a79..b1346ae 100644 --- a/src/static/constants/colors.js +++ b/src/static/constants/colors.js @@ -14,7 +14,6 @@ export const WILD_SAND = '#F5F5F5'; export const WHITE = '#FFFFFF'; // light theme -export const DIESEL = '#0A000A'; export const PLUM = '#6F256F'; export const BOUQUET = '#A568A5'; export const ORCHID = '#EDB8ED'; diff --git a/src/store/index.js b/src/store/index.js index 179d469..ef6999b 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -21,6 +21,7 @@ export const initialProgress = { const initialState = { js: 'es5', mode: 'dark', + intro: true, patterns: answers, progress: initialProgress }; diff --git a/src/styles/themes/theme.dark.js b/src/styles/themes/theme.dark.js index 3d6cb2e..8cea383 100644 --- a/src/styles/themes/theme.dark.js +++ b/src/styles/themes/theme.dark.js @@ -37,5 +37,7 @@ export const themeDark = { // text and header header: C.GRAY, - text: C.WILD_SAND + text: C.SILVER, + + border: C.TUNDORA }; diff --git a/src/styles/themes/theme.light.js b/src/styles/themes/theme.light.js index 43e0f49..4ba5b68 100644 --- a/src/styles/themes/theme.light.js +++ b/src/styles/themes/theme.light.js @@ -37,5 +37,7 @@ export const themeLight = { // text and header header: C.PLUM, - text: C.DIESEL + text: C.PLUM, + + border: C.PRIM };
+ Each question contains a code snippet and four answer choices. + + Look carefully at the code and choose the one correct answer. +
After answering all 23 questions you'll be shown your results.