Better support for testing from engines
What are you trying to test relevant to modules? It is already possible to
play <video>
from within a module. What "trusted" events are you trying
to dispatch at HTMLMediaElement
within a module?
Assuming code like this:
import { compoteGraph } from './compute-graph';
export function doTheMath() {
// Elaborate work to gather parameters for `computeGraph`.
const param1 = 1;
const param2 = 'a';
const param3 = 'A';
return computeGraph(param1, param2, param3);
}
And it's test
import { doTheMath } from './do-the-math';
describe(..., () => {
it(..., () => {
expect(doTheMath()).toEqual([1, 'a', 'A']);
});
});
If you would like to mock the computeGraph
to return fixed value, for
example array of parameters, you to my knowledge don't have other way, than
using Jest, that does it by utilizing webpack (and possibli other) in the
middle.
Or am I wrong? Is there a way to mock imported (computeGraph
) function
from within the test?
About video try reloading the page and doing video.play()
, it will reject,
as the event is not trusted.
Is there a way to mock imported (
computeGraph
) function from within the test?
If gather the requirement correctly you can substitute utilizing
console.assert()
shipped with the browser for a third-party library.
About video try reloading the page and doing
video.play()
, it will reject, as the event is not trusted.
Not sure what the code or test is for playing <video>
in a module or what
lead to the Promise
rejection described when the document
is reloaded?
Have run this code plnkr.co/edit/5bvp9xv0ciMYfVzG?p=preview (which
plays <video>
in a JavaScript module) several times sequentially using
autoplay
without a Promise
rejection occurring.
If gather the requirement correctly you can substitute utilizing
console.assert()
shipped with the browser for a third-party library.
Yet MDN says:
Writes an error message to the console if the assertion is false. If the assertion is true, nothing happens.
I am not sure, but console.assert
seems only to do similar thing to expect(a).toBe(b)
About video, any video without sound can be played at any time, yet if it has sound, it is considered disruptive and thus should be blocked, unless the play is resulted via user action. This also apply for audio, webSpeech API, and few I may have forgotten.
I've not used import maps yet myself (WICG/import-maps)
but they'd probably allow you to swap an imported module for a dummy. Or
you could swizzle them with a service worker.
Obviously, there are much easier ways of handling your toy example. But I
appreciate that real world cases tend to be "non-trivial".
Peter
console.assert(Array.isArray(input) && input[0] === 1 && input[1] === 'a' && input[2] === 'A', {input})
or console.assert(JSON.stringify([1,'a','A']) === JSON.stringify(doTheMath()), {input})
should be equivalent to the third-party code
example.
About video, any video without sound can be played at any time, yet if it has sound, it is considered disruptive and thus should be blocked, unless the play is resulted via user action. This also apply for audio, webSpeech API, and few I may have forgotten.
Autoplay can be configured (enabled or disabled) at the browser preferences/settings and policy. If necessary a user gesture can be set to dispatch an event where the audio is played. How is the default autoplay preference/setting or policy of the browser currently affecting testing and this proposal?
The point is not how to write assertions, but how to replace implementation
of compoteGraph
with some other that would return something else for sake
of testing only one module instead of all deeply dependant modules.
I suppose that the user gesture might be solvable by starting browser with correct configuration. It isn't the easy plug-play style that javascript usually have, but that might be fine, as this isn't the most typical use case anyway.
The point is not how to write assertions, but how to replace implementation of compoteGraph with some other that would return something else for sake of testing only one module instead of all deeply dependant modules.
What do you mean by "replace implementation"?
Are you trying to verify if compoteGraph
returns what you are expecting
the function to return?
If that is the case, how do you know what compoteGraph
is expected to
return in the first instance?
In general, it is not possible to predict the return value of a function without executing the function.
As we are looking into the bright future when we will have native module support, but how will we test it then? As of now the only way to mock any module function, classes or other exports are by way of exploiting the fact that webpack (or similar) is in the middle.
Things to think about:
Mocking modules
Accessing private private fields/ variables (This might be controversial, but many would love that feature)
Ability to dispatch "trusted" events (needed for any video/audio or similar APIs)
I thing that having some kind of
'testing'
mode the same way as we do have'strict'
mode might be a way to solve it. The'testing'
keyword is ignored unless, it is included via<script>
, or an other'testing'
module.
The closest we have now is puppeteer, but would it be able to do all of it at reasonable speed? Also how about cross-platform?
What are your thoughts on this topic, have I missed any important hard/ impossible to test thing? Or library that does some woodoo?