Skip to content

Commit a401d07

Browse files
authored
Merge pull request #36 from trurl-master/animations
Web Animations API
2 parents 45b4561 + 49dbded commit a401d07

File tree

79 files changed

+47694
-14390
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+47694
-14390
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist

.eslintrc.cjs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* eslint-env node */
2+
3+
module.exports = {
4+
root: true,
5+
parser: '@typescript-eslint/parser',
6+
plugins: ['@typescript-eslint', 'jsx-a11y'],
7+
extends: [
8+
'eslint:recommended',
9+
'plugin:@typescript-eslint/recommended',
10+
'plugin:react/recommended',
11+
'prettier',
12+
],
13+
rules: {
14+
'no-unused-vars': 'off',
15+
'@typescript-eslint/no-unused-vars': [
16+
'error',
17+
{ ignoreRestSiblings: true },
18+
],
19+
'react/jsx-uses-react': 'off',
20+
'react/react-in-jsx-scope': 'off',
21+
},
22+
};

.github/workflows/main.yml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
name: CI
1+
name: Validate
2+
23
on: [push]
4+
35
jobs:
46
build:
57
name: Build, lint, and test on Node ${{ matrix.node }} and ${{ matrix.os }}
68

79
runs-on: ${{ matrix.os }}
810
strategy:
911
matrix:
10-
node: ['12.x', '14.x', '16.x']
12+
node: ['14.x', '16.x', '18.x']
1113
os: [ubuntu-latest, windows-latest, macOS-latest]
1214

1315
steps:
@@ -21,12 +23,16 @@ jobs:
2123

2224
- name: Install deps and build (with cache)
2325
uses: bahmutov/npm-install@v1
26+
with:
27+
working-directory: |
28+
.
29+
examples
2430
2531
- name: Lint
26-
run: yarn lint
32+
run: npm run lint
2733

2834
- name: Test
29-
run: yarn test --ci --coverage --maxWorkers=2
35+
run: npm run test:all --ci --coverage --maxWorkers=2
3036

3137
- name: Build
32-
run: yarn build
38+
run: npm run build

.github/workflows/publish.yml

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ name: Publish
22

33
on:
44
release:
5+
# This specifies that the build will be triggered when we publish a release
56
types: [published]
67

78
jobs:
8-
publish-npm:
9-
name: 'Publish to npm'
9+
publish:
10+
name: 'Publish'
1011
runs-on: ubuntu-latest
12+
if: "!contains(github.ref_name, 'beta')"
1113
steps:
1214
- uses: actions/checkout@v2
1315

@@ -16,10 +18,32 @@ jobs:
1618
node-version: 'lts/*'
1719
registry-url: https://registry.npmjs.org/
1820

19-
- run: yarn install
21+
- name: Install deps and build (with cache)
22+
uses: bahmutov/npm-install@v1
2023

21-
- run: yarn build
24+
- run: npm run build
2225

2326
- run: npm publish --access public
2427
env:
2528
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
29+
30+
publish_beta:
31+
name: 'Publish beta'
32+
runs-on: ubuntu-latest
33+
if: contains(github.ref_name, 'beta')
34+
steps:
35+
- uses: actions/checkout@v2
36+
37+
- uses: actions/setup-node@v2
38+
with:
39+
node-version: 'lts/*'
40+
registry-url: https://registry.npmjs.org/
41+
42+
- name: Install deps and build (with cache)
43+
uses: bahmutov/npm-install@v1
44+
45+
- run: npm run build
46+
47+
- run: npm publish --tag beta --access public
48+
env:
49+
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}

.github/workflows/size.yml

Lines changed: 0 additions & 12 deletions
This file was deleted.

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"typescript.tsdk": "node_modules/typescript/lib"
3+
}

README.md

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ A set of tools for emulating browser behavior in jsdom environment
1515
## Installation
1616

1717
```sh
18-
npm install --save-dev jsdom-testing-mocks
18+
npm i --D jsdom-testing-mocks
1919
```
2020

