25 + 5 Clock - Why Does Test 8 in Content Fail?

The error messages aren’t super helpful. I think what happens is that the tests start running, with multiple tests for each user story, and as soon as they run into an error, that’s going to be the error message displayed.

For example. Test #8 checks if the element with id="time-left" displays the correct time. They let the timer run down and check if at the end, it shows 00:00. Then they increment the session-time up to 60 and test if it shows 60:00. As you can’t really know what particular part of a certain test failed, you can only guess what they were trying to achieve.

In your case - you put 25:00 as starting time, and the test passed for “does the timer show 25:00 at the beginning” (or after a reset, who knows). Then other tests run where the output should’ve been 60 but your code runs into an error, and that’s the error that you’ll get a report about.
If you put 60:00 as the start time, the first test (“does the timer show 25:00 at the beginning”) already fails before any other tests can run, so you obviously get a different error message.

Usually people that are having trouble with test 8 aren’t formatting their time correctly. So they might have a format like 0:00, 00:0, 00 : 00, etc.

I don’t think they’re running multiple tests at a time. They reset everything, run through their procedure, then reset again. If you’re curious about what they’re doing, I added a click event listener and console logged everything they did.

The last issue that I’m having that appears to be universal is the fact that there is drift when using setInterval. Even the example clock code admits this and refers to a stackOverflow thread about it. But you should be able to pass Test 8 without worrying about this yet.

Makes sense.

I made some more changes to the code and updated the Fiddle.

All of the tests from “Content” pass now, but most of the tests in the areas after that fail. Check the Fiddle to see the errors and such.

The reset button doesn’t work right. After changing the session and break lengths, clicking the reset button doesn’t bring them back to the default values. I also made it so that the value in the time-left element changes to session-length-minutes:00 in session mode and break-length-minutes:00 in break mode, so when the session and break length values are set to 1 by the tests, the amount of time remaining that’s displayed in the clock is “1:00”.

You’re doing this with React, right? A nice alternative to setInterval is a combination of setTimeout and useEffect. Put the current time in your useEffect dependency array and if it has changed, run the effect (set up a new timeout) again.

1 Like

Ah, yes I had quite a time with the reset button! It’s rather sloppy and I need to eventually refactor it. I basically said “if the reset button gets pressed, enable another function that changes the values back to 25 and 5”

What do you guys suggest about this test?

7. I should not be able to set a session or break length to > 60.
Value in element with id of "session-length" is greater than 60.: expected '41' to equal '60'
AssertionError: Value in element with id of "session-length" is greater than 60.: expected '41' to equal '60'

Test 7 in “Timer”. This is the code I have for the increment and decrement buttons:

const breakDecrementButton = $("#break-decrement");
breakDecrementButton.on("click", () => {
  const breakLength = $("#break-length");
  let lengthValue = Number(breakLength.text());
  if (lengthValue > 1) {
    lengthValue--;
  }
  breakLength.text(lengthValue);
  if (!isSessionRunning) {
    timerElem.text(`${breakLength.text()}:00`);
  }
});

const breakIncrementButton = $("#break-increment");
breakIncrementButton.on("click", () => {
  const breakLength = $("#break-length");
  let lengthValue = Number(breakLength.text());
  if (lengthValue < 60) {
    lengthValue++;
  }
  breakLength.text(lengthValue);
  if (!isSessionRunning) {
    timerElem.text(`${breakLength.text()}:00`);
  }
});

const sessionDecrementButton = $("#session-decrement");
sessionDecrementButton.on("click", () => {
  const sessionLength = $("#session-length");
  let lengthValue = Number(sessionLength.text());
  if (lengthValue > 1) {
    lengthValue--;
  }
  sessionLength.text(lengthValue);
  if (isSessionRunning) {
    timerElem.text(`${sessionLength.text()}:00`);
  }
});

const sessionIncrementButton = $("#session-increment");
sessionIncrementButton.on("click", () => {
  const sessionLength = $("#session-length");
  let lengthValue = Number(sessionLength.text());
  if (lengthValue < 60) {
    lengthValue++;
  }
  sessionLength.text(lengthValue);
  if (isSessionRunning) {
    timerElem.text(`${sessionLength.text()}:00`);
  }
});

@thompsonjl07 Did you call that other function inside the reset button handler?

Updated Fiddle again.

Actually no. What I did was changed one of my states to be either false. In my functional component that contains the counters, I put an if statement (inside of useEffect) in there. When that if statement sees props coming through that says my state is true, it then resets each of the counters to the hard-coded 5 and 25. And then I have something to change that state back to false.

As to your problem, I think the play and pause button needs to be the same button. I remember getting the exact same error you did until I fixed my buttons. I don’t know if it has to do with anything, but there’s a broken image inside of your reset button.

