Skip to content

Commit

Permalink
Console presentational component (#704)
Browse files Browse the repository at this point in the history
* make jest work again

* make initial console presentational component

* fix js doc string

* update yarn.lock file

* add babel-plugin-transform-class-properties

* Add IDEConsole component with LogEntries

* Allocate a larger area for the console

* Update snapshot tests

* Merge branch 'master' into console_component

* insert logs param

* Add shape for log entries proptypes

* Update snapshots for new array
  • Loading branch information
mrniket authored and OlafSzmidt committed Aug 2, 2018
1 parent 2937452 commit 9e9cc5a
Show file tree
Hide file tree
Showing 16 changed files with 1,146 additions and 280 deletions.
3 changes: 2 additions & 1 deletion game_frontend/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"alias": {
"features": "./src/redux/features"
}
}]
}],
"transform-class-properties"
]
}
1 change: 1 addition & 0 deletions game_frontend/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = {
'testURL': 'http://localhost/',
'setupTestFrameworkScriptFile': '<rootDir>/src/setupTests.js',
'snapshotSerializers': ['enzyme-to-json/serializer']
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ exports[`<GamePage /> matches snapshot 1`] = `
exports[`<GamePageLayout /> matches snapshot 1`] = `
.c0 {
display: grid;
grid-template: 80px 1fr 150px / 1fr 1fr;
grid-template: 80px 1fr 250px / 1fr 1fr;
grid-template-areas: "ide-menu game-menu" "ide-editor game-view" "ide-console game-view";
width: 100vw;
height: 100vh;
Expand Down
2 changes: 1 addition & 1 deletion game_frontend/src/components/GamePage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Game from 'components/Game'

export const GamePageLayout = styled.div`
display: grid
grid-template: 80px 1fr 150px / 1fr 1fr
grid-template: 80px 1fr 250px / 1fr 1fr
grid-template-areas: "ide-menu game-menu"
"ide-editor game-view"
"ide-console game-view";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ exports[`<IDE /> renders correctly 1`] = `
<React.Fragment>
<Connect(IDEMenu) />
<Connect(WithTheme(IDEEditor)) />
<styled.div />
<IDEConsole
logs={Array []}
/>
</React.Fragment>
`;
2 changes: 1 addition & 1 deletion game_frontend/src/components/IDE/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default class IDE extends Component {
<Fragment>
<IDEMenu />
<IDEEditor />
<IDEConsole />
<IDEConsole logs={[]} />
</Fragment>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,51 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<IDEConsole /> renders correctly 1`] = `
<styled.div
innerRef={[Function]}
>
<LogEntries
lastLogRef={[Function]}
logs={
Array [
Object {
"log": "hello",
"timestamp": "1",
},
Object {
"log": "bye",
"timestamp": 2,
},
]
}
/>
</styled.div>
`;

exports[`<StyledConsole /> renders correctly 1`] = `
.c0 {
background-color: #303030;
grid-area: ide-console;
color: #fff;
background-color: #303030;
font-family: 'Source Code Pro',monospace;
overflow: auto;
white-space: pre-line;
padding-bottom: 0px;
}
.c0::-webkit-scrollbar {
background-color: rgba(255,255,255,0.12);
}
.c0::-webkit-scrollbar-track {
background: rgba(255,255,255,0.12);
}
.c0::-webkit-scrollbar-thumb {
background: #aaaaaa;
border-radius: 100px;
border: 2px solid transparent;
background-clip: content-box;
}
<div
Expand Down
70 changes: 66 additions & 4 deletions game_frontend/src/components/IDEConsole/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,70 @@
import styled from 'styled-components'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import LogEntries from 'components/LogEntries'

export const IDEConsole = styled.div`
background-color: ${props => props.theme.palette.background.default}
grid-area: ide-console
export const StyledConsole = styled.div`
grid-area: ide-console;
color: ${props => props.theme.palette.text.primary};
background-color: ${props => props.theme.palette.background.default};
font-family: ${props => props.theme.additionalVariables.typography.code.fontFamily};
overflow: auto;
white-space: pre-line;
padding-bottom: 0px;
::-webkit-scrollbar {
background-color: ${props => props.theme.palette.divider};
}
::-webkit-scrollbar-track {
background: ${props => props.theme.palette.divider};
}
::-webkit-scrollbar-thumb {
background: ${props => props.theme.palette.grey['A200']};
border-radius: 100px;
border: ${props => props.theme.spacing.unit / 4}px solid transparent;
background-clip: content-box;
}
`

export default IDEConsole
export default class IDEConsole extends Component {
state = {
scrolledToBottom: true
}

handleScroll = event => {
let srcElement = event.srcElement
this.setState({...this.state, scrolledToBottom: srcElement.offsetHeight + srcElement.scrollTop === srcElement.scrollHeight})
}

componentDidMount () {
if (this.consoleRef) {
this.consoleRef.addEventListener('scroll', this.handleScroll)
}
}

componentWillUnmount () {
this.consoleRef.removeEventListener('scroll', this.handleScroll)
}

componentDidUpdate () {
if (this.lastLogRef && this.state.scrolledToBottom) {
this.lastLogRef.scrollIntoView(false)
}
}

render () {
return (
<StyledConsole innerRef={ref => { this.consoleRef = ref }}>
<LogEntries
logs={this.props.logs}
lastLogRef={ref => { this.lastLogRef = ref }} />
</StyledConsole>
)
}
}

IDEConsole.propTypes = {
logs: PropTypes.arrayOf(PropTypes.object)
}
11 changes: 9 additions & 2 deletions game_frontend/src/components/IDEConsole/index.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
/* eslint-env jest */
import React from 'react'
import IDEConsole from 'components/IDEConsole'
import IDEConsole, { StyledConsole } from 'components/IDEConsole'
import createShallowWithTheme from 'testHelpers/createShallow'

describe('<IDEConsole />', () => {
it('renders correctly', () => {
const tree = createShallowWithTheme(<IDEConsole />)
const tree = createShallowWithTheme(<IDEConsole logs={[{ timestamp: '1', log: 'hello' }, { timestamp: 2, log: 'bye' }]} />)
expect(tree).toMatchSnapshot()
})
})

describe('<StyledConsole />', () => {
it('renders correctly', () => {
const tree = createShallowWithTheme(<StyledConsole />)
expect(tree).toMatchSnapshot()
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<LogEntries /> renders correctly with logs 1`] = `
<styled.ul>
<styled.li
innerRef={[Function]}
key="1"
>
hello
</styled.li>
<styled.li
innerRef={[Function]}
key="2"
>
bye
</styled.li>
</styled.ul>
`;

exports[`<LogEntries /> renders correctly without logs 1`] = `<styled.ul />`;

exports[`<LogEntry /> renders correctly 1`] = `
.c0 {
list-style: none;
padding: 8px;
}
<li
className="c0"
>
hello
</li>
`;

exports[`<StyledLogEntries /> renders correctly 1`] = `
.c0 {
list-style: none;
margin: 0;
padding: 0;
}
<ul
className="c0"
/>
`;
53 changes: 53 additions & 0 deletions game_frontend/src/components/LogEntries/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import styled from 'styled-components'
import React, { Component } from 'react'
import PropTypes from 'prop-types'

export const LogEntry = styled.li`
list-style: none;
padding: ${props => props.theme.spacing.unit}px;
`

export const StyledLogEntries = styled.ul`
list-style: none;
margin: 0;
padding: 0;
`

export default class LogEntries extends Component {
generateLogEntries () {
const lastLogEntry = this.props.logs[this.props.logs.length - 1]
const logEntries = this.props.logs.map(logEntry =>
<LogEntry
key={logEntry.timestamp}
innerRef={this.setLastLogEntryRef(logEntry, lastLogEntry)}>
{logEntry.log}
</LogEntry>
)
return logEntries
}

setLastLogEntryRef (logEntry, lastLogEntry) {
return node => {
if (logEntry.timestamp === lastLogEntry.timestamp) {
this.props.lastLogRef(node)
}
}
}

render () {
return (
<StyledLogEntries>
{this.generateLogEntries()}
</StyledLogEntries>
)
}
}

LogEntries.propTypes = {
logs: PropTypes.arrayOf(
PropTypes.shape({
timestamp: PropTypes.int,
log: PropTypes.string
})),
lastLogRef: PropTypes.func
}
30 changes: 30 additions & 0 deletions game_frontend/src/components/LogEntries/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* eslint-env jest */
import React from 'react'
import LogEntries, { StyledLogEntries, LogEntry } from 'components/LogEntries'
import createShallowWithTheme from 'testHelpers/createShallow'

describe('<LogEntries />', () => {
it('renders correctly with logs', () => {
const tree = createShallowWithTheme(<LogEntries logs={[{ timestamp: '1', log: 'hello' }, { timestamp: 2, log: 'bye' }]} />)
expect(tree).toMatchSnapshot()
})

it('renders correctly without logs', () => {
const tree = createShallowWithTheme(<LogEntries logs={[]} />)
expect(tree).toMatchSnapshot()
})
})

describe('<StyledLogEntries />', () => {
it('renders correctly', () => {
const tree = createShallowWithTheme(<StyledLogEntries logs={[{ timestamp: '1', log: 'hello' }, { timestamp: 2, log: 'bye' }]} />)
expect(tree).toMatchSnapshot()
})
})

describe('<LogEntry />', () => {
it('renders correctly', () => {
const tree = createShallowWithTheme(<LogEntry>hello</LogEntry>)
expect(tree).toMatchSnapshot()
})
})
2 changes: 1 addition & 1 deletion game_frontend/src/testHelpers/createShallow.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const muiTheme = createMuiTheme(theme)
*
* @example
* const tree = createShallowWithTheme(component)
* expect(component).toMatchSnapshot()
* expect(tree).toMatchSnapshot()
*
* @param {React.Component} component The component you want to test
*
Expand Down
Loading

0 comments on commit 9e9cc5a

Please sign in to comment.