-
Notifications
You must be signed in to change notification settings - Fork 781
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Let the test.each callback access the current case key #1764
Comments
I agree exposing the key would be interesting to persue. I will say there is also a separate proposal to bring nice reporting to array values: #1733. Perhaps you'd be interested to help with that as well? In terms of ergonomics I imagine it'd be simpler not to have to introduce a new way to expose the current dataset key as another thing to learn, but I'm not opposed to it either if it can be done in a sufficiently simple/intuitive way. Adding more callback parameters is tricky and somewhat prone to mistakes, but that's a gut reaction. I will ponder on it :) |
sure 👍
do you have something in mind? |
The drawback of appending a callback parameter is that it locks us in. If we need an extra parameter for something else later, in Hence, I'm cautious. But, so far I've not found a compelling issue or potential thing we would need it for, so maybe we should just add this! 🙂
I don't have a preference yet. Alternatives won't be as minimal as adding a third argument. But, here's a few ideas in case one of these jumps out as appealing. // Status quo
QUnit.test.each('example', {
Running: { status: 'Running', expected: true },
Canceling: { status: 'Canceling', expected: true },
Canceled: { status: 'Canceled', expected: false }
}, function (assert, { status, expected }) {
assert.true(true);
});
// 1. Key as third callback argument
QUnit.test.each('example', {
Running: true,
Canceling: true,
Canceled: false
}, function (assert, value, key) {
assert.true(true);
});
// 2. Key as second callback argument
QUnit.test.each('example', {
Running: true,
Canceling: true,
Canceled: false
}, function (assert, key, value) {
assert.true(true);
});
// 3. Key in callback context
QUnit.test.each('example', {
Running: true,
Canceling: true,
Canceled: false
}, function (assert, value) {
// this.dataKey
// this.$key
// this.somethingElse?
assert.true(true);
});
// 4. labelKey parameter to each() method
// Optional labelKey as second argument to each(), which produces
// test case names as "example [Running]" instead of "example [0]"
QUnit.test.each('example', 'status', [
{ status: 'Running', expected: true },
{ status: 'Canceling', expected: true },
{ status: 'Canceled', expected: false }
], function (assert, { status, expected }) {
assert.true(true);
});
// 5. New eachKeyed() method
// Opt-in to expanding the object to key/value pairs
QUnit.test.eachKeyed('example', {
Running: true, // translated to { key: 'Running', value: true }
Canceling: true,
Canceled: false
}, function (assert, { key, value }) {
assert.true(true);
}); |
So I've thought about this a bit more, also in context of well-known JavaScript idioms. Number 1 and number 5 both have appeal in that sense as playing to an existing and familiar pattern. Number 1, by adding third parameter, is backward-compatible (apart from monkey-patching, which was common in the QUnit 1.x ecosystem, but mostly in the past now, I think?), and resembles how Array.forEach works in JavaScript. While the ordering is perhaps suboptimal if observed in isolation (key-value seems more intuitive than value-key), it resembles the familiar forEach-pattern. And, perhaps reflects their relative priority. The value is the most importand and always used. The key is an optional extra argument, for when you need it. var dataset = ['foo', bar'];
dataset.forEach( function ( value ) {
// value = "foo", "bar"
} );
dataset.forEach( function ( value, i ) {
// value = "foo", "bar"
// i = 0, 1
} ); This makes the following fairly natural, noting that we can have both arrays and objects in // 1. Add key as third parameter
QUnit.test.each('example', {
Running: true,
Canceling: true,
Canceled: false
}, function (assert, value, key) {
assert.true(true);
}); Number 5, can resemble the way Object.entries() works in JavaScript, which converts an object into an array of key-value pairs: var dataset = { foo: 123, bar: 456 };
Object.entries(dataset);
// [
// [ "foo", 123 ],
// [ "bar", 356 ]
// ]
Object.entries(dataset).forEach( function ( [key, value] ) {
// key = "foo", "bar"
// value = 123, 456
} ):
// 5b. New eachEntry() method
QUnit.test.eachEntry('example', {
Running: true, // translated to [ 'Running', true ]
Canceling: true,
Canceled: false
}, function (assert, [ key, value ]) {
assert.true(true);
}); By using an array and destructured arguments, you have have freedom over the naming. This can be Between the two, I think after all this, I lean toward @vtintillier's original proposal (Number 1). The main reason being to keep the QUnit API as short and simple as possible. I think a third argument is more natural to discover and won't be as big a stretch to adopt, then to have to know about a new top-level method name. This will also benefit in the short-term with linting (eslint-plugin-qunit), TypeScript, and wrapper like ember-qunit who then won't have to know about 5 new methods (test.eachEntry, test.only.eachEntry, test.todo.eachEntry, test.skip.eachEntry, test.if.eachEntry) |
This is a feature request for
QUnit.test.each
. I can do a PR if this is something you think is desirable to add.Tell us about your runtime:
What are you trying to do?
When using
QUnit.test.each
it would sometimes be nice to have access to the test case key.Code that reproduces the problem: for example notice the duplication here where both the status and the test case keys are the same:
What did you expect to happen?
I would expect to be able to write something like this:
where we get the test case key as an additional argument to the test callback.
What actually happened?
This is not possible yet, and we have to duplicate values to get nice reporting (instead of e.g. using an array where we just see integers as test case names).
The text was updated successfully, but these errors were encountered: