Better support for testing from engines

# Adam Eisenreich (5 years ago)

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?

# guest271314 (5 years ago)

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?

# Adam Eisenreich (5 years ago)

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?

# Adam Eisenreich (5 years ago)

About video try reloading the page and doing video.play(), it will reject, as the event is not trusted.

# guest271314 (5 years ago)

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.

# Adam Eisenreich (5 years ago)

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.

# peter miller (5 years ago)

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

# guest271314 (5 years ago)

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?

# Adam Eisenreich (5 years ago)

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.

# guest271314 (5 years ago)

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.