Exercise: Pet Adoption Profiles
Finish five functions for a pet adoption site, building profile lines with destructuring and safe copies with spread, and let the tests check each one.
Apprentice · JavaScript · Updated
Happy Tails Rescue is putting its pets online, and the volunteers need the code behind each pet's profile: a one-line summary for the listing page, a way to show only the dogs (or only the cats), and safe ways to update a pet. "Safe" is the important word. When Mochi the cat is adopted, the adoption papers need a copy that says so, while the listing keeps the original until the paperwork is done. Every task is a function for you to finish, and tests check each one as you go.
Before you start
You need Node.js, version 24 or later. In a terminal, node --version shows the version you have. Nothing else needs installing: the tests use the test runner that comes with Node.
Get the exercise code
In the Exercise box beside the lesson, choose Get the starter on GitHub to open its GitHub repository. Click Code, then Download ZIP, and unzip it into your objects-practice folder (or any folder you like). The folder holds:
pets.js: the five functions you'll finish.listing.js: prints the shelter's listing with your functions, so you can watch them work. You don't need to change it.pets.test.js: the tests that check your functions. You don't need to change these.package.json: tells Node that these files share functions withimportandexport. You don't need to change it.
Open the folder in VS Code, and open a terminal there with Terminal > New Terminal.
What to do
Every function is already written down with its name and parameters, and returns an empty value for now: '', [] or {}. The comment above it says what it should return, with examples:
/*
* Return a copy of the pet with adopted set to true. The pet you're given stays as it is,
* because the listing still needs it until the paperwork is done.
*
* markAdopted({ name: 'Mochi', species: 'cat', adopted: false })
* -> { name: 'Mochi', species: 'cat', adopted: true }
*/
export function markAdopted(pet) {
return {};
}
profileLine(pet): one line for the listing, such asBiscuit (dog, 3 years): loves fetch, good with kids. Unpack the pet with destructuring. A pet aged 1 is1 year, and a pet with no traits showsno traits listed yet.petsOfSpecies(pets, species): a new array with only the pets of one species, in their order.markAdopted(pet): a copy of the pet withadopted: true.mergeDetails(pet, updates): a copy of the pet with the updated details merged in, such as Juniper's new age after her birthday.addTrait(pet, trait): a copy of the pet with one more trait at the end of its list.
The rule for all five: none of them changes what it's given. Make a copy, then change the copy.
Check your work
In the terminal, in the exercise folder:
node --test
At first all 11 tests fail. That's expected: each function you finish turns its tests green. When a test fails, its message says what it expected, for example The pet you were given still says adopted: false. Make a copy, then change the copy.
To see your functions at work, run the listing:
node listing.js
Hints
- Start with the examples. Each function's comment shows what goes in and what comes out. Work one out by hand before you write code.
- A default fills a gap. A pet with no
traitsproperty still needs a list. Destructuring shows how a default covers a missing property. To turn the list into text,traits.join(', ')glues the items together with a comma and a space between them (String Methods, in chapter 4, coversjoinfully). - "Later wins" does the merging. In Spread and Rest, a property written after a spread replaces the copied one. That's all
markAdoptedandmergeDetailsneed. - Watch the inner list. A spread copy of a pet shares its
traitsarray with the original. If the original's traits change when you add one, copy the array too. - Loop, check, collect.
petsOfSpeciesis the loop from Arrays of Objects: start with an empty array andpusheach match.
When you're done
Every test is green, and node listing.js prints:
Happy Tails Rescue: waiting for a home
Biscuit (dog, 3 years): loves fetch, good with kids
Mochi (cat, 2 years): lap cat, chatty
Pepper (rabbit, 1 year): shy
Juniper (dog, 7 years): calm, house-trained
Clover (guinea pig, 2 years): no traits listed yet
Dogs: Biscuit, Juniper
Mochi's adoption papers say adopted: true. The listing still says false.
After her birthday: Juniper (dog, 8 years): calm, house-trained (nickname June)
New note: Biscuit (dog, 3 years): loves fetch, good with kids, snores
The listing still has: Biscuit (dog, 3 years): loves fetch, good with kids
Look at the last two lines. Biscuit has a new trait in the copy and the old list in the listing. What would have happened to the last line if addTrait had pushed onto the pet's own traits array?
So what
Copy, then change: that's how real apps update data without breaking the screen that still shows the old version, and it's the habit frameworks such as React expect from you.