1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Update tests, plus some lint fixes, for gas-price-chart

This commit is contained in:
Dan Miller 2018-10-23 20:06:36 -02:30
parent 6f0406125d
commit d0619b024f
3 changed files with 204 additions and 53 deletions

View File

@ -1,18 +1,13 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import * as d3 from 'd3' import * as d3 from 'd3'
import c3 from 'c3'
import { import {
appendOrUpdateCircle,
generateChart, generateChart,
generateDataUIObj,
getAdjacentGasPrices,
getCoordinateData, getCoordinateData,
getNewXandTimeEstimate,
handleChartUpdate, handleChartUpdate,
hideDataUI, hideDataUI,
setSelectedCircle,
setTickPosition, setTickPosition,
handleMouseMove,
} from './gas-price-chart.utils.js' } from './gas-price-chart.utils.js'
export default class GasPriceChart extends Component { export default class GasPriceChart extends Component {
@ -61,7 +56,7 @@ export default class GasPriceChart extends Component {
const { x: chartXStart, width: chartWidth } = getCoordinateData('.c3-areas-data1') const { x: chartXStart, width: chartWidth } = getCoordinateData('.c3-areas-data1')
handleChartUpdate ({ handleChartUpdate({
chart, chart,
gasPrices, gasPrices,
newPrice: currentPrice, newPrice: currentPrice,
@ -69,24 +64,14 @@ export default class GasPriceChart extends Component {
}) })
d3.select('.c3-chart').on('mousemove', function () { d3.select('.c3-chart').on('mousemove', function () {
const { currentPosValue, newTimeEstimate } = getNewXandTimeEstimate({ handleMouseMove({
xMousePos: d3.event.clientX, xMousePos: d3.event.clientX,
chartXStart, chartXStart,
chartWidth, chartWidth,
gasPrices, gasPrices,
estimatedTimes, estimatedTimes,
chart,
}) })
if (currentPosValue === null && newTimeEstimate === null) {
hideDataUI(chart, '#overlayed-circle')
}
const indexOfNewCircle = estimatedTimes.length + 1
const dataUIObj = generateDataUIObj(currentPosValue, indexOfNewCircle, newTimeEstimate)
chart.internal.overlayPoint(dataUIObj, indexOfNewCircle)
chart.internal.showTooltip([dataUIObj], d3.select('.c3-areas-data1')._groups[0])
chart.internal.showXGridFocus([dataUIObj])
}) })
}, 0) }, 0)
@ -97,7 +82,7 @@ export default class GasPriceChart extends Component {
const { gasPrices, currentPrice: newPrice } = this.props const { gasPrices, currentPrice: newPrice } = this.props
if (prevProps.currentPrice !== newPrice) { if (prevProps.currentPrice !== newPrice) {
handleChartUpdate ({ handleChartUpdate({
chart: this.chart, chart: this.chart,
gasPrices, gasPrices,
newPrice, newPrice,

View File

@ -1,6 +1,27 @@
import * as d3 from 'd3' import * as d3 from 'd3'
import c3 from 'c3' import c3 from 'c3'
export function handleMouseMove ({ xMousePos, chartXStart, chartWidth, gasPrices, estimatedTimes, chart }) {
const { currentPosValue, newTimeEstimate } = getNewXandTimeEstimate({
xMousePos,
chartXStart,
chartWidth,
gasPrices,
estimatedTimes,
})
if (currentPosValue === null && newTimeEstimate === null) {
hideDataUI(chart, '#overlayed-circle')
}
const indexOfNewCircle = estimatedTimes.length + 1
const dataUIObj = generateDataUIObj(currentPosValue, indexOfNewCircle, newTimeEstimate)
chart.internal.overlayPoint(dataUIObj, indexOfNewCircle)
chart.internal.showTooltip([dataUIObj], d3.select('.c3-areas-data1')._groups[0])
chart.internal.showXGridFocus([dataUIObj])
}
export function getCoordinateData (selector) { export function getCoordinateData (selector) {
return d3.select(selector).node().getBoundingClientRect() return d3.select(selector).node().getBoundingClientRect()
} }
@ -37,7 +58,7 @@ export function handleChartUpdate ({ chart, gasPrices, newPrice, cssId }) {
} }
} }
export function getAdjacentGasPrices({ gasPrices, priceToPosition }) { export function getAdjacentGasPrices ({ gasPrices, priceToPosition }) {
const closestLowerValueIndex = gasPrices.findIndex((e, i, a) => e <= priceToPosition && a[i + 1] >= priceToPosition) const closestLowerValueIndex = gasPrices.findIndex((e, i, a) => e <= priceToPosition && a[i + 1] >= priceToPosition)
const closestHigherValueIndex = gasPrices.findIndex((e, i, a) => e > priceToPosition) const closestHigherValueIndex = gasPrices.findIndex((e, i, a) => e > priceToPosition)
return { return {
@ -76,7 +97,7 @@ export function getNewXandTimeEstimate ({ xMousePos, chartXStart, chartWidth, ga
} }
: { : {
currentPosValue, currentPosValue,
newTimeEstimate: extrapolateY ({ newTimeEstimate: extrapolateY({
higherY: estimatedTimes[closestHigherValueIndex], higherY: estimatedTimes[closestHigherValueIndex],
lowerY: estimatedTimes[closestLowerValueIndex], lowerY: estimatedTimes[closestLowerValueIndex],
higherX: closestHigherValue, higherX: closestHigherValue,
@ -144,7 +165,7 @@ export function setSelectedCircle ({
const { x: higherX, y: higherY } = getCoordinateData(`.c3-circle-${closestHigherValueIndex}`) const { x: higherX, y: higherY } = getCoordinateData(`.c3-circle-${closestHigherValueIndex}`)
const currentX = lowerX + (higherX - lowerX) * (newPrice - closestLowerValue) / (closestHigherValue - closestLowerValue) const currentX = lowerX + (higherX - lowerX) * (newPrice - closestLowerValue) / (closestHigherValue - closestLowerValue)
const newTimeEstimate = extrapolateY ({ higherY, lowerY, higherX, lowerX, xForExtrapolation: currentX }) const newTimeEstimate = extrapolateY({ higherY, lowerY, higherX, lowerX, xForExtrapolation: currentX })
chart.internal.selectPoint( chart.internal.selectPoint(
generateDataUIObj(currentX, numberOfValues, newTimeEstimate), generateDataUIObj(currentX, numberOfValues, newTimeEstimate),

View File

@ -5,36 +5,59 @@ import sinon from 'sinon'
import shallow from '../../../../../lib/shallow-with-context' import shallow from '../../../../../lib/shallow-with-context'
import * as d3 from 'd3' import * as d3 from 'd3'
const mockSelectReturn = { function timeout (time) {
...d3.select('div'), return new Promise((resolve, reject) => {
node: () => ({ setTimeout(resolve, time)
getBoundingClientRect: () => ({ x: 123, y: 321, width: 400 }), })
}), }
const propsMethodSpies = {
updateCustomGasPrice: sinon.spy(),
}
const selectReturnSpies = {
empty: sinon.spy(), empty: sinon.spy(),
remove: sinon.spy(), remove: sinon.spy(),
style: sinon.spy(), style: sinon.spy(),
select: d3.select, select: d3.select,
attr: sinon.spy(), attr: sinon.spy(),
on: sinon.spy(), on: sinon.spy(),
datum: sinon.stub().returns({ x: 'mockX' }),
}
const mockSelectReturn = {
...d3.select('div'),
node: () => ({
getBoundingClientRect: () => ({ x: 123, y: 321, width: 400 }),
}),
...selectReturnSpies,
}
const gasPriceChartUtilsSpies = {
appendOrUpdateCircle: sinon.spy(),
generateChart: sinon.stub().returns({ mockChart: true }),
generateDataUIObj: sinon.spy(),
getAdjacentGasPrices: sinon.spy(),
getCoordinateData: sinon.stub().returns({ x: 'mockCoordinateX', width: 'mockWidth' }),
getNewXandTimeEstimate: sinon.spy(),
handleChartUpdate: sinon.spy(),
hideDataUI: sinon.spy(),
setSelectedCircle: sinon.spy(),
setTickPosition: sinon.spy(),
handleMouseMove: sinon.spy(),
}
const testProps = {
gasPrices: [1.5, 2.5, 4, 8],
estimatedTimes: [100, 80, 40, 10],
gasPricesMax: 9,
estimatedTimesMax: 100,
currentPrice: 6,
updateCustomGasPrice: propsMethodSpies.updateCustomGasPrice,
} }
const GasPriceChart = proxyquire('../gas-price-chart.component.js', { const GasPriceChart = proxyquire('../gas-price-chart.component.js', {
'c3': { './gas-price-chart.utils.js': gasPriceChartUtilsSpies,
generate: function ({ data: { columns } }) {
return {
internal: {
showTooltip: () => {},
showXGridFocus: () => {},
hideXGridFocus: () => {},
data: {
xs: {
[columns[1][0]]: columns[1].slice(1),
},
},
},
}
},
},
'd3': { 'd3': {
...d3, ...d3,
select: function (...args) { select: function (...args) {
@ -43,20 +66,19 @@ const GasPriceChart = proxyquire('../gas-price-chart.component.js', {
? mockSelectReturn ? mockSelectReturn
: result : result
}, },
event: {
clientX: 'mockClientX',
},
}, },
}).default }).default
sinon.spy(GasPriceChart.prototype, 'renderChart')
describe('GasPriceChart Component', function () { describe('GasPriceChart Component', function () {
let wrapper let wrapper
beforeEach(() => { beforeEach(() => {
wrapper = shallow(<GasPriceChart wrapper = shallow(<GasPriceChart {...testProps} />)
priceAndTimeEstimates={[
{ gasprice: 1, expectedTime: 10 },
{ gasprice: 2, expectedTime: 20 },
{ gasprice: 3, expectedTime: 30 },
]}
/>)
}) })
describe('render()', () => { describe('render()', () => {
@ -70,4 +92,127 @@ describe('GasPriceChart Component', function () {
}) })
}) })
describe('componentDidMount', () => {
it('should call this.renderChart with the components props', () => {
assert(GasPriceChart.prototype.renderChart.callCount, 1)
wrapper.instance().componentDidMount()
assert(GasPriceChart.prototype.renderChart.callCount, 2)
assert.deepEqual(GasPriceChart.prototype.renderChart.getCall(1).args, [{...testProps}])
})
})
describe('componentDidUpdate', () => {
it('should call handleChartUpdate if props.currentPrice has changed', () => {
gasPriceChartUtilsSpies.handleChartUpdate.resetHistory()
wrapper.instance().componentDidUpdate({ currentPrice: 7 })
assert.equal(gasPriceChartUtilsSpies.handleChartUpdate.callCount, 1)
})
it('should call handleChartUpdate with the correct props', () => {
gasPriceChartUtilsSpies.handleChartUpdate.resetHistory()
wrapper.instance().componentDidUpdate({ currentPrice: 7 })
assert.deepEqual(gasPriceChartUtilsSpies.handleChartUpdate.getCall(0).args, [{
chart: { mockChart: true },
gasPrices: [1.5, 2.5, 4, 8],
newPrice: 6,
cssId: '#set-circle',
}])
})
it('should not call handleChartUpdate if props.currentPrice has not changed', () => {
gasPriceChartUtilsSpies.handleChartUpdate.resetHistory()
wrapper.instance().componentDidUpdate({ currentPrice: 6 })
assert.equal(gasPriceChartUtilsSpies.handleChartUpdate.callCount, 0)
})
})
describe('renderChart', () => {
it('should call setTickPosition 4 times, with the expected props', async () => {
await timeout(0)
gasPriceChartUtilsSpies.setTickPosition.resetHistory()
assert.equal(gasPriceChartUtilsSpies.setTickPosition.callCount, 0)
wrapper.instance().renderChart(testProps)
await timeout(0)
assert.equal(gasPriceChartUtilsSpies.setTickPosition.callCount, 4)
assert.deepEqual(gasPriceChartUtilsSpies.setTickPosition.getCall(0).args, ['y', 0, -5, 8])
assert.deepEqual(gasPriceChartUtilsSpies.setTickPosition.getCall(1).args, ['y', 1, -3, -5])
assert.deepEqual(gasPriceChartUtilsSpies.setTickPosition.getCall(2).args, ['x', 0, 3, 15])
assert.deepEqual(gasPriceChartUtilsSpies.setTickPosition.getCall(3).args, ['x', 1, 3, -8])
})
it('should call handleChartUpdate with the correct props', async () => {
await timeout(0)
gasPriceChartUtilsSpies.handleChartUpdate.resetHistory()
wrapper.instance().renderChart(testProps)
await timeout(0)
assert.deepEqual(gasPriceChartUtilsSpies.handleChartUpdate.getCall(0).args, [{
chart: { mockChart: true },
gasPrices: [1.5, 2.5, 4, 8],
newPrice: 6,
cssId: '#set-circle',
}])
})
it('should add three events to the chart', async () => {
await timeout(0)
selectReturnSpies.on.resetHistory()
assert.equal(selectReturnSpies.on.callCount, 0)
wrapper.instance().renderChart(testProps)
await timeout(0)
assert.equal(selectReturnSpies.on.callCount, 3)
const firstOnEventArgs = selectReturnSpies.on.getCall(0).args
assert.equal(firstOnEventArgs[0], 'mouseout')
const secondOnEventArgs = selectReturnSpies.on.getCall(1).args
assert.equal(secondOnEventArgs[0], 'click')
const thirdOnEventArgs = selectReturnSpies.on.getCall(2).args
assert.equal(thirdOnEventArgs[0], 'mousemove')
})
it('should hide the data UI on mouseout', async () => {
await timeout(0)
selectReturnSpies.on.resetHistory()
wrapper.instance().renderChart(testProps)
gasPriceChartUtilsSpies.hideDataUI.resetHistory()
await timeout(0)
const mouseoutEventArgs = selectReturnSpies.on.getCall(0).args
assert.equal(gasPriceChartUtilsSpies.hideDataUI.callCount, 0)
mouseoutEventArgs[1]()
assert.equal(gasPriceChartUtilsSpies.hideDataUI.callCount, 1)
assert.deepEqual(gasPriceChartUtilsSpies.hideDataUI.getCall(0).args, [{ mockChart: true }, '#overlayed-circle'])
})
it('should updateCustomGasPrice on click', async () => {
await timeout(0)
selectReturnSpies.on.resetHistory()
wrapper.instance().renderChart(testProps)
propsMethodSpies.updateCustomGasPrice.resetHistory()
await timeout(0)
const mouseoutEventArgs = selectReturnSpies.on.getCall(1).args
assert.equal(propsMethodSpies.updateCustomGasPrice.callCount, 0)
mouseoutEventArgs[1]()
assert.equal(propsMethodSpies.updateCustomGasPrice.callCount, 1)
assert.equal(propsMethodSpies.updateCustomGasPrice.getCall(0).args[0], 'mockX')
})
it('should handle mousemove', async () => {
await timeout(0)
selectReturnSpies.on.resetHistory()
wrapper.instance().renderChart(testProps)
gasPriceChartUtilsSpies.handleMouseMove.resetHistory()
await timeout(0)
const mouseoutEventArgs = selectReturnSpies.on.getCall(2).args
assert.equal(gasPriceChartUtilsSpies.handleMouseMove.callCount, 0)
mouseoutEventArgs[1]()
assert.equal(gasPriceChartUtilsSpies.handleMouseMove.callCount, 1)
assert.deepEqual(gasPriceChartUtilsSpies.handleMouseMove.getCall(0).args, [{
xMousePos: 'mockClientX',
chartXStart: 'mockCoordinateX',
chartWidth: 'mockWidth',
gasPrices: testProps.gasPrices,
estimatedTimes: testProps.estimatedTimes,
chart: { mockChart: true },
}])
})
})
}) })