Build a Bookmark Manager App - step 5

I’m stuck on test 5. I’ve tried making my code more robust by implementing several additional tests, but I just can’t get test 5 to pass. I would appreciate any help with this.

function getBookmarks() {
  // Get the raw string value from localStorage
  const bookmarksDataString = localStorage.getItem("bookmarks");

  // Handle case where the key doesn't exist at all
  if (bookmarksDataString === null) {
    return [];
  }

  const bookmarks = JSON.parse(bookmarksDataString);

  // Check if parsing resulted in null or the value is not an array
  if (bookmarks === null || !Array.isArray(bookmarks)) {
    return [];
  }

  if (bookmarks.length === 0) {
    return [];
  }

  // Validate that *every* item in the array is a valid bookmark object

  const allItemsValid = bookmarks.every(bookmark => {
    return typeof bookmark === 'object' && // Must be an object type
      bookmark !== null &&           // Must not be null
      'name' in bookmark &&          // Must have 'name' key
      'category' in bookmark &&      // Must have 'category' key
      'url' in bookmark;             // Must have 'url' key
  });

  // Return the original array only if all items were valid, otherwise return empty
  if (allItemsValid) {
    return bookmarks;
  } else {
    return [];
  }
}

It’s not a good idea to add anything that the instructions don’t ask for.

Can you share a link to the step that you’re working on?

Test 5 isn’t passing for me. I’ve also noticed that sometimes even Test 2 fails, and the fix seems to be clearing the FreeCodeCamp local storage in Chrome, then Test 2 passes.

  1. When the bookmarks key in the localStorage does not contain a valid array of bookmark objects, the getBookmarks function should return an empty array.

What have you done to test this out?

First, I checked if the input is an array and if it’s not empty. Then, I performed a more detailed check using the every() method, where I verified if each object within the array contains the required properties. If this check returns true, I return the original bookmarks array, otherwise, I return an empty array.

You need to discover what automated tests are being sent through your function and what is causing it to fail.

You can use “console.log()” on your bookmarksDataString right after it’s loaded and also console.log(getBookmarks()) at the end of your code (after the function) and then run the tests.

Now you will see all the tests being loaded and what your function is returning.

bookmarksDataString is typeof string, the result is [], and the function return value (Array.isArray?) returns true for it, and the result is []

You should get a long string of results from all the tests. Did you run the tests after adding console.log()s?

So, if I understand correctly, I have a syntax error (i.e., invalid JSON), which would mean that my function crashed and didn’t return an array?

// tests completed
// console output
[]
[]
[]
[{"name":"example1","category":"news","url":"example1.com"},{"name":"example2","category":"entertainment","url":"example2.com"},{"name":"example3","category":"work","url":"example3.com"},{"name":"example4","category":"news","url":"example4.com"}]
[]
null
invalid
[SyntaxError: Unexpected token 'i', "invalid" is not valid JSON]
1 Like

I’ve edited your post to improve the readability of the code. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').

1 Like

Each one of these is the output after a different test. You can see sometimes it returns an empty array or a filled array. What you’re missing is the input.

add a console.log() for bookmarksDataString right after it’s loaded in the function so you can see the input of the tests.

function getBookmarks() {
  // Get the raw string value from localStorage
  const bookmarksDataString = localStorage.getItem("bookmarks");
  console.log(bookmarksDataString);
  // Handle case where the key doesn't exist at all
  if (bookmarksDataString === null) {
    return [];
  }

  const bookmarks = JSON.parse(bookmarksDataString);

  // Check if parsing resulted in null or the value is not an array
  if (bookmarks === null || !Array.isArray(bookmarks)) {
    return [];
  }

  if (bookmarks.length === 0) {
    return [];
  }

  // Validate that *every* item in the array is a valid bookmark object

  const allItemsValid = bookmarks.every(bookmark => {
    return typeof bookmark === 'object' && // Must be an object type
      bookmark !== null &&           // Must not be null
      'name' in bookmark &&          // Must have 'name' key
      'category' in bookmark &&      // Must have 'category' key
      'url' in bookmark;             // Must have 'url' key
  });

  // Return the original array only if all items were valid, otherwise return empty
  if (allItemsValid) {
    return bookmarks;
  } else {
    return [];
  }
}

console output:

// tests completed
// console output
[]
[{"name":"example1","category":"news","url":"example1.com"},{"name":"example2","category":"entertainment","url":"example2.com"},{"name":"example3","category":"work","url":"example3.com"},{"name":"example4","category":"news","url":"example4.com"}]
[]
null
invalid
[SyntaxError: Unexpected token 'i', "invalid" is not valid JSON]
[ReferenceError: displayOrCloseForm is not defined]
[ReferenceError: displayOrCloseForm is not defined]
[{"name":"example1","category":"news","url":"example1.com"},{"name":"example2","category":"entertainment","url":"example2.com"},{"name":"example3","category":"work","url":"example3.com"},{"name":"example4","category":"news","url":"example4.com"}]
[ReferenceError: displayOrHideCategory is not defined]
[ReferenceError: displayOrHideCategory is not defined]
[TypeError: Cannot set properties of null (setting 'checked')]

Ok, but not quite that clear.

We can see some errors here that are related to other tests.

You function will always return [] or a bookmarks array, right? (unless there is an error). You can add a console.log here:

 console.log("return bookmarks:", bookmarks)
    return bookmarks;

You can see when it’s returning an array. If it returns something other than an array or empty array, you know that input cause an error you need to account for.

Look through the output you’ve posted for errors. You can ignore this because you haven’t implemented it, right? [ReferenceError: displayOrCloseForm is not defined]

It might be more clear once you’ve implemented more, you could move on from this test from now and complete more of the function.

These stand out though:

Does your function return [] after this error?

1 Like

I found the problem: I wasn’t using a try...catch block. The parse method was throwing an error that halted code execution. Because of that, the code never reached the return statement in that specific case, which is why test 5 was failing. The try...catch block catches that error and then executes the code in the catch block. So, I implemented return []; inside the catch.

1 Like

your code helped me, i had the same problem. only i was using try…catch, but was not checking for validity for every item in the array