Skip to content

Commit

Permalink
Improve suspense test spies (#3856)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewiggins authored Jan 10, 2023
1 parent d527b4b commit 2ce7b0a
Showing 1 changed file with 85 additions and 98 deletions.
183 changes: 85 additions & 98 deletions compat/test/browser/suspense.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,11 +338,7 @@ describe('suspense', () => {
});
});

it('should not call lifecycle methods of an initially suspending component', () => {
let componentWillMount = sinon.spy();
let componentDidMount = sinon.spy();
let componentWillUnmount = sinon.spy();

it('should properly call lifecycle methods of an initially suspending component', () => {
/** @type {() => Promise<void>} */
let resolve;
let resolved = false;
Expand All @@ -361,17 +357,18 @@ describe('suspense', () => {
}
return <div>Lifecycle</div>;
}
componentWillMount() {
componentWillMount();
}
componentDidMount() {
componentDidMount();
}
componentWillUnmount() {
componentWillUnmount();
}
componentWillMount() {}
componentDidMount() {}
componentDidUpdate() {}
componentWillUnmount() {}
}

const lifecycles = LifecycleSuspender.prototype;
sinon.spy(lifecycles, 'componentWillMount');
sinon.spy(lifecycles, 'componentDidMount');
sinon.spy(lifecycles, 'componentDidUpdate');
sinon.spy(lifecycles, 'componentWillUnmount');

render(
<Suspense fallback={<div>Suspended...</div>}>
<LifecycleSuspender />
Expand All @@ -380,33 +377,32 @@ describe('suspense', () => {
);

expect(scratch.innerHTML).to.eql(``);
expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.not.have.been.called;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.not.have.been.called;
expect(lifecycles.componentDidUpdate).to.not.have.been.called;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;

rerender();

expect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);
expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.not.have.been.called;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.not.have.been.called;
expect(lifecycles.componentDidUpdate).to.not.have.been.called;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;

return resolve().then(() => {
rerender();
expect(scratch.innerHTML).to.eql(`<div>Lifecycle</div>`);

expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
// TODO: This is unexpected. See TODO in next test regarding this and preactjs/preact#2098
expect(lifecycles.componentDidUpdate).to.have.been.calledOnce;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;
});
});

it('should properly call lifecycle methods and maintain state of a delayed suspending component', () => {
let componentWillMount = sinon.spy();
let componentDidMount = sinon.spy();
let componentDidUpdate = sinon.spy();
let componentWillUnmount = sinon.spy();

/** @type {() => void} */
let increment;

Expand Down Expand Up @@ -439,20 +435,18 @@ describe('suspense', () => {
</Fragment>
);
}
componentWillMount() {
componentWillMount();
}
componentDidMount() {
componentDidMount();
}
componentWillUnmount() {
componentWillUnmount();
}
componentDidUpdate() {
componentDidUpdate();
}
componentWillMount() {}
componentDidMount() {}
componentWillUnmount() {}
componentDidUpdate() {}
}

const lifecycles = LifecycleSuspender.prototype;
sinon.spy(lifecycles, 'componentWillMount');
sinon.spy(lifecycles, 'componentDidMount');
sinon.spy(lifecycles, 'componentDidUpdate');
sinon.spy(lifecycles, 'componentWillUnmount');

render(
<Suspense fallback={<div>Suspended...</div>}>
<LifecycleSuspender />
Expand All @@ -461,63 +455,61 @@ describe('suspense', () => {
);

expect(scratch.innerHTML).to.eql(`<p>Count: 0</p>`);
expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(componentDidUpdate).to.not.have.been.called;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
expect(lifecycles.componentDidUpdate).to.not.have.been.called;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;

increment();
rerender();

expect(scratch.innerHTML).to.eql(`<p>Count: 1</p>`);
expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(componentDidUpdate).to.have.been.calledOnce;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
expect(lifecycles.componentDidUpdate).to.have.been.calledOnce;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;

increment();
rerender();

expect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);
expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(componentDidUpdate).to.have.been.calledOnce;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
expect(lifecycles.componentDidUpdate).to.have.been.calledOnce;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;

return resolve().then(() => {
rerender();

expect(scratch.innerHTML).to.eql(`<p>Count: 2</p>`);
expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
// TODO: This is called thrice since the cDU queued up after the second
// increment is never cleared once the component suspends. So when it
// resumes and the component is rerendered, we queue up another cDU so
// cDU is called an extra time.
expect(componentDidUpdate).to.have.been.calledThrice;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentDidUpdate).to.have.been.calledThrice;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;
});
});

it('should not call lifecycle methods when a sibling suspends', () => {
let componentWillMount = sinon.spy();
let componentDidMount = sinon.spy();
let componentWillUnmount = sinon.spy();
class LifecycleLogger extends Component {
render() {
return <div>Lifecycle</div>;
}
componentWillMount() {
componentWillMount();
}
componentDidMount() {
componentDidMount();
}
componentWillUnmount() {
componentWillUnmount();
}
componentWillMount() {}
componentDidMount() {}
componentDidUpdate() {}
componentWillUnmount() {}
}

const lifecycles = LifecycleLogger.prototype;
sinon.spy(lifecycles, 'componentWillMount');
sinon.spy(lifecycles, 'componentDidMount');
sinon.spy(lifecycles, 'componentDidUpdate');
sinon.spy(lifecycles, 'componentWillUnmount');

const [Suspender, suspend] = createSuspender(() => <div>Suspense</div>);

render(
Expand All @@ -529,28 +521,31 @@ describe('suspense', () => {
);

expect(scratch.innerHTML).to.eql(`<div>Suspense</div><div>Lifecycle</div>`);
expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
expect(lifecycles.componentDidUpdate).to.not.have.been.called;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;

const [resolve] = suspend();

rerender();

expect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);
expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
expect(lifecycles.componentDidUpdate).to.not.have.been.called;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;

return resolve(() => <div>Suspense 2</div>).then(() => {
rerender();
expect(scratch.innerHTML).to.eql(
`<div>Suspense 2</div><div>Lifecycle</div>`
);

expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
expect(lifecycles.componentDidUpdate).to.have.been.calledOnce;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;
});
});

Expand All @@ -564,18 +559,10 @@ describe('suspense', () => {
componentWillUnmount() {}
}

const componentWillMount = sinon.spy(
LifecycleLogger.prototype,
'componentWillMount'
);
const componentDidMount = sinon.spy(
LifecycleLogger.prototype,
'componentDidMount'
);
const componentWillUnmount = sinon.spy(
LifecycleLogger.prototype,
'componentWillUnmount'
);
const lifecycles = LifecycleLogger.prototype;
sinon.spy(lifecycles, 'componentWillMount');
sinon.spy(lifecycles, 'componentDidMount');
sinon.spy(lifecycles, 'componentWillUnmount');

const [Suspender, suspend] = createSuspender(() => <div>Suspense</div>);

Expand All @@ -587,26 +574,26 @@ describe('suspense', () => {
);

expect(scratch.innerHTML).to.eql(`<div>Suspense</div>`);
expect(componentWillMount).to.not.have.been.called;
expect(componentDidMount).to.not.have.been.called;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.not.have.been.called;
expect(lifecycles.componentDidMount).to.not.have.been.called;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;

const [resolve] = suspend();

rerender();

expect(scratch.innerHTML).to.eql(`<div>Lifecycle</div>`);
expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(componentWillUnmount).to.not.have.been.called;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
expect(lifecycles.componentWillUnmount).to.not.have.been.called;

return resolve(() => <div>Suspense 2</div>).then(() => {
rerender();
expect(scratch.innerHTML).to.eql(`<div>Suspense 2</div>`);

expect(componentWillMount).to.have.been.calledOnce;
expect(componentDidMount).to.have.been.calledOnce;
expect(componentWillUnmount).to.have.been.calledOnce;
expect(lifecycles.componentWillMount).to.have.been.calledOnce;
expect(lifecycles.componentDidMount).to.have.been.calledOnce;
expect(lifecycles.componentWillUnmount).to.have.been.calledOnce;
});
});

Expand Down

0 comments on commit 2ce7b0a

Please sign in to comment.