The broken image in the reset button on the Fiddle is because I have an actual image file I’m using that I couldn’t bring into the Fiddle. It has nothing to do with the app’s functionality.

Anyone have any idea why the clock gets stuck on “00:01” and doesn’t go below that, and how I could fix this problem?

I just managed to get 19 of the tests to pass. These are the tests that don’t pass:

1. When I click the element with the id of "reset", any running timer should be stopped, the value within id="break-length" should return to 5, the value within id="session-length" should return to 25, and the element with id="time-left" should reset to it's default state.
Timer has not reached 00:00.
Error: Timer has not reached 00:00.
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:168085

9. If the timer is running, the element with the id of "time-left" should display the remaining time in mm:ss format (decrementing by a value of 1 and updating the display every 1000ms).
25 + 5 clock has started but time displayed is not changing : expected 0 to be above 0
AssertionError: 25 + 5 clock has started but time displayed is not changing : expected 0 to be above 0
    at Proxy.f (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:549:2957)
    at Proxy.l (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:431:130)
    at Function.n.isAbove (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:574:960)
    at a.<anonymous> (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:176143)
    at l (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:98461)
    at Generator._invoke (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:98214)
    at Generator.forEach.e.<computed> [as next] (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:98818)
    at r (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:1:1054)
    at i (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:1:1265)

10. If the timer is running and I click the element with id="start_stop", the countdown should pause.
25 + 5 has started but time displayed is not changing: expected '00' to not equal '00'
AssertionError: 25 + 5 has started but time displayed is not changing: expected '00' to not equal '00'
    at Proxy.c (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:549:1889)
    at Proxy.l (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:431:130)
    at Function.n.notStrictEqual (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:574:736)
    at a.<anonymous> (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:176660)
    at l (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:98461)
    at Generator._invoke (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:98214)
    at Generator.forEach.e.<computed> [as next] (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:98818)
    at r (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:1:1054)
    at i (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:1:1265)

11. If the timer is paused and I click the element with id="start_stop", the countdown should resume running from the point at which it was paused.
25 + 5 clock has started but time displayed is not changing: expected '00' to not equal '00'
AssertionError: 25 + 5 clock has started but time displayed is not changing: expected '00' to not equal '00'
    at Proxy.c (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:549:1889)
    at Proxy.l (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:431:130)
    at Function.n.notStrictEqual (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:574:736)
    at a.<anonymous> (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:177398)
    at l (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:98461)
    at Generator._invoke (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:98214)
    at Generator.forEach.e.<computed> [as next] (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:98818)
    at r (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:1:1054)
    at i (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:1:1265)

12. When a session countdown reaches zero (NOTE: timer MUST reach 00:00), and a new countdown begins, the element with the id of "timer-label" should display a string indicating a break has begun.
Timer has not reached 00:00.
Error: Timer has not reached 00:00.
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:168153

13. When a session countdown reaches zero (NOTE: timer MUST reach 00:00), a new break countdown should begin, counting down from the value currently displayed in the id="break-length" element.
Timer has not reached 00:00.
Error: Timer has not reached 00:00.
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:168085

14. When a break countdown reaches zero (NOTE: timer MUST reach 00:00), and a new countdown begins, the element with the id of "timer-label" should display a string indicating a session has begun.
Timer has not reached 00:00.
Error: Timer has not reached 00:00.
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:168153

15. When a break countdown reaches zero (NOTE: timer MUST reach 00:00), a new session countdown should begin, counting down from the value currently displayed in the id="session-length" element.
Timer has not reached 00:00.
Error: Timer has not reached 00:00.
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:168085

From “Timer” and

1. When a countdown reaches zero (NOTE: timer MUST reach 00:00), a sound indicating that time is up should play. This should utilize an HTML5 <audio> tag and have a corresponding id="beep".
Timer has not reached 00:00.
Error: Timer has not reached 00:00.
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:168153

3. The audio element with id of "beep" must stop playing and be rewound to the beginning when the element with the id of "reset" is clicked.
Audio element was not stopped when reset was clicked.: expected false to be true
AssertionError: Audio element was not stopped when reset was clicked.: expected false to be true
    at o.<anonymous> (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:549:14996)
    at o.e (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:425:182)
    at Reflect.get (<anonymous>)
    at Object.e [as get] (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:92:1382)
    at Function.n.isTrue (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:574:1222)
    at a.<anonymous> (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:657:182880)
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:598:38668
    at i.g.run (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:598:38963)
    at N.runTest (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:598:45686)
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:598:46651

From “Audio”.

Updated Fiddle

