Skip to content

Commit

Permalink
feat: 🎸 add windowSizeRaf$ obsevable
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed May 2, 2020
1 parent af9cce7 commit 7f1ba89
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Sensor and side-effect library for [`rxjs`](https://rxjs-dev.firebaseapp.com/).
## Observables

- [`location$`](./docs/location$.md) — browser location and history sensor.
- [`windowSize$`](./docs/windowSize$.md) — browser window dimension sensor.
- [`windowSize$`](./docs/windowSize$.md) and [`windowSizeRaf$`](./docs/windowSizeRaf$.md) — browser window dimension sensor.


## Operators
Expand Down
4 changes: 4 additions & 0 deletions docs/windowSizeRaf$.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# `windowSizeRaf$`

Same as [`windowSize$`](./windowSize$.md), but also throttles event using
browser's `window.requestAnimationFrame`.
125 changes: 125 additions & 0 deletions src/__tests__/windowSizeRaf$.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import {SizeWindow} from '../windowSize$';
import {windowSizeRaf$} from '../windowSizeRaf$';
const {window, _listeners} = require('../window');

type Listener = {event: string; listener: (...args: any) => void};

const listeners: Listener[] = _listeners;

jest.mock('../window', () => {
const listeners: Listener[] = [];
const removedListeners: Listener[] = [];
const wnd: SizeWindow = {
innerHeight: -1,
innerWidth: -1,
addEventListener: (event, listener) => {
listeners.push({event, listener});
},
removeEventListener: (event, listener) => {
removedListeners.push({event, listener});
},
};
return {
window: wnd,
_listeners: listeners,
_removedListeners: removedListeners,
};
});

test('can subscribe', () => {
windowSizeRaf$.subscribe(() => {});
});

test('attaches 1 listener', () => {
expect(listeners.length).toBe(1);
expect(listeners).toMatchInlineSnapshot(`
Array [
Object {
"event": "resize",
"listener": [Function],
},
]
`);
});

test('holds default state', () => {
expect(windowSizeRaf$.getValue()).toMatchInlineSnapshot(`
Object {
"height": -1,
"width": -1,
}
`);
});

test('emits new value when window resizes', () => {
const spy = jest.fn();
windowSizeRaf$.subscribe(spy);
expect(spy).toHaveBeenCalledTimes(1);
window.innerWidth = 1024;
window.innerHeight = 768;
listeners[0].listener(new Event('resize'));
expect(spy).toHaveBeenCalledTimes(2);
});

test('does not emit new value when window size hasn\'t changed', () => {
const spy = jest.fn();
windowSizeRaf$.subscribe(spy);
expect(spy).toHaveBeenCalledTimes(1);
listeners[0].listener(new Event('resize'));
expect(spy).toHaveBeenCalledTimes(1);
});

test('multiple resizes with multiple subscribers work', () => {
const spy1 = jest.fn();
const spy2 = jest.fn();
const sub1 = windowSizeRaf$.subscribe(spy1);

expect(spy1).toHaveBeenCalledTimes(1);
expect(spy2).toHaveBeenCalledTimes(0);

listeners[0].listener(new Event('resize'));

const sub2 = windowSizeRaf$.subscribe(spy2);

expect(spy1).toHaveBeenCalledTimes(1);
expect(spy2).toHaveBeenCalledTimes(1);

window.innerWidth = 1111;
window.innerHeight = 2222;
listeners[0].listener(new Event('resize'));

expect(spy1).toHaveBeenCalledTimes(2);
expect(spy2).toHaveBeenCalledTimes(2);

window.innerWidth = 333;
listeners[0].listener(new Event('resize'));

expect(spy1).toHaveBeenCalledTimes(3);
expect(spy2).toHaveBeenCalledTimes(3);

window.innerHeight = 555;
listeners[0].listener(new Event('resize'));

expect(spy1).toHaveBeenCalledTimes(4);
expect(spy2).toHaveBeenCalledTimes(4);

sub1.unsubscribe();

window.innerHeight = 666;
listeners[0].listener(new Event('resize'));

expect(spy1).toHaveBeenCalledTimes(4);
expect(spy2).toHaveBeenCalledTimes(5);

sub2.unsubscribe();

window.innerHeight = 777;
listeners[0].listener(new Event('resize'));

expect(spy1).toHaveBeenCalledTimes(4);
expect(spy2).toHaveBeenCalledTimes(5);
});

test('still has a single global event listener', () => {
expect(listeners.length).toBe(1);
});
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './location$';
export * from './windowSize$';
export * from './windowSizeRaf$';
export * from './raf';
7 changes: 7 additions & 0 deletions src/windowSizeRaf$.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {BehaviorSubject} from 'rxjs';
import {windowSize$} from './windowSize$';
import {raf} from './raf';

export const windowSizeRaf$ = new BehaviorSubject(windowSize$.getValue());

windowSize$.pipe(raf()).subscribe(windowSizeRaf$);

0 comments on commit 7f1ba89

Please sign in to comment.