-
Notifications
You must be signed in to change notification settings - Fork 195
Maintainable tests of actual SVG output #47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
8629649
Add infrastructure for easy direct testing of SVG output
motiz88 1b9c149
Write directly to fixture.js at end of bootstrap-tests.js
motiz88 e29bcbb
Work around JSX parsing quirk triggered by bootstrap-tests's output
motiz88 2e8ec9c
Add an auto-generated, passing, fixtures.js
motiz88 e4d164f
Use hiff to compare SVG output to fixtures
motiz88 bf7209c
Add informative header to bootstrap-tests.js
motiz88 e787d2b
Add graphical test fixtures based on demo.js
motiz88 598caaf
Detect references to sampleData etc when generating test fixtures & r…
motiz88 1d6eb06
Add test:bootstrap npm script -> bootstrap-tests.js
motiz88 a530df1
Peg react-element-to-jsx-string version to exactly 2.5.0
motiz88 5c63238
Configure travis to use npm@3 and node@{0.12, 4, 5}
motiz88 af832ab
Merge branch 'fix-travis' into graphical-tests
motiz88 ee13bf2
Add transform-object-assign to .babelrc -> support Node 0.12
motiz88 f6fd34f
Merge remote-tracking branch 'upstream/master' into fix-travis
motiz88 00b14fd
Merge branch 'fix-travis' into graphical-tests
motiz88 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,8 @@ | |
"es2015", | ||
"stage-1" | ||
], | ||
"plugins": [ | ||
"transform-object-assign" | ||
], | ||
"sourceMaps": true, | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
language: node_js | ||
before_install: npm install -g npm@3 | ||
script: travis_retry npm test | ||
node_js: | ||
- '0.12' | ||
- '4' | ||
- '5' | ||
sudo: false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import hiff from 'hiff'; | ||
|
||
function normalizeStyle(style) { | ||
style = (style || '').split(';').map(s => s.trim()); | ||
style.sort(); | ||
return style.join(';'); | ||
} | ||
|
||
function normalizeAttrs(...$ns) { | ||
for (let $n of $ns) { | ||
if ($n.attr('style')) | ||
$n.attr('style', normalizeStyle($n.attr('style'))); | ||
} | ||
} | ||
|
||
function comparatorFn($n1, $n2, childChanges) { | ||
normalizeAttrs($n1, $n2); | ||
return hiff.defaultTagComparisonFn($n1, $n2, childChanges); | ||
} | ||
|
||
export default function compareSvg(svg1, svg2, options = {}) { | ||
return hiff.compare(svg1, svg2, Object.assign({}, options, {tagComparison: comparatorFn})); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
{ | ||
"sampleData": [0.26789611283279424, -1.5618808743590797, -0.46848826820269196, -0.02429709108986638, -0.07347501430506465, | ||
0.938722048681125, -0.02488170176918398, | ||
0.014511315562131895, -1.0920317808493079, -1.6226651458214956, | ||
0.6777968350341455, -1.0989601025670448, | ||
1.402853678778828, -1.7923422052616966, -0.37025235972161835, -0.10254054014867667, | ||
0.3709902985604339, | ||
2.5285657626539253, -0.18958673659343403, | ||
0.8578243085059141, | ||
1.7395812075504404, | ||
0.9723534409914075, -0.6799757002898873, | ||
1.153081489500828, | ||
1.3851189843556257, | ||
0.19355625368483506, | ||
1.262069965103209, -0.8628137671385424, -0.6118030618030503, -0.25257403618789087 | ||
], | ||
"sampleData100": [-0.2809926205121489, | ||
0.5993223086924007, | ||
0.5450586119753267, -0.4794107823559421, -0.18298272472350668, | ||
0.3219712568468161, | ||
2.0566174540438324, -1.6442809970641576, | ||
1.971025186834513, | ||
0.37237930811331116, -0.4015753275277232, | ||
1.0601229819271032, -2.0983317267366988, | ||
0.26835584955818786, -0.2899975217753408, -0.6342464890422705, -0.10975205424415876, | ||
0.39583180670735013, | ||
1.4695948548213784, -1.2295606440627673, | ||
1.0056333434310312, | ||
1.006402733277956, -1.4092655719724325, | ||
0.17595701557726026, -0.19396518917878047, -1.4314174397644206, -0.34402041741926476, | ||
0.6986827111240516, -0.6157663396302129, | ||
1.0606864486721386, | ||
1.3537300165741912, -0.9521291296713654, -1.089926042595364, -0.9723342804049446, | ||
0.2286317959508994, | ||
0.2613862542298905, | ||
0.24840731355644413, | ||
2.08064561830636, | ||
0.44534855831763426, | ||
1.5511436162779393, -1.5514313805901196, -0.7497893094776009, | ||
0.4027674242193654, -0.38986316786208264, -1.2167765233154504, | ||
0.18879490542570268, -1.5284852088503573, | ||
0.8789559275619153, -1.2451506359938267, -0.7226040247250638, -0.07157034383583998, | ||
1.9901707247581082, | ||
0.22166972734467405, | ||
0.058080839429433054, -0.6324465858010533, -0.8091687560181702, -1.293296284426419, | ||
1.8436776591711028, -0.28314101700652944, | ||
1.358988312176975, -0.1152691343859452, -2.425199332455914, | ||
0.6696100792204956, | ||
1.7308347028588733, -0.9997610678433961, -0.10106296722138419, | ||
0.3157348177184432, -0.34931234065268996, | ||
0.4662049447935582, | ||
0.8793589099345607, | ||
2.069923608446714, | ||
1.3861543531394107, -0.2705101572065443, | ||
0.5980871990258989, -0.5871146157743545, -0.9844080263005216, | ||
0.2972697252124295, -0.6119868603373193, -1.8902200290484288, | ||
0.6996282188319667, -0.24883654266800448, -0.1156025389007573, | ||
1.0370156630612894, | ||
0.9750054921585302, -0.635000984672242, | ||
0.16076716404020402, | ||
0.1379262931648021, -0.6838899322825195, | ||
0.6088591150304701, -0.3408579041001186, -0.08790701313160872, -0.38412257182424137, -1.3319278452946857, | ||
0.7154759857504911, -2.8727571205730915, -1.3501468729225303, -0.0865770144109483, | ||
0.505651174224522, -2.2111682240498753, | ||
2.035381345199811 | ||
] | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import fixtures from './fixtures'; | ||
import {render} from 'enzyme'; | ||
import { expect } from 'chai'; | ||
import compareSvg from './compareSvg'; | ||
|
||
describe('Graphical tests from fixtures.js', function() { | ||
for (let key of Object.keys(fixtures)) { | ||
describe(`${key}`, function() { | ||
it('should render as specified', function() { | ||
const wrapper = render(fixtures[key].jsx); | ||
const result = compareSvg(wrapper.html(), fixtures[key].svg); | ||
const errorMessage = 'SVG output changed:\n' + result.changes.map(change => change.message).join('\n') + '\n'; | ||
expect(result.changes, errorMessage).to.be.empty; | ||
}); | ||
}); | ||
} | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// bootstrap-tests.js - A tool for updating the test cases in __tests__/fixtures.js | ||
// | ||
// 1) Reads __tests__/fixtures.js and looks for a "dynamic part", which should be a list of fields | ||
// belonging to that file's default export, enclosed in a pair of markers (see "signal" constants | ||
// below). | ||
// 2) Imports the same fixtures file and (re-)renders each ReactElement to a static SVG string. | ||
// 3) On success, overwrites __tests__/fixtures.js with an updated copy. | ||
// | ||
// Run with babel-node or using "npm run test:bootstrap". | ||
|
||
import path from 'path'; | ||
import {render} from 'enzyme'; | ||
import LineByLineReader from 'line-by-line'; | ||
import reactElementToJsx from 'react-element-to-jsx-string'; | ||
import {writeFileSync} from 'fs'; | ||
import replaceAll from 'replaceall'; | ||
import React from 'react'; | ||
|
||
const fixturesFile = path.resolve(__dirname, './__tests__/fixtures.js'); | ||
const dynamicPartStartSignal = '// AUTO-GENERATED PART STARTS HERE'; | ||
const dynamicPartEndSignal = '// AUTO-GENERATED PART ENDS HERE'; | ||
|
||
const fixtures = require(fixturesFile).default; | ||
|
||
// Handle recurring data constants | ||
import {sampleData, sampleData100} from './__tests__/data.json'; | ||
const recognizedDataConstants = { | ||
sampleData, sampleData100 | ||
}; | ||
const recognizedDataStrings = {}; | ||
for (let dataKey of Object.keys(recognizedDataConstants)) { | ||
recognizedDataStrings[dataKey] = markupToOneLine(reactElementToJsx(<div data-value={recognizedDataConstants[dataKey]} />) | ||
.replace(/[^{]*\{|\}[^}]*/g, '')); | ||
} | ||
|
||
// Output control | ||
let outData = ''; | ||
const write = content => { outData += content + '\n'; } | ||
const save = () => writeFileSync(fixturesFile, outData); | ||
function writeFixtures() { | ||
for (let key of Object.keys(fixtures)) { | ||
const jsx = fixtures[key].jsx; | ||
const wrapper = render(jsx); | ||
let jsxCode = `(${markupToOneLine(reactElementToJsx(jsx))})`; | ||
const htmlCode = JSON.stringify(wrapper.html()); | ||
for (let dataKey of Object.keys(recognizedDataStrings)) { | ||
jsxCode = replaceAll(recognizedDataStrings[dataKey], dataKey, jsxCode); | ||
} | ||
write(`\t${JSON.stringify(key)}: {jsx: ${jsxCode}, svg: ${htmlCode}},`); | ||
} | ||
} | ||
function markupToOneLine(code) { | ||
return code.replace(/\s*[\r\n]\s*/g, ' ').replace(/\s+/g, ' ').replace(/\s*([<>])\s*/g, '$1'); | ||
} | ||
|
||
// Input control | ||
const lr = new LineByLineReader(fixturesFile, {skipEmptyLines: false}); | ||
let inDynamicPart = false, dynamicPartCount = 0, lineCount = 0; | ||
|
||
lr.on('line', line => { | ||
++lineCount; | ||
if (line === dynamicPartStartSignal) { | ||
if (inDynamicPart) | ||
throw new LineError('Dynamic part opened again'); | ||
++dynamicPartCount; | ||
if (dynamicPartCount > 1) | ||
throw new LineError('Multiple dynamic parts found'); | ||
inDynamicPart = true; | ||
write(line); | ||
try { | ||
writeFixtures(); | ||
} catch(e) { | ||
throw new LineError(e); | ||
} | ||
} | ||
else if (line === dynamicPartEndSignal) { | ||
if (!inDynamicPart) | ||
throw new LineError('Dynamic part closed again'); | ||
inDynamicPart = false; | ||
write(line); | ||
} | ||
else if (!inDynamicPart) | ||
write(line); | ||
}); | ||
|
||
lr.on('end', () => { | ||
if (inDynamicPart) { | ||
throw new LineError('Dynamic part not closed'); | ||
} | ||
if (!dynamicPartCount) { | ||
throw new LineError('No dynamic part found in file!'); | ||
} | ||
save(); | ||
}); | ||
|
||
lr.on('error', function (err) { | ||
throw new LineError(err); | ||
}); | ||
|
||
class LineError extends Error { | ||
constructor(message) { | ||
super(`${fixturesFile}:${lineCount}: ${message}`); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@borisyankov This allows us to write
data={sampleData}
infixtures.js
rather thandata={[0.26789611283279424, ...]}
every time. Yes, I used string replacement to do this. It's slow and kind of inelegant but it works :) Which to my taste is good enough for this kind of dev script.