Skip to content

Commit

Permalink
updater functions; more MarionetteComponent tests
Browse files Browse the repository at this point in the history
  • Loading branch information
xsburg committed Jan 30, 2018
1 parent 7daa738 commit 965159c
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 14 deletions.
7 changes: 6 additions & 1 deletion package.json
Expand Up @@ -48,7 +48,12 @@
"rollup-plugin-babel": "^3.0.2",
"rollup-plugin-node-resolve": "^3.0.2",
"typescript": "^2.4.2",
"typings-tester": "^0.2.2"
"typings-tester": "^0.2.2",
"@types/react": "16.0.31",
"backbone.marionette": "^2.0.0",
"prop-types": "^15.6.0",
"react": "^16.2.0",
"react-dom": "^16.2.0"
},
"dependencies": {},
"peerDependencies": {
Expand Down
29 changes: 18 additions & 11 deletions src/MarionetteComponent.jsx
Expand Up @@ -27,17 +27,24 @@ class MarionetteComponent extends React.Component {
this._hostRegion = this._regionManager.addRegion('hostRegion', {
el: this._el
});
this._rebuildView(this.props);
this._rebuildView();
}

shouldComponentUpdate(nextProps) {
if (nextProps.onUpdateOptions) {
nextProps.onUpdateOptions(this._view);
componentWillReceiveProps(nextProps) {
if (this.props.view !== nextProps.view) {
throw new Error(
'[MarionetteComponent] error: `props.view` cannot be changed after the initial render.'
);
}
if (this._view.shouldViewRebuild && this._view.shouldViewRebuild(nextProps.viewOptions)) {
this._rebuildView(nextProps);
}

componentDidUpdate(prevProps) {
if (this.props.onUpdateOptions) {
this.props.onUpdateOptions(this._view, prevProps.viewOptions, this.props.viewOptions);
}
if (this._view.shouldViewRebuild && this._view.shouldViewRebuild(this.props.viewOptions)) {
this._rebuildView();
}
return false;
}

componentWillUnmount() {
Expand All @@ -48,13 +55,13 @@ class MarionetteComponent extends React.Component {
return this._hostRegion;
}

_rebuildView(props) {
if (!props.view) {
_rebuildView() {
if (!this.props.view) {
return;
}

const View = props.view; // tslint:disable-line
this._view = new View(props.viewOptions);
const View = this.props.view;
this._view = new View(this.props.viewOptions);
this._hostRegion.show(this._view);
}

Expand Down
2 changes: 1 addition & 1 deletion src/index.d.ts
Expand Up @@ -7,7 +7,7 @@ type MarionetteViewClass = any;
interface OwnProps {
view: MarionetteViewClass;
viewOptions: any;
onUpdateOptions?: (view: MarionetteView) => boolean;
onUpdateOptions?: (view: MarionetteView, viewOptions: any, nextViewOptions: any) => boolean;
className?: string;
}

Expand Down
102 changes: 101 additions & 1 deletion test/MarionetteComponent.spec.jsx
Expand Up @@ -28,9 +28,109 @@ describe('MarionetteComponent', () => {
/>
</div>
);
const marionetteElementHtml = component.getDOMNode().getElementsByClassName('marionette-wrapper')[0].innerHTML;
const marionetteElementHtml = component
.getDOMNode()
.getElementsByClassName('marionette-wrapper')[0].innerHTML;

expect(component).toMatchSnapshot();
expect(marionetteElementHtml).toMatchSnapshot();
});

it('should not update view when options change (w/o update checkers)', () => {
const component = mount(
<MarionetteComponent
className="marionette-wrapper"
view={SimpleView}
viewOptions={{
name: 'Marionette'
}}
/>
);
component.setProps({
viewOptions: {
name: 'Billy'
}
});
const marionetteElementHtml = component.getDOMNode().innerHTML;

expect(marionetteElementHtml).toMatchSnapshot();
});

it('should update view when options change (w/ onUpdateOptions)', () => {
const component = mount(
<MarionetteComponent
className="marionette-wrapper"
view={SimpleView}
viewOptions={{
name: 'Marionette'
}}
onUpdateOptions={(view, options, nextOptions) => {
view.options = nextOptions;
view.render();
}}
/>
);
component.setProps({
viewOptions: {
name: 'Billy'
}
});
const marionetteElementHtml = component.getDOMNode().innerHTML;

expect(marionetteElementHtml).toMatchSnapshot();
});

it('should update view when options change (w/ shouldViewRebuild that returns true)', () => {
const SimpleViewWithRebuild = SimpleView.extend({
shouldViewRebuild(newOptions) {
return true;
}
});

const component = mount(
<MarionetteComponent
className="marionette-wrapper"
view={SimpleViewWithRebuild}
viewOptions={{
name: 'Marionette'
}}
/>
);
component.setProps({
viewOptions: {
name: 'Billy'
}
});
const marionetteElementHtml = component.getDOMNode().innerHTML;

expect(marionetteElementHtml).toMatchSnapshot();
});

it('should update view when options change (w/ shouldViewRebuild that does the update itself)', () => {
const SimpleViewWithRebuild = SimpleView.extend({
shouldViewRebuild(newOptions) {
this.options = newOptions;
this.render();
return false;
}
});

const component = mount(
<MarionetteComponent
className="marionette-wrapper"
view={SimpleViewWithRebuild}
viewOptions={{
name: 'Marionette'
}}
/>
);
component.setProps({
viewOptions: {
name: 'Billy'
}
});
const marionetteElementHtml = component.getDOMNode().innerHTML;

expect(marionetteElementHtml).toMatchSnapshot();
});
});
8 changes: 8 additions & 0 deletions test/__snapshots__/MarionetteComponent.spec.jsx.snap
@@ -1,5 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`MarionetteComponent should not update view when options change (w/o update checkers) 1`] = `"<div class=\\"sample-view\\">Hello, Marionette</div>"`;
exports[`MarionetteComponent should render simple marionette view 1`] = `
<div
className="react-block"
Expand All @@ -21,3 +23,9 @@ exports[`MarionetteComponent should render simple marionette view 1`] = `
`;

exports[`MarionetteComponent should render simple marionette view 2`] = `"<div class=\\"sample-view\\">Hello, Marionette</div>"`;
exports[`MarionetteComponent should update view when options change (w/ onUpdateOptions) 1`] = `"<div class=\\"sample-view\\">Hello, Billy</div>"`;
exports[`MarionetteComponent should update view when options change (w/ shouldViewRebuild that does the update itself) 1`] = `"<div class=\\"sample-view\\">Hello, Billy</div>"`;
exports[`MarionetteComponent should update view when options change (w/ shouldViewRebuild that returns true) 1`] = `"<div class=\\"sample-view\\">Hello, Billy</div>"`;
55 changes: 55 additions & 0 deletions yarn.lock
Expand Up @@ -18,6 +18,10 @@
version "9.4.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.0.tgz#b85a0bcf1e1cc84eb4901b7e96966aedc6f078d1"

"@types/react@16.0.31":
version "16.0.31"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.0.31.tgz#5285da62f3ac62b797f6d0729a1d6181f3180c3e"

abab@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"
Expand Down Expand Up @@ -797,6 +801,35 @@ babylon@^6.17.0, babylon@^6.18.0:
version "6.18.0"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"

backbone.babysitter@^0.1.0:
version "0.1.12"
resolved "https://registry.yarnpkg.com/backbone.babysitter/-/backbone.babysitter-0.1.12.tgz#7ca946434eeefbde1a553605c74b7049b6dfafc1"
dependencies:
backbone ">=0.9.9 <=1.3.x"
underscore ">=1.4.0 <=1.8.3"

backbone.marionette@^2.0.0:
version "2.4.7"
resolved "https://registry.yarnpkg.com/backbone.marionette/-/backbone.marionette-2.4.7.tgz#a573d21b9c464741b80de18351faeacf1872e25f"
dependencies:
backbone "1.0.0 - 1.3.x"
backbone.babysitter "^0.1.0"
backbone.wreqr "^1.0.0"
underscore "1.4.4 - 1.8.3"

backbone.wreqr@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/backbone.wreqr/-/backbone.wreqr-1.4.0.tgz#7682030c9aaf090ecd873b21dbf48501693b2696"
dependencies:
backbone ">=0.9.9 <=1.3.x"
underscore ">=1.3.3 <=1.8.3"

"backbone@1.0.0 - 1.3.x", "backbone@>=0.9.9 <=1.3.x":
version "1.3.3"
resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.3.3.tgz#4cc80ea7cb1631ac474889ce40f2f8bc683b2999"
dependencies:
underscore ">=1.8.3"

balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
Expand Down Expand Up @@ -3379,6 +3412,15 @@ rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"

react-dom@^16.2.0:
version "16.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"

react-reconciler@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.7.0.tgz#9614894103e5f138deeeb5eabaf3ee80eb1d026d"
Expand All @@ -3396,6 +3438,15 @@ react-test-renderer@^16.0.0-0:
object-assign "^4.1.1"
prop-types "^15.6.0"

react@^16.2.0:
version "16.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"

read-pkg-up@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
Expand Down Expand Up @@ -4087,6 +4138,10 @@ ultron@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"

"underscore@1.4.4 - 1.8.3", "underscore@>=1.3.3 <=1.8.3", "underscore@>=1.4.0 <=1.8.3", underscore@>=1.8.3:
version "1.8.3"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"

underscore@~1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604"
Expand Down

0 comments on commit 965159c

Please sign in to comment.