Build a Pokémon Search App Project - Build a Pokémon Search App

Tell us what’s happening:

my code doesn’t pass, i get these errors:

[Error: AssertionError: expected to have a length of 1 but got +0]
[Error: AssertionError: expected to have a length of 2 but got +0]

pls help

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/124.0.0.0 Safari/537.36

Challenge Information:

Build a Pokémon Search App Project - Build a Pokémon Search App

Hello,
How can we understand what is wrong on your code? Could you share your codes with this ‘formatted-text’ boxes:

Additionally, please explain what is wrong there, what you have tried so far, and which tests couldn’t pass. Describe your approach to the code and help others understand your structure and the problems. This will also help you understand the origin of your problem.

Note that your challenge information link only redirects to the related challenge. You can try opening it in a private window, it won’t show your code.
Happy coding.

const searchInput = document.getElementById("search-input");
const searchBtn = document.getElementById("search-button");
const container = document.getElementById("container");
const imageContainer = document.getElementById("imageContainer");
const pokemonName = document.getElementById("pokemon-name");
const pokemonId = document.getElementById("pokemon-id");
const weight = document.getElementById("weight");
const height = document.getElementById("height");
const types = document.getElementById("types"); 
const hp = document.getElementById("hp");
const attack = document.getElementById("attack");
const defense = document.getElementById("defense");
const specialAttack = document.getElementById("special-attack");
const specialDefence = document.getElementById("special-defense"); 
const speed = document.getElementById("speed");

const resetBtn = document.getElementById("resetBtn");

const pokemonTraitData = document.getElementById("pokemonData");
const pokemonData = "https://pokeapi-proxy.freecodecamp.rocks/api/pokemon";


const fetchFunc = ()=>{
return new Promise((resolve)=>{
fetch(pokemonData)
.then(res => res.json())
.then(data => resolve(data)) 
})
}

 searchBtn.addEventListener("click",()=> searchBtnFunc())

function fetchError(){
  console.error("Problem fetching data from API")
}

function searchBtnFunc(){
fetchFunc() 
.then(searchFunc)
.catch(fetchError)
}

resetBtn.addEventListener("click", ()=> {
  searchInput.value = "";
  pokemonName.textContent = "";
  pokemonId.textContent = "";              
  weight.textContent = ""; 
  height.textContent = ""; 
  hp.textContent = "";
  attack.textContent = "";
  defense.textContent = "";
  specialAttack.textContent = "";
  specialDefence.textContent = "";
  speed.textContent = "";
  types.innerHTML = "";
  imageContainer.innerHTML = "";

  imageContainer.classList.add("display")
  pokemonTraitData.classList.add("display")
 
  searchInput.readOnly = false;

})  
    
 
 function displayPokemonTraits(traitData){
  weight.textContent =  traitData.weight;
  height.textContent = traitData.height;
  hp.textContent = traitData.stats[0].base_stat;
  attack.textContent = traitData.stats[1].base_stat;
  defense.textContent = traitData.stats[2].base_stat;
  specialAttack.textContent = traitData.stats[3].base_stat;
  specialDefence.textContent = traitData.stats[4].base_stat;
  speed.textContent = traitData.stats[5].base_stat;
  types.textContent = `${traitData.types[0].type.name.toUpperCase()} `;
 
imageContainer.innerHTML = `<img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemonId.textContent}.png" id="sprite">`

 types.textContent += `${traitData.types[1].type.name.toUpperCase()}`;

}

