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


#1427

What is supposed to happen is that the selector that we gave upTo, is supposed to give us the parent that matches that selector. This is now a good time to use a unit test, to help us get this thing right.

The unit test will really help, because not only does it tell us when we've got things right, but it helps to warn us when regressions happen to our code that take it back to those problems that we want solved.

I've added the Jasmine unit test code to https://jsfiddle.net/pmw57/tavcvcu6/339/ from where we can start to deal with this problem.


#1428

To test the code, we need to access the code in some way, so we can assign the button code to an app variable:

var app = {};
app.buttone = (function iife() {
 // ...

and at the end of the code, return the functions that we want to be able to access:

  // ...
  return {
  	upTo
  };
}());

We can now add a simple test, using elements different from the ones that we intend to find. Why different ones? If we use the same elements then we cannot know if it works with other ones. Testing with other elements, svg/path in this case, helps us to be sure that we've solved things for more general cases too.

describe("Buttone", function () {
  it("Finds a parent", function () {
    var svg = document.querySelector("svg");
    var path = svg.querySelector("path");
    expect(buttone.upTo(path, "svg")).toBe(svg);
  });
});

I've added that test code to https://jsfiddle.net/pmw57/tavcvcu6/341/ from where we can start to make things right.


#1429

The problem seems to be happening in the upTo() function, which looks like this:

  function upTo(el, selector) {
    if (!el || el.nodeName === "HTML") {
      return;
    }
    if (el.matches(selector) === false) {
      return upTo(el.parentNode, selector);
    }
  }

When path and svg are given as arguments to the upTo function, we can use the debugger to make sure that the code properly works. In this case, the code ignores the first if statement, because the condition on that if statement isn't met, and execution moves on to the second if statement.

The second if statement is met because path is not an svg element, so the return statement occurs. That return statement gives new arguments to the upTo function, those being el.parentNode, and selector

In this case, the parentNode of path is svg, and the selector is "svg"

Starting from the top of the function again, the first if statement isn't met, so execution moves on to the second if statement.
The condition of the second if statement isn't met this time either, because the match equals true and the condition is for if it equals false.

Therefore, what? The function just ends, which isn't correct. What needs to happen is that the function needs to return el at the end of the function.

I bet you that it'll work after doing that.


#1430

Oh, but first, there's a problem with the test. It says that buttone doesn't exist. Using app.buttone makes the test fail in a more proper manner, and testing can continue from https://jsfiddle.net/pmw57/tavcvcu6/342/ with finding and fixing that upTo problem from there.


#1431

The was the original code:

  function upTo(el, selector) {
    while (el.matches(selector) === false) {
      el = el.parentNode;
    }
    return el;
  }

#1432

What does the unit test say when you fix the problem in the code at https://jsfiddle.net/pmw57/tavcvcu6/342/


#1433

Failing 1 spec1 spec | 1 failing
Buttone Finds a parent.
Expected undefined to be HTMLNode.


#1434

It says that from when it previously had the problem. Run the code again with the fix in place, and you should see something different from the test.


#1435

This one says passing:
https://jsfiddle.net/tavcvcu6/348/


#1436

What do I do next?


#1437

Excellent, that's what we want. Leave the tests there while developing the code, for they help to protect us from regression issues if anything goes wrong, and warns us immediately if anything makes the tests break.

Now that upTo is working properly, we can move on to investigating more about why clicking on the initial image doesn't make it go away.


#1438

The next issue is shown on the console when we click on the initial image. Clicking on the line number that's reported to us in the console, takes us to the problem.


#1439

while (el.matches(selector) === false) {


#1440

All of that code is good now, we have a test that helps to confirm that for us.

What code are you working with now?


#1441

https://jsfiddle.net/tavcvcu6/348/


#1442

That upTo function is different from the one that we were using before, and doesn't protect us from when an element isn't found.

Here's another test that demonstrates the problem that the code you're using fails to protect from.

  it("Safely handles an unfound element", function() {
    var svg = document.querySelector("svg");
    var path = svg.querySelector("path");
    expect(app.buttone.upTo(svg, "path")).toBeUndefined();
  });

Add that code below the other test, and we'll work on making that upTo function even better.


#1443

https://jsfiddle.net/tavcvcu6/352/

(function() {
  var env = jasmine.getEnv();
  env.addReporter(new jasmine.HtmlReporter());
  env.execute();
}());


  it("Safely handles an unfound element", function() {
    var svg = document.querySelector("svg");
    var path = svg.querySelector("path");
    expect(app.buttone.upTo(svg, "path")).toBeUndefined();
  });

#1444

No not there, place it inside the describe section, below the other it section of code.


#1445

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


#1446

You've placed it below the describe section which is the wrong place to put it.

It must be inside the describe section, just below the other it section of code.