There appears to be compound errors. In Fiddle, when both break and session are set to 1, the timer does not appear to start.

Yeah, I see it. So when it’s set to 59 seconds it doesn’t start, and when 1 second is left it doesn’t move anymore.

I’m logging secondsRemaining. On 1 minute, the timer doesn’t move because secondsRemaining doesn’t decrease.

I hope someone can help me out here. Like, what am I doing wrong? Or is there something I’m doing that I shouldn’t be? Or maybe some combination of both? I need help on getting the timer to reach zero as well because it currently doesn’t.

@DragonOsman, I tried to reduce the session time to test your timer, but after adjusting session time, the clock won’t start

This is the code I have for that:

      if (sessionIncremented || sessionDecremented || breakIncremented || breakDecremented) {
        // reset secondsRemaining
        today = new Date();
        deadline = new Date();
        deadlineMins = ((isSessionRunning) ? 
          Number($("#session-length").text()) : 
          Number($("#break-length").text())
        );
        deadline.setMinutes(today.getMinutes() + deadlineMins);
        total = Date.parse(deadline.toString()) - Date.parse(today.toString());
        secondsRemaining = total / 1000;

        const minutes = parseInt(secondsRemaining.toString() / 60);
        const seconds = parseInt(secondsRemaining.toString() % 60);
        secondsRemaining--;
        timerTextContent = `${addLeadingZeroes(minutes)}:${addLeadingZeroes(seconds)}`;
        timerElem.text(timerTextContent);
      }

Any ideas on what the problem could be and how how to fix it?

Full code:

"use strict";

let isSessionRunning = true;
const timerElem = $("#time-left");
let breakIncremented = false;
let breakDecremented = false;
let sessionIncremented = false;
let sessionDecremented = false;

const breakDecrementButton = $("#break-decrement");
breakDecrementButton.on("click", () => {
  breakDecremented = true;
  const breakLength = $("#break-length");
  let lengthValue = Number(breakLength.text());
  if (lengthValue > 1) {
    lengthValue--;
  }
  breakLength.text(lengthValue);
  if (!isSessionRunning) {
    timerElem.text(`${breakLength.text()}:00`);
  }
});

const breakIncrementButton = $("#break-increment");
breakIncrementButton.on("click", () => {
  breakIncremented = true;
  const breakLength = $("#break-length");
  let lengthValue = Number(breakLength.text());
  if (lengthValue < 60) {
    lengthValue++;
  } else if (lengthValue === 60) {
    // do nothing to the value
    lengthValue;
  }
  breakLength.text(lengthValue);
  if (!isSessionRunning) {
    timerElem.text(`${breakLength.text()}:00`);
  }
});

const sessionDecrementButton = $("#session-decrement");
sessionDecrementButton.on("click", () => {
  sessionDecremented = true;
  const sessionLength = $("#session-length");
  let lengthValue = Number(sessionLength.text());
  if (lengthValue > 1) {
    lengthValue--;
  }
  sessionLength.text(lengthValue);
  if (isSessionRunning) {
    timerElem.text(`${sessionLength.text()}:00`);
  }
});

const sessionIncrementButton = $("#session-increment");
sessionIncrementButton.on("click", () => {
  sessionIncremented = true;
  const sessionLength = $("#session-length");
  let lengthValue = Number(sessionLength.text());
  if (lengthValue < 60) {
    lengthValue++;
  } else if (lengthValue === 60) {
    // do nothing to the value
    lengthValue;
  }
  sessionLength.text(lengthValue);
  if (isSessionRunning) {
    timerElem.text(`${sessionLength.text()}:00`);
  }
});

const addLeadingZeroes = time => {
  return time < 10 ? `0${time}` : time;
};

let today = new Date();
let deadline = new Date();
let deadlineMins = ((isSessionRunning) ? 
  Number($("#session-length").text()) : 
  Number($("#break-length").text())
);
deadline.setMinutes(today.getMinutes() + deadlineMins);
let total = Date.parse(deadline.toString()) - Date.parse(today.toString());
let secondsRemaining = total / 1000;

