Skip to content

Commit 63f71cf

Browse files
Enoah NetzachEnoahNetzach
authored andcommitted
Test various features separately
1 parent 4f9be9c commit 63f71cf

File tree

8 files changed

+206
-44
lines changed

8 files changed

+206
-44
lines changed

packages/react-scripts/scripts/init.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ module.exports = function(appPath, appName, verbose, originalDirectory, template
8686
var templateDependenciesPath = path.join(appPath, '.template.dependencies.json');
8787
if (fs.existsSync(templateDependenciesPath)) {
8888
var templateDependencies = require(templateDependenciesPath).dependencies;
89-
args = args.concat(templateDependencies);
89+
args = args.concat(Object.keys(templateDependencies).map(function (key) {
90+
return key + '@' + templateDependencies[key];
91+
}));
9092
fs.unlinkSync(templateDependenciesPath);
9193
}
9294

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
{
2-
"dependencies": ["jsdom"]
2+
"dependencies": {
3+
"jsdom": "9.8.3"
4+
}
35
}

packages/react-scripts/templates/kitchensink/src/App.js

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,39 @@
11
// @flow
2-
import React, { Component } from 'react';
3-
// testing absolute imports using NODE_PATH=src
4-
import CommentsList from 'CommentsList';
5-
import UsersList from 'UsersList';
6-
import logo from './logo.svg';
7-
import './App.css';
8-
import EnvVariableMessages from './EnvVariableMessages';
9-
import { abstract } from './abstract.json';
10-
import verySmallImage from './1x1-img.jpg';
11-
import aFileWithoutExt from './aFileWithoutExt';
12-
import aFileWithUnknownExt from './aFileWithExt.unknown'
13-
import aDeepJsModule from './subfolder/lol'
2+
import React from 'react';
143

15-
class App extends Component {
16-
render() {
17-
const templateName : string = "Kitchen Sink"
18-
return (
19-
<div className="App">
20-
<div className="App-header">
21-
<img id="svg-import" src={logo} className="App-logo" alt="logo" />
22-
<h2>Welcome to the {templateName} Template</h2>
23-
</div>
24-
25-
<details>
26-
<summary>
27-
{abstract}
28-
</summary>
29-
30-
<p className="App-intro">
31-
To get started, edit <code>src/App.js</code> and save to reload.
32-
</p>
33-
</details>
4+
class App extends React.Component {
5+
constructor(props) {
6+
super(props)
347

35-
<img id="img-import" src={verySmallImage} alt="a very small cat" />
8+
this.state = { feature: null }
9+
}
3610

37-
<span id="no-ext-import">{aFileWithoutExt}</span>
38-
<span id="unknown-ext-import">{aFileWithUnknownExt}</span>
39-
<span id="subfolder-js-import">{aDeepJsModule()} {aDeepJsModule.toString()}</span>
11+
componentDidMount() {
12+
switch (location.hash.slice(1)) {
13+
case 'promises':
14+
require.ensure(['./features/Promises'], () => {
15+
this.setState({ feature: require('./features/Promises').default })
16+
});
17+
break;
18+
case 'generators':
19+
require.ensure(['./features/Generators'], () => {
20+
this.setState({ feature: require('./features/Generators').default })
21+
});
22+
break;
23+
case 'async-await':
24+
require.ensure(['./features/AsyncAwait'], () => {
25+
this.setState({ feature: require('./features/AsyncAwait').default })
26+
});
27+
break;
28+
default:
29+
this.setState({ feature: null });
30+
break;
31+
}
32+
}
4033

41-
<EnvVariableMessages />
42-
<UsersList />
43-
<CommentsList user="User 1" />
44-
</div>
45-
);
34+
render() {
35+
const Feature = this.state.feature;
36+
return Feature ? <Feature /> : null;
4637
}
4738
}
4839

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react'
2+
3+
async function load() {
4+
return [
5+
{ id: 1, name: '1' },
6+
{ id: 2, name: '2' },
7+
{ id: 3, name: '3' },
8+
{ id: 4, name: '4' }
9+
];
10+
}
11+
12+
export default class extends React.Component {
13+
constructor(props) {
14+
super(props)
15+
16+
this.state = { users: [] }
17+
}
18+
19+
async componentDidMount() {
20+
const users = await load();
21+
this.setState({ users });
22+
}
23+
24+
render() {
25+
return (
26+
<div id="feature-async-await">
27+
{this.state.users.map(user => (
28+
<div key={user.id}>{user.name}</div>
29+
))}
30+
</div>
31+
)
32+
}
33+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react'
2+
3+
function * load(limit) {
4+
let i = 1;
5+
while (i <= limit) {
6+
yield { id: i, name: i };
7+
i++;
8+
}
9+
}
10+
11+
export default class extends React.Component {
12+
constructor(props) {
13+
super(props)
14+
15+
this.state = { users: [] }
16+
}
17+
18+
componentDidMount() {
19+
const users = [];
20+
for (let user of load(5)) {
21+
users.push(user);
22+
}
23+
this.setState({ users });
24+
}
25+
26+
render() {
27+
return (
28+
<div id="feature-generators">
29+
{this.state.users.map(user => (
30+
<div key={user.id}>{user.name}</div>
31+
))}
32+
</div>
33+
)
34+
}
35+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react'
2+
3+
function load() {
4+
return Promise.resolve([
5+
{ id: 1, name: '1' },
6+
{ id: 2, name: '2' },
7+
{ id: 3, name: '3' },
8+
{ id: 4, name: '4' }
9+
]);
10+
}
11+
12+
export default class extends React.Component {
13+
constructor(props) {
14+
super(props)
15+
16+
this.state = { users: [] }
17+
}
18+
19+
componentDidMount() {
20+
load().then(users => {
21+
this.setState({ users });
22+
})
23+
}
24+
25+
render() {
26+
return (
27+
<div id="feature-promises">
28+
{this.state.users.map(user => (
29+
<div key={user.id}>{user.name}</div>
30+
))}
31+
</div>
32+
)
33+
}
34+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
const fs = require('fs')
2+
const jsdom = require('jsdom')
3+
const path = require('path')
4+
5+
let resourcesResolver
6+
let markup
7+
8+
if (process.env.E2E_FILE) {
9+
const file = path.isAbsolute(process.env.E2E_FILE)
10+
? process.env.E2E_FILE
11+
: path.join(process.cwd(), process.env.E2E_FILE)
12+
13+
markup = fs.readFileSync(file, 'utf8')
14+
15+
resourcesResolver = resource => path.join(path.dirname(file), resource)
16+
} else if (process.env.E2E_URL) {
17+
// jsdomConfig.url = process.env.E2E_URL
18+
} else {
19+
it.only('can run jsdom (at least one of "E2E_FILE" or "E2E_URL" environment variables must be provided)', () => {
20+
expect(markup).toBeDefined()
21+
})
22+
}
23+
24+
// eslint-disable-next-line no-undef
25+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000
26+
27+
const initDOM = feature => new Promise(resolve => {
28+
const doc = jsdom.jsdom(markup, {
29+
features : {
30+
FetchExternalResources : ['script'],
31+
ProcessExternalResources : ['script'],
32+
},
33+
resourceLoader: (resource, callback) => {
34+
return callback(null, fs.readFileSync(resourcesResolver(resource.url.pathname), 'utf8'))
35+
},
36+
url: `http://localhost#${feature}`,
37+
virtualConsole: jsdom.createVirtualConsole().sendTo(console),
38+
})
39+
40+
doc.defaultView.addEventListener('load', () => {
41+
setTimeout(() => resolve(doc), 0)
42+
}, false)
43+
})
44+
45+
describe('Integration', () => {
46+
describe('Language syntax', () => {
47+
it('runs Promises', async () => {
48+
const doc = await initDOM('promises')
49+
50+
expect(doc.getElementById('feature-promises').childElementCount).toBe(4)
51+
})
52+
53+
it('runs generators', async () => {
54+
const doc = await initDOM('generators')
55+
56+
expect(doc.getElementById('feature-generators').childElementCount).toBe(5)
57+
})
58+
59+
it('runs async/await', async () => {
60+
const doc = await initDOM('async-await')
61+
62+
expect(doc.getElementById('feature-async-await').childElementCount).toBe(4)
63+
})
64+
})
65+
})

tasks/e2e.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ test -e build/static/media/*.svg
158158
test -e build/favicon.ico
159159

160160
# Run tests with CI flag
161-
CI=true NODE_PATH=src npm test
161+
E2E_FILE=./build/index.html CI=true NODE_PATH=src npm test
162162
# Uncomment when snapshot testing is enabled by default:
163163
# test -e src/__snapshots__/App.test.js.snap
164164

@@ -191,7 +191,7 @@ test -e build/favicon.ico
191191
# `CI=true npm test` won't work here because `npm test` becomes just `jest`.
192192
# We should either teach Jest to respect CI env variable, or make
193193
# `scripts/test.js` survive ejection (right now it doesn't).
194-
NODE_PATH=src npm test -- --watch=no
194+
E2E_FILE=./build/index.html NODE_PATH=src npm test -- --watch=no
195195
# Uncomment when snapshot testing is enabled by default:
196196
# test -e src/__snapshots__/App.test.js.snap
197197

0 commit comments

Comments
 (0)