The next test is for when target playerVars has a parameter and source has no playerVars.
it("with target playerVars param and no source playerVars, keeps playerVars param", function() {
const target = {
playerVars: {
test: "target value"
}
};
const source = {};
const combined = combinePlayerOptions(target, source);
expect(combined.playerVars.test).to.equal("target value");
});
That all works, so another checkbox updates the table.
target | no property | no params | has params
source | ----------- | --------- | ----------
no property | ✅ | ✅ | ✅
no params | ✅ | ✅ |
has params | ✅ | ✅ |
I’m getting nervous now because there are only two situations left to check.
Well no, there’s more. There’s also the situation when playerVars is undefined which would result in a 16x16 grid. That’s not expected use for the function, but I might check what happens there afterwards.
For now, we are checking what happens when target has a playerVars param and source has an empty playerVars param. From experience, this is what has caused trouble for you in your code.
it("with target playerVars param and empty source playerVars, keeps playerVars param", function() {
const target = {
playerVars: {
test: "target value"
}
};
const source = {
playerVars: {}
};
const combined = combinePlayerOptions(target, source);
expect(combined.playerVars.test).to.equal("target value");
});
And we at last get a failing test.
AssertionError: expected undefined to equal 'target value'
The source playerVars is clobbering everything that was in the target playerVars.
We can deal with that by assigning the assigned object to a combined
variable. That way we can separately assign the playerVars objects.
function combinePlayerOptions(target, source) {
const combined = Object.assign({}, target, source);
combined.playerVars = Object.assign({}, target.playerVars, source.playerVars);
return combined;
}
But, some of the tests still fail telling us:
TypeError: Cannot read properties of undefined (reading 'playerVars')
That is because target or source are undefined. We can add a default parameter value to them, to solve that problem with those tests.
function combinePlayerOptions(target = {}, source = {}) {
and all of the tests pass. We can add another checkbox to the table now.
target | no property | no params | has params
source | ----------- | --------- | ----------
no property | ✅ | ✅ | ✅
no params | ✅ | ✅ | ✅
has params | ✅ | ✅ |
There’s one last situation to check, and that’s when both target and source playerVars have parameters. When they’re the same parameters source should overwrite target.
it("with the same target and source playerVars params, source should win", function() {
const target = {
playerVars: {
test: "target value"
}
};
const source = {
playerVars: {
test: "source value"
}
}
const combined = combinePlayerOptions(target, source);
expect(combined.playerVars.test).to.equal("source value");
});
That one works, and the last test that we plan to do is when both target and source have different playerVars parameters. Both of those parameters should be kept.
it("with the different target and source playerVars params, both are kept", function() {
const target = {
playerVars: {
targetTest: "target value"
}
};
const source = {
playerVars: {
sourceTest: "source value"
}
}
const combined = combinePlayerOptions(target, source);
expect(combined.playerVars.targetTest).to.equal("target value");
expect(combined.playerVars.sourceTest).to.equal("source value");
});
That test passes fine, and so we can add a final checkbox to the table.
target | no property | no params | has params
source | ----------- | --------- | ----------
no property | ✅ | ✅ | ✅
no params | ✅ | ✅ | ✅
has params | ✅ | ✅ | ✅
That’s a lot of tests, and the function is very small, being only the following:
function combinePlayerOptions(target = {}, source = {}) {
const combined = Object.assign({}, target, source);
combined.playerVars = Object.assign({}, target.playerVars, source.playerVars);
return combined;
}
But as the tests all attest, that function is capable of correctly dealing with a wide variety of situations. https://jsfiddle.net/1zkow8x9/6/
We also need to check that other expected objects work properly such as with the events object. We could even make the code more generalized so that it works with all nested objects instead of playerVars and events, but that will be for the next post.