Skip to content

Commit

Permalink
Add tests from docs examples
Browse files Browse the repository at this point in the history
  • Loading branch information
poteto committed Sep 9, 2022
1 parent 07fc453 commit 05dbfd3
Showing 1 changed file with 163 additions and 2 deletions.
165 changes: 163 additions & 2 deletions packages/react-reconciler/src/__tests__/useEvent-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,27 @@ describe('useEvent', () => {
let ReactNoop;
let Scheduler;
let act;
let createContext;
let useContext;
let useState;
let useEvent;
let useEffect;
let useLayoutEffect;
let useMemo;

beforeEach(() => {
React = require('react');
ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler');

act = require('jest-react').act;
createContext = React.createContext;
useContext = React.useContext;
useState = React.useState;
useEvent = React.experimental_useEvent;
useEffect = React.useEffect;
useLayoutEffect = React.useLayoutEffect;
useMemo = React.useMemo;
});

function span(prop) {
Expand Down Expand Up @@ -150,7 +156,7 @@ describe('useEvent', () => {
});

// @gate enableUseEventHook
it('useLayoutEffect shouldnt re-fire when event handlers change', () => {
it("useLayoutEffect shouldn't re-fire when event handlers change", () => {
class IncrementButton extends React.PureComponent {
increment = () => {
this.props.onClick();
Expand Down Expand Up @@ -235,7 +241,7 @@ describe('useEvent', () => {
});

// @gate enableUseEventHook
it('useEffect shouldnt re-fire when event handlers change', () => {
it("useEffect shouldn't re-fire when event handlers change", () => {
class IncrementButton extends React.PureComponent {
increment = () => {
this.props.onClick();
Expand Down Expand Up @@ -431,4 +437,159 @@ describe('useEvent', () => {
act(() => ReactNoop.render(<Counter value={2} />));
expect(Scheduler).toHaveYielded(['Effect value: 2', 'Event value: 2']);
});

// @gate enableUseEventHook
it('integration: implements docs chat room example', () => {
function createConnection() {
let connectedCallback;
let timeout;
return {
connect() {
timeout = setTimeout(() => {
if (connectedCallback) {
connectedCallback();
}
}, 100);
},
on(event, callback) {
if (connectedCallback) {
throw Error('Cannot add the handler twice.');
}
if (event !== 'connected') {
throw Error('Only "connected" event is supported.');
}
connectedCallback = callback;
},
disconnect() {
clearTimeout(timeout);
},
};
}

function ChatRoom({roomId, theme}) {
const onConnected = useEvent(() => {
Scheduler.unstable_yieldValue('Connected! theme: ' + theme);
});

useEffect(() => {
const connection = createConnection(roomId);
connection.on('connected', () => {
onConnected();
});
connection.connect();
return () => connection.disconnect();
}, [roomId, onConnected]);

return <Text text={`Welcome to the ${roomId} room!`} />;
}

act(() => ReactNoop.render(<ChatRoom roomId="general" theme="light" />));
expect(Scheduler).toHaveYielded(['Welcome to the general room!']);
expect(ReactNoop.getChildren()).toEqual([
span('Welcome to the general room!'),
]);

jest.advanceTimersByTime(100);
Scheduler.unstable_advanceTime(100);
expect(Scheduler).toHaveYielded(['Connected! theme: light']);

// change roomId only
act(() => ReactNoop.render(<ChatRoom roomId="music" theme="light" />));
expect(Scheduler).toHaveYielded(['Welcome to the music room!']);
expect(ReactNoop.getChildren()).toEqual([
span('Welcome to the music room!'),
]);
jest.advanceTimersByTime(100);
Scheduler.unstable_advanceTime(100);
// should trigger a reconnect
expect(Scheduler).toHaveYielded(['Connected! theme: light']);

// change theme only
act(() => ReactNoop.render(<ChatRoom roomId="music" theme="dark" />));
expect(Scheduler).toHaveYielded(['Welcome to the music room!']);
expect(ReactNoop.getChildren()).toEqual([
span('Welcome to the music room!'),
]);
jest.advanceTimersByTime(100);
Scheduler.unstable_advanceTime(100);
// should not trigger a reconnect
expect(Scheduler).toFlushWithoutYielding();

// change roomId only
act(() => ReactNoop.render(<ChatRoom roomId="travel" theme="dark" />));
expect(Scheduler).toHaveYielded(['Welcome to the travel room!']);
expect(ReactNoop.getChildren()).toEqual([
span('Welcome to the travel room!'),
]);
jest.advanceTimersByTime(100);
Scheduler.unstable_advanceTime(100);
// should trigger a reconnect
expect(Scheduler).toHaveYielded(['Connected! theme: dark']);
});

// @gate enableUseEventHook
it('integration: implements the docs logVisit example', () => {
class AddToCartButton extends React.PureComponent {
addToCart = () => {
this.props.onClick();
};
render() {
return <Text text="Add to cart" />;
}
}
const ShoppingCartContext = createContext(null);

function AppShell({children}) {
const [items, updateItems] = useState([]);
const value = useMemo(() => ({items, updateItems}), [items, updateItems]);

return (
<ShoppingCartContext.Provider value={value}>
{children}
</ShoppingCartContext.Provider>
);
}

function Page({url}) {
const {items, updateItems} = useContext(ShoppingCartContext);
const onClick = useEvent(() => updateItems([...items, 1]));
const numberOfItems = items.length;

const onVisit = useEvent(visitedUrl => {
Scheduler.unstable_yieldValue(
'url: ' + url + ', numberOfItems: ' + numberOfItems,
);
});

useEffect(() => {
onVisit(url);
}, [url]);

return <AddToCartButton onClick={onClick} ref={button} />;
}

const button = React.createRef(null);
act(() =>
ReactNoop.render(
<AppShell>
<Page url="/shop/1" />
</AppShell>,
),
);
expect(Scheduler).toHaveYielded([
'Add to cart',
'url: /shop/1, numberOfItems: 0',
]);
act(button.current.addToCart);
expect(Scheduler).toFlushWithoutYielding();

act(() =>
ReactNoop.render(
<AppShell>
<Page url="/shop/2" />
</AppShell>,
),
);
expect(Scheduler).toHaveYielded(['url: /shop/2, numberOfItems: 1']);
});
});

0 comments on commit 05dbfd3

Please sign in to comment.