let isClockRunning = false;
let timerTextContent = timerElem.text();
let timerId;
const initializeClock = () => {  
  if (!isClockRunning) {
    isClockRunning = true;
    timerId = setInterval(() => {
      if (secondsRemaining <= 0) {
        clearInterval(timerId);
        const audioElem = $("#beep");
        audioElem.play();
        if ($("#timer-label").text() === "Session") {
          isSessionRunning = false;
          $("#timer-label").text("Break");
        } else if ($("#timer-label").text() === "Break") {
          isSessionRunning = true;
          $("#timer-label").text("Session");
        }
      }
  
      if ($("#timer-label").text() === "Session") {
        isSessionRunning = true;
      } else if ($("#timer-label").text === "Break") {
        isSessionRunning = false;
      }
  
      timerElem.text(`${((isSessionRunning) ? 
        Number($("#session-length").text()) : 
        Number($("#break-length").text())
      )}:00`);
  
      if (sessionIncremented || sessionDecremented || breakIncremented || breakDecremented) {
        // reset secondsRemaining
        today = new Date();
        deadline = new Date();
        deadlineMins = ((isSessionRunning) ? 
          Number($("#session-length").text()) : 
          Number($("#break-length").text())
        );
        deadline.setMinutes(today.getMinutes() + deadlineMins);
        total = Date.parse(deadline.toString()) - Date.parse(today.toString());
        secondsRemaining = total / 1000;

        const minutes = parseInt(secondsRemaining.toString() / 60);
        const seconds = parseInt(secondsRemaining.toString() % 60);
        secondsRemaining--;
        timerTextContent = `${addLeadingZeroes(minutes)}:${addLeadingZeroes(seconds)}`;
        timerElem.text(timerTextContent);
      }

      const minutes = parseInt(secondsRemaining.toString() / 60);
      const seconds = parseInt(secondsRemaining.toString() % 60);

      secondsRemaining--;
      timerTextContent = `${addLeadingZeroes(minutes)}:${addLeadingZeroes(seconds)}`;
      timerElem.text(timerTextContent);
      console.log(secondsRemaining);
      isClockRunning = true;
    }, 1000);
  } else {
    clearInterval(timerId);
    isClockRunning = false;
  }
};

const startStopButton = $("#start_stop");
startStopButton.on("click", initializeClock);

const resetButton = $("#reset");
resetButton.on("click", () => {
  // reset app state to default
  clearInterval(timerId);
  const sessionLengthElem = $("#session-length");
  sessionLengthElem.text("25");
  
  const breakLengthElem = $("#break-length");
  breakLengthElem.text("5");
  
  $("#timer-label").text("Session");

  today = new Date();
  deadline = new Date();
  deadline.setMinutes(today.getMinutes() + 25);
  total = Date.parse(deadline.toString()) - Date.parse(today.toString());
  secondsRemaining = total / 1000;
  
  const minutes = parseInt(secondsRemaining.toString() / 60);
  const seconds = parseInt(secondsRemaining.toString() % 60);

  timerTextContent = `${addLeadingZeroes(minutes)}:${addLeadingZeroes(seconds)}`;
  timerElem.text(timerTextContent);
});

There’s some repetition and I don’t like that, so I also need to know of a better way to write the timer reset and other code so that I don’t repeat code so much. A function, maybe?

Okay, this is what I have now: http://jsfiddle.net/DragonOsman/z8wv29Lh/41/ .

The timer still doesn’t move after session and break values change, and it also doesn’t move after the reset button is clicked. But I’ve refactored some code and taken some of the repetition in the code.

Can anyone tell what the problem is with how the timer doesn’t move after resetting or after changing the session and break length values? And also why the timer value doesn’t become zero? I really need some help here (of course I’m not asking to just be given the solution). Thanks.

Actually the timer doesn’t start at all, even after refreshing the page. I can see that the code is running though because something is getting logged. Without React, I’m not familiar with the ways of getting elements to re-render on their own.

I noticed it. The timer doesn’t start. And secondsRemaining only decreases by 1 once. I’m logging it so I know. Isn’t there anyone on here who remembers how to use regular JS? Or do most of the people here only remember how to use React now? For jQuery you just need to know regular JS and the syntax and functions of jQuery.

By the way, about my current code: I have an image file for the reset button’s inner text value and also an audio file for the audio element. I didn’t know until now how to the put them into the Fiddle, though.

I uploaded it to GitHub; here’s the repo link.

I was sufficiently annoyed with the fact that I couldn’t solve the challenge with React that I actually did it with pure JS - for what it’s worth, here’s the codepen:
https://codepen.io/jsdisco/pen/xxOEWZP

The only tests that fail are the ones testing the audio (couldn’t be bothered to implement that yet).

Thanks for that. I’ll look at it when I don’t think I can do it myself anymore.

I have a question: what’s supposed to happen when the break length or session length is changed while the clock is running? Is the timer supposed to stop and then start again with the new length value when the start-stop button is clicked, or is it supposed to continue where it left off with the new length value? I think the former option would be easier to implement so I want to go that route.

I was confused about that as well but the example codepen shows that the decrement and increment buttons are disabled while the clock is running.

Yeah, I think that’s the intention (to disable those buttons while the timer is running). On an earlier version of the code test, that appeared to be one of the required user stories.

1 Like