Build an RPG Creature Search App Project - Build an RPG Creature Search App

Tell us what’s happening:

I suggest you to open in a full screen tab the code… The code works but keeps telling me these error I am not understanding… I am stuck here.
[Error: AssertionError: expected ‘HP’ to equal ‘65’]
[Error: AssertionError: expected ‘HP’ to equal ‘85’]

Your code so far

<!-- file: index.html -->

/* file: styles.css */

/* file: script.js */

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36

Challenge Information:

Build an RPG Creature Search App Project - Build an RPG Creature Search App

Hello, there is no code can you retry, use the </> and paste your files again please.

const el = {
  searchBtn: document.getElementById("search-button"),
  searchInput: document.getElementById("search-input"),
  // Gen info
  creatureName: document.getElementById("creature-name"),
  creatureId: document.getElementById("creature-id"),
  weight: document.getElementById("weight"),
  height: document.getElementById("height"),
  types: document.getElementById("types"),
  moveName: document.getElementById("move-name"),
  moveInfo: document.getElementById("move-info"),
  // Stats
  hpStats: document.getElementById("hp-stats"),
  attackStats: document.getElementById("attack-stats"),
  defenseStats: document.getElementById("defense-stats"),
  specialAttackStats: document.getElementById("special-attack-stats"),
  specialDefenseStats: document.getElementById("special-defense-stats"),
  speedStats: document.getElementById("speed-stats")
};

const typesColors = {
  fire: "#F08030",
  water: "#6890F0",
  grass: "#78C850",
  electric: "#F8D030",
  ice: "#98D8D8",
  fighting: "#C03028",
  poison: "#A040A0",
  ground: "#E0C068",
  flying: "#A890F0",
  psychic: "#F85888",
  bug: "#A8B820",
  rock: "#B8A038",
  ghost: "#705898",
  dragon: "#7038F8",
  dark: "#705848",
  steel: "#B8B8D0",
  fairy: "#EE99AC"
};

clearAll();

async function getData() {
  try {
    const response = await fetch(
      "https://rpg-creature-api.freecodecamp.rocks/api/creatures"
    );
    return await response.json();
  } catch (error) {
    console.error("Error fetching creature list:", error);
    return [];
  }
}

async function specificCreature(nameOrId) {
  try {
    const res = await fetch(
      `https://rpg-creature-api.freecodecamp.rocks/api/creature/${nameOrId}`
    );
    return await res.json();
  } catch (error) {
    console.error("Error fetching specific creature:", error);
  }
}

async function searchCreature(input, creatures_list) {
  input = input.trim().toLowerCase();
  if (input === "") {
    clearAll();
    return;
  }

  const creature = creatures_list.find(
    (creat) => creat.name.toLowerCase() === input || String(creat.id) === input
  );

  if (creature) {
    const infoCreat = await specificCreature(creature.id);
    updateCreatureInfo(infoCreat);
    el.searchInput.value = "";
  } else {
    alert("Creature not found");
    el.searchInput.value = "";
  }
}

function updateCreatureInfo(info) {
  el.creatureName.textContent = info.name.toUpperCase();
  el.creatureId.textContent = `#${info.id}`;
  el.weight.textContent = `Weight: ${info.weight}`;
  el.height.textContent = `Height: ${info.height}`;

  // Types
  el.types.innerHTML = "";
  info.types.forEach((type) => {
    const typeEl = document.createElement("span");
    typeEl.textContent = type.name.toUpperCase();
    typeEl.style.backgroundColor = typesColors[type.name] || "#777";
    typeEl.style.padding = "4px";
    typeEl.style.marginRight = "5px";
    typeEl.style.borderRadius = "5px";
    el.types.appendChild(typeEl);
  });

  // Special move
  el.moveName.textContent = info.special.name;
  el.moveInfo.textContent = info.special.description;

// Stats
  el.hpStats.textContent = info.stats[0].base_stat;
  el.attackStats.textContent = info.stats[1].base_stat;
  el.defenseStats.textContent = info.stats[2].base_stat;
  el.specialAttackStats.textContent = info.stats[3].base_stat;
  el.specialDefenseStats.textContent = info.stats[4].base_stat;
  el.speedStats.textContent = info.stats[5].base_stat;
}