function cantDisplay(){
  console.error("Error collecting data")
}


  
const searchFunc = (data)=> {

if(searchInput.value > 1025){
   alert("Pokémon not found")
   pokemonTraitData.classList.add("display")
   return

 } 


imageContainer.classList.remove("display")
 pokemonTraitData.classList.remove("display")
searchInput.readOnly = true;

fetch(`https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/${searchInput.value.toLowerCase()}`)
   .then(res => res.json())
   .then(traitData => traitData)
.then(displayPokemonTraits)
.catch(cantDisplay)
 

if(searchInput.value == ""){
alert("Please type in a pokemon name or id");

}  
else if(searchInput.value <= 1025){
  
   const inputId = searchInput.value - 1;

   const pokemonNameViaId = data.results[inputId].name
    pokemonName.textContent = `${pokemonNameViaId.toUpperCase()}`;
pokemonId.textContent = `${searchInput.value}` ;

}
                           
if(!/[0-9]+/.test(searchInput.value)){
for(let i = 0; i < 1025; i++){ 
  const pokemonsNames = data.results[i].name //names from API
  
  const pokemonNameLowerCase = searchInput.value.toLowerCase();  //converts input value to lowercase



  if(pokemonsNames === pokemonNameLowerCase){

pokemonName.textContent = `${(searchInput.value.toUpperCase())} `;
pokemonId.textContent = `${i + 1}` 
}
} 
if(pokemonId.textContent === ""){
   alert("Pokémon not found")
   pokemonTraitData.classList.add("display")

 } 
}

}

these tests arent passing

When the #search-input element contains the value Pikachu and the #search-button element is clicked, the #types element should contain a single inner element with the value ELECTRIC. Make sure the #type
element content is cleared between searches.

When the #search-input element contains the value 94 and the #search-button element is clicked, the #types element should contain two inner elements with the text values GHOST and POISON, respectively. Make sure the #type element content is cleared between searches.

i get these errors :

[Error: AssertionError: expected to have a length of 1 but got +0]
[Error: AssertionError: expected to have a length of 2 but got +0]

but my app functions as expected, i dont know what to do

Your HTML codes would be beneficial for debugging purposes if you provide them.
Several issues are present:

Firstly, the condition searchInput.value > 1025 will always return false with any kind of string input. This is not right control for alert("Pokémon not found").

Also control to same thing with two different way is not quite well. You can check input response or not from api to trow ...not found alert.

Secondly, the fetchFunc unnecessarily fetches all data from the API. It would be more efficient to fetch only the required data, as already implemented in the traitData fetch code block. Additionally, using the same variable name for all fetched data can lead to confusion and is not optimal for performance. Be mindful of memory usage and handle cases where the requested pokemon ID or name couldn’t be fetched from the API by throwing an appropriate error or alert.

Furthermore, try to retrieve the sprite URL from the specific id or name API response for a better approach.

In the displayPokemonTraits function, the types.textContent values setting just twice but types can be more than two. Also writing same types.textContent updated codes twice or more not the best approach.

Lastly, although it’s unclear what the origin of the assertionError is, addressing these general issues should improve the overall functionality. Consider revising your searchFunc to fetch only the relevant pokemon data based on the input. If you provide your HTML codes, I can assist with debugging. Also please explain your code and your approaches because your code is very hard to understand…

Thanks ill try improve my code

here’s the HTML code

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">

   <link rel="stylesheet" href="styles.css">
</head>
<body>
   <h1>Pokémon Search App</h1>
   <div id="container">
<div id="inputAndButtons">
<input id="search-input" required>
<button id="search-button">Search</button>

<button id="resetBtn">Reset</button>
</div>
<br><br><br>

<div id="pokemonData" class="display">

<div id="pokemon-name" class="data"></div>
<div id="pokemon-id" class="data"></div>
<div id="weight" class="data"></div>
<div id="height" class="data"></div>
<div id="types" class="data"></div>
<div id="hp" class="data"></div>
<div id="attack" class="data"></div>
<div id="defense" class="data"></div>
<div id="special-attack" class="data"></div>
<div id="special-defense" class="data"></div>
<div id="speed" class="data"></div>
<div id="imageContainer"></div>
</div>



