Adding tests to video player code

1st argument: ".playb"

2nd argument: "coverHandler"

manageCover.addCoverHandler("1st argument", "2nd argument")

Am I supposed to do this?

    manageCover.addCoverHandler({

        });

Maybe this?

I don’t understand what I need to do.

    manageCover.addCoverHandler({
        coverSelector: ".playb",
        coverHandler: "coverHandler"
      });

I’m lost.

This:
manageCover.addCoverHandler(".playb");

Becomes this is wrong:
manageCover.addCoverHandler(".playb", "coverHandler");

Then I am completely lost.

This is wrong:
manageCover.addCoverHandler(".playb", "coverHandler");

This is wrong:
manageCover.addCoverHandler(".playb", coverHandler);

Both of those are wrong, I don’t understand what I need to do.

Let’s go back to the error message, because we should not yet be dealing with addCoverHandler.

The error message is:

TypeError: Failed to execute 'addEventListener' on 'EventTarget': parameter 2 is not of type 'Object'.

Where is that addEventListener? What is EventTarget? What is parameter 2? Why isn’t is an Object?

That addEventListener is in the following manageCover code:

  function addCoverHandler(coverSelector, handler) {
    const cover = document.querySelector(coverSelector);
    cover.addEventListener("click", handler);
  }

The syntax is addEventListener is given at https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#syntax

That syntax is:

addEventListener(type, listener);
addEventListener(type, listener, options);
addEventListener(type, listener, useCapture);

In the addCoverHandler function we are using the first version of the syntax which has two parameters. The first parameter is called type, and the second parameter is called listener.

In the addCoverHandler function we call addEventListener with:

cover.addEventListener("click", handler);

where the first argument of “click” received by addEventListener as the type parameter, and the second argument of handler is received by the addEventListener as the listener parameter.

Parameter 2 of addEventListener is the listener parameter, which is the handler argument that we gave to it.

listener
    The object that receives a notification (an object that implements
    the Event interface) when an event of the specified type occurs.
    This must be an object implementing the EventListener interface,
    or a JavaScript function. See The event listener callback for details
    on the callback itself.

The error message tells us that the handler variable isn’t an object. It is expected to be a JavaScript function, as functions are also objects.

Why isn’t that handler variable a function? The handler variable is received by the addCoverHandler as its second parameter. That second parameter is given to the addCoverHandler as the second argument when we make the addCoverHandler function call.

      const coverHandler = jasmine.createSpy("coverHandler");
      manageCover.addCoverHandler(".playb", "coverHandler");

That second argument shouldn’t be a string. It needs to be a reference to the coverHandler variable instead.

When you fix that you will get another error message, but it’s important to note that it’s a different error message and that progress is being made.

This? https://jsfiddle.net/86f0qnhL/

      const coverHandler = jasmine.createSpy("coverHandler");
      manageCover.addCoverHandler(".playb", coverHandler);

TypeError: el.dispatchEvent is not a function

In which function is that error coming from?

Here is the error image:

Does it say in here?

If no, how do I find out?

I don’t know where the error is coming from.

All I know is I followed your instructions where I was supposed to get a different error, and this is a different error.

The error occurs after I added: coverHandler

manageCover.addCoverHandler(".playb", coverHandler);

The addCoverHandler function?

Well, after the error message line, which function do you recognize from there?

simulateClick(".playb");

So it is this function then?

  function simulateClick(el) {
    const clickEvent = new MouseEvent('click', {
      currentTarget: 'el'
    });
    el.dispatchEvent(clickEvent);
  }

How is that error fixed in the code?

Will there be more errors after this one?

or, should it be passing after this one is fixed?

Yes, that is the function. The dispatchEvent part is not pleased because the dispatchEvent function doesn’t exist on the el parameter.

I recommend that you change how you’re dealing with simulateClick, so that you do it in the same way as is being done in other tests.

I did that here and the code passes: https://jsfiddle.net/3n9fxjuc/1/

    it("with coverSelector and coverHandler parameters", function() {

      // given
      manageCover.init({
        playButton: ".playb"
      });

      const coverHandler = jasmine.createSpy("coverHandler");
      manageCover.addCoverHandler(".playb", coverHandler);

      const playButton = document.querySelector(".playb");
      simulateClick(playButton);

      expect(coverHandler).toHaveBeenCalled();

    });

Next I placed the html and the css from the broken code into the test code:

Where I receive this error: https://jsfiddle.net/3n9fxjuc/2/

The error points to this it section, or this part of the test code.

it("when not initialized", function() {

        // given
        manageCover.init({
          container: ".play1",
          playButton: ".playa"
        });

        document.body.classList.remove("initial-fade");

        // when
        const playButton = document.querySelector(".playb");
        simulateClick(playButton);

        // then
        expect(document.body).not.toHaveClass("initial-fade");
      });

