Skip to content

Commit

Permalink
Merge 7326c16 into a6fcffe
Browse files Browse the repository at this point in the history
  • Loading branch information
leofavre committed Jan 28, 2019
2 parents a6fcffe + 7326c16 commit 20c40fb
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 36 deletions.
40 changes: 27 additions & 13 deletions packages/sling-framework/src/v1/src/business/withRequestParams.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { isFunction, toFlatEntries } from 'sling-helpers';
import { isFunction, toFlatEntries, toFlatObject } from 'sling-helpers';

const isValidEntry = ([, value]) => value != null && value !== '';

const CHANGES_QUEUE = Symbol('CHANGES_QUEUE');

export const withRequestParams = (Base = class {}) =>
class extends Base {
static get requestParamNames() {
Expand All @@ -22,6 +24,7 @@ export const withRequestParams = (Base = class {}) =>
constructor() {
super();
this.requestParams = {};
this[CHANGES_QUEUE] = [];

this.constructor.requestAttrNames
.forEach((attrName) => {
Expand All @@ -44,23 +47,34 @@ export const withRequestParams = (Base = class {}) =>
const { requestAttrNames, requestParamNames } = this.constructor;
const requestAttrIndex = requestAttrNames.indexOf(attrName);

const shouldTrigger = requestAttrIndex > -1 &&
isFunction(this.requestParamsChangedCallback) &&
oldValue !== newValue;
const shouldUpdate = requestAttrIndex > -1 && oldValue !== newValue;
const shouldTrigger = isFunction(this.requestParamsChangedCallback);

if (shouldTrigger) {
if (shouldUpdate) {
const changedParamName = requestParamNames[requestAttrIndex];
const changedParam = { [changedParamName]: newValue || null };
this[CHANGES_QUEUE].push(changedParam);
const queueSize = this[CHANGES_QUEUE].length;

Promise.resolve().then(() => {
if (this[CHANGES_QUEUE].length === queueSize) {
const allChanges = this[CHANGES_QUEUE].reduce(toFlatObject, {});

this.requestParams = Object
.entries({
...this.requestParams,
...changedParam,
})
.filter(isValidEntry)
.reduce(toFlatEntries, {});
this.requestParams = Object
.entries({
...this.requestParams,
...allChanges,
})
.filter(isValidEntry)
.reduce(toFlatEntries, {});

this.requestParamsChangedCallback(this.requestParams, changedParam);
if (shouldTrigger) {
this.requestParamsChangedCallback(this.requestParams, allChanges);
}

this[CHANGES_QUEUE] = [];
}
});
}

if (isFunction(super.attributeChangedCallback)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,40 +175,40 @@ describe('withRequestParams', () => {
});

it('Should call requestParamsChangedCallback if a request ' +
'param changes.', () => {
'param changes.', async () => {
const dummy = new Dummy();
dummy.requestParamsChangedCallback = sinon.spy();
dummy.attributeChangedCallback('startdate', '20180901', '20180915');
await dummy.attributeChangedCallback('startdate', '20180901', '20180915');
expect(dummy.requestParamsChangedCallback).to.have.been.called;
});

it('Should not call requestParamsChangedCallback if a request param ' +
'changes to the previous value.', () => {
'changes to the previous value.', async () => {
const dummy = new Dummy();
dummy.requestParamsChangedCallback = sinon.spy();
dummy.attributeChangedCallback('startdate', 'sameDate', 'sameDate');
await dummy.attributeChangedCallback('startdate', 'sameDate', 'sameDate');
expect(dummy.requestParamsChangedCallback).not.to.have.been.called;
});

it('Should not call requestParamsChangedCallback if a changed attribute ' +
'is not a request param.', () => {
'is not a request param.', async () => {
const dummy = new Dummy();
dummy.requestParamsChangedCallback = sinon.spy();
dummy.attributeChangedCallback('notSet', 'oldValue', 'newValue');
await dummy.attributeChangedCallback('notSet', 'oldValue', 'newValue');
expect(dummy.requestParamsChangedCallback).not.to.have.been.called;
});

it('Should receive an object containing all the request parameters ' +
'as the first argument.', () => {
'as the first argument.', async () => {
const dummy = new Dummy();
dummy.requestParamsChangedCallback = sinon.spy();
dummy.attributeChangedCallback('startdate', '20180901', '20180915');
await dummy.attributeChangedCallback('startdate', '20180901', '20180915');

expect(dummy.requestParamsChangedCallback).to.have.been.calledWith({
startDate: '20180915',
});

dummy.attributeChangedCallback('finaldate', '20200901', '20200915');
await dummy.attributeChangedCallback('finaldate', '20200901', '20200915');

expect(dummy.requestParamsChangedCallback).to.have.been.calledWith({
startDate: '20180915',
Expand All @@ -217,35 +217,35 @@ describe('withRequestParams', () => {
});

it('Should exclude parameters with empty values ' +
'at the first argument.', () => {
'at the first argument.', async () => {
const dummy = new Dummy();
dummy.requestParamsChangedCallback = sinon.spy();

dummy.attributeChangedCallback('startdate', '20180901', null);
await dummy.attributeChangedCallback('startdate', '20180901', null);
expect(dummy.requestParamsChangedCallback).to.have.been.calledWith({});

dummy.attributeChangedCallback('finaldate', '20200901', '');
await dummy.attributeChangedCallback('finaldate', '20200901', '');
expect(dummy.requestParamsChangedCallback).to.have.been.calledWith({});

dummy.attributeChangedCallback('affiliationcode', '', '123456789');
await dummy.attributeChangedCallback('affiliationcode', '', '123456789');
expect(dummy.requestParamsChangedCallback).to.have.been.calledWith({
affiliationCode: '123456789',
});
});

it('Should receive an object containing only the changed parameters ' +
'as the second argument.', () => {
'as the second argument.', async () => {
const dummy = new Dummy();
dummy.requestParamsChangedCallback = sinon.spy();
dummy.attributeChangedCallback('startdate', '20180901', '20180915');
await dummy.attributeChangedCallback('startdate', '20180901', '20180915');

expect(dummy.requestParamsChangedCallback).to.have.been.calledWith({
startDate: '20180915',
}, {
startDate: '20180915',
});

dummy.attributeChangedCallback('finaldate', '20200901', '20200915');
await dummy.attributeChangedCallback('finaldate', '20200901', '20200915');

expect(dummy.requestParamsChangedCallback).to.have.been.calledWith({
startDate: '20180915',
Expand All @@ -261,16 +261,16 @@ describe('withRequestParams', () => {
});

it('Should not exclude parameters with empty or undefined values ' +
'at the second argument.', () => {
'at the second argument.', async () => {
const dummy = new Dummy();
dummy.requestParamsChangedCallback = sinon.spy();
dummy.attributeChangedCallback('startdate', '20180901', null);
await dummy.attributeChangedCallback('startdate', '20180901', null);

expect(dummy.requestParamsChangedCallback).to.have.been.calledWith({}, {
startDate: null,
});

dummy.attributeChangedCallback('finaldate', '20200901', '');
await dummy.attributeChangedCallback('finaldate', '20200901', '');

expect(dummy.requestParamsChangedCallback).to.have.been.calledWith({}, {
finalDate: null,
Expand All @@ -280,11 +280,55 @@ describe('withRequestParams', () => {
});

it('Should not break if requestParamsChangedCallback ' +
'is not a function.', () => {
'is not a function.', async () => {
const dummy = new Dummy();
await dummy.attributeChangedCallback('startdate', '20180901', '20200915');

expect(dummy.requestParams).to.deep.equal({
startDate: '20200915',
});
});

it('Should change requestParams only once after many ' +
'attribute changes.', async () => {
const dummy = new Dummy();

dummy.attributeChangedCallback('affiliationcode', '123', '321');
dummy.attributeChangedCallback('startdate', '20180901', '20180915');
dummy.attributeChangedCallback('finaldate', '20200901', '20200915');

expect(dummy.requestParams).to.deep.equal({});

await Promise.resolve();

expect(dummy.requestParams).to.deep.equal({
affiliationCode: '321',
startDate: '20180915',
finalDate: '20200915',
});
});

it('Should trigger requestParamsChangedCallback only once after many ' +
'attribute changes.', async () => {
const dummy = new Dummy();
const value = dummy
.attributeChangedCallback('startdate', '20180901', '20200915');
expect(value).to.be.undefined;
dummy.requestParamsChangedCallback = sinon.spy();

dummy.attributeChangedCallback('affiliationcode', '123', '321');
dummy.attributeChangedCallback('startdate', '20180901', '20180915');
dummy.attributeChangedCallback('finaldate', '20200901', '20200915');

expect(dummy.requestParamsChangedCallback).not.to.have.been.called;

await Promise.resolve();

const changes = {
affiliationCode: '321',
startDate: '20180915',
finalDate: '20200915',
};

expect(dummy.requestParamsChangedCallback)
.to.have.been.calledWith(changes, changes);
});
});
});

0 comments on commit 20c40fb

Please sign in to comment.