Getting audio players to play their respective streams out of their element


#1467

Now what?
https://jsfiddle.net/tavcvcu6/361/


#1468

Now what? We are considering the playButtone element, and trying to understand how we can have the code get from there to the linkse element.


#1469

Do you now understand what needs to be done?

or it can't be done?


#1470

Oh I've known exactly what needs to be done. I've been waiting for you to understand how we can have the code get from the playButtone element to the linkse element.

There is a better process though that will help us with this task, and that is the red/green/refactor system of test driven development. We've already experienced some of that, and so it's now time to continue doing that.

The main question is:

In this case, we expect that clicking on the initial image, to remove the "inactive" classname from the links.

We can test for that by first checking that links starts off with "inactive", then click on the button, and check to see if "inactive" was removed.

Here is that test, which goes inside of the describe section, below the last it section of code.

  it("shows links when initial is clicked", function () {
    var button = document.querySelector(".playButtone");
    var link = document.querySelector(".linkse");
    expect(link.classList.contains("inactive")).toBe(true);
    button.click();
    expect(link.classList.contains("inactive")).toBe(false);
  });

That gives us a failing test where it expects true to be false, which is exactly what we want. The changes that we make to the button code after this, will be to make the failing test pass.

Edit:

Fixed code to call rename links to link

#1471

Here:
https://jsfiddle.net/tavcvcu6/368/


#1472

There's a slight error in the test code, where links needs to be link instead.

Get that change made, and the rest of the work will be easy.


#1473

I added this wrong?

  it("shows links when initial is clicked", function () {
    var button = document.querySelector(".playButtone");
    var links = document.querySelector(".linkse");
    expect(links.classList.contains("inactive")).toBe(true);
    button.click();
    expect(links.classList.contains("inactive")).toBe(false);
  });

#1474

No you added it right, but I did something wrong. links needs to be just link instead.


#1475

Here:
https://jsfiddle.net/tavcvcu6/370/


#1476

Good one. Now with the hideInitialOverlay function, that var link line has been giving us trouble.
Replace that line with the var link line from the test. That should get the test passing.

After that we need to do some refactoring, as given by the red/green/refactor nature of testing.


#1477

Replace this:
var link = upTo(button, ".linkse");

With this?
var link = document.querySelector(".linkse");


#1478

https://jsfiddle.net/tavcvcu6/372/


#1479

Strictly speaking it wasn't a mistake that was made in the test with the links/link issue. Instead, it was more important to have the variable name match what was used in the code, to make it easier for you to apply a working solution.

Now with refactoring, we can keep the green test passing, and fix up a few things.
What link refers to is the linkse element, which does contain a series of links, so renaming link to links both in the code and in the test, is the appropriate thing to do now.

Also, cleaning up after the test must be done, where we return things back to how they started.
We can do that by recording how things were before the test, and afterwards setting things back to what it was.

The following code records the classes on button/links/initial, and after the tests sets them back to what they should be again.

var button = document.querySelector(".playButtone");
var links = document.querySelector(".linkse");
var initial = document.querySelector(".initiale");
var buttonClassNames;
var linkClassNames;
var initialCassNames;
beforeEach(function () {
  buttonClassNames = button.className;
  linksClassNames = links.className;
  initialClassNames = initial.className;
});
afterEach(function () {
  button.className = buttonClassNames;
  links.className = linksClassNames;
  initial.className = initialClassNames;
});

When that's done, we can carry on the refactoring, to fix up a few other problems that will bite you in the ass later on down the road.


#1480

To help out, here's the code after having made those adjustments.

https://jsfiddle.net/tavcvcu6/368/


#1481

From here, refactoring has us consider the links variable. That's coming from document.querySelector which is going to break when it's not the first button on the page.

To fix that, we can make it button.querySelector instead. The same can be done in the test code too.

    var links = button.querySelector(".linkse");
// ...
var links = button.querySelector(".linkse");
var initial = button.querySelector(".initiale");

And lastly, in the final test we don't need to use var button and var links because we already have them assigned from just below the describe line of code instead, so those other var statements in the test can be removed, helping to simplify things there.

  it("shows links when initial is clicked", function () {
    expect(links.classList.contains("inactive")).toBe(true);
    button.click();
    expect(links.classList.contains("inactive")).toBe(false);
  });

Here's the updated code after those improvements.

https://jsfiddle.net/pmw57/tavcvcu6/376/


#1482

Isn't it supposed to be link, not links?


#1483

https://jsfiddle.net/tavcvcu6/380/


#1484

Updated:
https://jsfiddle.net/tavcvcu6/382/


#1485

There's one more thing, and that is that the test has resulted in the initial click handler not being on the button anymore.

We can deal with that by improving some of the code so that we can easily add the initial click handler on to the button, which I'm going to take a look at now.


#1486

That addEventListener code has been floating loose at the end of the button code, and can now be given a place to stay, in an init() function.

  function init(button) {
    document.querySelector(".linkse").classList.add("inactive");
    button.addEventListener("click", initialOverlayClickHandler);
  }
  return {
    upTo,
    init
  };
}());
app.buttone.init(document.querySelector(".playButtone"));

And we can add that init code to the end of the afterEach function too.

  afterEach(function() {
    // ...
    app.buttone.init(button);
  });

We can now tell the init() function to remove the playButton click handler when it adds the initialOverlay click handler, and things return to working as they should.

    playButton.removeEventListener("click", playButtonClickHandler);
    playButton.addEventListener("click", initialOverlayClickHandler);

The code after those changes is seen at https://jsfiddle.net/pmw57/tavcvcu6/389/