Where do we make changes to fix the broken code?

Inside the broken code that I placed inside the test code: https://jsfiddle.net/3n9fxjuc/2/

or, inside the the full working broken code: https://jsfiddle.net/panmhg2q/

Also, what would be the instructions I would do to fix that?

Did I do this wrong? https://jsfiddle.net/3n9fxjuc/1/

I may have done it not right.

I thought I did it good because it passed, and the error went away.

If this is wrong, how would I fix it?

 it("with coverSelector and coverHandler parameters", function() {

      // given
      manageCover.init({
        playButton: ".playb"
      });

      const coverHandler = jasmine.createSpy("coverHandler");
      manageCover.addCoverHandler(".playb", coverHandler);

      const playButton = document.querySelector(".playb");
      simulateClick(playButton);

      expect(coverHandler).toHaveBeenCalled();

    });

No, the tests are not ready for that yet.

Yes, the tests pass, but they’re not complete. Here’s what we currently have:

  • :white_check_mark: init needs a function parameter
  • :white_check_mark: init container with a single container
  • :white_check_mark: init container with multiple containers
  • :white_check_mark: init playButton when not initialized
  • :white_check_mark: init playButton with one playButton
  • :white_check_mark: init playButton with all playButtons
  • :white_check_mark: addCoverHandler needs coverSelector
  • :white_check_mark: addCoverHandler with coverSelector and coverHandler

The tests are passing, but are they any good?

Crosschecks now need to occur, where we check two things:

  • Can any of the test code (mainly the when section) be commented out, and the tests still pass?
  • Can any of the manageCover code be commented out, and the tests still pass?

Both of those a problems that need to be fixed, and the code at https://jsfiddle.net/3n9fxjuc/1/ has both of those problems.

Here are the problems that I found with a few simple checks:

  • The single-container test is currently broken, because it shows a pass when it shouldn’t.
  • The multiple-containers test is currently broken, because it shows a pass when it shouldn’t.
  • The showCover() code in manageCover is not yet being tested at all

That gives us an updated list of the following:

  • :white_check_mark: init needs a function parameter
  • :x: init container with a single container
  • :x: init container with multiple containers
  • :x: fails to check showCover() code
  • :white_check_mark: init playButton when not initialized
  • :white_check_mark: init playButton with one playButton
  • :white_check_mark: init playButton with all playButtons
  • :white_check_mark: addCoverHandler needs coverSelector
  • :white_check_mark: addCoverHandler with coverSelector and coverHandler

We’re made some good progress, but there’s a way to go yet before the tests are ready to be used.

The first issue is experienced in the single container test, just by commenting out the simulateAnimationEnd line. That’s the first problem that needs to be fixed. With that line commented out, it must show a fail instead.

I commented that line out here: https://jsfiddle.net/exh8o17p/

What am I supposed to do?

How do I get it to show a fail?

      it("with a single container", function() {

        // given
        manageCover.init({
          container: ".play1",
          playButton: ".playa"
        });

        const container = document.querySelector(".play1");
        container.classList.add("hide");

        // when
        const playButton = document.querySelector(".playa");
        simulateClick(playButton);

        //simulateAnimationEnd();

That test is supposed to check for something that happens when the animationEndHandler() function gets run. Here is that function:

  function animationEndHandler(evt) {
    const animationName = evt.animationName;

    if (animationName === "initial-fade") {
      body.classList.remove("initial-fade");
      showCover(currentPlayButton);
    }
  }

In manageCover we earlier defined body to be document.body. What the event handler does is that it removes initial-fade from document.body.

We need the test to add initial-fade to document.body, and after we simulate animation-end we need to check that initial-fade has been removed from document.body.

The test code that uses the container variable all needs to be removed too.

I removed the container variable here: https://jsfiddle.net/jbced2uk/1/

      it("with a single container", function() {

        // given
        manageCover.init({
          // container: ".play1",
          playButton: ".playa"
        });

        // const container = document.querySelector(".play1");
        // container.classList.add("hide");

        // when
        const playButton = document.querySelector(".playa");
        simulateClick(playButton);

        // simulateAnimationEnd();

        // then
        expect(document.body).not.toHaveClass("hide");
      });

I’m going to take a break from this code.

The container property (the first of the three you commented out) doesn’t get commented out. That needs to be uncommented.

The next thing to do after that is in the given section to add the class “initial-fade” to document.body, and in the then section to expect that document.body doesn’t have the class “initial-fade”.

That way the test suitably fails, and when we uncomment the simulateAnimationEnd() that causes things to change, and the test will properly pass.

Yes well this is a marathon, not a sprint.