aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/preact/test/browser/context.js
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/preact/test/browser/context.js')
-rw-r--r--thirdparty/preact/test/browser/context.js170
1 files changed, 170 insertions, 0 deletions
diff --git a/thirdparty/preact/test/browser/context.js b/thirdparty/preact/test/browser/context.js
new file mode 100644
index 000000000..e62a948a4
--- /dev/null
+++ b/thirdparty/preact/test/browser/context.js
@@ -0,0 +1,170 @@
+import { h, render, Component } from '../../src/preact';
+/** @jsx h */
+
+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({}, {}, CONTEXT);
+
+ CONTEXT.foo = 'bar';
+ render(<Outer {...PROPS} />, scratch, scratch.lastChild);
+
+ expect(Outer.prototype.getChildContext).to.have.been.calledTwice;
+
+ 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({}, {});
+ 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({}, {}, CONTEXT);
+
+ CONTEXT.foo = 'bar';
+ render(<Outer {...PROPS} />, scratch, scratch.lastChild);
+
+ expect(Outer.prototype.getChildContext).to.have.been.calledTwice;
+
+ 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({}, {});
+ 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({}, {}, { outerContext });
+ expect(InnerMost.prototype.render).to.have.been.calledWith({}, {}, { outerContext, innerContext });
+ });
+});