Build a Theme Switcher - Build a Theme Switcher

Tell us what’s happening:

I cannot pass Tests #26 and #27 even after looking through the existing posts. The theme color changes and the correct message displays in the preview window and the correct class names and messages are inserted into the HTML when I open up the inspector. Please help guide me to what I’m missing!

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Theme Switcher</title>
  <link rel="stylesheet" href="./styles.css">
</head>
<body>
  
  <button id="theme-switcher-button" aria-haspopup="true" aria-expanded="false" aria-controls="theme-dropdown">Switch Theme</button>
  <ul id="theme-dropdown" role="menu" aria-labelledby="theme-switcher-button" hidden>
    <li role="menu-item" id="theme-sunshine">sunshine</li>
    <li role="menu-item" id="theme-night">night</li>
  </ul>
  <div aria-live="polite" id="status"></div>
  <script src="./script.js"></script>
</body>
</html>
/* file: styles.css */
body {
  margin: 0;
  font-family: sans-serif;
  transition: background 0.3s, color 0.3s;
}

.theme-sunshine {
  background-color: #F7DE79;
}

.theme-night {
  background-color: #32314D;
  color: #E2E1F2;
}

button {
  height: 30px;
  border: none;
  width: 100px;
}

ul {
  margin: 0;
  padding: 0;
  background-color: white;
  width: 100px;
  
}

li {
  list-style-type: none;
  height: 20px;
  padding-top: 5px;
  padding-left: 5px;
  cursor: pointer;
  color: black;
}

li:hover {
  background-color: lightgrey;
}

#status {
  text-align: center;
  min-height: 20px;
  position: sticky;
}


/* file: script.js */
const themes = [
  { name: "sunshine", message: "Feel the warmth"},
  { name: "night", message: "Twinkle in the sky"}
];

const button = document.getElementById("theme-switcher-button");
const dropdownMenu = document.getElementById("theme-dropdown");
const body = document.body;
const themeMessageDiv = document.getElementById("status")
const menu = Array.from(document.querySelectorAll("[role='menu-item']"))

dropdownMenu.addEventListener("click", (event) => {
  event.stopPropagation();
  const menuItem = event.target.closest("[role='menu-item']");

  if (!menuItem) {
    return;
  }
  const index = menu.indexOf(menuItem);

  if (index !== -1) {
    themes.forEach(theme => {
      body.classList.remove(`theme-${theme.name}`);
    });
    body.classList.add(`theme-${themes[index].name}`);
    if (themeMessageDiv) {
      themeMessageDiv.textContent = themes[index].message;
    }
    
    dropdownMenu.setAttribute("hidden", "true");
    button.setAttribute("aria-expanded", "false");
  }

})

button.addEventListener("click", (event) => {
  
  if (dropdownMenu.hasAttribute("hidden")) {
    dropdownMenu.removeAttribute("hidden");
    button.setAttribute("aria-expanded", "true");
  } else {
    dropdownMenu.setAttribute("hidden", "true");
    button.setAttribute("aria-expanded", "false");
  }
})

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/142.0

Challenge Information:

Build a Theme Switcher - Build a Theme Switcher

https://www.freecodecamp.org/learn/full-stack-developer/lab-theme-switcher/lab-theme-switcher

the tests are clicking on a specific item in the dropdown menu, and the click is not being bubbled to the dropdown menu, I don’t think you can use this approach

it’s tested like this:

const themeDropdownBtn = document.getElementById("theme-switcher-button");
const listItems = document.querySelectorAll("#theme-dropdown li");

themeDropdownBtn.dispatchEvent(new Event("click"));

const clickedItem = listItems[1]; 
clickedItem?.dispatchEvent(new Event("click"));

const expectedClass = clickedItem?.id; 
const actualClass = document.body.className;

console.log(expectedClass);
console.log(actualClass);
console.log("test passed:", expectedClass === actualClass)

you can report this as a bug if you want

Thank you for explaining how it’s tested. I just refactored the code to attach event listeners to each menu item so now I’m getting confetti!

I created an issue on Github for this problem because I had the same issue. I’m assured that adding {bubbles: true} to the events fired by the tester will let us (IMO properly) attach the listener to the menu instead of the menu items.