Skip to content

Commit

Permalink
Add fixture components (#8860)
Browse files Browse the repository at this point in the history
* add fixture components

* add a few more options and styles

* Test fixture updates

- Pull in React from window global
- Add field to TestCase for fix PR links
- Update some styles

* Remove unused Fixture.Result comment

* Remove leading # from resolvedBy link

* Implement tag loading utility that caches response

Don't bust the cache doing feature detection

COME ON

* Use 'local' without version for option
  • Loading branch information
jquense authored and aweary committed Mar 2, 2017
1 parent a190cfc commit 2757a53
Show file tree
Hide file tree
Showing 15 changed files with 701 additions and 18 deletions.
4 changes: 3 additions & 1 deletion fixtures/dom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
"react-scripts": "0.8.4"
},
"dependencies": {
"classnames": "^2.2.5",
"query-string": "^4.2.3",
"react": "^15.4.1",
"react-dom": "^15.4.1"
"react-dom": "^15.4.1",
"semver": "^5.3.0"
},
"scripts": {
"start": "react-scripts start",
Expand Down
21 changes: 21 additions & 0 deletions fixtures/dom/src/components/Fixture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const React = window.React;

const propTypes = {
children: React.PropTypes.node.isRequired,
};

class Fixture extends React.Component {
render() {
const { children } = this.props;

return (
<div className="test-fixture">
{children}
</div>
);
}
}

Fixture.propTypes = propTypes;

export default Fixture
28 changes: 28 additions & 0 deletions fixtures/dom/src/components/FixtureSet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

const propTypes = {
title: React.PropTypes.node.isRequired,
description: React.PropTypes.node.isRequired,
};

class FixtureSet extends React.Component {

render() {
const { title, description, children } = this.props;

return (
<div>
<h1>{title}</h1>
{description && (
<p>{description}</p>
)}

{children}
</div>
);
}
}

FixtureSet.propTypes = propTypes;

export default FixtureSet
9 changes: 5 additions & 4 deletions fixtures/dom/src/components/Header.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { parse, stringify } from 'query-string';
import getVersionTags from '../tags';
const React = window.React;

const Header = React.createClass({
Expand All @@ -9,13 +10,12 @@ const Header = React.createClass({
return { version, versions };
},
componentWillMount() {
fetch('https://api.github.com/repos/facebook/react/tags', { mode: 'cors' })
.then(res => res.json())
getVersionTags()
.then(tags => {
let versions = tags.map(tag => tag.name.slice(1));
versions = ['local', ...versions];
versions = [`local`, ...versions];
this.setState({ versions });
});
})
},
handleVersionChange(event) {
const query = parse(window.location.search);
Expand Down Expand Up @@ -46,6 +46,7 @@ const Header = React.createClass({
<option value="/text-inputs">Text Inputs</option>
<option value="/selects">Selects</option>
<option value="/textareas">Textareas</option>
<option value="/input-change-events">Input change events</option>
</select>
</label>
<label htmlFor="react_version">
Expand Down
145 changes: 145 additions & 0 deletions fixtures/dom/src/components/TestCase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import cn from 'classnames';
import semver from 'semver';
import React from 'react';
import { parse } from 'query-string';
import { semverString } from './propTypes'

const propTypes = {
children: React.PropTypes.node.isRequired,
title: React.PropTypes.node.isRequired,
resolvedIn: semverString,
resolvedBy: React.PropTypes.string
};

class TestCase extends React.Component {
constructor(props, context) {
super(props, context);

this.state = {
complete: false,
};
}

handleChange = (e) => {
this.setState({
complete: e.target.checked
})
};

render() {
const {
title,
description,
resolvedIn,
resolvedBy,
affectedBrowsers,
children,
} = this.props;

let { complete } = this.state;

const { version } = parse(window.location.search);
const isTestRelevant = (
!version ||
!resolvedIn ||
semver.gte(version, resolvedIn)
);

complete = !isTestRelevant || complete;

return (
<section
className={cn(
"test-case",
complete && 'test-case--complete'
)}
>
<h2 className="test-case__title type-subheading">
<label>
<input
className="test-case__title__check"
type="checkbox"
checked={complete}
onChange={this.handleChange}
/>
{' '}{title}
</label>
</h2>

<dl className="test-case__details">
{resolvedIn && (
<dt>First supported in: </dt>)}
{resolvedIn && (
<dd>
<a href={'https://github.com/facebook/react/tag/v' + resolvedIn}>
<code>{resolvedIn}</code>
</a>
</dd>
)}

{resolvedBy && (
<dt>Fixed by: </dt>)}
{resolvedBy && (
<dd>
<a href={'https://github.com/facebook/react/pull/' + resolvedBy.slice(1)}>
<code>{resolvedBy}</code>
</a>
</dd>
)}

{affectedBrowsers &&
<dt>Affected browsers: </dt>}
{affectedBrowsers &&
<dd>{affectedBrowsers}</dd>
}
</dl>

<p className="test-case__desc">
{description}
</p>

<div className="test-case__body">
{!isTestRelevant &&(
<p className="test-case__invalid-version">
<strong>Note:</strong> This test case was fixed in a later version of React.
This test is not expected to pass for the selected version, and that's ok!
</p>
)}

{children}
</div>
</section>
);
}
}

TestCase.propTypes = propTypes;

TestCase.Steps = class extends React.Component {
render() {
const { children } = this.props;
return (
<div>
<h3>Steps to reproduce:</h3>
<ol>
{children}
</ol>
</div>
)
}
}

TestCase.ExpectedResult = class extends React.Component {
render() {
const { children } = this.props
return (
<div>
<h3>Expected Result:</h3>
<p>
{children}
</p>
</div>
)
}
}
export default TestCase
5 changes: 4 additions & 1 deletion fixtures/dom/src/components/fixtures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ const React = window.React;
import RangeInputFixtures from './range-inputs';
import TextInputFixtures from './text-inputs';
import SelectFixtures from './selects';
import TextAreaFixtures from './textareas/';
import TextAreaFixtures from './textareas';
import InputChangeEvents from './input-change-events';

/**
* A simple routing component that renders the appropriate
Expand All @@ -19,6 +20,8 @@ const FixturesPage = React.createClass({
return <SelectFixtures />;
case '/textareas':
return <TextAreaFixtures />;
case '/input-change-events':
return <InputChangeEvents />;
default:
return <p>Please select a test fixture.</p>;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react';

import Fixture from '../../Fixture';



class InputPlaceholderFixture extends React.Component {
constructor(props, context) {
super(props, context);

this.state = {
placeholder: 'A placeholder',
changeCount: 0,
};
}

handleChange = () => {
this.setState(({ changeCount }) => {
return {
changeCount: changeCount + 1
}
})
}
handleGeneratePlaceholder = () => {
this.setState({
placeholder: `A placeholder: ${Math.random() * 100}`
})
}

handleReset = () => {
this.setState({
changeCount: 0,
})
}

render() {
const { placeholder, changeCount } = this.state;
const color = changeCount === 0 ? 'green' : 'red';

return (
<Fixture>
<input
type='text'
placeholder={placeholder}
onChange={this.handleChange}
/>
{' '}
<button onClick={this.handleGeneratePlaceholder}>
Change placeholder
</button>

<p style={{ color }}>
<code>onChange</code>{' calls: '}<strong>{changeCount}</strong>
</p>
<button onClick={this.handleReset}>Reset count</button>
</Fixture>
)
}
}

export default InputPlaceholderFixture;
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react';

import Fixture from '../../Fixture';

class RadioClickFixture extends React.Component {
constructor(props, context) {
super(props, context);

this.state = {
changeCount: 0,
};
}

handleChange = () => {
this.setState(({ changeCount }) => {
return {
changeCount: changeCount + 1
}
})
}

handleReset = () => {
this.setState({
changeCount: 0,
})
}

render() {
const { changeCount } = this.state;
const color = changeCount === 0 ? 'green' : 'red';

return (
<Fixture>
<label>
<input
defaultChecked
type='radio'
onChange={this.handleChange}
/>
Test case radio input
</label>
{' '}
<p style={{ color }}>
<code>onChange</code>{' calls: '}<strong>{changeCount}</strong>
</p>
<button onClick={this.handleReset}>Reset count</button>
</Fixture>
)
}
}

export default RadioClickFixture;
Loading

0 comments on commit 2757a53

Please sign in to comment.