function clearAll() {
  const elements = [
    el.creatureName,
    el.creatureId,
    el.weight,
    el.height,
    el.types,
    el.moveName,
    el.moveInfo,
    el.hpStats,
    el.attackStats,
    el.defenseStats,
    el.specialAttackStats,
    el.specialDefenseStats,
    el.speedStats
  ];

  elements.forEach((elem) => {
    if (!elem) return;
    if (elem === el.types) {
      elem.innerHTML = "";
    } else if (elem.id?.includes("stats")) {
      elem.textContent = "?";
    } else {
      elem.textContent = "";
    }
  });
}

el.searchBtn.addEventListener("click", async () => {
  const creatures = await getData();
  clearAll(); // Solo se stai cercando di nuovo
  searchCreature(el.searchInput.value, creatures);
});

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>RPG Creature Search App</title>
    <link rel="stylesheet" href="styles.css">
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap" rel="stylesheet">
  </head>
  <body>
    <img src="https://i.imgur.com/jqe4DD9.png" alt="RPG Creature Search App Logo" class="logo">
    <h1>RPG Creature Search App</h1>
    <div class="main-container" id="cont-1">
      <p class="instructions" id="search-instructions">Search for Creature Name or ID:</p>
      <div class="secondary-container" id="cont-1_5">
        <form>
          <input type="text" class="search" id="search-input" required>
          <button class="search-btn" id="search-button">Search</button>
        </form>
      </div>
      <div class="secondary-container" id="cont-2">
        <div class="secondary-container" id="cont-2_5">
          <p class="creature-gen" id="creature-name">Name</p><p class="creature-gen" id="creature-id">#ID</p>
          <p class="creature-size" id="weight">Weight: </p><p class="creature-size" id="height">Height: </p>
          <span id="types"></span>
        </div>
        <p class="moves" id="move-name">Move Name</p>
        <p class="moves" id="move-info">Move info</p>
      </div>
      <div class="secondary-container" id="cont-3">
        <span class="base" id="base-label">Base</span><span class="stats" id="stats-label">Stats</span>
        <span class="base" id="hp">HP</span><span class="stats" id="hp-stats">?</span>
        <span class="base" id="attack">Attack</span><span class="stats" id="attack-stats">?</span>
        <span class="base" id="defense">Defense</span><span class="stats" id="defense-stats">?</span>
        <span class="base" id="special-attack">Sp. Attack</span><span class="stats" id="special-attack-stats">?</span>
        <span class="base" id="special-defense">Sp. Defense</span><span class="stats" id="special-defense-stats">?</span>
        <span class="base" id="speed">Speed</span><span class="stats" id="speed-stats">?</span>
      </div>
    </div>
    <br>
    <script src="script.js"></script>
  </body>
</html>

/* ====== GENERALI ====== */
body {
  background-color: #1B1B32;
  margin: 0;
  font-family: 'Roboto', sans-serif;
}

.logo {
  max-width: 8%;
  height: auto;
  display: block;
  margin: 0 auto;
  padding-top: 0.75rem;
}

h1 {
  color: white;
  text-align: center;
  font-family: "Courier", sans-serif;
  font-size: 2rem;
  font-weight: bold;
}

/* ====== CONTENITORI PRINCIPALI ====== */
#cont-1 {
  margin: 0 auto;
  background-color: #F5F6F7;
  width: 33vw;
  height: 108vh;
  border-radius: 15px;
  box-shadow: 10px 10px 0px #AEACB2;
  padding-bottom:20px;
}

#cont-1_5 {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 31vw;
  margin: 0 auto;
}

/* ====== INPUT E BUTTON ====== */
input {
  width: 180px;
  height: 35px;
  font-size: 0.8rem;
  padding-left: 5px;
  margin: 0 10px;
}

input:focus {
  outline: 2px solid #198EEE;
}

