Setting up single-player tests before adding spinner

🗹 Fail 🗹 Pass Refactor

Yes, because we have completed the refactor stage.

🗹 Fail 🗹 Pass 🗹 Refactor

Are these testing stage-indicators of helpful to remind about what we are focusing on?

That brings us to an end of the testing cycle, and we can now cycle back around to the fail stage where we add a new test.

Fail ☐ Pass ☐ Refactor

We want a test failing in such a way that the manageCover.init code will be able to make it pass.

We have been testing what happens when manageCover.init() is initialized. Our focus currently has been on the openCurtain() function.

  function openCurtain(cover) {
    hide(cover);
    const curtain = document.querySelector(".curtain");
    curtain.classList.add("slide");
    return curtain;
  }

We have tested the hide. Now we have the “slide” to test.

  • The new test is to be called “slides the curtain when cover is clicked”
  • In that test we start by initializing manageCover.
  • Then we remove “slide” from the curtain which will be two lines of code:
    • One to define a curtain variable,
    • and another to remove the “slide” class from the curtain.
  • Then we expect that that curtain has the “slide” class.

We deliberately remove “slide” then expect “slide” to be there, to get a failing test. Between those two lines we will do something with manageCover to make the test pass. But not yet. Right now the focus is on having a suitably failing test.

Here is what I have: https://jsfiddle.net/94tqaepf/

Expected <div class="curtain">...</div> to have class 'slide'.

Should I remove: simulateClick(cover);

If it is in there the code passes, and you said we don’t want it to pass, so I removed it.

 it("slides the curtain when cover is clicked", function() {
    manageCover.init();
    const curtain = document.querySelector(".curtain");
    curtain.classList.remove("slide");
    // simulateClick(cover);
    expect(curtain).toHaveClass("slide");
  });

Fail ☐ Pass ☐ Refactor

The test is useless if it doesn’t fail. That’s why it’s important to sight the test as failing first, before using the manageCover code to make it pass.

☒ Fail ☐ Pass ☐ Refactor

The test suitably fails.

🗹 Fail Pass ☐ Refactor

We can now work on making the test pass, which in this case is by uncommenting the simulateClick() function call.

1 Like

And here the code passes: https://jsfiddle.net/tvq0jw1c/

it("slides the curtain when cover is clicked", function() {
    manageCover.init();
    const curtain = document.querySelector(".curtain");
    curtain.classList.remove("slide");
    simulateClick(cover);
    expect(curtain).toHaveClass("slide");
  });
});

Am I up to doing a new test?

🗹 Fail 🗹 Pass ☐ Refactor

Yes the code passes. A new test doesn’t happen just here yet.

🗹 Fail 🗹 Pass Refactor

Does any refactoring need to occur, based on what we’ve done?
It’s important to not skip the refactoring step. Sometimes nothing needs to be done, but now is the time for consideration.

🗹 Fail 🗹 Pass 🗹 Refactor

We have completed another test, and are ready for the next test.

Fail ☐ Pass ☐ Refactor

What are we next going to test? The openCurtain code seems to all be tested. After that it shows the video, which is the next thing that we test.

Here is the showVideo code that we are testing.

  function showVideo(curtain) {
    const thewrap = curtain.parentElement.querySelector(".wrap");
    show(thewrap);
  }

We should next test that the wrap element gets shown. The next test is called: “shows the video when cover is clicked”.

Remember those given/when/then sections from other tests? Even though those may not be explicitly in the code as comments, we should still structure the code in that kind of order. You can fill in the given, when, and then section comments if you think that will help you to make sense of things.

In the given section at the start of the test, we have same manageCover.init() function call with no parameters.

In the then section at the end of the test We can expect that a variable called wrap does not have a “hide” class.

The test tells us that wrap is not defined so in the given section below the initialization, we should define a wrap variable, and use querySelector to get the “.wrap” element.

The test passes. but it’s not supposed to pass yet. We are still in the stage of making a failing test.

Fail ☐ Pass ☐ Refactor

The test needs to fail. That means updating the wrap element so that the expectation doesn’t have it’s looking for. In the given section after defining the wrap variable, we add the “hide” class to the wrap element.

And we now have a suitably failing test, with an empty when section.

I need to do this:

In the given section after defining the wrap variable

Isn’t that done in the //when section?

Isn’t the wrap variable defined in the when section?

Then I need to do this:

we add the “hide” class to the wrap element.

Here is what I have: https://jsfiddle.net/shfoyc7n/