</div>
<div id="lables"> <!-- labels for the pokemon data-->
<div id="lab">Name:</div>
<div id="lab">ID:</div>
<div id="lab">Weight:</div>
<div id="lab">Height:</div>
<div id="lab">Type:</div>
<div id="lab">HP:</div>
<div id="lab">ATT:</div>
<div id="lab">DEF:</div>
<div id="lab">S-ATT:</div>
<div id="lab">S-DEF:</div>
<div id="lab">Speed:</div>


</div>

    <script src="script.js"></script>
  </body>
  </html>

The test is looking for HTML elements inside the types element, not just text nodes.

the #types element should contain a single inner element with the value ELECTRIC

the #types element should contain two inner elements with the text values GHOST and POISON


As said, your code could use a refactor. But it will pass if you fix the two issues above.

You’ve set searchInput.readOnly to true for each search until it’s reset by the reset button, but this is not the best approach.

… the #types element should contain two inner elements…

Additionally, the test specifies that the #types element should contain two inner elements, meaning each type should be in a separate HTML element.

Furthermore, your fetch process mostly results in Error collecting data because it catches errors from the displayPokemonTraits function too. This function throws an error because you always try to access types[1] even when there is no types[1] value in the api response.

Additionally, the search process for the Pokemon in the code you’ve written is proceeding very slowly. I can see that the data is being displayed on the screen bit by bit, making the user feel like they’re on a old school dial-up network.

This is happening because, upon each search button click, fetchFunc is triggered, fetching all the data.

Then, searchFunc is executed, and only after the entire data is fetched, the input value is checked to see if it exceeds 1025.

Then, the display class is removed from the imageContainer and pokemonTraitData class lists. Since I’m not familiar with these classes, I cannot understand their purpose either. And the searchInput become readOnly until it get reset.

Then, the input value is inserted into the API endpoint to fetch the corresponding pokemon (the fetch process being this way is quite sufficient).

After the fetch process is completed, an if statement checks if searchInput.value is empty. If it is, an alert("Please type in a pokemon name or id"); is triggered.

Additionally, if it’s empty, an Error collecting data is thrown by cantDisplay function, and if it’s empty, pokemonId.textContent becomes empty, triggering alert("Pokémon not found");.

Also, if the input is not a number, a for loop is initiated from 0 to 1025. Within the loop, it checks if the names from the data variable, assigned to the fetch data’s results index, match searchInput.value. If they do, pokemonName.textContent and pokemonId.textContent are updated.

Moreover, when the fetch process returns the response for the specific pokemon assigned to the traitData variable, the displayPokemonTraits function is executed. Regardless of the name check, all the data is assigned to the relevant HTML elements.

In conclusion, if you had started explaining all the functions you’ve written in this way, you could have noticed many errors or unnecessary repetitions. Your use of fetch, checking if the input is a number with regex, and appending the searchInput to the api endpoint with string template are all valuable pieces of knowledge, and I assume you’ve done all of them yourself rather than piecing them together from various sources. Even if you had done so, you’ve made an effort to solve the problem, didn’t just copy paste completly from somewhere, and passed most of the tests, which is commendable enough!

If you want, you can fix the remaining tests by making the correction I suggested at the begining of this conversation, but if you want this project to always be visible proudable in your portfolio, you can improve the process by simplifying and shortening some of the operations.

For example, as I suggested, you can run displayPokemonTraits by placing the search input in the endpoint, so if it returns a response, it will fill in all the data to be filled, such as name, etc., at once. If it doesn’t respond, you can throw the relevant alert. Additionally, before that, you can check the validation of the input, and if it’s empty, throw the relevant message without starting any fetch. You can also leave the searchInput as readOnly and open to new searches without converting it, and only clean the parts of the data that need to be cleared. For example, names, ids, or attacks are all present in every response, but only the number of type data is uncertain, some have one, some have two or three. You can place the types according to how many there are using a loop.

I hope this will helps you, happy coding :slightly_smiling_face: