Skip to content
Closed
105 changes: 103 additions & 2 deletions Sprint-3/alarmclock/alarmclock.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,105 @@
function setAlarm() {}




let timeLeft = 0;
let timer = null;
let flashing = null;

// DOM references
window.addEventListener("DOMContentLoaded", () => {

const stopButton = document.getElementById("stop");

// Event listeners

if (stopButton) stopButton.addEventListener("click", stopAlarm);
Comment thread
cjyuan marked this conversation as resolved.
Outdated

// Show 00:00 on load
updateDisplay(0);
});

// -------------------------------
// FUNCTIONS
// -------------------------------

function setAlarm() {
const inputEl = document.getElementById("alarmSet");
const input = inputEl.value.trim();

// Check empty input
if (input === "") {
alert("Please enter a number of seconds.");
return;
}

const parsed = parseInt(input, 10);

// Check invalid or negative number
if (isNaN(parsed) || parsed < 0) {
alert("Please enter a valid non-negative number.");
return;
}

timeLeft = parsed;

// Update display immediately
updateDisplay(timeLeft);

// Clear previous countdown
clearInterval(timer);
clearInterval(flashing); // stop flashing if it was active
flashing = null;
document.body.style.backgroundColor = "";
pauseAlarm(); // stop any playing audio
audio.currentTime = 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could consider placing this "reset" code in a function and call the function here.


function tick() {
if (timeLeft > 0) {
timeLeft--;
updateDisplay(timeLeft);
} else {
clearInterval(timer);
startAlarm();
}
}

Comment thread
cjyuan marked this conversation as resolved.
// Run once immediately for consistency
tick();
timer = setInterval(tick, 1000);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering the following two cases:

Case 1: When the input is 0 (i.e., timeLeft is 0)
Line 69 will also be executed, resulting the code on line 62-63 being executed twice.

Case 2: When the input is 1 (i.e., timeLeft is 1)
Line 68 is executed, causing the display to show "00:00" immediately (instead of showing "00:01").
But startAlarm() is only executed one second afterward.
(Ideally, the alarm could sound as soon as the display show "00:00")

Suggestion: Since 0 is such a special case, you can consider doing something like

if (timeLeft === 0) {


}
else { // Other other cases


}

}

function updateDisplay(seconds) {
const mins = String(Math.floor(seconds / 60)).padStart(2, "0");
const secs = String(seconds % 60).padStart(2, "0");

const display = document.getElementById("timeRemaining");
if (!display) return;
display.textContent = `Time Remaining: ${mins}:${secs}`;
}

function startAlarm() {
playAlarm();

// Flashing background
if (!flashing){
flashing = setTimeout(() => {
document.body.style.backgroundColor =
document.body.style.backgroundColor === "red" ? "orange" : "red";
}, 300);
}
}

function stopAlarm() {

clearInterval(flashing);
flashing = null;
document.body.style.backgroundColor = "";
}


// module.exports= setAlarm;


// DO NOT EDIT BELOW HERE

Expand All @@ -20,6 +121,6 @@ function playAlarm() {

function pauseAlarm() {
audio.pause();
}
}

window.onload = setup;
10 changes: 7 additions & 3 deletions Sprint-3/alarmclock/alarmclock.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ There are some Tests in this file that will help you work out if your code is wo
*/

const path = require("path");
// const { setAlarm } = require("./alarmclock.js");

const { JSDOM } = require("jsdom");

let page = null;
Expand Down Expand Up @@ -35,6 +37,8 @@ afterEach(() => {
page = null;
});



test("should set heading when button is clicked", () => {
const heading = page.window.document.querySelector("#timeRemaining");
const input = page.window.document.querySelector("#alarmSet");
Expand Down Expand Up @@ -89,16 +93,16 @@ test("should count down every 1000 ms", () => {

test("should play audio when the timer reaches zero", () => {
const input = page.window.document.querySelector("#alarmSet");
const button = page.window.document.querySelector("#set");
const startButton = page.window.document.querySelector("#set");
const mockPlayAlarm = jest.fn();

page.window.playAlarm = mockPlayAlarm;
input.value = "10";
button.click();
startButton.click();

expect(mockPlayAlarm).toHaveBeenCalledTimes(0);

jest.runAllTimers();

expect(mockPlayAlarm).toHaveBeenCalledTimes(1);
});
4 changes: 2 additions & 2 deletions Sprint-3/alarmclock/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>Title here</title>
<title>Alarm clock-app</title>
</head>
<body>
<div class="centre">
Expand All @@ -15,6 +15,6 @@ <h1 id="timeRemaining">Time Remaining: 00:00</h1>
<button id="set" type="button">Set Alarm</button>
<button id="stop" type="button">Stop Alarm</button>
</div>
<script src="alarmclock.js"></script>
<script src="alarmclock.js" defer></script>
</body>
</html>
6 changes: 6 additions & 0 deletions Sprint-3/alarmclock/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('jest').Config} */
module.exports = {
testEnvironment: "jsdom",
verbose: true,
testMatch: ["**/*.test.js"],
};
6 changes: 5 additions & 1 deletion Sprint-3/alarmclock/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@
"bugs": {
"url": "https://github.com/CodeYourFuture/CYF-Coursework-Template/issues"
},
"homepage": "https://github.com/CodeYourFuture/CYF-Coursework-Template#readme"
"homepage": "https://github.com/CodeYourFuture/CYF-Coursework-Template#readme",
"dependencies": {
"@testing-library/jest-dom": "^6.9.1",
"jest": "^27.5.1"
}
}