2121
or
@@ -171,7 +171,7 @@ const DivWithSize = () => {
171171
const ref = useRef(null);
172172

173173
useEffect(() => {
174-
const observer = new ResizeObserver(entries => {
174+
const observer = new ResizeObserver((entries) => {
175175
setSize({
176176
width: entries[0].contentRect.width,
177177
height: entries[0].contentRect.height,
@@ -227,6 +227,83 @@ it('prints the size of the div', () => {
227227

228228
Triggers all resize observer callbacks for all observers that observe the passed elements
229229

230+
## Mock Web Animations API
231+
232+
_Warning: **experimental**, bug reports, tests and feedback are greatly appreciated_
233+
234+
Mocks WAAPI functionality using `requestAnimationFrame`. With one important limitation — there are no style interpolations. Each frame applies the closest keyframe from list of passed keyframes or a generated "initial keyframe" if only one keyframe is passed (initial keyframe removes/restores all the properties set by the one keyframe passed). As the implementation is based on the [official spec](https://www.w3.org/TR/web-animations-1/) it should support the majority of cases, but the test suite is far from complete, so _here be dragons_
235+
236+
Example, using `React Testing Library`:
237+
238+
```jsx
239+
import { mockAnimationsApi } from 'jsdom-testing-mocks';
240+
241+
const TestComponent = () => {
242+
const [isShown, setIsShown] = useState(false);
243+
244+
return (
245+
<div>
246+
{/* AnimatePresence is a component that adds its children in the dom
247+
and fades it in using WAAPI, with 2 keyframes: [{ opacity: 0 }, { opacity: 1 }],
248+
also adding a div with the word "Done!" after the animation has finished
249+
You can find implementation in examples
250+
*/}
251+
<AnimatePresence>{isShown && <div>Hehey!</div>}</AnimatePresence>
252+
<button
253+
onClick={() => {
254+
setIsShown(true);
255+
}}
256+
>
257+
Show
258+
</button>
259+
</div>
260+
);
261+
};
262+
263+
mockAnimationsApi();
264+
265+
it('adds an element into the dom and fades it in', async () => {
266+
render(<TestComponent />);
267+
268+
expect(screen.queryByText('Hehey!')).not.toBeInTheDocument();
269+
270+
await userEvent.click(screen.getByText('Show'));
271+
272+
// assume there's only one animation present in the document at this point
273+
// in practice it's better to get the running animation from the element itself
274+
const element = screen.getByText('Hehey!');
275+
const animation = document.getAnimations()[0];
276+
277+
// our AnimatePresence implementation has 2 keyframes: opacity: 0 and opacity: 1
278+
// which allows us to test the visibility of the element, the first keyframe
279+
// is applied right after the animation is ready
280+
await animation.ready;
281+
282+
expect(element).not.toBeVisible();
283+
284+
// this test will pass right after 50% of the animation is complete
285+
// because this mock doesn't interpolate keyframes values,
286+
// but chooses the closest one at each frame
287+
await waitFor(() => {
288+
expect(element).toBeVisible();
289+
});
290+
291+
// AnimatePresence will also add a div with the text 'Done!' after animation is complete
292+
await waitFor(() => {
293+
expect(screen.getByText('Done!')).toBeInTheDocument();
294+
});
295+
});
296+
```
297+
298+
### Using with fake timers
299+
300+
It's perfectly usable with fake timers, except for the [issue with promises](https://github.com/facebook/jest/issues/2157). Also note that you would need to manually advance timers by the duration of the animation taking frame duration (which currently is set to 16ms in `jest`/`sinon.js`) into account. So if you, say, have an animation with a duration of `300ms`, you will need to advance your timers by the value that is at least the closest multiple of the frame duration, which in this case is `304ms` (`19` frames \* `16ms`). Otherwise the last frame may not fire and the animation won't finish.
301+
302+
### Current issues
303+
304+
- No support for `steps` easings
305+
- Needs more tests
306+
230307
<!-- prettier-ignore-start -->
231308

232309
[version-badge]: https://img.shields.io/npm/v/jsdom-testing-mocks.svg?style=flat-square

example/.npmignore

Lines changed: 0 additions & 4 deletions
This file was deleted.

example/App.tsx

Lines changed: 0 additions & 33 deletions
This file was deleted.

0 commit comments

Comments
 (0)