-
Notifications
You must be signed in to change notification settings - Fork 47.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create DOM fixture that tests state preservation of timed out content
- Loading branch information
Showing
2 changed files
with
248 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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 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,247 @@ | ||
import Fixture from '../../Fixture'; | ||
import FixtureSet from '../../FixtureSet'; | ||
import TestCase from '../../TestCase'; | ||
import InputTestCase from './InputTestCase'; | ||
import ReplaceEmailInput from './ReplaceEmailInput'; | ||
|
||
const React = window.React; | ||
const ReactDOM = window.ReactDOM; | ||
|
||
const Suspense = React.unstable_Suspense; | ||
|
||
let cache = new Set(); | ||
|
||
function AsyncStep({text, ms}) { | ||
if (!cache.has(text)) { | ||
throw new Promise(resolve => | ||
setTimeout(() => { | ||
cache.add(text); | ||
resolve(); | ||
}, ms) | ||
); | ||
} | ||
return null; | ||
} | ||
|
||
let suspendyTreeIdCounter = 0; | ||
class SuspendyTree extends React.Component { | ||
id = suspendyTreeIdCounter++; | ||
state = { | ||
step: 1, | ||
isHidden: false, | ||
}; | ||
increment = () => this.setState(s => ({step: s.step + 1})); | ||
|
||
componentDidMount() { | ||
document.addEventListener('keydown', this.onKeydown); | ||
} | ||
|
||
componentWillUnmount() { | ||
document.removeEventListener('keydown', this.onKeydown); | ||
} | ||
|
||
onKeydown = event => { | ||
if (event.metaKey && event.key === 'Enter') { | ||
this.increment(); | ||
} | ||
}; | ||
|
||
render() { | ||
return ( | ||
<React.Fragment> | ||
<Suspense fallback={<div>"Loading..."</div>}> | ||
<div> | ||
<AsyncStep text={`${this.state.step} + ${this.id}`} ms={500} /> | ||
{this.props.children} | ||
</div> | ||
</Suspense> | ||
<button onClick={this.increment}>Go</button> | ||
</React.Fragment> | ||
); | ||
} | ||
} | ||
|
||
class TextInputFixtures extends React.Component { | ||
render() { | ||
return ( | ||
<FixtureSet | ||
title="Suspense" | ||
description="Preserving the state of timed-out children"> | ||
<div className="footnote"> | ||
Clicking "Go" will cause the fixtures to time-out for 1 second, then | ||
restore. You can also use Command + Enter (or Control + Enter on | ||
Windows, Linux), which is useful for preserving focus. | ||
</div> | ||
<TestCase title="Text selection where entire range times out"> | ||
<TestCase.Steps> | ||
<li>Use your cursor to select the text below.</li> | ||
<li>Click "Go".</li> | ||
</TestCase.Steps> | ||
|
||
<TestCase.ExpectedResult> | ||
The text selection should not be lost. | ||
</TestCase.ExpectedResult> | ||
|
||
<Fixture> | ||
<SuspendyTree> | ||
Select this entire sentence (and only this sentence). | ||
</SuspendyTree> | ||
</Fixture> | ||
</TestCase> | ||
<TestCase title="Text selection that extends outside timed-out subtree"> | ||
<TestCase.Steps> | ||
<li> | ||
Use your cursor to select a range that includes both the text and | ||
the "Go" button. | ||
</li> | ||
<li>Click "Go".</li> | ||
</TestCase.Steps> | ||
|
||
<TestCase.ExpectedResult> | ||
The text selection should not be lost. | ||
</TestCase.ExpectedResult> | ||
|
||
<Fixture> | ||
<SuspendyTree> | ||
Select a range that includes both this sentence and the "Go" | ||
button. | ||
</SuspendyTree> | ||
</Fixture> | ||
</TestCase> | ||
<TestCase title="Focus"> | ||
<TestCase.Steps> | ||
<li> | ||
Use your cursor to select a range that includes both the text and | ||
the "Go" button. | ||
</li> | ||
<li> | ||
Intead of clicking "Go", which switches focus, press Command + | ||
Enter (or Control + Enter on Windows, Linux). | ||
</li> | ||
</TestCase.Steps> | ||
|
||
<TestCase.ExpectedResult> | ||
The ideal behavior is that the focus would not be lost, but | ||
currently it is. | ||
</TestCase.ExpectedResult> | ||
|
||
<Fixture> | ||
<SuspendyTree> | ||
<button>Focus me</button> | ||
</SuspendyTree> | ||
</Fixture> | ||
</TestCase> | ||
|
||
<TestCase title="Uncontrolled form input"> | ||
<TestCase.Steps> | ||
<li>Type something ("Hello") into the text input.</li> | ||
<li>Click "Go".</li> | ||
</TestCase.Steps> | ||
|
||
<TestCase.ExpectedResult> | ||
The text field's contents should not reset. | ||
</TestCase.ExpectedResult> | ||
|
||
<Fixture> | ||
<SuspendyTree> | ||
<input type="text" /> | ||
</SuspendyTree> | ||
</Fixture> | ||
</TestCase> | ||
|
||
<TestCase title="Image flicker"> | ||
<TestCase.Steps> | ||
<li>Click "Go".</li> | ||
</TestCase.Steps> | ||
|
||
<TestCase.ExpectedResult> | ||
The image should reappear without flickering. The text should not | ||
reflow. | ||
</TestCase.ExpectedResult> | ||
|
||
<Fixture> | ||
<SuspendyTree> | ||
<img src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Atom_%282%29.png" />React | ||
is cool | ||
</SuspendyTree> | ||
</Fixture> | ||
</TestCase> | ||
|
||
<TestCase title="Iframe"> | ||
<TestCase.Steps> | ||
<li> | ||
The iframe shows a nested version of this fixtures app. Navigate | ||
to the "Text inputs" page. | ||
</li> | ||
<li>Select one of the checkboxes.</li> | ||
<li>Click "Go".</li> | ||
</TestCase.Steps> | ||
|
||
<TestCase.ExpectedResult> | ||
The iframe should still be on the "Text inputs" page. The checkbox | ||
should still be checked. (Unfortunately, scroll position is lost.) | ||
</TestCase.ExpectedResult> | ||
|
||
<Fixture> | ||
<SuspendyTree> | ||
<iframe width="500" height="300" src="/" /> | ||
</SuspendyTree> | ||
</Fixture> | ||
</TestCase> | ||
|
||
<TestCase title="Video playback"> | ||
<TestCase.Steps> | ||
<li>Start playing the video, or seek to a specific position.</li> | ||
<li>Click "Go".</li> | ||
</TestCase.Steps> | ||
|
||
<TestCase.ExpectedResult> | ||
The playback position should stay the same. | ||
</TestCase.ExpectedResult> | ||
|
||
<Fixture> | ||
<SuspendyTree> | ||
<video controls> | ||
<source | ||
src="http://techslides.com/demos/sample-videos/small.webm" | ||
type="video/webm" | ||
/> | ||
<source | ||
src="http://techslides.com/demos/sample-videos/small.ogv" | ||
type="video/ogg" | ||
/> | ||
<source | ||
src="http://techslides.com/demos/sample-videos/small.mp4" | ||
type="video/mp4" | ||
/> | ||
<source | ||
src="http://techslides.com/demos/sample-videos/small.3gp" | ||
type="video/3gp" | ||
/> | ||
</video> | ||
</SuspendyTree> | ||
</Fixture> | ||
</TestCase> | ||
<TestCase title="Audio playback"> | ||
<TestCase.Steps> | ||
<li>Start playing the audio, or seek to a specific position.</li> | ||
<li>Click "Go".</li> | ||
</TestCase.Steps> | ||
|
||
<TestCase.ExpectedResult> | ||
The playback position should stay the same. | ||
</TestCase.ExpectedResult> | ||
<Fixture> | ||
<SuspendyTree> | ||
<audio controls={true}> | ||
<source src="https://upload.wikimedia.org/wikipedia/commons/e/ec/Mozart_K448.ogg" /> | ||
</audio> | ||
</SuspendyTree> | ||
</Fixture> | ||
</TestCase> | ||
</FixtureSet> | ||
); | ||
} | ||
} | ||
|
||
export default TextInputFixtures; |