ice/packages/miniapp-react-dom/tests/unmountComponentAtNode.spec...

120 lines
4.0 KiB
React
Raw Permalink Normal View History

feat: miniapp (#333) * feat(miniapp): use platform in cli to generate miniapp code * fix: lint error * feat(miniapp): add miniapp project * chore: revert example code * chore: optimize code * feat(miniapp): migrate some packages to ice * feat(miniapp): update swcOptions for miniapp * chore(example): add more pages * feat(miniapp): add miniapp runClientApp * feat(miniapp): update compile config for miniapp * feat(miniapp): support get app and routes config in compile * fix(miniapp): lint warning * feat(miniapp): support routeData/routeConfig and reduce size * fix: lint warning * fix: lint warning * feat(miniapp): support global css and page css * feat(miniapp): support css modules * feat(miniapp): support copying assets in public dir * feat(miniapp): support Link and getSearchParams * feat(miniapp): use index.ts.ejs as template * feat(miniapp): support passing params in Link * feat(miniapp): support history in miniapp * fix(miniapp): build without compiling server bundle * fix(miniapp): use getRoutesConfig * feat(miniapp): support build options like outputDir * chore(miniapp): update miniapp examples * feat(miniapp): support html tags * feat(miniapp): remove taro related code * fix(miniapp): some cases * fix(miniapp): use require.resolve to get page loader * chore(miniapp): update lock * fix(miniapp): page loader check this name * chore(miniapp): add devDependencies * chore: update index ejs template * refactor(miniapp): update multiple platforms logic in ice * chore: lock regenerator-runtime version * chore(miniapp): add ali miniapp build command * fix(ice): set default value of platform to web * fix(runtime): remove duplicated denpdencies * chore: set default value of platform to web * feat(miniapp): registerSerialization when plugin activated * test(miniapp): suit for vitest * chore(miniapp): add webpack-sources to bundles * chore: clean code * chore(miniapp): remove jest config file * fix: lint error * fix: add default value of outputDir * refactor(miniapp): remove openBrowser from logMessage * chore(miniapp): remove unnecessary ts-ignore * fix: type error * chore(miniapp): rename Adapter to adapter * chore(miniapp): update interface name * refactor: use plugins to support miniapp * chore(miniapp): update example name * fix: update dependencies * feat(miniapp): add platform check in cli * chore: update lock * fix: remove useless platform option * fix: lint warning * fix: lint warning * test: use src code in tests * chore(miniapp): remove ||= operators * fix(miniapp): exclude miniapp-runtime esm code * fix(ice-cli): update platform for build command
2022-09-23 11:11:38 +08:00
import { expect, describe, test, vi } from 'vitest';
import * as React from 'react';
import { document } from '@ice/miniapp-runtime';
import { render, unmountComponentAtNode, unstable_batchedUpdates as batchedUpdates } from '../src/index';
describe('unmountComponentAtNode', () => {
test('throws when given a non-node', () => {
expect(() => {
unmountComponentAtNode(null);
}).toThrowError(
'unmountComponentAtNode(...): Target container is not a DOM element.',
);
});
test('returns false on non-React containers', () => {
const d = document.createElement('div');
d.id = 'test';
expect(unmountComponentAtNode(d)).toBe(false);
expect(d.id).toBe('test');
});
test('returns true on React containers', () => {
const d = document.createElement('div');
render(<b>hellooo</b>, d);
expect(d.textContent).toBe('hellooo');
expect(unmountComponentAtNode(d)).toBe(true);
expect(d.textContent).toBe('');
});
test('should render different components in same root', () => {
const container = document.createElement('container');
render(<div />, container);
expect(container.firstChild.tagName).toBe('DIV');
render(<span />, container);
expect(container.firstChild.tagName).toBe('SPAN');
});
test('should unmount and remount if the key changes', () => {
const container = document.createElement('container');
const mockMount = vi.fn();
const mockUnmount = vi.fn();
class Component extends React.Component {
componentDidMount = mockMount;
componentWillUnmount = mockUnmount;
render() {
return <span>{this.props.text}</span>;
}
}
expect(mockMount.mock.calls.length).toBe(0);
expect(mockUnmount.mock.calls.length).toBe(0);
render(<Component text="orange" key="A" />, container);
expect(container.firstChild.textContent).toBe('orange');
expect(mockMount.mock.calls.length).toBe(1);
expect(mockUnmount.mock.calls.length).toBe(0);
// If we change the key, the component is unmounted and remounted
render(<Component text="green" key="B" />, container);
expect(container.firstChild.textContent).toBe('green');
expect(mockMount.mock.calls.length).toBe(2);
expect(mockUnmount.mock.calls.length).toBe(1);
// But if we don't change the key, the component instance is reused
render(<Component text="blue" key="B" />, container);
expect(container.firstChild.textContent).toBe('blue');
expect(mockMount.mock.calls.length).toBe(2);
expect(mockUnmount.mock.calls.length).toBe(1);
});
test('should reuse markup if rendering to the same target twice', () => {
const container = document.createElement('container');
const instance1 = render(<div />, container);
const instance2 = render(<div />, container);
expect(instance1 === instance2).toBe(true);
});
test.skip('initial mount is sync inside batchedUpdates, but task work is deferred until the end of the batch', () => {
const container1 = document.createElement('div');
const container2 = document.createElement('div');
class Foo extends React.Component {
state = { active: false };
componentDidMount() {
this.setState({ active: true });
}
render() {
return (
<div>{this.props.children + (this.state.active ? '!' : '')}</div>
);
}
}
render(<Foo>a</Foo>, container2);
batchedUpdates(() => {
// Update. Does not flush yet.
render(<div>2</div>, container1);
expect(container1.textContent).toEqual('1');
// Initial mount on another root. Should flush immediately.
render(<Foo>a</Foo>, container2);
// The update did not flush yet.
expect(container1.textContent).toEqual('1');
// The initial mount flushed, but not the update scheduled in cDU.
expect(container2.textContent).toEqual('a');
});
// All updates have flushed.
expect(container1.textContent).toEqual('2');
expect(container2.textContent).toEqual('a!');
});
});