diff --git a/Sprint-3/quote-generator/index.html b/Sprint-3/quote-generator/index.html
index 30b434bcf..1f6ae4f73 100644
--- a/Sprint-3/quote-generator/index.html
+++ b/Sprint-3/quote-generator/index.html
@@ -1,15 +1,35 @@
-
+
- Title here
-
+ Quote Generator App
+
- hello there
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ Auto-play: OFF
+
+
+
+
diff --git a/Sprint-3/quote-generator/package.json b/Sprint-3/quote-generator/package.json
index 0f6f98917..8a9bdb901 100644
--- a/Sprint-3/quote-generator/package.json
+++ b/Sprint-3/quote-generator/package.json
@@ -4,7 +4,7 @@
"license": "CC-BY-SA-4.0",
"description": "You must update this package",
"scripts": {
- "test": "jest --config=../jest.config.js quote-generator"
+ "test": "jest --env=jsdom"
},
"repository": {
"type": "git",
@@ -13,5 +13,11 @@
"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": {
+ "jsdom": "^20.0.3"
+ },
+ "devDependencies": {
+ "@testing-library/jest-dom": "^6.9.1"
+ }
}
diff --git a/Sprint-3/quote-generator/quotes.js b/Sprint-3/quote-generator/quotes.js
index 4a4d04b72..dade31b31 100644
--- a/Sprint-3/quote-generator/quotes.js
+++ b/Sprint-3/quote-generator/quotes.js
@@ -15,11 +15,6 @@
// ---------------
// pickFromArray(['a','b','c','d']) // maybe returns 'c'
-// You don't need to change this function
-function pickFromArray(choices) {
- return choices[Math.floor(Math.random() * choices.length)];
-}
-
// A list of quotes you can use in your app.
// DO NOT modify this array, otherwise the tests may break!
const quotes = [
@@ -491,3 +486,52 @@ const quotes = [
];
// call pickFromArray with the quotes array to check you get a random quote
+
+// Function to pick a random quote
+function pickFromArray() {
+ const quoteEl = document.getElementById("quote");
+ const authorEl = document.getElementById("author");
+ const randomIndex = Math.floor(Math.random() * quotes.length);
+
+ quoteEl.textContent = `" ${quotes[randomIndex].quote} "`;
+ authorEl.textContent = `-- ${quotes[randomIndex].author} --`;
+ return randomIndex;
+}
+
+// Setup function for browser only
+function setupQuoteApp() {
+ const button = document.getElementById("new-quote");
+ const autoplayCheckbox = document.getElementById("autoplay");
+ const autoplayStatus = document.getElementById("autoplay-status");
+
+ // Don't call pickFromArray here for Jest test
+ if (typeof window !== "undefined" && window.document) {
+ pickFromArray();
+
+ button.addEventListener("click", () => pickFromArray());
+
+ let autoplayInterval = null;
+ autoplayCheckbox.addEventListener("change", () => {
+ if (autoplayCheckbox.checked) {
+ autoplayInterval = setInterval(pickFromArray, 5000);
+ autoplayStatus.textContent = "Auto-play: ON";
+ autoplayStatus.style.color = "#4CAF50";
+ } else {
+ clearInterval(autoplayInterval);
+ autoplayInterval = null;
+ autoplayStatus.textContent = "Auto-play: OFF";
+ autoplayStatus.style.color = "brown";
+ }
+ });
+ }
+}
+
+// Only run setup in browser environment
+if (typeof window !== "undefined") {
+ window.addEventListener("DOMContentLoaded", setupQuoteApp);
+}
+
+// Export function for Jest tests
+if (typeof module !== "undefined") {
+ module.exports = pickFromArray;
+}
diff --git a/Sprint-3/quote-generator/quotes.test.js b/Sprint-3/quote-generator/quotes.test.js
index f7b128bf7..d0631cb58 100644
--- a/Sprint-3/quote-generator/quotes.test.js
+++ b/Sprint-3/quote-generator/quotes.test.js
@@ -2,6 +2,9 @@
There are some Tests in this file that will help you work out if your code is working.
*/
+require("@testing-library/jest-dom");
+// @jest-environment jsdom
+const pickFromArray = require("./quotes.js");
const path = require("path");
const { JSDOM } = require("jsdom");
diff --git a/Sprint-3/quote-generator/style.css b/Sprint-3/quote-generator/style.css
index 63cedf2d2..55a6bfb47 100644
--- a/Sprint-3/quote-generator/style.css
+++ b/Sprint-3/quote-generator/style.css
@@ -1 +1,147 @@
-/** Write your CSS in here **/
+/* Reset */
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
+}
+
+body {
+ min-height: 100vh;
+ background: #abd5e9;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 15px;
+}
+
+.container {
+ background: rgba(221, 221, 221, 0.4);
+ padding: 10px;
+ border-radius: 16px;
+ width: 100%;
+ max-width: 420px;
+ text-align: center;
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ box-shadow: 0 12px 30px rgba(0, 0, 0, 0.2);
+ display: flex;
+ flex-direction: column;
+ min-height: 450px;
+}
+
+.header {
+ flex: 0 0 25%; /* 25% of container height */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-bottom: 15px;
+}
+
+.header h1 {
+ font-size: 1.8rem;
+ color: #333;
+}
+
+.quote-box {
+ flex: 1 0 50%; /* take remaining middle space */
+ background: #f4f4f4;
+ padding: 10px;
+ border-radius: 12px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ margin: 10px 0;
+
+ min-height: 100px;
+ transition: all 0.3s ease;
+ word-wrap: break-word;
+ text-align: center;
+}
+
+.quote-box p {
+ margin: 0;
+ font-size: 1rem;
+ line-height: 1.4;
+}
+
+.bottom-controls {
+ flex: 0 0 25%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ gap: 10px;
+ margin-bottom: 0px;
+}
+
+.button button {
+ width: 100%;
+ padding: 10px;
+ font-size: large;
+ border: none;
+ border-radius: 10px;
+ background: rgb(3, 73, 195);
+ color: #fff;
+ cursor: pointer;
+ transition: 0.3s ease;
+}
+
+.button button:hover {
+ background: #4259c8;
+ transform: scale(1.03);
+ font-weight: bold;
+}
+
+.autoplay-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 10px;
+}
+
+.autoplay-container label {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ cursor: pointer;
+}
+
+.autoplay-container input[type="checkbox"] {
+ width: 18px;
+ height: 18px;
+ cursor: pointer;
+}
+
+#autoplay-status {
+ font-weight: bold;
+ color: brown;
+}
+
+/* Responsive */
+@media (min-width: 600px) {
+ .container {
+ padding: 40px 35px;
+ }
+ .header h1 {
+ font-size: 2rem;
+ }
+ .quote-box p {
+ font-size: 1.1rem;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 500px;
+ }
+ .header h1 {
+ font-size: 2.2rem;
+ }
+ .quote-box p {
+ font-size: 1.2rem;
+ }
+ .button button {
+ width: auto;
+ padding: 12px 25px;
+ }
+}