Expected <div class="wrap hide">...</div> not to have class 'hide'.

  it("shows the video when cover is clicked", function() {

    //given
    manageCover.init();

    //when
    const wrap = document.querySelector(".wrap");
    wrap.classList.add("hide");
    
    //simulateClick(cover);

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

The test then passes after uncommenting simulateClick(cover);

https://jsfiddle.net/shfoyc7n/1/

it("shows the video when cover is clicked", function() {

    //given
    manageCover.init();

    //when
    const wrap = document.querySelector(".wrap");
    wrap.classList.add("hide");
    
    simulateClick(cover);

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

The wrap variable is a part of given, because that represents “a given” about the system. A part of that given is when the wrap starts off as hidden.

The only thing that should be in the when section is the minimal thing that’s needed to turn the test from a fail to a pass, which in this case is only the simulateClick() statement.

We cannot move on yet, because the when section of the code has a given about the system, the wrap part, that needs to be in the given section instead.

1 Like

Fixed:

Here is what I have: https://jsfiddle.net/qyz149uv/

Expected <div class="wrap hide">...</div> not to have class 'hide'.

  it("shows the video when cover is clicked", function() {

    //given
    manageCover.init();

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

     //when
    //simulateClick(cover);

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

The test then passes after uncommenting simulateClick(cover);

https://jsfiddle.net/qyz149uv/1/

it("shows the video when cover is clicked", function() {

    //given
    manageCover.init();

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

     //when
    simulateClick(cover);

    //then
    expect(wrap).not.toHaveClass("hide");
  });
1 Like

What will we be testing in the next it section, and how would that test be set up?

  it("              ", function() {

  });

It’s not time for that yet.

🗹 Fail 🗹 Pass ☐ Refactor

The test passes so we have completed step 2 of the testing cycle:

🗹 Fail 🗹 Pass Refactor

And we are now on to refactoring, step 3 of the testing cycle.

The tests need to be cleaned up. Where given, when, or then, is used in a test, they all should be used in that test. There are also some things in a when section that shouldn’t be there. It’s only be the simulateClick() function that should be in a when section.

Also, the const definitions are a distraction from what’s happening in the tests. The curtain and wrap variables can be defined in the same way that cover is defined, and they can be assigned in the beforeEach function too.

It’s only be the simulateClick() function that should be in a when section.

I did that here: https://jsfiddle.net/Leyq0m1j/

Next:

Also, the const definitions are a distraction from what’s happening in the tests. The curtain and wrap variables can be defined in the same way that cover is defined, and they can be assigned in the beforeEach function too.

I did that here: https://jsfiddle.net/Leyq0m1j/3/

describe("init manageCover", function() {

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

  function removeEventHandlers(el) {
    el.outerHTML = el.outerHTML;
  }

  let curtain;
  let wrap;
  let cover;

  beforeEach(function() {
    curtain = document.querySelector(".curtain");
    wrap = document.querySelector(".wrap");
    cover = document.querySelector(".play");
  });

  afterEach(function() {
    removeEventHandlers(cover);
  });

  it("uninitialized cover doesn’t hide when clicked", function() {

    cover.classList.remove("hide");

    //when
    simulateClick(cover);

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

  it("hides the cover when clicked", function() {

    //given
    manageCover.init();

    cover.classList.remove("hide");

    //when
    simulateClick(cover);

    //then
    expect(cover).toHaveClass("hide");
  });

  it("slides the curtain when cover is clicked", function() {

    //given
    manageCover.init();

    curtain.classList.remove("slide");

    //when
    simulateClick(cover);

    // then
    expect(curtain).toHaveClass("slide");
  });

  it("shows the video when cover is clicked", function() {

    //given
    manageCover.init();

    wrap.classList.add("hide");

    //when
    simulateClick(cover);

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

We are still on refactoring.

🗹 Fail 🗹 Pass Refactor

The uninitialized test is missing a given section name.

After that’s tidied up we can move on to tests involving the afterClickCover event.

1 Like

I did that here: https://jsfiddle.net/fkyo3qdz/

 it("uninitialized cover doesn’t hide when clicked", function() {
  
    //given
    cover.classList.remove("hide");

    //when
    simulateClick(cover);

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

🗹 Fail 🗹 Pass 🗹 Refactor

The refactoring is now complete. We can move on to the next test.

Fail ☐ Pass ☐ Refactor

We have tested about all that we can in regards to no parameters, so the next test is when we use a parameter.

This test is about the afterClickCover event, which can be called “it triggers afterClickCover when cover is clicked”

There’s a lot of “when cover is clicked” so the next refactoring will be in regard to that. But it’s not yet. For now, we are wanting a failing test.

The part that we are wanting to test is at the end of the coverClickHandler function, where the dispatch occurs.

  function coverClickHandler(evt) {
    const cover = evt.currentTarget;
    const curtain = openCurtain(cover);
    showVideo(curtain);
    cover.dispatchEvent(events.afterClickCover);
  }

We will have to use a spy in the place of that afterClickCover. We want our new test to expect that a spy has been called, using the toHaveBeenCalled matcher. Eventually we’ll pass that spy as a callback to the init function, but first we are needing that failing test.

Because, I don’t know how to do this,

This is how I set it up:

My head can’t wrap around what I need to do here.

it("it triggers afterClickCover when cover is clicked", function() {

    //given
    manageCover.init();

    const = jasmine.createSpy("         ");
    manageCover.      ("              ", );

    //when
    // simulateClick(cover);

    //then
    expect().toHaveBeenCalled();

  });

My attempt:

Is any of this good?

  it("it triggers afterClickCover when cover is clicked", function() {

    //given
    manageCover.init();

    const afterClickCover = jasmine.createSpy("afterClickCover");
    manageCover.coverClickHandler(".play", afterClickCover);

    //when
    // simulateClick(cover);

    //then
    expect(afterClickCover).toHaveBeenCalled();

  });

The afterClickCover spy needs to go before the init statement, because you are going to give it as the first argument to the init method.

Is this close? https://jsfiddle.net/k52fsuct/

 it("it triggers afterClickCover when cover is clicked", function() {

    //given
    const afterClickCover = jasmine.createSpy("afterClickCover");
    manageCover.coverClickHandler(".play", afterClickCover);

    manageCover.init({
      afterClickCover: ".play"
    });
    
    //when
    //simulateClick(cover);

    //then
    expect(afterClickCover).toHaveBeenCalled();

  });

It’s looks like you’ve made yourself confused by copy/pasting things in there.

Please start over with only the expect line in the test, and follow the error messages.

The code now passes which is not what was supposed to occur, we wanted it to fail.

https://jsfiddle.net/7anjwdey/

 it("it triggers afterClickCover when cover is clicked", function() {

    //given
    const afterClickCover = jasmine.createSpy("afterClickCover");
    afterClickCover();

    manageCover.init();

    //then
    expect(afterClickCover).toHaveBeenCalled();

  });

/me repeats the advice given in his previous post.