aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/preact/test/browser
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/preact/test/browser')
-rw-r--r--thirdparty/preact/test/browser/components.js712
-rw-r--r--thirdparty/preact/test/browser/context.js174
-rw-r--r--thirdparty/preact/test/browser/devtools.js234
-rw-r--r--thirdparty/preact/test/browser/keys.js85
-rw-r--r--thirdparty/preact/test/browser/lifecycle.js495
-rw-r--r--thirdparty/preact/test/browser/linked-state.js110
-rw-r--r--thirdparty/preact/test/browser/performance.js245
-rw-r--r--thirdparty/preact/test/browser/refs.js305
-rw-r--r--thirdparty/preact/test/browser/render.js439
-rw-r--r--thirdparty/preact/test/browser/spec.js127
-rw-r--r--thirdparty/preact/test/browser/svg.js112
11 files changed, 0 insertions, 3038 deletions
diff --git a/thirdparty/preact/test/browser/components.js b/thirdparty/preact/test/browser/components.js
deleted file mode 100644
index 9ef43cb1c..000000000
--- a/thirdparty/preact/test/browser/components.js
+++ /dev/null
@@ -1,712 +0,0 @@
-import { h, render, rerender, Component } from '../../src/preact';
-/** @jsx h */
-
-let spyAll = obj => Object.keys(obj).forEach( key => sinon.spy(obj,key) );
-
-function getAttributes(node) {
- let attrs = {};
- if (node.attributes) {
- for (let i=node.attributes.length; i--; ) {
- attrs[node.attributes[i].name] = node.attributes[i].value;
- }
- }
- return attrs;
-}
-
-// hacky normalization of attribute order across browsers.
-function sortAttributes(html) {
- return html.replace(/<([a-z0-9-]+)((?:\s[a-z0-9:_.-]+=".*?")+)((?:\s*\/)?>)/gi, (s, pre, attrs, after) => {
- let list = attrs.match(/\s[a-z0-9:_.-]+=".*?"/gi).sort( (a, b) => a>b ? 1 : -1 );
- if (~after.indexOf('/')) after = '></'+pre+'>';
- return '<' + pre + list.join('') + after;
- });
-}
-
-const Empty = () => null;
-
-describe('Components', () => {
- let scratch;
-
- before( () => {
- scratch = document.createElement('div');
- (document.body || document.documentElement).appendChild(scratch);
- });
-
- beforeEach( () => {
- let c = scratch.firstElementChild;
- if (c) render(<Empty />, scratch, c);
- scratch.innerHTML = '';
- });
-
- after( () => {
- scratch.parentNode.removeChild(scratch);
- scratch = null;
- });
-
- it('should render components', () => {
- class C1 extends Component {
- render() {
- return <div>C1</div>;
- }
- }
- sinon.spy(C1.prototype, 'render');
- render(<C1 />, scratch);
-
- expect(C1.prototype.render)
- .to.have.been.calledOnce
- .and.to.have.been.calledWithMatch({}, {})
- .and.to.have.returned(sinon.match({ nodeName:'div' }));
-
- expect(scratch.innerHTML).to.equal('<div>C1</div>');
- });
-
-
- it('should render functional components', () => {
- const PROPS = { foo:'bar', onBaz:()=>{} };
-
- const C3 = sinon.spy( props => <div {...props} /> );
-
- render(<C3 {...PROPS} />, scratch);
-
- expect(C3)
- .to.have.been.calledOnce
- .and.to.have.been.calledWithMatch(PROPS)
- .and.to.have.returned(sinon.match({
- nodeName: 'div',
- attributes: PROPS
- }));
-
- expect(scratch.innerHTML).to.equal('<div foo="bar"></div>');
- });
-
-
- it('should render components with props', () => {
- const PROPS = { foo:'bar', onBaz:()=>{} };
- let constructorProps;
-
- class C2 extends Component {
- constructor(props) {
- super(props);
- constructorProps = props;
- }
- render(props) {
- return <div {...props} />;
- }
- }
- sinon.spy(C2.prototype, 'render');
-
- render(<C2 {...PROPS} />, scratch);
-
- expect(constructorProps).to.deep.equal(PROPS);
-
- expect(C2.prototype.render)
- .to.have.been.calledOnce
- .and.to.have.been.calledWithMatch(PROPS, {})
- .and.to.have.returned(sinon.match({
- nodeName: 'div',
- attributes: PROPS
- }));
-
- expect(scratch.innerHTML).to.equal('<div foo="bar"></div>');
- });
-
-
- // Test for Issue #73
- it('should remove orphaned elements replaced by Components', () => {
- class Comp extends Component {
- render() {
- return <span>span in a component</span>;
- }
- }
-
- let root;
- function test(content) {
- root = render(content, scratch, root);
- }
-
- test(<Comp />);
- test(<div>just a div</div>);
- test(<Comp />);
-
- expect(scratch.innerHTML).to.equal('<span>span in a component</span>');
- });
-
-
- // Test for Issue #176
- it('should remove children when root changes to text node', () => {
- let comp;
-
- class Comp extends Component {
- render(_, { alt }) {
- return alt ? 'asdf' : <div>test</div>;
- }
- }
-
- render(<Comp ref={c=>comp=c} />, scratch);
-
- comp.setState({ alt:true });
- comp.forceUpdate();
- expect(scratch.innerHTML, 'switching to textnode').to.equal('asdf');
-
- comp.setState({ alt:false });
- comp.forceUpdate();
- expect(scratch.innerHTML, 'switching to element').to.equal('<div>test</div>');
-
- comp.setState({ alt:true });
- comp.forceUpdate();
- expect(scratch.innerHTML, 'switching to textnode 2').to.equal('asdf');
- });
-
-
- describe('props.children', () => {
- it('should support passing children as a prop', () => {
- const Foo = props => <div {...props} />;
-
- render(<Foo a="b" children={[
- <span class="bar">bar</span>,
- '123',
- 456
- ]} />, scratch);
-
- expect(scratch.innerHTML).to.equal('<div a="b"><span class="bar">bar</span>123456</div>');
- });
-
- it('should be ignored when explicit children exist', () => {
- const Foo = props => <div {...props}>a</div>;
-
- render(<Foo children={'b'} />, scratch);
-
- expect(scratch.innerHTML).to.equal('<div>a</div>');
- });
- });
-
-
- describe('High-Order Components', () => {
- it('should render nested functional components', () => {
- const PROPS = { foo:'bar', onBaz:()=>{} };
-
- const Outer = sinon.spy(
- props => <Inner {...props} />
- );
-
- const Inner = sinon.spy(
- props => <div {...props}>inner</div>
- );
-
- render(<Outer {...PROPS} />, scratch);
-
- expect(Outer)
- .to.have.been.calledOnce
- .and.to.have.been.calledWithMatch(PROPS)
- .and.to.have.returned(sinon.match({
- nodeName: Inner,
- attributes: PROPS
- }));
-
- expect(Inner)
- .to.have.been.calledOnce
- .and.to.have.been.calledWithMatch(PROPS)
- .and.to.have.returned(sinon.match({
- nodeName: 'div',
- attributes: PROPS,
- children: ['inner']
- }));
-
- expect(scratch.innerHTML).to.equal('<div foo="bar">inner</div>');
- });
-
- it('should re-render nested functional components', () => {
- let doRender = null;
- class Outer extends Component {
- componentDidMount() {
- let i = 1;
- doRender = () => this.setState({ i: ++i });
- }
- componentWillUnmount() {}
- render(props, { i }) {
- return <Inner i={i} {...props} />;
- }
- }
- sinon.spy(Outer.prototype, 'render');
- sinon.spy(Outer.prototype, 'componentWillUnmount');
-
- let j = 0;
- const Inner = sinon.spy(
- props => <div j={ ++j } {...props}>inner</div>
- );
-
- render(<Outer foo="bar" />, scratch);
-
- // update & flush
- doRender();
- rerender();
-
- expect(Outer.prototype.componentWillUnmount)
- .not.to.have.been.called;
-
- expect(Inner).to.have.been.calledTwice;
-
- expect(Inner.secondCall)
- .to.have.been.calledWithMatch({ foo:'bar', i:2 })
- .and.to.have.returned(sinon.match({
- attributes: {
- j: 2,
- i: 2,
- foo: 'bar'
- }
- }));
-
- expect(getAttributes(scratch.firstElementChild)).to.eql({
- j: '2',
- i: '2',
- foo: 'bar'
- });
-
- // update & flush
- doRender();
- rerender();
-
- expect(Inner).to.have.been.calledThrice;
-
- expect(Inner.thirdCall)
- .to.have.been.calledWithMatch({ foo:'bar', i:3 })
- .and.to.have.returned(sinon.match({
- attributes: {
- j: 3,
- i: 3,
- foo: 'bar'
- }
- }));
-
- expect(getAttributes(scratch.firstElementChild)).to.eql({
- j: '3',
- i: '3',
- foo: 'bar'
- });
- });
-
- it('should re-render nested components', () => {
- let doRender = null,
- alt = false;
-
- class Outer extends Component {
- componentDidMount() {
- let i = 1;
- doRender = () => this.setState({ i: ++i });
- }
- componentWillUnmount() {}
- render(props, { i }) {
- if (alt) return <div is-alt />;
- return <Inner i={i} {...props} />;
- }
- }
- sinon.spy(Outer.prototype, 'render');
- sinon.spy(Outer.prototype, 'componentDidMount');
- sinon.spy(Outer.prototype, 'componentWillUnmount');
-
- let j = 0;
- class Inner extends Component {
- constructor(...args) {
- super();
- this._constructor(...args);
- }
- _constructor() {}
- componentWillMount() {}
- componentDidMount() {}
- componentWillUnmount() {}
- componentDidUnmount() {}
- render(props) {
- return <div j={ ++j } {...props}>inner</div>;
- }
- }
- sinon.spy(Inner.prototype, '_constructor');
- sinon.spy(Inner.prototype, 'render');
- sinon.spy(Inner.prototype, 'componentWillMount');
- sinon.spy(Inner.prototype, 'componentDidMount');
- sinon.spy(Inner.prototype, 'componentDidUnmount');
- sinon.spy(Inner.prototype, 'componentWillUnmount');
-
- render(<Outer foo="bar" />, scratch);
-
- expect(Outer.prototype.componentDidMount).to.have.been.calledOnce;
-
- // update & flush
- doRender();
- rerender();
-
- expect(Outer.prototype.componentWillUnmount).not.to.have.been.called;
-
- expect(Inner.prototype._constructor).to.have.been.calledOnce;
- expect(Inner.prototype.componentWillUnmount).not.to.have.been.called;
- expect(Inner.prototype.componentDidUnmount).not.to.have.been.called;
- expect(Inner.prototype.componentWillMount).to.have.been.calledOnce;
- expect(Inner.prototype.componentDidMount).to.have.been.calledOnce;
- expect(Inner.prototype.render).to.have.been.calledTwice;
-
- expect(Inner.prototype.render.secondCall)
- .to.have.been.calledWithMatch({ foo:'bar', i:2 })
- .and.to.have.returned(sinon.match({
- attributes: {
- j: 2,
- i: 2,
- foo: 'bar'
- }
- }));
-
- expect(getAttributes(scratch.firstElementChild)).to.eql({
- j: '2',
- i: '2',
- foo: 'bar'
- });
-
- expect(sortAttributes(scratch.innerHTML)).to.equal(sortAttributes('<div foo="bar" j="2" i="2">inner</div>'));
-
- // update & flush
- doRender();
- rerender();
-
- expect(Inner.prototype.componentWillUnmount).not.to.have.been.called;
- expect(Inner.prototype.componentDidUnmount).not.to.have.been.called;
- expect(Inner.prototype.componentWillMount).to.have.been.calledOnce;
- expect(Inner.prototype.componentDidMount).to.have.been.calledOnce;
- expect(Inner.prototype.render).to.have.been.calledThrice;
-
- expect(Inner.prototype.render.thirdCall)
- .to.have.been.calledWithMatch({ foo:'bar', i:3 })
- .and.to.have.returned(sinon.match({
- attributes: {
- j: 3,
- i: 3,
- foo: 'bar'
- }
- }));
-
- expect(getAttributes(scratch.firstElementChild)).to.eql({
- j: '3',
- i: '3',
- foo: 'bar'
- });
-
-
- // update & flush
- alt = true;
- doRender();
- rerender();
-
- expect(Inner.prototype.componentWillUnmount).to.have.been.calledOnce;
- expect(Inner.prototype.componentDidUnmount).to.have.been.calledOnce;
-
- expect(scratch.innerHTML).to.equal('<div is-alt="true"></div>');
-
- // update & flush
- alt = false;
- doRender();
- rerender();
-
- expect(sortAttributes(scratch.innerHTML)).to.equal(sortAttributes('<div foo="bar" j="4" i="5">inner</div>'));
- });
-
- it('should resolve intermediary functional component', () => {
- let ctx = {};
- class Root extends Component {
- getChildContext() {
- return { ctx };
- }
- render() {
- return <Func />;
- }
- }
- const Func = sinon.spy( () => <Inner /> );
- class Inner extends Component {
- componentWillMount() {}
- componentDidMount() {}
- componentWillUnmount() {}
- componentDidUnmount() {}
- render() {
- return <div>inner</div>;
- }
- }
-
- spyAll(Inner.prototype);
-
- let root = render(<Root />, scratch);
-
- expect(Inner.prototype.componentWillMount).to.have.been.calledOnce;
- expect(Inner.prototype.componentDidMount).to.have.been.calledOnce;
- expect(Inner.prototype.componentWillMount).to.have.been.calledBefore(Inner.prototype.componentDidMount);
-
- render(<asdf />, scratch, root);
-
- expect(Inner.prototype.componentWillUnmount).to.have.been.calledOnce;
- expect(Inner.prototype.componentDidUnmount).to.have.been.calledOnce;
- expect(Inner.prototype.componentWillUnmount).to.have.been.calledBefore(Inner.prototype.componentDidUnmount);
- });
-
- it('should unmount children of high-order components without unmounting parent', () => {
- let outer, inner2, counter=0;
-
- class Outer extends Component {
- constructor(props, context) {
- super(props, context);
- outer = this;
- this.state = {
- child: this.props.child
- };
- }
- componentWillUnmount(){}
- componentDidUnmount(){}
- componentWillMount(){}
- componentDidMount(){}
- render(_, { child:C }) {
- return <C />;
- }
- }
- spyAll(Outer.prototype);
-
- class Inner extends Component {
- componentWillUnmount(){}
- componentDidUnmount(){}
- componentWillMount(){}
- componentDidMount(){}
- render() {
- return h('element'+(++counter));
- }
- }
- spyAll(Inner.prototype);
-
- class Inner2 extends Component {
- constructor(props, context) {
- super(props, context);
- inner2 = this;
- }
- componentWillUnmount(){}
- componentDidUnmount(){}
- componentWillMount(){}
- componentDidMount(){}
- render() {
- return h('element'+(++counter));
- }
- }
- spyAll(Inner2.prototype);
-
- render(<Outer child={Inner} />, scratch);
-
- // outer should only have been mounted once
- expect(Outer.prototype.componentWillMount, 'outer initial').to.have.been.calledOnce;
- expect(Outer.prototype.componentDidMount, 'outer initial').to.have.been.calledOnce;
- expect(Outer.prototype.componentWillUnmount, 'outer initial').not.to.have.been.called;
- expect(Outer.prototype.componentDidUnmount, 'outer initial').not.to.have.been.called;
-
- // inner should only have been mounted once
- expect(Inner.prototype.componentWillMount, 'inner initial').to.have.been.calledOnce;
- expect(Inner.prototype.componentDidMount, 'inner initial').to.have.been.calledOnce;
- expect(Inner.prototype.componentWillUnmount, 'inner initial').not.to.have.been.called;
- expect(Inner.prototype.componentDidUnmount, 'inner initial').not.to.have.been.called;
-
- outer.setState({ child:Inner2 });
- outer.forceUpdate();
-
- expect(Inner2.prototype.render).to.have.been.calledOnce;
-
- // outer should still only have been mounted once
- expect(Outer.prototype.componentWillMount, 'outer swap').to.have.been.calledOnce;
- expect(Outer.prototype.componentDidMount, 'outer swap').to.have.been.calledOnce;
- expect(Outer.prototype.componentWillUnmount, 'outer swap').not.to.have.been.called;
- expect(Outer.prototype.componentDidUnmount, 'outer swap').not.to.have.been.called;
-
- // inner should only have been mounted once
- expect(Inner2.prototype.componentWillMount, 'inner2 swap').to.have.been.calledOnce;
- expect(Inner2.prototype.componentDidMount, 'inner2 swap').to.have.been.calledOnce;
- expect(Inner2.prototype.componentWillUnmount, 'inner2 swap').not.to.have.been.called;
- expect(Inner2.prototype.componentDidUnmount, 'inner2 swap').not.to.have.been.called;
-
- inner2.forceUpdate();
-
- expect(Inner2.prototype.render, 'inner2 update').to.have.been.calledTwice;
- expect(Inner2.prototype.componentWillMount, 'inner2 update').to.have.been.calledOnce;
- expect(Inner2.prototype.componentDidMount, 'inner2 update').to.have.been.calledOnce;
- expect(Inner2.prototype.componentWillUnmount, 'inner2 update').not.to.have.been.called;
- expect(Inner2.prototype.componentDidUnmount, 'inner2 update').not.to.have.been.called;
- });
-
- it('should remount when swapping between HOC child types', () => {
- class Outer extends Component {
- render({ child: Child }) {
- return <Child />;
- }
- }
-
- class Inner extends Component {
- componentWillMount() {}
- componentWillUnmount() {}
- render() {
- return <div class="inner">foo</div>;
- }
- }
- spyAll(Inner.prototype);
-
- const InnerFunc = () => (
- <div class="inner-func">bar</div>
- );
-
- let root = render(<Outer child={Inner} />, scratch, root);
-
- expect(Inner.prototype.componentWillMount, 'initial mount').to.have.been.calledOnce;
- expect(Inner.prototype.componentWillUnmount, 'initial mount').not.to.have.been.called;
-
- Inner.prototype.componentWillMount.reset();
- root = render(<Outer child={InnerFunc} />, scratch, root);
-
- expect(Inner.prototype.componentWillMount, 'unmount').not.to.have.been.called;
- expect(Inner.prototype.componentWillUnmount, 'unmount').to.have.been.calledOnce;
-
- Inner.prototype.componentWillUnmount.reset();
- root = render(<Outer child={Inner} />, scratch, root);
-
- expect(Inner.prototype.componentWillMount, 'remount').to.have.been.calledOnce;
- expect(Inner.prototype.componentWillUnmount, 'remount').not.to.have.been.called;
- });
- });
-
- describe('Component Nesting', () => {
- let useIntermediary = false;
-
- let createComponent = (Intermediary) => {
- class C extends Component {
- componentWillMount() {}
- componentDidUnmount() {}
- render({ children }) {
- if (!useIntermediary) return children[0];
- let I = useIntermediary===true ? Intermediary : useIntermediary;
- return <I>{children}</I>;
- }
- }
- spyAll(C.prototype);
- return C;
- };
-
- let createFunction = () => sinon.spy( ({ children }) => children[0] );
-
- let root;
- let rndr = n => root = render(n, scratch, root);
-
- let F1 = createFunction();
- let F2 = createFunction();
- let F3 = createFunction();
-
- let C1 = createComponent(F1);
- let C2 = createComponent(F2);
- let C3 = createComponent(F3);
-
- let reset = () => [C1, C2, C3].reduce(
- (acc, c) => acc.concat( Object.keys(c.prototype).map(key => c.prototype[key]) ),
- [F1, F2, F3]
- ).forEach( c => c.reset && c.reset() );
-
-
- it('should handle lifecycle for no intermediary in component tree', () => {
- reset();
- rndr(<C1><C2><C3>Some Text</C3></C2></C1>);
-
- expect(C1.prototype.componentWillMount, 'initial mount').to.have.been.calledOnce;
- expect(C2.prototype.componentWillMount, 'initial mount').to.have.been.calledOnce;
- expect(C3.prototype.componentWillMount, 'initial mount').to.have.been.calledOnce;
-
- reset();
- rndr(<C1><C2>Some Text</C2></C1>);
-
- expect(C1.prototype.componentWillMount, 'unmount innermost, C1').not.to.have.been.called;
- expect(C2.prototype.componentWillMount, 'unmount innermost, C2').not.to.have.been.called;
- expect(C3.prototype.componentDidUnmount, 'unmount innermost, C3').to.have.been.calledOnce;
-
- reset();
- rndr(<C1><C3>Some Text</C3></C1>);
-
- expect(C1.prototype.componentWillMount, 'swap innermost').not.to.have.been.called;
- expect(C2.prototype.componentDidUnmount, 'swap innermost').to.have.been.calledOnce;
- expect(C3.prototype.componentWillMount, 'swap innermost').to.have.been.calledOnce;
-
- reset();
- rndr(<C1><C2><C3>Some Text</C3></C2></C1>);
-
- expect(C1.prototype.componentDidUnmount, 'inject between, C1').not.to.have.been.called;
- expect(C1.prototype.componentWillMount, 'inject between, C1').not.to.have.been.called;
- expect(C2.prototype.componentWillMount, 'inject between, C2').to.have.been.calledOnce;
- expect(C3.prototype.componentDidUnmount, 'inject between, C3').to.have.been.calledOnce;
- expect(C3.prototype.componentWillMount, 'inject between, C3').to.have.been.calledOnce;
- });
-
-
- it('should handle lifecycle for nested intermediary functional components', () => {
- useIntermediary = true;
-
- rndr(<div />);
- reset();
- rndr(<C1><C2><C3>Some Text</C3></C2></C1>);
-
- expect(C1.prototype.componentWillMount, 'initial mount w/ intermediary fn, C1').to.have.been.calledOnce;
- expect(C2.prototype.componentWillMount, 'initial mount w/ intermediary fn, C2').to.have.been.calledOnce;
- expect(C3.prototype.componentWillMount, 'initial mount w/ intermediary fn, C3').to.have.been.calledOnce;
-
- reset();
- rndr(<C1><C2>Some Text</C2></C1>);
-
- expect(C1.prototype.componentWillMount, 'unmount innermost w/ intermediary fn, C1').not.to.have.been.called;
- expect(C2.prototype.componentWillMount, 'unmount innermost w/ intermediary fn, C2').not.to.have.been.called;
- expect(C3.prototype.componentDidUnmount, 'unmount innermost w/ intermediary fn, C3').to.have.been.calledOnce;
-
- reset();
- rndr(<C1><C3>Some Text</C3></C1>);
-
- expect(C1.prototype.componentWillMount, 'swap innermost w/ intermediary fn').not.to.have.been.called;
- expect(C2.prototype.componentDidUnmount, 'swap innermost w/ intermediary fn').to.have.been.calledOnce;
- expect(C3.prototype.componentWillMount, 'swap innermost w/ intermediary fn').to.have.been.calledOnce;
-
- reset();
- rndr(<C1><C2><C3>Some Text</C3></C2></C1>);
-
- expect(C1.prototype.componentDidUnmount, 'inject between, C1 w/ intermediary fn').not.to.have.been.called;
- expect(C1.prototype.componentWillMount, 'inject between, C1 w/ intermediary fn').not.to.have.been.called;
- expect(C2.prototype.componentWillMount, 'inject between, C2 w/ intermediary fn').to.have.been.calledOnce;
- expect(C3.prototype.componentDidUnmount, 'inject between, C3 w/ intermediary fn').to.have.been.calledOnce;
- expect(C3.prototype.componentWillMount, 'inject between, C3 w/ intermediary fn').to.have.been.calledOnce;
- });
-
-
- it('should handle lifecycle for nested intermediary elements', () => {
- useIntermediary = 'div';
-
- rndr(<div />);
- reset();
- rndr(<C1><C2><C3>Some Text</C3></C2></C1>);
-
- expect(C1.prototype.componentWillMount, 'initial mount w/ intermediary div, C1').to.have.been.calledOnce;
- expect(C2.prototype.componentWillMount, 'initial mount w/ intermediary div, C2').to.have.been.calledOnce;
- expect(C3.prototype.componentWillMount, 'initial mount w/ intermediary div, C3').to.have.been.calledOnce;
-
- reset();
- rndr(<C1><C2>Some Text</C2></C1>);
-
- expect(C1.prototype.componentWillMount, 'unmount innermost w/ intermediary div, C1').not.to.have.been.called;
- expect(C2.prototype.componentDidUnmount, 'unmount innermost w/ intermediary div, C2 ummount').not.to.have.been.called;
- expect(C2.prototype.componentWillMount, 'unmount innermost w/ intermediary div, C2').not.to.have.been.called;
- expect(C3.prototype.componentDidUnmount, 'unmount innermost w/ intermediary div, C3').to.have.been.calledOnce;
-
- reset();
- rndr(<C1><C3>Some Text</C3></C1>);
-
- expect(C1.prototype.componentWillMount, 'swap innermost w/ intermediary div').not.to.have.been.called;
- expect(C2.prototype.componentDidUnmount, 'swap innermost w/ intermediary div').to.have.been.calledOnce;
- expect(C3.prototype.componentWillMount, 'swap innermost w/ intermediary div').to.have.been.calledOnce;
-
- reset();
- rndr(<C1><C2><C3>Some Text</C3></C2></C1>);
-
- expect(C1.prototype.componentDidUnmount, 'inject between, C1 w/ intermediary div').not.to.have.been.called;
- expect(C1.prototype.componentWillMount, 'inject between, C1 w/ intermediary div').not.to.have.been.called;
- expect(C2.prototype.componentWillMount, 'inject between, C2 w/ intermediary div').to.have.been.calledOnce;
- expect(C3.prototype.componentDidUnmount, 'inject between, C3 w/ intermediary div').to.have.been.calledOnce;
- expect(C3.prototype.componentWillMount, 'inject between, C3 w/ intermediary div').to.have.been.calledOnce;
- });
- });
-});
diff --git a/thirdparty/preact/test/browser/context.js b/thirdparty/preact/test/browser/context.js
deleted file mode 100644
index ed5f81471..000000000
--- a/thirdparty/preact/test/browser/context.js
+++ /dev/null
@@ -1,174 +0,0 @@
-import { h, render, Component } from '../../src/preact';
-/** @jsx h */
-
-const CHILDREN_MATCHER = sinon.match( v => v==null || Array.isArray(v) && !v.length , '[empty children]');
-
-describe('context', () => {
- let scratch;
-
- before( () => {
- scratch = document.createElement('div');
- (document.body || document.documentElement).appendChild(scratch);
- });
-
- beforeEach( () => {
- scratch.innerHTML = '';
- });
-
- after( () => {
- scratch.parentNode.removeChild(scratch);
- scratch = null;
- });
-
- it('should pass context to grandchildren', () => {
- const CONTEXT = { a:'a' };
- const PROPS = { b:'b' };
- // let inner;
-
- class Outer extends Component {
- getChildContext() {
- return CONTEXT;
- }
- render(props) {
- return <div><Inner {...props} /></div>;
- }
- }
- sinon.spy(Outer.prototype, 'getChildContext');
-
- class Inner extends Component {
- // constructor() {
- // super();
- // inner = this;
- // }
- shouldComponentUpdate() { return true; }
- componentWillReceiveProps() {}
- componentWillUpdate() {}
- componentDidUpdate() {}
- render(props, state, context) {
- return <div>{ context && context.a }</div>;
- }
- }
- sinon.spy(Inner.prototype, 'shouldComponentUpdate');
- sinon.spy(Inner.prototype, 'componentWillReceiveProps');
- sinon.spy(Inner.prototype, 'componentWillUpdate');
- sinon.spy(Inner.prototype, 'componentDidUpdate');
- sinon.spy(Inner.prototype, 'render');
-
- render(<Outer />, scratch, scratch.lastChild);
-
- expect(Outer.prototype.getChildContext).to.have.been.calledOnce;
-
- // initial render does not invoke anything but render():
- expect(Inner.prototype.render).to.have.been.calledWith({ children:CHILDREN_MATCHER }, {}, CONTEXT);
-
- CONTEXT.foo = 'bar';
- render(<Outer {...PROPS} />, scratch, scratch.lastChild);
-
- expect(Outer.prototype.getChildContext).to.have.been.calledTwice;
-
- let props = { children: CHILDREN_MATCHER, ...PROPS };
- expect(Inner.prototype.shouldComponentUpdate).to.have.been.calledOnce.and.calledWith(props, {}, CONTEXT);
- expect(Inner.prototype.componentWillReceiveProps).to.have.been.calledWith(props, CONTEXT);
- expect(Inner.prototype.componentWillUpdate).to.have.been.calledWith(props, {});
- expect(Inner.prototype.componentDidUpdate).to.have.been.calledWith({ children:CHILDREN_MATCHER }, {});
- expect(Inner.prototype.render).to.have.been.calledWith(props, {}, CONTEXT);
-
-
- /* Future:
- * Newly created context objects are *not* currently cloned.
- * This test checks that they *are* cloned.
- */
- // Inner.prototype.render.reset();
- // CONTEXT.foo = 'baz';
- // inner.forceUpdate();
- // expect(Inner.prototype.render).to.have.been.calledWith(PROPS, {}, { a:'a', foo:'bar' });
- });
-
- it('should pass context to direct children', () => {
- const CONTEXT = { a:'a' };
- const PROPS = { b:'b' };
-
- class Outer extends Component {
- getChildContext() {
- return CONTEXT;
- }
- render(props) {
- return <Inner {...props} />;
- }
- }
- sinon.spy(Outer.prototype, 'getChildContext');
-
- class Inner extends Component {
- shouldComponentUpdate() { return true; }
- componentWillReceiveProps() {}
- componentWillUpdate() {}
- componentDidUpdate() {}
- render(props, state, context) {
- return <div>{ context && context.a }</div>;
- }
- }
- sinon.spy(Inner.prototype, 'shouldComponentUpdate');
- sinon.spy(Inner.prototype, 'componentWillReceiveProps');
- sinon.spy(Inner.prototype, 'componentWillUpdate');
- sinon.spy(Inner.prototype, 'componentDidUpdate');
- sinon.spy(Inner.prototype, 'render');
-
- render(<Outer />, scratch, scratch.lastChild);
-
- expect(Outer.prototype.getChildContext).to.have.been.calledOnce;
-
- // initial render does not invoke anything but render():
- expect(Inner.prototype.render).to.have.been.calledWith({ children: CHILDREN_MATCHER }, {}, CONTEXT);
-
- CONTEXT.foo = 'bar';
- render(<Outer {...PROPS} />, scratch, scratch.lastChild);
-
- expect(Outer.prototype.getChildContext).to.have.been.calledTwice;
-
- let props = { children: CHILDREN_MATCHER, ...PROPS };
- expect(Inner.prototype.shouldComponentUpdate).to.have.been.calledOnce.and.calledWith(props, {}, CONTEXT);
- expect(Inner.prototype.componentWillReceiveProps).to.have.been.calledWith(props, CONTEXT);
- expect(Inner.prototype.componentWillUpdate).to.have.been.calledWith(props, {});
- expect(Inner.prototype.componentDidUpdate).to.have.been.calledWith({ children: CHILDREN_MATCHER }, {});
- expect(Inner.prototype.render).to.have.been.calledWith(props, {}, CONTEXT);
-
- // make sure render() could make use of context.a
- expect(Inner.prototype.render).to.have.returned(sinon.match({ children:['a'] }));
- });
-
- it('should preserve existing context properties when creating child contexts', () => {
- let outerContext = { outer:true },
- innerContext = { inner:true };
- class Outer extends Component {
- getChildContext() {
- return { outerContext };
- }
- render() {
- return <div><Inner /></div>;
- }
- }
-
- class Inner extends Component {
- getChildContext() {
- return { innerContext };
- }
- render() {
- return <InnerMost />;
- }
- }
-
- class InnerMost extends Component {
- render() {
- return <strong>test</strong>;
- }
- }
-
- sinon.spy(Inner.prototype, 'render');
- sinon.spy(InnerMost.prototype, 'render');
-
- render(<Outer />, scratch);
-
- expect(Inner.prototype.render).to.have.been.calledWith({ children: CHILDREN_MATCHER }, {}, { outerContext });
- expect(InnerMost.prototype.render).to.have.been.calledWith({ children: CHILDREN_MATCHER }, {}, { outerContext, innerContext });
- });
-});
diff --git a/thirdparty/preact/test/browser/devtools.js b/thirdparty/preact/test/browser/devtools.js
deleted file mode 100644
index 12c0e3369..000000000
--- a/thirdparty/preact/test/browser/devtools.js
+++ /dev/null
@@ -1,234 +0,0 @@
-import { h, Component, render } from '../../src/preact';
-import { initDevTools } from '../../devtools/devtools';
-import { unmountComponent } from '../../src/vdom/component';
-
-class StatefulComponent extends Component {
- constructor(props) {
- super(props);
-
- this.state = {count: 0};
- }
-
- render() {
- return h('span', {}, String(this.state.count));
- }
-}
-
-function FunctionalComponent() {
- return h('span', {class: 'functional'}, 'Functional');
-}
-
-function Label({label}) {
- return label;
-}
-
-class MultiChild extends Component {
- constructor(props) {
- super(props);
- this.state = {count: props.initialCount};
- }
-
- render() {
- return h('div', {}, Array(this.state.count).fill('child'));
- }
-}
-
-let describe_ = describe;
-if (!('name' in Function.prototype)) {
- // Skip these tests under Internet Explorer
- describe_ = describe.skip;
-}
-
-describe_('React Developer Tools integration', () => {
- let cleanup;
- let container;
- let renderer;
-
- // Maps of DOM node to React*Component-like objects.
- // For composite components, there will be two instances for each node, one
- // for the composite component (instanceMap) and one for the root child DOM
- // component rendered by that component (domInstanceMap)
- let instanceMap = new Map();
- let domInstanceMap = new Map();
-
- beforeEach(() => {
- container = document.createElement('div');
- document.body.appendChild(container);
-
- const onMount = instance => {
- if (instance._renderedChildren) {
- domInstanceMap.set(instance.node, instance);
- } else {
- instanceMap.set(instance.node, instance);
- }
- };
-
- const onUnmount = instance => {
- instanceMap.delete(instance.node);
- domInstanceMap.delete(instance.node);
- };
-
- global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
- inject: sinon.spy(_renderer => {
- renderer = _renderer;
- renderer.Mount._renderNewRootComponent = sinon.stub();
- renderer.Reconciler.mountComponent = sinon.spy(onMount);
- renderer.Reconciler.unmountComponent = sinon.spy(onUnmount);
- renderer.Reconciler.receiveComponent = sinon.stub();
- })
- };
- cleanup = initDevTools();
- });
-
- afterEach(() => {
- container.remove();
- cleanup();
- });
-
- it('registers preact as a renderer with the React DevTools hook', () => {
- expect(global.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject).to.be.called;
- });
-
- // Basic component addition/update/removal tests
- it('notifies dev tools about new components', () => {
- render(h(StatefulComponent), container);
- expect(renderer.Reconciler.mountComponent).to.be.called;
- });
-
- it('notifies dev tools about component updates', () => {
- const node = render(h(StatefulComponent), container);
- node._component.forceUpdate();
- expect(renderer.Reconciler.receiveComponent).to.be.called;
- });
-
- it('notifies dev tools when components are removed', () => {
- const node = render(h(StatefulComponent), container);
- unmountComponent(node._component, true);
- expect(renderer.Reconciler.unmountComponent).to.be.called;
- });
-
- // Test properties of DOM components exposed to devtools via
- // ReactDOMComponent-like instances
- it('exposes the tag name of DOM components', () => {
- const node = render(h(StatefulComponent), container);
- const domInstance = domInstanceMap.get(node);
- expect(domInstance._currentElement.type).to.equal('span');
- });
-
- it('exposes DOM component props', () => {
- const node = render(h(FunctionalComponent), container);
- const domInstance = domInstanceMap.get(node);
- expect(domInstance._currentElement.props.class).to.equal('functional');
- });
-
- it('exposes text component contents', () => {
- const node = render(h(Label, {label: 'Text content'}), container);
- const textInstance = domInstanceMap.get(node);
- expect(textInstance._stringText).to.equal('Text content');
- });
-
- // Test properties of composite components exposed to devtools via
- // ReactCompositeComponent-like instances
- it('exposes the name of composite component classes', () => {
- const node = render(h(StatefulComponent), container);
- expect(instanceMap.get(node).getName()).to.equal('StatefulComponent');
- });
-
- it('exposes composite component props', () => {
- const node = render(h(Label, {label: 'Text content'}), container);
- const instance = instanceMap.get(node);
- expect(instance._currentElement.props.label).to.equal('Text content');
- });
-
- it('exposes composite component state', () => {
- const node = render(h(StatefulComponent), container);
-
- node._component.setState({count: 42});
- node._component.forceUpdate();
-
- expect(instanceMap.get(node).state).to.deep.equal({count: 42});
- });
-
- // Test setting state via devtools
- it('updates component when setting state from devtools', () => {
- const node = render(h(StatefulComponent), container);
-
- instanceMap.get(node).setState({count: 10});
- instanceMap.get(node).forceUpdate();
-
- expect(node.textContent).to.equal('10');
- });
-
- // Test that the original instance is exposed via `_instance` so it can
- // be accessed conveniently via `$r` in devtools
-
- // Functional component handling tests
- it('wraps functional components with stateful ones', () => {
- const vnode = h(FunctionalComponent);
- expect(vnode.nodeName.prototype).to.have.property('render');
- });
-
- it('exposes the name of functional components', () => {
- const node = render(h(FunctionalComponent), container);
- const instance = instanceMap.get(node);
- expect(instance.getName()).to.equal('FunctionalComponent');
- });
-
- it('exposes a fallback name if the component has no useful name', () => {
- const node = render(h(() => h('div')), container);
- const instance = instanceMap.get(node);
- expect(instance.getName()).to.equal('(Function.name missing)');
- });
-
- // Test handling of DOM children
- it('notifies dev tools about DOM children', () => {
- const node = render(h(StatefulComponent), container);
- const domInstance = domInstanceMap.get(node);
- expect(renderer.Reconciler.mountComponent).to.have.been.calledWith(domInstance);
- });
-
- it('notifies dev tools when a component update adds DOM children', () => {
- const node = render(h(MultiChild, {initialCount: 2}), container);
-
- node._component.setState({count: 4});
- node._component.forceUpdate();
-
- expect(renderer.Reconciler.mountComponent).to.have.been.called.twice;
- });
-
- it('notifies dev tools when a component update modifies DOM children', () => {
- const node = render(h(StatefulComponent), container);
-
- instanceMap.get(node).setState({count: 10});
- instanceMap.get(node).forceUpdate();
-
- const textInstance = domInstanceMap.get(node.childNodes[0]);
- expect(textInstance._stringText).to.equal('10');
- });
-
- it('notifies dev tools when a component update removes DOM children', () => {
- const node = render(h(MultiChild, {initialCount: 1}), container);
-
- node._component.setState({count: 0});
- node._component.forceUpdate();
-
- expect(renderer.Reconciler.unmountComponent).to.be.called;
- });
-
- // Root component info
- it('exposes root components on the _instancesByReactRootID map', () => {
- render(h(StatefulComponent), container);
- expect(Object.keys(renderer.Mount._instancesByReactRootID).length).to.equal(1);
- });
-
- it('notifies dev tools when new root components are mounted', () => {
- render(h(StatefulComponent), container);
- expect(renderer.Mount._renderNewRootComponent).to.be.called;
- });
-
- it('removes root components when they are unmounted', () => {
- const node = render(h(StatefulComponent), container);
- unmountComponent(node._component, true);
- expect(Object.keys(renderer.Mount._instancesByReactRootID).length).to.equal(0);
- });
-});
diff --git a/thirdparty/preact/test/browser/keys.js b/thirdparty/preact/test/browser/keys.js
deleted file mode 100644
index e0a6b9ae8..000000000
--- a/thirdparty/preact/test/browser/keys.js
+++ /dev/null
@@ -1,85 +0,0 @@
-import { h, Component, render } from '../../src/preact';
-/** @jsx h */
-
-describe('keys', () => {
- let scratch;
-
- before( () => {
- scratch = document.createElement('div');
- (document.body || document.documentElement).appendChild(scratch);
- });
-
- beforeEach( () => {
- scratch.innerHTML = '';
- });
-
- after( () => {
- scratch.parentNode.removeChild(scratch);
- scratch = null;
- });
-
- // See developit/preact-compat#21
- it('should remove orphaned keyed nodes', () => {
- let root = render((
- <div>
- <div>1</div>
- <li key="a">a</li>
- </div>
- ), scratch);
-
- root = render((
- <div>
- <div>2</div>
- <li key="b">b</li>
- </div>
- ), scratch, root);
-
- expect(scratch.innerHTML).to.equal('<div><div>2</div><li>b</li></div>');
- });
-
- it('should set VNode#key property', () => {
- expect(<div />).to.have.property('key').that.is.empty;
- expect(<div a="a" />).to.have.property('key').that.is.empty;
- expect(<div key="1" />).to.have.property('key', '1');
- });
-
- it('should remove keyed nodes (#232)', () => {
- class App extends Component {
- componentDidMount() {
- setTimeout(() => this.setState({opened: true,loading: true}), 10);
- setTimeout(() => this.setState({opened: true,loading: false}), 20);
- }
-
- render({ opened, loading }) {
- return (
- <BusyIndicator id="app" busy={loading}>
- <div>This div needs to be here for this to break</div>
- { opened && !loading && <div>{[]}</div> }
- </BusyIndicator>
- );
- }
- }
-
- class BusyIndicator extends Component {
- render({ children, busy }) {
- return <div class={busy ? "busy" : ""}>
- { children && children.length ? children : <div class="busy-placeholder"></div> }
- <div class="indicator">
- <div>indicator</div>
- <div>indicator</div>
- <div>indicator</div>
- </div>
- </div>;
- }
- }
-
- let root;
-
- root = render(<App />, scratch, root);
- root = render(<App opened loading />, scratch, root);
- root = render(<App opened />, scratch, root);
-
- let html = String(root.innerHTML).replace(/ class=""/g, '');
- expect(html).to.equal('<div>This div needs to be here for this to break</div><div></div><div class="indicator"><div>indicator</div><div>indicator</div><div>indicator</div></div>');
- });
-});
diff --git a/thirdparty/preact/test/browser/lifecycle.js b/thirdparty/preact/test/browser/lifecycle.js
deleted file mode 100644
index 4deb92163..000000000
--- a/thirdparty/preact/test/browser/lifecycle.js
+++ /dev/null
@@ -1,495 +0,0 @@
-import { h, render, rerender, Component } from '../../src/preact';
-/** @jsx h */
-
-let spyAll = obj => Object.keys(obj).forEach( key => sinon.spy(obj,key) );
-
-const EMPTY_CHILDREN = [];
-
-describe('Lifecycle methods', () => {
- let scratch;
-
- before( () => {
- scratch = document.createElement('div');
- (document.body || document.documentElement).appendChild(scratch);
- });
-
- beforeEach( () => {
- scratch.innerHTML = '';
- });
-
- after( () => {
- scratch.parentNode.removeChild(scratch);
- scratch = null;
- });
-
-
- describe('#componentWillUpdate', () => {
- it('should NOT be called on initial render', () => {
- class ReceivePropsComponent extends Component {
- componentWillUpdate() {}
- render() {
- return <div />;
- }
- }
- sinon.spy(ReceivePropsComponent.prototype, 'componentWillUpdate');
- render(<ReceivePropsComponent />, scratch);
- expect(ReceivePropsComponent.prototype.componentWillUpdate).not.to.have.been.called;
- });
-
- it('should be called when rerender with new props from parent', () => {
- let doRender;
- class Outer extends Component {
- constructor(p, c) {
- super(p, c);
- this.state = { i: 0 };
- }
- componentDidMount() {
- doRender = () => this.setState({ i: this.state.i + 1 });
- }
- render(props, { i }) {
- return <Inner i={i} {...props} />;
- }
- }
- class Inner extends Component {
- componentWillUpdate(nextProps, nextState) {
- expect(nextProps).to.be.deep.equal({ children:EMPTY_CHILDREN, i: 1 });
- expect(nextState).to.be.deep.equal({});
- }
- render() {
- return <div />;
- }
- }
- sinon.spy(Inner.prototype, 'componentWillUpdate');
- sinon.spy(Outer.prototype, 'componentDidMount');
-
- // Initial render
- render(<Outer />, scratch);
- expect(Inner.prototype.componentWillUpdate).not.to.have.been.called;
-
- // Rerender inner with new props
- doRender();
- rerender();
- expect(Inner.prototype.componentWillUpdate).to.have.been.called;
- });
-
- it('should be called on new state', () => {
- let doRender;
- class ReceivePropsComponent extends Component {
- componentWillUpdate() {}
- componentDidMount() {
- doRender = () => this.setState({ i: this.state.i + 1 });
- }
- render() {
- return <div />;
- }
- }
- sinon.spy(ReceivePropsComponent.prototype, 'componentWillUpdate');
- render(<ReceivePropsComponent />, scratch);
- expect(ReceivePropsComponent.prototype.componentWillUpdate).not.to.have.been.called;
-
- doRender();
- rerender();
- expect(ReceivePropsComponent.prototype.componentWillUpdate).to.have.been.called;
- });
- });
-
- describe('#componentWillReceiveProps', () => {
- it('should NOT be called on initial render', () => {
- class ReceivePropsComponent extends Component {
- componentWillReceiveProps() {}
- render() {
- return <div />;
- }
- }
- sinon.spy(ReceivePropsComponent.prototype, 'componentWillReceiveProps');
- render(<ReceivePropsComponent />, scratch);
- expect(ReceivePropsComponent.prototype.componentWillReceiveProps).not.to.have.been.called;
- });
-
- it('should be called when rerender with new props from parent', () => {
- let doRender;
- class Outer extends Component {
- constructor(p, c) {
- super(p, c);
- this.state = { i: 0 };
- }
- componentDidMount() {
- doRender = () => this.setState({ i: this.state.i + 1 });
- }
- render(props, { i }) {
- return <Inner i={i} {...props} />;
- }
- }
- class Inner extends Component {
- componentWillMount() {
- expect(this.props.i).to.be.equal(0);
- }
- componentWillReceiveProps(nextProps) {
- expect(nextProps.i).to.be.equal(1);
- }
- render() {
- return <div />;
- }
- }
- sinon.spy(Inner.prototype, 'componentWillReceiveProps');
- sinon.spy(Outer.prototype, 'componentDidMount');
-
- // Initial render
- render(<Outer />, scratch);
- expect(Inner.prototype.componentWillReceiveProps).not.to.have.been.called;
-
- // Rerender inner with new props
- doRender();
- rerender();
- expect(Inner.prototype.componentWillReceiveProps).to.have.been.called;
- });
-
- it('should be called in right execution order', () => {
- let doRender;
- class Outer extends Component {
- constructor(p, c) {
- super(p, c);
- this.state = { i: 0 };
- }
- componentDidMount() {
- doRender = () => this.setState({ i: this.state.i + 1 });
- }
- render(props, { i }) {
- return <Inner i={i} {...props} />;
- }
- }
- class Inner extends Component {
- componentDidUpdate() {
- expect(Inner.prototype.componentWillReceiveProps).to.have.been.called;
- expect(Inner.prototype.componentWillUpdate).to.have.been.called;
- }
- componentWillReceiveProps() {
- expect(Inner.prototype.componentWillUpdate).not.to.have.been.called;
- expect(Inner.prototype.componentDidUpdate).not.to.have.been.called;
- }
- componentWillUpdate() {
- expect(Inner.prototype.componentWillReceiveProps).to.have.been.called;
- expect(Inner.prototype.componentDidUpdate).not.to.have.been.called;
- }
- render() {
- return <div />;
- }
- }
- sinon.spy(Inner.prototype, 'componentWillReceiveProps');
- sinon.spy(Inner.prototype, 'componentDidUpdate');
- sinon.spy(Inner.prototype, 'componentWillUpdate');
- sinon.spy(Outer.prototype, 'componentDidMount');
-
- render(<Outer />, scratch);
- doRender();
- rerender();
-
- expect(Inner.prototype.componentWillReceiveProps).to.have.been.calledBefore(Inner.prototype.componentWillUpdate);
- expect(Inner.prototype.componentWillUpdate).to.have.been.calledBefore(Inner.prototype.componentDidUpdate);
- });
- });
-
-
- let _it = it;
- describe('#constructor and component(Did|Will)(Mount|Unmount)', () => {
- /* global DISABLE_FLAKEY */
- let it = DISABLE_FLAKEY ? xit : _it;
-
- let setState;
- class Outer extends Component {
- constructor(p, c) {
- super(p, c);
- this.state = { show:true };
- setState = s => this.setState(s);
- }
- render(props, { show }) {
- return (
- <div>
- { show && (
- <Inner {...props} />
- ) }
- </div>
- );
- }
- }
-
- class LifecycleTestComponent extends Component {
- constructor(p, c) { super(p, c); this._constructor(); }
- _constructor() {}
- componentWillMount() {}
- componentDidMount() {}
- componentWillUnmount() {}
- componentDidUnmount() {}
- render() { return <div />; }
- }
-
- class Inner extends LifecycleTestComponent {
- render() {
- return (
- <div>
- <InnerMost />
- </div>
- );
- }
- }
-
- class InnerMost extends LifecycleTestComponent {
- render() { return <div />; }
- }
-
- let spies = ['_constructor', 'componentWillMount', 'componentDidMount', 'componentWillUnmount', 'componentDidUnmount'];
-
- let verifyLifycycleMethods = (TestComponent) => {
- let proto = TestComponent.prototype;
- spies.forEach( s => sinon.spy(proto, s) );
- let reset = () => spies.forEach( s => proto[s].reset() );
-
- it('should be invoked for components on initial render', () => {
- reset();
- render(<Outer />, scratch);
- expect(proto._constructor).to.have.been.called;
- expect(proto.componentDidMount).to.have.been.called;
- expect(proto.componentWillMount).to.have.been.calledBefore(proto.componentDidMount);
- expect(proto.componentDidMount).to.have.been.called;
- });
-
- it('should be invoked for components on unmount', () => {
- reset();
- setState({ show:false });
- rerender();
-
- expect(proto.componentDidUnmount).to.have.been.called;
- expect(proto.componentWillUnmount).to.have.been.calledBefore(proto.componentDidUnmount);
- expect(proto.componentDidUnmount).to.have.been.called;
- });
-
- it('should be invoked for components on re-render', () => {
- reset();
- setState({ show:true });
- rerender();
-
- expect(proto._constructor).to.have.been.called;
- expect(proto.componentDidMount).to.have.been.called;
- expect(proto.componentWillMount).to.have.been.calledBefore(proto.componentDidMount);
- expect(proto.componentDidMount).to.have.been.called;
- });
- };
-
- describe('inner components', () => {
- verifyLifycycleMethods(Inner);
- });
-
- describe('innermost components', () => {
- verifyLifycycleMethods(InnerMost);
- });
-
- describe('when shouldComponentUpdate() returns false', () => {
- let setState;
-
- class Outer extends Component {
- constructor() {
- super();
- this.state = { show:true };
- setState = s => this.setState(s);
- }
- render(props, { show }) {
- return (
- <div>
- { show && (
- <div>
- <Inner {...props} />
- </div>
- ) }
- </div>
- );
- }
- }
-
- class Inner extends Component {
- shouldComponentUpdate(){ return false; }
- componentWillMount() {}
- componentDidMount() {}
- componentWillUnmount() {}
- componentDidUnmount() {}
- render() {
- return <div />;
- }
- }
-
- let proto = Inner.prototype;
- let spies = ['componentWillMount', 'componentDidMount', 'componentWillUnmount', 'componentDidUnmount'];
- spies.forEach( s => sinon.spy(proto, s) );
-
- let reset = () => spies.forEach( s => proto[s].reset() );
-
- beforeEach( () => reset() );
-
- it('should be invoke normally on initial mount', () => {
- render(<Outer />, scratch);
- expect(proto.componentWillMount).to.have.been.called;
- expect(proto.componentWillMount).to.have.been.calledBefore(proto.componentDidMount);
- expect(proto.componentDidMount).to.have.been.called;
- });
-
- it('should be invoked normally on unmount', () => {
- setState({ show:false });
- rerender();
-
- expect(proto.componentWillUnmount).to.have.been.called;
- expect(proto.componentWillUnmount).to.have.been.calledBefore(proto.componentDidUnmount);
- expect(proto.componentDidUnmount).to.have.been.called;
- });
-
- it('should still invoke mount for shouldComponentUpdate():false', () => {
- setState({ show:true });
- rerender();
-
- expect(proto.componentWillMount).to.have.been.called;
- expect(proto.componentWillMount).to.have.been.calledBefore(proto.componentDidMount);
- expect(proto.componentDidMount).to.have.been.called;
- });
-
- it('should still invoke unmount for shouldComponentUpdate():false', () => {
- setState({ show:false });
- rerender();
-
- expect(proto.componentWillUnmount).to.have.been.called;
- expect(proto.componentWillUnmount).to.have.been.calledBefore(proto.componentDidUnmount);
- expect(proto.componentDidUnmount).to.have.been.called;
- });
- });
- });
-
- describe('Lifecycle DOM Timing', () => {
- it('should be invoked when dom does (DidMount, WillUnmount) or does not (WillMount, DidUnmount) exist', () => {
- let setState;
- class Outer extends Component {
- constructor() {
- super();
- this.state = { show:true };
- setState = s => {
- this.setState(s);
- this.forceUpdate();
- };
- }
- componentWillMount() {
- expect(document.getElementById('OuterDiv'), 'Outer componentWillMount').to.not.exist;
- }
- componentDidMount() {
- expect(document.getElementById('OuterDiv'), 'Outer componentDidMount').to.exist;
- }
- componentWillUnmount() {
- expect(document.getElementById('OuterDiv'), 'Outer componentWillUnmount').to.exist;
- }
- componentDidUnmount() {
- expect(document.getElementById('OuterDiv'), 'Outer componentDidUnmount').to.not.exist;
- }
- render(props, { show }) {
- return (
- <div id="OuterDiv">
- { show && (
- <div>
- <Inner {...props} />
- </div>
- ) }
- </div>
- );
- }
- }
-
- class Inner extends Component {
- componentWillMount() {
- expect(document.getElementById('InnerDiv'), 'Inner componentWillMount').to.not.exist;
- }
- componentDidMount() {
- expect(document.getElementById('InnerDiv'), 'Inner componentDidMount').to.exist;
- }
- componentWillUnmount() {
- // @TODO Component mounted into elements (non-components)
- // are currently unmounted after those elements, so their
- // DOM is unmounted prior to the method being called.
- //expect(document.getElementById('InnerDiv'), 'Inner componentWillUnmount').to.exist;
- }
- componentDidUnmount() {
- expect(document.getElementById('InnerDiv'), 'Inner componentDidUnmount').to.not.exist;
- }
-
- render() {
- return <div id="InnerDiv" />;
- }
- }
-
- let proto = Inner.prototype;
- let spies = ['componentWillMount', 'componentDidMount', 'componentWillUnmount', 'componentDidUnmount'];
- spies.forEach( s => sinon.spy(proto, s) );
-
- let reset = () => spies.forEach( s => proto[s].reset() );
-
- render(<Outer />, scratch);
- expect(proto.componentWillMount).to.have.been.called;
- expect(proto.componentWillMount).to.have.been.calledBefore(proto.componentDidMount);
- expect(proto.componentDidMount).to.have.been.called;
-
- reset();
- setState({ show:false });
-
- expect(proto.componentWillUnmount).to.have.been.called;
- expect(proto.componentWillUnmount).to.have.been.calledBefore(proto.componentDidUnmount);
- expect(proto.componentDidUnmount).to.have.been.called;
-
- reset();
- setState({ show:true });
-
- expect(proto.componentWillMount).to.have.been.called;
- expect(proto.componentWillMount).to.have.been.calledBefore(proto.componentDidMount);
- expect(proto.componentDidMount).to.have.been.called;
- });
-
- it('should remove this.base for HOC', () => {
- let createComponent = (name, fn) => {
- class C extends Component {
- componentWillUnmount() {
- expect(this.base, `${name}.componentWillUnmount`).to.exist;
- }
- componentDidUnmount() {
- expect(this.base, `${name}.componentDidUnmount`).not.to.exist;
- }
- render(props) { return fn(props); }
- }
- spyAll(C.prototype);
- return C;
- };
-
- class Wrapper extends Component {
- render({ children }) {
- return <div class="wrapper">{children}</div>;
- }
- }
-
- let One = createComponent('One', () => <Wrapper>one</Wrapper> );
- let Two = createComponent('Two', () => <Wrapper>two</Wrapper> );
- let Three = createComponent('Three', () => <Wrapper>three</Wrapper> );
-
- let components = [One, Two, Three];
-
- let Selector = createComponent('Selector', ({ page }) => {
- let Child = components[page];
- return <Child />;
- });
-
- class App extends Component {
- render(_, { page }) {
- return <Selector page={page} />;
- }
- }
-
- let app;
- render(<App ref={ c => app=c } />, scratch);
-
- for (let i=0; i<20; i++) {
- app.setState({ page: i%components.length });
- app.forceUpdate();
- }
- });
- });
-});
diff --git a/thirdparty/preact/test/browser/linked-state.js b/thirdparty/preact/test/browser/linked-state.js
deleted file mode 100644
index 03db2a7b8..000000000
--- a/thirdparty/preact/test/browser/linked-state.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import { Component } from '../../src/preact';
-import { createLinkedState } from '../../src/linked-state';
-
-describe('linked-state', () => {
- class TestComponent extends Component { }
- let testComponent, linkFunction;
-
- before( () => {
- testComponent = new TestComponent();
- sinon.spy(TestComponent.prototype, 'setState');
- });
-
- describe('createLinkedState without eventPath argument', () => {
-
- before( () => {
- linkFunction = createLinkedState(testComponent,'testStateKey');
- expect(linkFunction).to.be.a('function');
- });
-
- beforeEach( () => {
- TestComponent.prototype['setState'].reset();
- });
-
- it('should use value attribute on text input when no eventPath is supplied', () => {
- let element = document.createElement('input');
- element.type= 'text';
- element.value = 'newValue';
-
- linkFunction({
- currentTarget: element,
- target: element
- });
-
- expect(TestComponent.prototype.setState).to.have.been.calledOnce;
- expect(TestComponent.prototype.setState).to.have.been.calledWith({'testStateKey': 'newValue'});
-
- linkFunction.call(element);
-
- expect(TestComponent.prototype.setState).to.have.been.calledTwice;
- expect(TestComponent.prototype.setState.secondCall).to.have.been.calledWith({'testStateKey': 'newValue'});
- });
-
- it('should use checked attribute on checkbox input when no eventPath is supplied', () => {
- let checkboxElement = document.createElement('input');
- checkboxElement.type= 'checkbox';
- checkboxElement.checked = true;
-
- linkFunction({
- currentTarget: checkboxElement,
- target: checkboxElement
- });
-
- expect(TestComponent.prototype.setState).to.have.been.calledOnce;
- expect(TestComponent.prototype.setState).to.have.been.calledWith({'testStateKey': true});
- });
-
- it('should use checked attribute on radio input when no eventPath is supplied', () => {
- let radioElement = document.createElement('input');
- radioElement.type= 'radio';
- radioElement.checked = true;
-
- linkFunction({
- currentTarget: radioElement,
- target: radioElement
- });
-
- expect(TestComponent.prototype.setState).to.have.been.calledOnce;
- expect(TestComponent.prototype.setState).to.have.been.calledWith({'testStateKey': true});
- });
-
-
- it('should set dot notated state key appropriately', () => {
- linkFunction = createLinkedState(testComponent,'nested.state.key');
- let element = document.createElement('input');
- element.type= 'text';
- element.value = 'newValue';
-
- linkFunction({
- currentTarget: element,
- target: element
- });
-
- expect(TestComponent.prototype.setState).to.have.been.calledOnce;
- expect(TestComponent.prototype.setState).to.have.been.calledWith({nested: {state: {key: 'newValue'}}});
- });
-
- });
-
- describe('createLinkedState with eventPath argument', () => {
-
- before( () => {
- linkFunction = createLinkedState(testComponent,'testStateKey', 'nested.path');
- expect(linkFunction).to.be.a('function');
- });
-
- beforeEach( () => {
- TestComponent.prototype['setState'].reset();
- });
-
- it('should give precedence to nested.path on event over nested.path on component', () => {
- let event = {nested: {path: 'nestedPathValueFromEvent'}};
- let component = {_component: {nested: {path: 'nestedPathValueFromComponent'}}};
-
- linkFunction.call(component, event);
-
- expect(TestComponent.prototype.setState).to.have.been.calledOnce;
- expect(TestComponent.prototype.setState).to.have.been.calledWith({'testStateKey': 'nestedPathValueFromEvent'});
- });
- });
-});
diff --git a/thirdparty/preact/test/browser/performance.js b/thirdparty/preact/test/browser/performance.js
deleted file mode 100644
index e1f7d7956..000000000
--- a/thirdparty/preact/test/browser/performance.js
+++ /dev/null
@@ -1,245 +0,0 @@
-/*global coverage, ENABLE_PERFORMANCE, NODE_ENV*/
-/*eslint no-console:0*/
-/** @jsx h */
-
-let { h, Component, render } = require(NODE_ENV==='production' ? '../../dist/preact.min.js' : '../../src/preact');
-
-const MULTIPLIER = ENABLE_PERFORMANCE ? (coverage ? 5 : 1) : 999999;
-
-
-let now = typeof performance!=='undefined' && performance.now ? () => performance.now() : () => +new Date();
-
-function loop(iter, time) {
- let start = now(),
- count = 0;
- while ( now()-start < time ) {
- count++;
- iter();
- }
- return count;
-}
-
-
-function benchmark(iter, callback) {
- let a = 0;
- function noop() {
- try { a++; } finally { a += Math.random(); }
- }
-
- // warm
- for (let i=3; i--; ) noop(), iter();
-
- let count = 5,
- time = 200,
- passes = 0,
- noops = loop(noop, time),
- iterations = 0;
-
- function next() {
- iterations += loop(iter, time);
- setTimeout(++passes===count ? done : next, 10);
- }
-
- function done() {
- let ticks = Math.round(noops / iterations * count),
- hz = iterations / count / time * 1000,
- message = `${hz|0}/s (${ticks} ticks)`;
- callback({ iterations, noops, count, time, ticks, hz, message });
- }
-
- next();
-}
-
-
-describe('performance', function() {
- let scratch;
-
- this.timeout(10000);
-
- before( () => {
- if (coverage) {
- console.warn('WARNING: Code coverage is enabled, which dramatically reduces performance. Do not pay attention to these numbers.');
- }
- scratch = document.createElement('div');
- (document.body || document.documentElement).appendChild(scratch);
- });
-
- beforeEach( () => {
- scratch.innerHTML = '';
- });
-
- after( () => {
- scratch.parentNode.removeChild(scratch);
- scratch = null;
- });
-
- it('should rerender without changes fast', done => {
- let jsx = (
- <div class="foo bar" data-foo="bar" p={2}>
- <header>
- <h1 class="asdf">a {'b'} c {0} d</h1>
- <nav>
- <a href="/foo">Foo</a>
- <a href="/bar">Bar</a>
- </nav>
- </header>
- <main>
- <form onSubmit={()=>{}}>
- <input type="checkbox" checked={true} />
- <input type="checkbox" checked={false} />
- <fieldset>
- <label><input type="radio" checked /></label>
- <label><input type="radio" /></label>
- </fieldset>
- <button-bar>
- <button style="width:10px; height:10px; border:1px solid #FFF;">Normal CSS</button>
- <button style="top:0 ; right: 20">Poor CSS</button>
- <button style="invalid-prop:1;padding:1px;font:12px/1.1 arial,sans-serif;" icon>Poorer CSS</button>
- <button style={{ margin:0, padding:'10px', overflow:'visible' }}>Object CSS</button>
- </button-bar>
- </form>
- </main>
- </div>
- );
-
- let root;
- benchmark( () => {
- root = render(jsx, scratch, root);
- }, ({ ticks, message }) => {
- console.log(`PERF: empty diff: ${message}`);
- expect(ticks).to.be.below(350 * MULTIPLIER);
- done();
- });
- });
-
- it('should rerender repeated trees fast', done => {
- class Header extends Component {
- render() {
- return (
- <header>
- <h1 class="asdf">a {'b'} c {0} d</h1>
- <nav>
- <a href="/foo">Foo</a>
- <a href="/bar">Bar</a>
- </nav>
- </header>
- );
- }
- }
- class Form extends Component {
- render() {
- return (
- <form onSubmit={()=>{}}>
- <input type="checkbox" checked={true} />
- <input type="checkbox" checked={false} />
- <fieldset>
- <label><input type="radio" checked /></label>
- <label><input type="radio" /></label>
- </fieldset>
- <ButtonBar />
- </form>
- );
- }
- }
- class ButtonBar extends Component {
- render() {
- return (
- <button-bar>
- <Button style="width:10px; height:10px; border:1px solid #FFF;">Normal CSS</Button>
- <Button style="top:0 ; right: 20">Poor CSS</Button>
- <Button style="invalid-prop:1;padding:1px;font:12px/1.1 arial,sans-serif;" icon>Poorer CSS</Button>
- <Button style={{ margin:0, padding:'10px', overflow:'visible' }}>Object CSS</Button>
- </button-bar>
- );
- }
- }
- class Button extends Component {
- render(props) {
- return <button {...props} />;
- }
- }
- class Main extends Component {
- render() {
- return <Form />;
- }
- }
- class Root extends Component {
- render() {
- return (
- <div class="foo bar" data-foo="bar" p={2}>
- <Header />
- <Main />
- </div>
- );
- }
- }
- class Empty extends Component {
- render() {
- return <div />;
- }
- }
- class Parent extends Component {
- render({ child:C }) {
- return <C />;
- }
- }
-
- let root;
- benchmark( () => {
- root = render(<Parent child={Root} />, scratch, root);
- root = render(<Parent child={Empty} />, scratch, root);
- }, ({ ticks, message }) => {
- console.log(`PERF: repeat diff: ${message}`);
- expect(ticks).to.be.below(2000 * MULTIPLIER);
- done();
- });
- });
-
- it('should construct large VDOM trees fast', done => {
- const FIELDS = [];
- for (let i=100; i--; ) FIELDS.push((i*999).toString(36));
-
- let out = [];
- function digest(vnode) {
- out.push(vnode);
- out.length = 0;
- }
- benchmark( () => {
- digest(
- <div class="foo bar" data-foo="bar" p={2}>
- <header>
- <h1 class="asdf">a {'b'} c {0} d</h1>
- <nav>
- <a href="/foo">Foo</a>
- <a href="/bar">Bar</a>
- </nav>
- </header>
- <main>
- <form onSubmit={()=>{}}>
- <input type="checkbox" checked />
- <input type="checkbox" />
- <fieldset>
- { FIELDS.map( field => (
- <label>
- {field}:
- <input placeholder={field} />
- </label>
- )) }
- </fieldset>
- <button-bar>
- <button style="width:10px; height:10px; border:1px solid #FFF;">Normal CSS</button>
- <button style="top:0 ; right: 20">Poor CSS</button>
- <button style="invalid-prop:1;padding:1px;font:12px/1.1 arial,sans-serif;" icon>Poorer CSS</button>
- <button style={{ margin:0, padding:'10px', overflow:'visible' }}>Object CSS</button>
- </button-bar>
- </form>
- </main>
- </div>
- );
- }, ({ ticks, message }) => {
- console.log(`PERF: large VTree: ${message}`);
- expect(ticks).to.be.below(2000 * MULTIPLIER);
- done();
- });
- });
-});
diff --git a/thirdparty/preact/test/browser/refs.js b/thirdparty/preact/test/browser/refs.js
deleted file mode 100644
index 337a9717b..000000000
--- a/thirdparty/preact/test/browser/refs.js
+++ /dev/null
@@ -1,305 +0,0 @@
-import { h, render, Component } from '../../src/preact';
-/** @jsx h */
-
-// gives call count and argument errors names (otherwise sinon just uses "spy"):
-let spy = (name, ...args) => {
- let spy = sinon.spy(...args);
- spy.displayName = `spy('${name}')`;
- return spy;
-};
-
-describe('refs', () => {
- let scratch;
-
- before( () => {
- scratch = document.createElement('div');
- (document.body || document.documentElement).appendChild(scratch);
- });
-
- beforeEach( () => {
- scratch.innerHTML = '';
- });
-
- after( () => {
- scratch.parentNode.removeChild(scratch);
- scratch = null;
- });
-
- it('should invoke refs in render()', () => {
- let ref = spy('ref');
- render(<div ref={ref} />, scratch);
- expect(ref).to.have.been.calledOnce.and.calledWith(scratch.firstChild);
- });
-
- it('should invoke refs in Component.render()', () => {
- let outer = spy('outer'),
- inner = spy('inner');
- class Foo extends Component {
- render() {
- return (
- <div ref={outer}>
- <span ref={inner} />
- </div>
- );
- }
- }
- render(<Foo />, scratch);
-
- expect(outer).to.have.been.calledWith(scratch.firstChild);
- expect(inner).to.have.been.calledWith(scratch.firstChild.firstChild);
- });
-
- it('should pass components to ref functions', () => {
- let ref = spy('ref'),
- instance;
- class Foo extends Component {
- constructor() {
- super();
- instance = this;
- }
- render() {
- return <div />;
- }
- }
- render(<Foo ref={ref} />, scratch);
-
- expect(ref).to.have.been.calledOnce.and.calledWith(instance);
- });
-
- it('should pass rendered DOM from functional components to ref functions', () => {
- let ref = spy('ref');
-
- const Foo = () => <div />;
-
- let root = render(<Foo ref={ref} />, scratch);
- expect(ref).to.have.been.calledOnce.and.calledWith(scratch.firstChild);
-
- ref.reset();
- render(<Foo ref={ref} />, scratch, root);
- expect(ref).to.have.been.calledOnce.and.calledWith(scratch.firstChild);
-
- ref.reset();
- render(<span />, scratch, root);
- expect(ref).to.have.been.calledOnce.and.calledWith(null);
- });
-
- it('should pass children to ref functions', () => {
- let outer = spy('outer'),
- inner = spy('inner'),
- rerender, inst;
- class Outer extends Component {
- constructor() {
- super();
- rerender = () => this.forceUpdate();
- }
- render() {
- return (
- <div>
- <Inner ref={outer} />
- </div>
- );
- }
- }
- class Inner extends Component {
- constructor() {
- super();
- inst = this;
- }
- render() {
- return <span ref={inner} />;
- }
- }
-
- let root = render(<Outer />, scratch);
-
- expect(outer).to.have.been.calledOnce.and.calledWith(inst);
- expect(inner).to.have.been.calledOnce.and.calledWith(inst.base);
-
- outer.reset();
- inner.reset();
-
- rerender();
-
- expect(outer).to.have.been.calledOnce.and.calledWith(inst);
- expect(inner).to.have.been.calledOnce.and.calledWith(inst.base);
-
- outer.reset();
- inner.reset();
-
- render(<div />, scratch, root);
-
- expect(outer).to.have.been.calledOnce.and.calledWith(null);
- expect(inner).to.have.been.calledOnce.and.calledWith(null);
- });
-
- it('should pass high-order children to ref functions', () => {
- let outer = spy('outer'),
- inner = spy('inner'),
- innermost = spy('innermost'),
- outerInst,
- innerInst;
- class Outer extends Component {
- constructor() {
- super();
- outerInst = this;
- }
- render() {
- return <Inner ref={inner} />;
- }
- }
- class Inner extends Component {
- constructor() {
- super();
- innerInst = this;
- }
- render() {
- return <span ref={innermost} />;
- }
- }
-
- let root = render(<Outer ref={outer} />, scratch);
-
- expect(outer, 'outer initial').to.have.been.calledOnce.and.calledWith(outerInst);
- expect(inner, 'inner initial').to.have.been.calledOnce.and.calledWith(innerInst);
- expect(innermost, 'innerMost initial').to.have.been.calledOnce.and.calledWith(innerInst.base);
-
- outer.reset();
- inner.reset();
- innermost.reset();
- root = render(<Outer ref={outer} />, scratch, root);
-
- expect(outer, 'outer update').to.have.been.calledOnce.and.calledWith(outerInst);
- expect(inner, 'inner update').to.have.been.calledOnce.and.calledWith(innerInst);
- expect(innermost, 'innerMost update').to.have.been.calledOnce.and.calledWith(innerInst.base);
-
- outer.reset();
- inner.reset();
- innermost.reset();
- root = render(<div />, scratch, root);
-
- expect(outer, 'outer unmount').to.have.been.calledOnce.and.calledWith(null);
- expect(inner, 'inner unmount').to.have.been.calledOnce.and.calledWith(null);
- expect(innermost, 'innerMost unmount').to.have.been.calledOnce.and.calledWith(null);
- });
-
- it('should not pass ref into component as a prop', () => {
- let foo = spy('foo'),
- bar = spy('bar');
-
- class Foo extends Component {
- render(){ return <div />; }
- }
- const Bar = spy('Bar', () => <div />);
-
- sinon.spy(Foo.prototype, 'render');
-
- render((
- <div>
- <Foo ref={foo} a="a" />
- <Bar ref={bar} b="b" />
- </div>
- ), scratch);
-
- expect(Foo.prototype.render).to.have.been.calledWithMatch({ ref:sinon.match.falsy, a:'a' }, { }, { });
- expect(Bar).to.have.been.calledWithMatch({ b:'b', ref:bar }, { });
- });
-
- // Test for #232
- it('should only null refs after unmount', () => {
- let root, outer, inner;
-
- class TestUnmount extends Component {
- componentWillUnmount() {
- expect(this).to.have.property('outer', outer);
- expect(this).to.have.property('inner', inner);
- }
-
- componentDidUnmount() {
- expect(this).to.have.property('outer', null);
- expect(this).to.have.property('inner', null);
- }
-
- render() {
- return (
- <div id="outer" ref={ c => this.outer=c }>
- <div id="inner" ref={ c => this.inner=c } />
- </div>
- );
- }
- }
-
- sinon.spy(TestUnmount.prototype, 'componentWillUnmount');
- sinon.spy(TestUnmount.prototype, 'componentDidUnmount');
-
- root = render(<div><TestUnmount /></div>, scratch, root);
- outer = scratch.querySelector('#outer');
- inner = scratch.querySelector('#inner');
-
- expect(TestUnmount.prototype.componentWillUnmount).not.to.have.been.called;
- expect(TestUnmount.prototype.componentDidUnmount).not.to.have.been.called;
-
- root = render(<div />, scratch, root);
-
- expect(TestUnmount.prototype.componentWillUnmount).to.have.been.calledOnce;
- expect(TestUnmount.prototype.componentDidUnmount).to.have.been.calledOnce;
- });
-
- it('should null and re-invoke refs when swapping component root element type', () => {
- let inst;
-
- class App extends Component {
- render() {
- return <div><Child /></div>;
- }
- }
-
- class Child extends Component {
- constructor(props, context) {
- super(props, context);
- this.state = { show:false };
- inst = this;
- }
- handleMount(){}
- render(_, { show }) {
- if (!show) return <div id="div" ref={this.handleMount}></div>;
- return <span id="span" ref={this.handleMount}>some test content</span>;
- }
- }
- sinon.spy(Child.prototype, 'handleMount');
-
- render(<App />, scratch);
- expect(inst.handleMount).to.have.been.calledOnce.and.calledWith(scratch.querySelector('#div'));
- inst.handleMount.reset();
-
- inst.setState({ show:true });
- inst.forceUpdate();
- expect(inst.handleMount).to.have.been.calledTwice;
- expect(inst.handleMount.firstCall).to.have.been.calledWith(null);
- expect(inst.handleMount.secondCall).to.have.been.calledWith(scratch.querySelector('#span'));
- inst.handleMount.reset();
-
- inst.setState({ show:false });
- inst.forceUpdate();
- expect(inst.handleMount).to.have.been.calledTwice;
- expect(inst.handleMount.firstCall).to.have.been.calledWith(null);
- expect(inst.handleMount.secondCall).to.have.been.calledWith(scratch.querySelector('#div'));
- });
-
-
- it('should add refs to components representing DOM nodes with no attributes if they have been pre-rendered', () => {
- // Simulate pre-render
- let parent = document.createElement('div');
- let child = document.createElement('div');
- parent.appendChild(child);
- scratch.appendChild(parent); // scratch contains: <div><div></div></div>
-
- let ref = spy('ref');
-
- function Wrapper() {
- return <div></div>;
- }
-
- render(<div><Wrapper ref={ref} /></div>, scratch, scratch.firstChild);
- expect(ref).to.have.been.calledOnce.and.calledWith(scratch.firstChild.firstChild);
- });
-});
diff --git a/thirdparty/preact/test/browser/render.js b/thirdparty/preact/test/browser/render.js
deleted file mode 100644
index 5d18fb282..000000000
--- a/thirdparty/preact/test/browser/render.js
+++ /dev/null
@@ -1,439 +0,0 @@
-/* global DISABLE_FLAKEY */
-
-import { h, render } from '../../src/preact';
-/** @jsx h */
-
-function getAttributes(node) {
- let attrs = {};
- for (let i=node.attributes.length; i--; ) {
- attrs[node.attributes[i].name] = node.attributes[i].value;
- }
- return attrs;
-}
-
-// hacky normalization of attribute order across browsers.
-function sortAttributes(html) {
- return html.replace(/<([a-z0-9-]+)((?:\s[a-z0-9:_.-]+=".*?")+)((?:\s*\/)?>)/gi, (s, pre, attrs, after) => {
- let list = attrs.match(/\s[a-z0-9:_.-]+=".*?"/gi).sort( (a, b) => a>b ? 1 : -1 );
- if (~after.indexOf('/')) after = '></'+pre+'>';
- return '<' + pre + list.join('') + after;
- });
-}
-
-describe('render()', () => {
- let scratch;
-
- before( () => {
- scratch = document.createElement('div');
- (document.body || document.documentElement).appendChild(scratch);
- });
-
- beforeEach( () => {
- scratch.innerHTML = '';
- });
-
- after( () => {
- scratch.parentNode.removeChild(scratch);
- scratch = null;
- });
-
- it('should create empty nodes (<* />)', () => {
- render(<div />, scratch);
- expect(scratch.childNodes)
- .to.have.length(1)
- .and.to.have.deep.property('0.nodeName', 'DIV');
-
- scratch.innerHTML = '';
-
- render(<span />, scratch);
- expect(scratch.childNodes)
- .to.have.length(1)
- .and.to.have.deep.property('0.nodeName', 'SPAN');
-
- scratch.innerHTML = '';
-
- render(<foo />, scratch);
- render(<x-bar />, scratch);
- expect(scratch.childNodes).to.have.length(2);
- expect(scratch.childNodes[0]).to.have.property('nodeName', 'FOO');
- expect(scratch.childNodes[1]).to.have.property('nodeName', 'X-BAR');
- });
-
- it('should nest empty nodes', () => {
- render((
- <div>
- <span />
- <foo />
- <x-bar />
- </div>
- ), scratch);
-
- expect(scratch.childNodes)
- .to.have.length(1)
- .and.to.have.deep.property('0.nodeName', 'DIV');
-
- let c = scratch.childNodes[0].childNodes;
- expect(c).to.have.length(3);
- expect(c).to.have.deep.property('0.nodeName', 'SPAN');
- expect(c).to.have.deep.property('1.nodeName', 'FOO');
- expect(c).to.have.deep.property('2.nodeName', 'X-BAR');
- });
-
- it('should not render falsey values', () => {
- render((
- <div>
- {null},{undefined},{false},{0},{NaN}
- </div>
- ), scratch);
-
- expect(scratch.firstChild).to.have.property('innerHTML', ',,,0,NaN');
- });
-
- it('should clear falsey attributes', () => {
- let root = render((
- <div anull="anull" aundefined="aundefined" afalse="afalse" anan="aNaN" a0="a0" />
- ), scratch);
-
- root = render((
- <div anull={null} aundefined={undefined} afalse={false} anan={NaN} a0={0} />
- ), scratch, root);
-
- expect(getAttributes(scratch.firstChild), 'from previous truthy values').to.eql({
- a0: '0',
- anan: 'NaN'
- });
-
- scratch.innerHTML = '';
-
- root = render((
- <div anull={null} aundefined={undefined} afalse={false} anan={NaN} a0={0} />
- ), scratch);
-
- expect(getAttributes(scratch.firstChild), 'initial render').to.eql({
- a0: '0',
- anan: 'NaN'
- });
- });
-
- it('should clear falsey input values', () => {
- let root = render((
- <div>
- <input value={0} />
- <input value={false} />
- <input value={null} />
- <input value={undefined} />
- </div>
- ), scratch);
-
- expect(root.children[0]).to.have.property('value', '0');
- expect(root.children[1]).to.have.property('value', 'false');
- expect(root.children[2]).to.have.property('value', '');
- expect(root.children[3]).to.have.property('value', '');
- });
-
- it('should clear falsey DOM properties', () => {
- let root;
- function test(val) {
- root = render((
- <div>
- <input value={val} />
- <table border={val} />
- </div>
- ), scratch, root);
- }
-
- test('2');
- test(false);
- expect(scratch).to.have.property('innerHTML', '<div><input><table></table></div>', 'for false');
-
- test('3');
- test(null);
- expect(scratch).to.have.property('innerHTML', '<div><input><table></table></div>', 'for null');
-
- test('4');
- test(undefined);
- expect(scratch).to.have.property('innerHTML', '<div><input><table></table></div>', 'for undefined');
- });
-
- it('should apply string attributes', () => {
- render(<div foo="bar" data-foo="databar" />, scratch);
-
- let div = scratch.childNodes[0];
- expect(div).to.have.deep.property('attributes.length', 2);
-
- expect(div).to.have.deep.property('attributes[0].name', 'foo');
- expect(div).to.have.deep.property('attributes[0].value', 'bar');
-
- expect(div).to.have.deep.property('attributes[1].name', 'data-foo');
- expect(div).to.have.deep.property('attributes[1].value', 'databar');
- });
-
- it('should apply class as String', () => {
- render(<div class="foo" />, scratch);
- expect(scratch.childNodes[0]).to.have.property('className', 'foo');
- });
-
- it('should alias className to class', () => {
- render(<div className="bar" />, scratch);
- expect(scratch.childNodes[0]).to.have.property('className', 'bar');
- });
-
- it('should apply style as String', () => {
- render(<div style="top:5px; position:relative;" />, scratch);
- expect(scratch.childNodes[0]).to.have.deep.property('style.cssText')
- .that.matches(/top\s*:\s*5px\s*/)
- .and.matches(/position\s*:\s*relative\s*/);
- });
-
- it('should only register on* functions as handlers', () => {
- let click = () => {},
- onclick = () => {};
-
- let proto = document.createElement('div').constructor.prototype;
-
- sinon.spy(proto, 'addEventListener');
-
- render(<div click={ click } onClick={ onclick } />, scratch);
-
- expect(scratch.childNodes[0]).to.have.deep.property('attributes.length', 0);
-
- expect(proto.addEventListener).to.have.been.calledOnce
- .and.to.have.been.calledWithExactly('click', sinon.match.func, false);
-
- proto.addEventListener.restore();
- });
-
- it('should add and remove event handlers', () => {
- let click = sinon.spy(),
- mousedown = sinon.spy();
-
- let proto = document.createElement('div').constructor.prototype;
- sinon.spy(proto, 'addEventListener');
- sinon.spy(proto, 'removeEventListener');
-
- function fireEvent(on, type) {
- let e = document.createEvent('Event');
- e.initEvent(type, true, true);
- on.dispatchEvent(e);
- }
-
- render(<div onClick={ () => click(1) } onMouseDown={ mousedown } />, scratch);
-
- expect(proto.addEventListener).to.have.been.calledTwice
- .and.to.have.been.calledWith('click')
- .and.calledWith('mousedown');
-
- fireEvent(scratch.childNodes[0], 'click');
- expect(click).to.have.been.calledOnce
- .and.calledWith(1);
-
- proto.addEventListener.reset();
- click.reset();
-
- render(<div onClick={ () => click(2) } />, scratch, scratch.firstChild);
-
- expect(proto.addEventListener).not.to.have.been.called;
-
- expect(proto.removeEventListener)
- .to.have.been.calledOnce
- .and.calledWith('mousedown');
-
- fireEvent(scratch.childNodes[0], 'click');
- expect(click).to.have.been.calledOnce
- .and.to.have.been.calledWith(2);
-
- fireEvent(scratch.childNodes[0], 'mousedown');
- expect(mousedown).not.to.have.been.called;
-
- proto.removeEventListener.reset();
- click.reset();
- mousedown.reset();
-
- render(<div />, scratch, scratch.firstChild);
-
- expect(proto.removeEventListener)
- .to.have.been.calledOnce
- .and.calledWith('click');
-
- fireEvent(scratch.childNodes[0], 'click');
- expect(click).not.to.have.been.called;
-
- proto.addEventListener.restore();
- proto.removeEventListener.restore();
- });
-
- it('should use capturing for events that do not bubble', () => {
- let click = sinon.spy(),
- focus = sinon.spy();
-
- let root = render((
- <div onClick={click} onFocus={focus}>
- <button />
- </div>
- ), scratch);
-
- root.firstElementChild.click();
- root.firstElementChild.focus();
-
- expect(click, 'click').to.have.been.calledOnce;
-
- if (DISABLE_FLAKEY!==true) {
- // Focus delegation requires a 50b hack I'm not sure we want to incur
- expect(focus, 'focus').to.have.been.calledOnce;
-
- // IE doesn't set it
- expect(click).to.have.been.calledWithMatch({ eventPhase: 0 }); // capturing
- expect(focus).to.have.been.calledWithMatch({ eventPhase: 0 }); // capturing
- }
- });
-
- it('should serialize style objects', () => {
- let root = render((
- <div style={{
- color: 'rgb(255, 255, 255)',
- background: 'rgb(255, 100, 0)',
- backgroundPosition: '10px 10px',
- 'background-size': 'cover',
- padding: 5,
- top: 100,
- left: '100%'
- }}>
- test
- </div>
- ), scratch);
-
- let { style } = scratch.childNodes[0];
- expect(style).to.have.property('color').that.equals('rgb(255, 255, 255)');
- expect(style).to.have.property('background').that.contains('rgb(255, 100, 0)');
- expect(style).to.have.property('backgroundPosition').that.equals('10px 10px');
- expect(style).to.have.property('backgroundSize', 'cover');
- expect(style).to.have.property('padding', '5px');
- expect(style).to.have.property('top', '100px');
- expect(style).to.have.property('left', '100%');
-
- root = render((
- <div style={{ color: 'rgb(0, 255, 255)' }}>test</div>
- ), scratch, root);
-
- expect(root).to.have.deep.property('style.cssText').that.equals('color: rgb(0, 255, 255);');
-
- root = render((
- <div style="display: inline;">test</div>
- ), scratch, root);
-
- expect(root).to.have.deep.property('style.cssText').that.equals('display: inline;');
-
- root = render((
- <div style={{ backgroundColor: 'rgb(0, 255, 255)' }}>test</div>
- ), scratch, root);
-
- expect(root).to.have.deep.property('style.cssText').that.equals('background-color: rgb(0, 255, 255);');
- });
-
- it('should serialize class/className', () => {
- render(<div class={{
- no1: false,
- no2: 0,
- no3: null,
- no4: undefined,
- no5: '',
- yes1: true,
- yes2: 1,
- yes3: {},
- yes4: [],
- yes5: ' '
- }} />, scratch);
-
- let { className } = scratch.childNodes[0];
- expect(className).to.be.a.string;
- expect(className.split(' '))
- .to.include.members(['yes1', 'yes2', 'yes3', 'yes4', 'yes5'])
- .and.not.include.members(['no1', 'no2', 'no3', 'no4', 'no5']);
- });
-
- it('should support dangerouslySetInnerHTML', () => {
- let html = '<b>foo &amp; bar</b>';
- let root = render(<div dangerouslySetInnerHTML={{ __html: html }} />, scratch);
-
- expect(scratch.firstChild).to.have.property('innerHTML', html);
- expect(scratch.innerHTML).to.equal('<div>'+html+'</div>');
-
- root = render(<div>a<strong>b</strong></div>, scratch, root);
-
- expect(scratch).to.have.property('innerHTML', `<div>a<strong>b</strong></div>`);
-
- root = render(<div dangerouslySetInnerHTML={{ __html: html }} />, scratch, root);
-
- expect(scratch.innerHTML).to.equal('<div>'+html+'</div>');
- });
-
- it('should reconcile mutated DOM attributes', () => {
- let check = p => render(<input type="checkbox" checked={p} />, scratch, scratch.lastChild),
- value = () => scratch.lastChild.checked,
- setValue = p => scratch.lastChild.checked = p;
- check(true);
- expect(value()).to.equal(true);
- check(false);
- expect(value()).to.equal(false);
- check(true);
- expect(value()).to.equal(true);
- setValue(true);
- check(false);
- expect(value()).to.equal(false);
- setValue(false);
- check(true);
- expect(value()).to.equal(true);
- });
-
- it('should ignore props.children if children are manually specified', () => {
- expect(
- <div a children={['a', 'b']}>c</div>
- ).to.eql(
- <div a>c</div>
- );
- });
-
- it('should reorder child pairs', () => {
- let root = render((
- <div>
- <a>a</a>
- <b>b</b>
- </div>
- ), scratch, root);
-
- let a = scratch.firstChild.firstChild;
- let b = scratch.firstChild.lastChild;
-
- expect(a).to.have.property('nodeName', 'A');
- expect(b).to.have.property('nodeName', 'B');
-
- root = render((
- <div>
- <b>b</b>
- <a>a</a>
- </div>
- ), scratch, root);
-
- expect(scratch.firstChild.firstChild).to.have.property('nodeName', 'B');
- expect(scratch.firstChild.lastChild).to.have.property('nodeName', 'A');
- expect(scratch.firstChild.firstChild).to.equal(b);
- expect(scratch.firstChild.lastChild).to.equal(a);
- });
-
- // Discussion: https://github.com/developit/preact/issues/287
- ('HTMLDataListElement' in window ? it : xit)('should allow <input list /> to pass through as an attribute', () => {
- render((
- <div>
- <input type="range" min="0" max="100" list="steplist" />
- <datalist id="steplist">
- <option>0</option>
- <option>50</option>
- <option>100</option>
- </datalist>
- </div>
- ), scratch);
-
- let html = scratch.firstElementChild.firstElementChild.outerHTML;
- expect(sortAttributes(html)).to.equal(sortAttributes('<input type="range" min="0" max="100" list="steplist">'));
- });
-});
diff --git a/thirdparty/preact/test/browser/spec.js b/thirdparty/preact/test/browser/spec.js
deleted file mode 100644
index d33cdb93f..000000000
--- a/thirdparty/preact/test/browser/spec.js
+++ /dev/null
@@ -1,127 +0,0 @@
-import { h, render, rerender, Component } from '../../src/preact';
-/** @jsx h */
-
-const EMPTY_CHILDREN = [];
-
-describe('Component spec', () => {
- let scratch;
-
- before( () => {
- scratch = document.createElement('div');
- (document.body || document.documentElement).appendChild(scratch);
- });
-
- beforeEach( () => {
- scratch.innerHTML = '';
- });
-
- after( () => {
- scratch.parentNode.removeChild(scratch);
- scratch = null;
- });
-
- describe('defaultProps', () => {
- it('should apply default props on initial render', () => {
- class WithDefaultProps extends Component {
- constructor(props, context) {
- super(props, context);
- expect(props).to.be.deep.equal({
- children: EMPTY_CHILDREN,
- fieldA: 1, fieldB: 2,
- fieldC: 1, fieldD: 2
- });
- }
- render() {
- return <div />;
- }
- }
- WithDefaultProps.defaultProps = { fieldC: 1, fieldD: 1 };
- render(<WithDefaultProps fieldA={1} fieldB={2} fieldD={2} />, scratch);
- });
-
- it('should apply default props on rerender', () => {
- let doRender;
- class Outer extends Component {
- constructor() {
- super();
- this.state = { i:1 };
- }
- componentDidMount() {
- doRender = () => this.setState({ i: 2 });
- }
- render(props, { i }) {
- return <WithDefaultProps fieldA={1} fieldB={i} fieldD={i} />;
- }
- }
- class WithDefaultProps extends Component {
- constructor(props, context) {
- super(props, context);
- this.ctor(props, context);
- }
- ctor(){}
- componentWillReceiveProps() {}
- render() {
- return <div />;
- }
- }
- WithDefaultProps.defaultProps = { fieldC: 1, fieldD: 1 };
-
- let proto = WithDefaultProps.prototype;
- sinon.spy(proto, 'ctor');
- sinon.spy(proto, 'componentWillReceiveProps');
- sinon.spy(proto, 'render');
-
- render(<Outer />, scratch);
- doRender();
-
- const PROPS1 = {
- fieldA: 1, fieldB: 1,
- fieldC: 1, fieldD: 1
- };
-
- const PROPS2 = {
- fieldA: 1, fieldB: 2,
- fieldC: 1, fieldD: 2
- };
-
- expect(proto.ctor).to.have.been.calledWithMatch(PROPS1);
- expect(proto.render).to.have.been.calledWithMatch(PROPS1);
-
- rerender();
-
- // expect(proto.ctor).to.have.been.calledWith(PROPS2);
- expect(proto.componentWillReceiveProps).to.have.been.calledWithMatch(PROPS2);
- expect(proto.render).to.have.been.calledWithMatch(PROPS2);
- });
-
- // @TODO: migrate this to preact-compat
- xit('should cache default props', () => {
- class WithDefaultProps extends Component {
- constructor(props, context) {
- super(props, context);
- expect(props).to.be.deep.equal({
- fieldA: 1, fieldB: 2,
- fieldC: 1, fieldD: 2,
- fieldX: 10
- });
- }
- getDefaultProps() {
- return { fieldA: 1, fieldB: 1 };
- }
- render() {
- return <div />;
- }
- }
- WithDefaultProps.defaultProps = { fieldC: 1, fieldD: 1 };
- sinon.spy(WithDefaultProps.prototype, 'getDefaultProps');
- render((
- <div>
- <WithDefaultProps fieldB={2} fieldD={2} fieldX={10} />
- <WithDefaultProps fieldB={2} fieldD={2} fieldX={10} />
- <WithDefaultProps fieldB={2} fieldD={2} fieldX={10} />
- </div>
- ), scratch);
- expect(WithDefaultProps.prototype.getDefaultProps).to.be.calledOnce;
- });
- });
-});
diff --git a/thirdparty/preact/test/browser/svg.js b/thirdparty/preact/test/browser/svg.js
deleted file mode 100644
index 684f4dd96..000000000
--- a/thirdparty/preact/test/browser/svg.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import { h, render } from '../../src/preact';
-/** @jsx h */
-
-
-// hacky normalization of attribute order across browsers.
-function sortAttributes(html) {
- return html.replace(/<([a-z0-9-]+)((?:\s[a-z0-9:_.-]+=".*?")+)((?:\s*\/)?>)/gi, (s, pre, attrs, after) => {
- let list = attrs.match(/\s[a-z0-9:_.-]+=".*?"/gi).sort( (a, b) => a>b ? 1 : -1 );
- if (~after.indexOf('/')) after = '></'+pre+'>';
- return '<' + pre + list.join('') + after;
- });
-}
-
-
-describe('svg', () => {
- let scratch;
-
- before( () => {
- scratch = document.createElement('div');
- (document.body || document.documentElement).appendChild(scratch);
- });
-
- beforeEach( () => {
- scratch.innerHTML = '';
- });
-
- after( () => {
- scratch.parentNode.removeChild(scratch);
- scratch = null;
- });
-
- it('should render SVG to string', () => {
- render((
- <svg viewBox="0 0 360 360">
- <path stroke="white" fill="black" d="M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z" />
- </svg>
- ), scratch);
-
- let html = sortAttributes(String(scratch.innerHTML).replace(' xmlns="http://www.w3.org/2000/svg"', ''));
- expect(html).to.equal(sortAttributes(`
- <svg viewBox="0 0 360 360">
- <path d="M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z" fill="black" stroke="white"></path>
- </svg>
- `.replace(/[\n\t]+/g,'')));
- });
-
- it('should render SVG to DOM', () => {
- const Demo = () => (
- <svg viewBox="0 0 360 360">
- <path d="M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z" fill="black" stroke="white" />
- </svg>
- );
- render(<Demo />, scratch);
-
- let html = sortAttributes(String(scratch.innerHTML).replace(' xmlns="http://www.w3.org/2000/svg"', ''));
- expect(html).to.equal(sortAttributes('<svg viewBox="0 0 360 360"><path stroke="white" fill="black" d="M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z"></path></svg>'));
- });
-
- it('should use attributes for className', () => {
- const Demo = ({ c }) => (
- <svg viewBox="0 0 360 360" {...(c ? {class:'foo_'+c} : {})}>
- <path class={c && ('bar_'+c)} stroke="white" fill="black" d="M347.1 357.9L183.3 256.5 13 357.9V1.7h334.1v356.2zM58.5 47.2v231.4l124.8-74.1 118.3 72.8V47.2H58.5z" />
- </svg>
- );
- let root = render(<Demo c="1" />, scratch, root);
- sinon.spy(root, 'removeAttribute');
- root = render(<Demo />, scratch, root);
- expect(root.removeAttribute).to.have.been.calledOnce.and.calledWith('class');
- root.removeAttribute.restore();
-
- root = render(<div />, scratch, root);
- root = render(<Demo />, scratch, root);
- sinon.spy(root, 'setAttribute');
- root = render(<Demo c="2" />, scratch, root);
- expect(root.setAttribute).to.have.been.calledOnce.and.calledWith('class', 'foo_2');
- root.setAttribute.restore();
- root = render(<Demo c="3" />, scratch, root);
- root = render(<Demo />, scratch, root);
- });
-
- it('should still support class attribute', () => {
- render((
- <svg viewBox="0 0 1 1" class="foo bar" />
- ), scratch);
-
- expect(scratch.innerHTML).to.contain(` class="foo bar"`);
- });
-
- it('should serialize class', () => {
- render((
- <svg viewBox="0 0 1 1" class={{ foo: true, bar: false, other: 'hello' }} />
- ), scratch);
-
- expect(scratch.innerHTML).to.contain(` class="foo other"`);
- });
-
- it('should switch back to HTML for <foreignObject>', () => {
- render((
- <svg>
- <g>
- <foreignObject>
- <a href="#foo">test</a>
- </foreignObject>
- </g>
- </svg>
- ), scratch);
-
- expect(scratch.getElementsByTagName('a'))
- .to.have.property('0')
- .that.is.a('HTMLAnchorElement');
- });
-});