Skip to content

Commit

Permalink
Merge pull request #39 from yahoo/updatemodel
Browse files Browse the repository at this point in the history
update i13n model when props changes
  • Loading branch information
kaesonho committed Aug 19, 2015
2 parents f2f2655 + 7f63e11 commit 2a6f412
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 10 deletions.
16 changes: 15 additions & 1 deletion src/libs/I13nNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var TAG_PATTERN = /<[^>]*>/g;
* I13nNode the virtual DOM Node used to build a I13n Tree for instrumentation
* @class I13nNode
* @param {Object} parentNode parent node
* @param {Object} model custom model values
* @param {Object|Function} model custom model values
* @param {Boolean} isLeafNode indicate if it's a link node
* @param {Boolean} isViewportEnabled indicate if viewport check enable
* @constructor
Expand Down Expand Up @@ -281,6 +281,20 @@ I13nNode.prototype.setParentNode = function setParentNode (parentNode) {
this._parentNode = parentNode;
};

/**
* Update the i13n model
* @method updateModel
* @param {Object|Function} newModel the new i13n model
*/
I13nNode.prototype.updateModel = function updateModel (newModel) {
// if i13n is a function, just assign it to _model, otherwise use object-assign to merge old and new model data
if ('function' === typeof newModel) {
this._model = newModel;
} else {
this._model = objectAssign({}, this._model, newModel);
}
};

/**
* Sort children according to the position in the page
* @method sortChildrenNodes
Expand Down
10 changes: 10 additions & 0 deletions src/mixins/I13nMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ var I13nMixin = {
})
},

/**
* componentWillUpdate
* @method componentWillUpdate
*/
componentWillUpdate: function (nextProps, nextState) {
if (nextProps) {
this._i13nNode.updateModel(nextProps.model || nextProps.i13nModel);
}
},

/**
* componentDidMount
* @method componentDidMount
Expand Down
7 changes: 4 additions & 3 deletions tests/functional/i13n-functional.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,16 @@ var I13nComponentLevel2Hidden = React.createClass({
var linkText = 'Link Level2 Hidden ' + i;
links.push(
<div className="P(4px) M(4px) Bgc(#ececec)" key={i}>
<I13nAnchor href="/mock-destination-page.html">{linkText}</I13nAnchor>
<I13nAnchor href="/mock-destination-page.html" follow={false}>{linkText}</I13nAnchor>
</div>
);
}
}
return (
<div className="P(4px) M(4px) Bgc(#fcf8e3) I13nComponentLevel2Hidden">
<I13nDiv className="HiddenBtn" onClick={this.clickHandler} bindClickEvent={true} i13nModel={{sec:'hidden-btn'}}>Show Hidden Links</I13nDiv>
{links}
<I13nDiv className="HiddenBtn" onClick={this.clickHandler} bindClickEvent={true} i13nModel={{sec:'hidden-btn', expend: this.state.expend}}>Show Hidden Links
{links}
</I13nDiv>
</div>
);
}
Expand Down
10 changes: 9 additions & 1 deletion tests/functional/i13n.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@ describe('React I13n test', function () {
expect(events[0].name).to.eql('pageview');
});

it('should fire an update event when dom change, click handler can work with custom click event', function () {
it('should fire an update event when dom change, should get i13n model updated', function () {
var hiddenBtn = document.querySelectorAll('.HiddenBtn')[0];
hiddenBtn.click();
var events = window.firedEvents;
var currentEventCount = events.length;
expect(events[currentEventCount - 2].name).to.eql('click');
expect(events[currentEventCount - 2].model).to.eql({sec: 'hidden-btn', page: 'test-page', expend: false});
expect(events[currentEventCount - 1].name).to.eql('created');

// click the link and expect the expend value is updated
var hiddenLink = document.querySelectorAll('.I13nComponentLevel2Hidden a')[0];
hiddenLink.click();
currentEventCount = events.length;
expect(events[currentEventCount - 1].name).to.eql('click');
expect(events[currentEventCount - 1].model).to.eql({sec: 'hidden-btn', page: 'test-page', expend: true});
});

it('should handle nested model data well', function () {
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/libs/I13nNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,10 @@ describe('I13nNode', function () {
i13nNode.setReactComponent(mockReactComponent);
expect(i13nNode.getReactComponent()).to.eql(mockReactComponent);
});

it('should be able to update i13n model', function () {
var i13nNode = new I13nNode(null, {sec: 'foo', sec2: 'bar'}, true, true);
i13nNode.updateModel({sec2: 'baz', sec3: 'foo'});
expect(i13nNode.getModel()).to.eql({sec: 'foo', sec2: 'baz', sec3: 'foo'});
});
});
35 changes: 30 additions & 5 deletions tests/unit/utils/createI13nNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ describe('createI13nNode', function () {
// should get a created event
expect(eventName).to.eql('created');
done();
}
};
expect(I13nTestComponent.displayName).to.eql('I13nTestComponent');
var container = document.createElement('div');
var component = React.render(React.createElement(I13nTestComponent, {i13nModel: {sec: 'foo'}}), container);
Expand All @@ -122,7 +122,7 @@ describe('createI13nNode', function () {
// should get a created event
expect(eventName).to.eql('created');
done();
}
};
expect(I13nTestComponent.displayName).to.eql('I13nTestComponent');
var container = document.createElement('div');
var component = React.render(React.createElement(I13nTestComponent, {model: {sec: 'foo'}}), container);
Expand Down Expand Up @@ -173,7 +173,7 @@ describe('createI13nNode', function () {
// should get a created event
expect(eventName).to.eql('created');
done();
}
};
var container = document.createElement('div');
var component = React.render(React.createElement(I13nTestComponent, {}), container);
expect(rootI13nNode.getChildrenNodes()[0]).to.be.an('object');
Expand Down Expand Up @@ -241,7 +241,7 @@ describe('createI13nNode', function () {
}
});
mockData.reactI13n.execute = function (eventName) {
}
};
mockData.isViewportEnabled = false;
var I13nTestComponent = createI13nNode(TestComponent);
var container = document.createElement('div');
Expand All @@ -263,12 +263,37 @@ describe('createI13nNode', function () {
expect(eventName).to.eql('foo');
done();
}
}
};
mockData.isViewportEnabled = false;
var I13nTestComponent = createI13nNode(TestComponent);
var container = document.createElement('div');
var component = React.render(React.createElement(I13nTestComponent, {i13nModel: {foo: 'bar'}}), container);
});

it('should update the i13n model when component updates', function () {
var i13nModel = {sec: 'foo'};
var TestComponent = React.createClass({
displayName: 'TestComponent',
contextTypes: {
i13n: React.PropTypes.object
},
render: function() {
return React.createElement('div');
}
});

// check the initial state is correct after render
var I13nTestComponent = createI13nNode(TestComponent);
mockData.reactI13n.execute = function (eventName) {
// should get a created event
expect(eventName).to.eql('created');
};
var container = document.createElement('div');
var component = React.render(React.createElement(I13nTestComponent, {i13nModel: i13nModel}), container);
i13nModel.sec = 'bar';
component.componentWillUpdate({i13nModel: i13nModel}, null);
expect(component._i13nNode.getModel()).to.eql(i13nModel);
});

it('should handle the case if we enable viewport checking', function (done) {
var TestComponent = React.createClass({
Expand Down

0 comments on commit 2a6f412

Please sign in to comment.