button {
  color: white;
  background-color: #7F21AB;
  border: none;
  width: 80px;
  height: 40px;
  border-radius: 18px;
  cursor: pointer;
}

/* ====== ISTRUZIONI ====== */
.instructions {
  font-size: 1.1rem;
  font-weight: bold;
  text-align: center;
  padding-top: 15px;
}

/* ====== CONTENUTO CREATURE ====== */
#cont-2 {
  margin: 25px auto 10px auto;
  background-color: #F0F1F7;
  width: 30vw;
  height: 34vh;
  padding: 10px;
  border-radius: 10px;
}

#cont-2_5 {
  width: 11vw;
  height: 10vh;
  margin: 10px auto 50px 1px;
}

/* ====== INFORMAZIONI CREATURE ====== */
.creature-gen {
  display: inline-flex;
  font-size: 0.9rem;
  font-family:"Arial",sans-serif;
  font-weight: bold;
  margin: 10px 0 5px 3px;
  white-space: nowrap;
}

#creature-id {
  white-space: nowrap;
  font-weight:normal;
  font-size:0.8rem;
  padding-left:5px;
}

.creature-size {
  display: inline;
  font-size: 0.8rem;
  font-weight: normal;
  margin: 5px 2px 0 5px;
  white-space: nowrap;
}

#creature-id {
  font-weight: bold;
  font-size: 0.7rem;
  margin-top: 2px;
}

/* ====== TYPES ====== */
#types {
  display: inline-flex;
  gap: 8px;
  margin: 10px -5px 40px 5px;
  padding: 4px;
  white-space: nowrap;
}

#types span {
  padding: 4px 10px;
  margin-bottom:10px;
  margin-left:-5px;
  border-radius: 5px;
  color: white;
  font-weight: bold;
  font-size: 0.8rem;
  white-space: nowrap;
  background-color: grey; /* fallback */
}

/* ====== MOSSE ====== */
.moves {
  margin-left: 9px;
  display: flex;
  flex-direction: column;
  font-family: 'Arial', sans-serif;
}

#move-name {
  font-size: 0.9rem;
  font-weight: bold;
  margin: 60px 0px 5px 9px;
  display: block;
}

#move-info {
  font-size: 0.85rem;
  margin-bottom: 15px;
}

/* ====== STATISTICHE ====== */
#cont-3 {
  width: 32vw;
  margin: 15px auto 0 auto;
}

.base,
.stats {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  background-color: #7F21AB;
  color: white;
  font-size: 1rem;
  font-weight: bold;
  text-align: center;
  height: 40px;
  width:auto;
  font-family: 'Roboto', sans-serif;
}

.base {
  width: 60%;
  margin: 0 0 5px 15px;
}

.stats {
  width: 30%;
  margin: 0 0 5px 5px;
}

#base-label,
#stats-label {
  font-size: 1.3rem;
  font-family: "Arial", sans-serif;
  font-weight: bold;
}

Thanks for being here. I literally asked everyone but not a solution found. The app works. I suggest you to open all in full screen tab.

1 Like

This is the full output I receive when running the test. All good except these steps:

// running tests
15. When the #search-input element contains the value Pyrolynx and the #search-button element is clicked, the values in the #creature-name, #creature-id, #weight, #height, #hp, #attack, #defense, #special-attack, #special-defense, and #speed elements should be PYROLYNX, #1 or 1, Weight: 42 or 42, Height: 32 or 32, 65, 80, 50, 90, 55, and 100, respectively.
17. When the #search-input element contains the value 2 and the #search-button element is clicked, the values in the #creature-name, #creature-id, #weight, #height, #hp, #attack, #defense, #special-attack, #special-defense, and #speed elements should be AQUOROC, #2 or 2, Weight: 220 or 220, Height: 53 or 53, 85, 90, 120, 60, 70, and 40, respectively.
// tests completed
// console output
[Error: AssertionError: expected ‘HP’ to equal ‘65’]
[Error: AssertionError: expected ‘HP’ to equal ‘85’]

I solved. It is due to a wrong naming of the id of stats elements… thanks anyway

1 Like

Good job, I was thinking the same thing but could not find it.