Skip to content

Commit b5695f4

Browse files
authored
Feature/test suite (#5)
* Update package.json. Configure jest test suite. Update lint rules * SCR: USNA - Add test suite for utils. Add deep object compare implementation * Improve compare. Clone mock graph data for sandbox * Clean generated config when clicking reset config button * Remove json stringify comparision usage * Organize test files * Add Link tests. Organize tests structure * Improve src/utils. Add documentation for src/utils * Test isEqual behavior against circular structures * Improve utils tests. Add coverage to gitignore * Add Node tests * Add empty object fix on isEqual method * Group private methods on top of files. Pseudo private function naming in helper graph * Fix lint errors. Some refactor accross code base. Add some new lint configs * Init tests for Graph component * Remove unnecessary webpack plugins * Remove usage of Object.values. Update graph snapshot * Major progress in Graph unit tests * Fix link highlight logic in graph helper 🐛
1 parent 6deebb5 commit b5695f4

23 files changed

+2866
-350
lines changed

.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": ["react", "es2015", "stage-0"]
3+
}

.eslintrc.js

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
11
module.exports = {
2-
"parser": "babel-eslint",
32
"extends": [
43
"eslint:recommended"
54
],
6-
"plugins": [
7-
"standard",
8-
"promise",
9-
"react"
10-
],
5+
"globals": {
6+
"document": true,
7+
"Reflect": true,
8+
"window": true
9+
},
10+
"parser": "babel-eslint",
1111
"parserOptions": {
12+
"ecmaVersion": 6,
1213
"ecmaFeatures": {
1314
"jsx": true
1415
}
1516
},
17+
"plugins": [
18+
"standard",
19+
"promise",
20+
"react"
21+
],
1622
"rules": {
1723
"react/jsx-uses-react": "error",
18-
"react/jsx-uses-vars": "error"
19-
},
20-
"globals": {
21-
"document": true,
22-
"Reflect": true,
23-
"window": true
24+
"react/jsx-uses-vars": "error",
25+
"camelcase": "error",
26+
"keyword-spacing": "error",
27+
"max-len": ["error", 120, 4, { "ignoreComments": true }],
28+
"max-lines": ["error", {"max": 250, "skipComments": true}],
29+
"newline-after-var": ["error", "always"],
30+
"no-nested-ternary": "error",
31+
"no-useless-constructor": "error",
32+
"semi": "error"
2433
}
2534
};

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,6 @@ typings/
6767
dist/
6868
DOCUMENTATION.md
6969
docs
70+
coverage
7071
sandbox/rd3g.sandbox.bundle.js
7172
sandbox/rd3g.sandbox.bundle.js.map

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,16 @@ export default {
4646
```
4747

4848
## TODOs
49-
This are some ideas to further development:
50-
- Expose a graph property **background-color** that is applied to the svg graph container.
49+
This consists in a list of ideas for further development:
50+
- Expose a graph property **background-color** that is applied to the svg graph container;
51+
- Expose d3-force values as configurable such as **alphaTarget** simulation value;
52+
- Improve opacity/highlightBehavior strategy maybe use a global *background: rgba(...)* value and then set a higher
53+
value on selected nodes;
54+
- At the moment highlightBehavior is highlighting the mouse hovered node, its 1st degree connections and their 1st
55+
degree connections. Make **highlightBehaviorDegree** which consists in a *step value* on the depth that we wish to highlight.
56+
57+
#### Sanbox/Playground
58+
- Improve page layout (optimize space).
5159

5260
## Contributions
5361
Contributions are welcome fell free to submit new features or simply grab something from

package.json

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,53 @@
44
"description": "React component to build interactive and configurable graphs with d3 effortlessly",
55
"author": "Daniel Caldas",
66
"license": "MIT",
7+
"scripts": {
8+
"dev": "node_modules/.bin/webpack-dev-server -d --content-base sandbox --inline --hot --port 3002",
9+
"dist": "node_modules/.bin/npm-run-all --parallel dist:*",
10+
"dist:rd3g": "webpack --config webpack.config.dist.js -p --display-modules",
11+
"dist:sandbox": "webpack --config webpack.config.js -p --display-modules",
12+
"docs": "node_modules/documentation/bin/documentation.js build src/**/*.js -f html -o docs && node_modules/documentation/bin/documentation.js build src/**/*.js -f md > DOCUMENTATION.md",
13+
"lint": "node_modules/eslint/bin/eslint.js --config=.eslintrc.js \"src/**/*.js\"",
14+
"test": "jest --verbose --coverage",
15+
"test:clean": "jest --no-cache --updateSnapshot --verbose --coverage",
16+
"test:watch": "jest --verbose --watchAll"
17+
},
718
"dependencies": {
819
"d3": "4.7.4",
9-
"react": "15.4.2"
20+
"react": "^15.5.0"
1021
},
1122
"devDependencies": {
1223
"babel-core": "6.24.0",
24+
"babel-jest": "19.0.0",
1325
"babel-loader": "6.4.1",
1426
"babel-plugin-add-module-exports": "0.2.1",
1527
"babel-plugin-react-html-attrs": "2.0.0",
1628
"babel-plugin-transform-class-properties": "6.22.0",
1729
"babel-plugin-transform-decorators-legacy": "1.3.4",
18-
"babel-preset-es2015": "6.16.0",
19-
"babel-preset-react": "6.16.0",
30+
"babel-preset-es2015": "6.24.1",
31+
"babel-preset-react": "6.24.1",
2032
"babel-preset-stage-0": "6.16.0",
21-
"css-loader": "^0.28.0",
33+
"css-loader": "0.28.0",
2234
"documentation": "4.0.0-beta.18",
2335
"eslint": "3.18.0",
2436
"eslint-config-recommended": "1.5.0",
2537
"eslint-plugin-promise": "3.5.0",
2638
"eslint-plugin-standard": "2.1.1",
2739
"html-webpack-plugin": "2.28.0",
40+
"jest": "19.0.2",
2841
"npm-run-all": "4.0.2",
29-
"react-dom": "15.4.2",
42+
"react-addons-test-utils": "^15.5.0",
43+
"react-dom": "^15.5.0",
3044
"react-jsonschema-form": "0.46.0",
3145
"react-router-dom": "4.0.0",
32-
"style-loader": "^0.16.1",
46+
"react-test-renderer": "^15.5.0",
47+
"style-loader": "0.16.1",
3348
"webpack": "2.3.2",
3449
"webpack-dev-server": "2.4.2"
3550
},
51+
"engines": {
52+
"node": ">=6.9.5"
53+
},
3654
"repository": {
3755
"type": "git",
3856
"url": "git+https://github.com/danielcaldas/react-d3-graph.git"
@@ -47,14 +65,5 @@
4765
"social-network-analysis",
4866
"social-network-graph",
4967
"visualization"
50-
],
51-
"scripts": {
52-
"dev": "node_modules/.bin/webpack-dev-server -d --content-base sandbox --inline --hot --port 3002",
53-
"dist": "node_modules/.bin/npm-run-all --parallel dist:*",
54-
"dist:rd3g": "webpack --config webpack.config.dist.js -p --display-modules",
55-
"dist:sandbox": "webpack --config webpack.config.js -p --display-modules",
56-
"docs": "node_modules/documentation/bin/documentation.js build src/**/*.js -f html -o docs && node_modules/documentation/bin/documentation.js build src/**/*.js -f md > DOCUMENTATION.md",
57-
"lint": "node_modules/eslint/bin/eslint.js --config=.eslintrc.js \"src/**/*.js\"",
58-
"test": "echo \"Error: no test specified\" && exit 1"
59-
}
68+
]
6069
}

sandbox/Sandbox.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ export default class Sandbox extends React.Component {
9393
}
9494

9595
resetGraphConfig = () => {
96+
const generatedConfig = {};
97+
9698
const schemaProps = Utils.generateFormSchema(defaultConfig, '', {});
9799

98100
const schema = {
@@ -102,14 +104,15 @@ export default class Sandbox extends React.Component {
102104

103105
this.setState({
104106
config: defaultConfig,
107+
generatedConfig,
105108
schema
106109
});
107110
}
108111

109112
render() {
110113
const graphProps = {
111114
id: 'graph',
112-
data: mock,
115+
data: JSON.parse(JSON.stringify(mock)),
113116
config: this.state.config,
114117
onClickNode: this.onClickNode,
115118
onClickLink: this.onClickLink,
@@ -130,7 +133,7 @@ export default class Sandbox extends React.Component {
130133
<Graph ref='graph' {...graphProps}/>
131134
</div>
132135
<div className='container__form'>
133-
<h4>Graph configurations</h4>
136+
<h4>react-d3-graph configurations</h4>
134137
<Form className='form-wrapper'
135138
schema={this.state.schema}
136139
uiSchema={this.uiSchema}
@@ -143,11 +146,11 @@ export default class Sandbox extends React.Component {
143146
</div>
144147
<div className='container__graph-config'>
145148
<h4>Your config</h4>
146-
<JSONContainer data={this.state.generatedConfig} />
149+
<JSONContainer data={this.state.generatedConfig} staticData={false} />
147150
</div>
148151
<div className='container__graph-data'>
149152
<h4>Graph data</h4>
150-
<JSONContainer data={mock} />
153+
<JSONContainer data={mock} staticData={true}/>
151154
</div>
152155
</div>
153156
);
@@ -156,7 +159,7 @@ export default class Sandbox extends React.Component {
156159

157160
class JSONContainer extends React.Component {
158161
shouldComponentUpdate(nextProps, nextState) {
159-
return JSON.stringify(nextProps.data) !== JSON.stringify(this.props.data);
162+
return !this.props.staticData && !ReactD3GraphUtils.isEqual(nextProps.data, this.props.data);
160163
}
161164

162165
render() {

sandbox/miserables.js

Lines changed: 77 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,82 @@
11
export default {
22
nodes: [
3-
{id: 'Myriel', group: 1},
4-
{id: 'Napoleon', group: 1},
5-
{id: 'Mlle.Baptistine', group: 1},
6-
{id: 'Mme.Magloire', group: 1},
7-
{id: 'CountessdeLo', group: 1},
8-
{id: 'Geborand', group: 1},
9-
{id: 'Champtercier', group: 1},
10-
{id: 'Cravatte', group: 1},
11-
{id: 'Count', group: 1},
12-
{id: 'OldMan', group: 1},
13-
{id: 'Labarre', group: 2},
14-
{id: 'Valjean', group: 2},
15-
{id: 'Marguerite', group: 3},
16-
{id: 'Mme.deR', group: 2},
17-
{id: 'Isabeau', group: 2},
18-
{id: 'Gervais', group: 2},
19-
{id: 'Tholomyes', group: 3},
20-
{id: 'Listolier', group: 3},
21-
{id: 'Fameuil', group: 3},
22-
{id: 'Blacheville', group: 3},
23-
{id: 'Favourite', group: 3},
24-
{id: 'Dahlia', group: 3},
25-
{id: 'Zephine', group: 3},
26-
{id: 'Fantine', group: 3},
27-
{id: 'Mme.Thenardier', group: 4},
28-
{id: 'Thenardier', group: 4},
29-
{id: 'Cosette', group: 5},
30-
{id: 'Javert', group: 4},
31-
{id: 'Fauchelevent', group: 0},
32-
{id: 'Bamatabois', group: 2},
33-
{id: 'Perpetue', group: 3},
34-
{id: 'Simplice', group: 2},
35-
{id: 'Scaufflaire', group: 2},
36-
{id: 'Woman1', group: 2},
37-
{id: 'Judge', group: 2},
38-
{id: 'Champmathieu', group: 2},
39-
{id: 'Brevet', group: 2},
40-
{id: 'Chenildieu', group: 2},
41-
{id: 'Cochepaille', group: 2},
42-
{id: 'Pontmercy', group: 4},
43-
{id: 'Boulatruelle', group: 6},
44-
{id: 'Eponine', group: 4},
45-
{id: 'Anzelma', group: 4},
46-
{id: 'Woman2', group: 5},
47-
{id: 'MotherInnocent', group: 0},
48-
{id: 'Gribier', group: 0},
49-
{id: 'Jondrette', group: 7},
50-
{id: 'Mme.Burgon', group: 7},
51-
{id: 'Gavroche', group: 8},
52-
{id: 'Gillenormand', group: 5},
53-
{id: 'Magnon', group: 5},
54-
{id: 'Mlle.Gillenormand', group: 5},
55-
{id: 'Mme.Pontmercy', group: 5},
56-
{id: 'Mlle.Vaubois', group: 5},
57-
{id: 'Lt.Gillenormand', group: 5},
58-
{id: 'Marius', group: 8},
59-
{id: 'BaronessT', group: 5},
60-
{id: 'Mabeuf', group: 8},
61-
{id: 'Enjolras', group: 8},
62-
{id: 'Combeferre', group: 8},
63-
{id: 'Prouvaire', group: 8},
64-
{id: 'Feuilly', group: 8},
65-
{id: 'Courfeyrac', group: 8},
66-
{id: 'Bahorel', group: 8},
67-
{id: 'Bossuet', group: 8},
68-
{id: 'Joly', group: 8},
69-
{id: 'Grantaire', group: 8},
70-
{id: 'MotherPlutarch', group: 9},
71-
{id: 'Gueulemer', group: 4},
72-
{id: 'Babet', group: 4},
73-
{id: 'Claquesous', group: 4},
74-
{id: 'Montparnasse', group: 4},
75-
{id: 'Toussaint', group: 5},
76-
{id: 'Child1', group: 10},
77-
{id: 'Child2', group: 10},
78-
{id: 'Brujon', group: 4},
79-
{id: 'Mme.Hucheloup', group: 8}
3+
{id: 'Myriel'},
4+
{id: 'Napoleon'},
5+
{id: 'Mlle.Baptistine'},
6+
{id: 'Mme.Magloire'},
7+
{id: 'CountessdeLo'},
8+
{id: 'Geborand'},
9+
{id: 'Champtercier'},
10+
{id: 'Cravatte'},
11+
{id: 'Count'},
12+
{id: 'OldMan'},
13+
{id: 'Labarre'},
14+
{id: 'Valjean'},
15+
{id: 'Marguerite'},
16+
{id: 'Mme.deR'},
17+
{id: 'Isabeau'},
18+
{id: 'Gervais'},
19+
{id: 'Tholomyes'},
20+
{id: 'Listolier'},
21+
{id: 'Fameuil'},
22+
{id: 'Blacheville'},
23+
{id: 'Favourite'},
24+
{id: 'Dahlia'},
25+
{id: 'Zephine'},
26+
{id: 'Fantine'},
27+
{id: 'Mme.Thenardier'},
28+
{id: 'Thenardier'},
29+
{id: 'Cosette'},
30+
{id: 'Javert'},
31+
{id: 'Fauchelevent'},
32+
{id: 'Bamatabois'},
33+
{id: 'Perpetue'},
34+
{id: 'Simplice'},
35+
{id: 'Scaufflaire'},
36+
{id: 'Woman1'},
37+
{id: 'Judge'},
38+
{id: 'Champmathieu'},
39+
{id: 'Brevet'},
40+
{id: 'Chenildieu'},
41+
{id: 'Cochepaille'},
42+
{id: 'Pontmercy'},
43+
{id: 'Boulatruelle'},
44+
{id: 'Eponine'},
45+
{id: 'Anzelma'},
46+
{id: 'Woman2'},
47+
{id: 'MotherInnocent'},
48+
{id: 'Gribier'},
49+
{id: 'Jondrette'},
50+
{id: 'Mme.Burgon'},
51+
{id: 'Gavroche'},
52+
{id: 'Gillenormand'},
53+
{id: 'Magnon'},
54+
{id: 'Mlle.Gillenormand'},
55+
{id: 'Mme.Pontmercy'},
56+
{id: 'Mlle.Vaubois'},
57+
{id: 'Lt.Gillenormand'},
58+
{id: 'Marius'},
59+
{id: 'BaronessT'},
60+
{id: 'Mabeuf'},
61+
{id: 'Enjolras'},
62+
{id: 'Combeferre'},
63+
{id: 'Prouvaire'},
64+
{id: 'Feuilly'},
65+
{id: 'Courfeyrac'},
66+
{id: 'Bahorel'},
67+
{id: 'Bossuet'},
68+
{id: 'Joly'},
69+
{id: 'Grantaire'},
70+
{id: 'MotherPlutarch'},
71+
{id: 'Gueulemer'},
72+
{id: 'Babet'},
73+
{id: 'Claquesous'},
74+
{id: 'Montparnasse'},
75+
{id: 'Toussaint'},
76+
{id: 'Child1'},
77+
{id: 'Child2'},
78+
{id: 'Brujon'},
79+
{id: 'Mme.Hucheloup'}
8080
],
8181
links: [
8282
{source: 'Napoleon', target: 'Myriel', value: 1},

0 commit comments

Comments
 (0)