mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(Curriculum): add movie review page lab (#59597)
This commit is contained in:
@@ -2001,6 +2001,13 @@
|
||||
"You'll practice concepts like <code>alt</code> attributes and aria roles."
|
||||
]
|
||||
},
|
||||
"lab-movie-review-page": {
|
||||
"title": "Design a Movie Review Page",
|
||||
"intro": [
|
||||
"In this lab, you'll create a movie review page.",
|
||||
"You'll practice concepts like semantic HTML, <code>alt</code> attributes, accessible lists, and hiding decorative content from screen readers using <code>aria-hidden</code>."
|
||||
]
|
||||
},
|
||||
"lab-multimedia-player": {
|
||||
"title": "Build a Multimedia Player",
|
||||
"intro": [
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Introduction to the Design a Movie Review Page
|
||||
block: lab-movie-review-page
|
||||
superBlock: full-stack-developer
|
||||
---
|
||||
|
||||
## Introduction to the Design a Movie Review Page
|
||||
|
||||
In this lab, you'll create a movie review page. You will practice using HTML, `alt` attributes, accessible lists, and hiding decorative content from screen readers using `aria-hidden`.
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Design a Movie Review Page",
|
||||
"blockType": "lab",
|
||||
"blockLayout": "link",
|
||||
"isUpcomingChange": false,
|
||||
"usesMultifileEditor": true,
|
||||
"dashedName": "lab-movie-review-page",
|
||||
"superBlock": "full-stack-developer",
|
||||
"challengeOrder": [
|
||||
{
|
||||
"id": "67ef8f695db52583424bd118",
|
||||
"title": "Design a Movie Review Page"
|
||||
}
|
||||
],
|
||||
"helpCategory": "HTML-CSS"
|
||||
}
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
---
|
||||
id: 67ef8f695db52583424bd118
|
||||
title: Design a Movie Review Page
|
||||
challengeType: 25
|
||||
dashedName: design-a-movie-review-page
|
||||
demoType: onClick
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
|
||||
|
||||
**User Stories:**
|
||||
|
||||
1. You should have a `main` element.
|
||||
2. Inside the `main` element, you should have an `h1` element for the movie title.
|
||||
3. Below the `h1` element, you should have an `img` element displaying the movie cover. Your `img` element should have a descriptive `alt` text describing the image. You are free to use the following image if you like: `https://cdn.freecodecamp.org/curriculum/labs/rise-beyond-2.png`.
|
||||
4. You should have a `p` element containing a brief movie description.
|
||||
5. You should have another `p` element to display the movie rating. Within it, you should have these items in the listed order:
|
||||
- A `strong` element with the text `Movie Rating:`.
|
||||
- A `span` element with an `aria-hidden` attribute set to `true` containing a visual representation of the rating using stars `⭐⭐⭐⭐⭐⭐⭐⭐⭐☆`.
|
||||
- A numerical value, representing the rating, in parentheses (e.g. `9.2/10`) after the span.
|
||||
6. You should have an `h2` element with the text `Cast Members`.
|
||||
7. You should have a `ul` element.
|
||||
8. Inside the `ul` element, you should have multiple `li` elements each containing a `strong` element for the actor's name followed by the corresponding character name preceded by the text `as`. (e.g., `James Holloway as Ethan Carter`).
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `main` element.
|
||||
|
||||
```js
|
||||
assert.isNotNull(document.querySelector("main"));
|
||||
```
|
||||
|
||||
Inside the `main` element, you should have an `h1` element containing the movie title.
|
||||
|
||||
```js
|
||||
const h1 = document.querySelector("main > h1");
|
||||
assert.isAbove(h1?.innerText.length, 0);
|
||||
```
|
||||
|
||||
Below the `h1` element, you should have an `img` element with a descriptive `alt` attribute.
|
||||
|
||||
```js
|
||||
const img = document.querySelector("main > h1 + img");
|
||||
assert.isNotNull(img);
|
||||
assert.isNotEmpty(img.getAttribute("alt"));
|
||||
```
|
||||
|
||||
You should have a `p` element after the image that contains the movie description.
|
||||
|
||||
```js
|
||||
const description = document.querySelector("main img + p");
|
||||
assert.isNotNull(description);
|
||||
assert.isNotEmpty(description.innerText);
|
||||
```
|
||||
|
||||
You should have another `p` element that contains the rating.
|
||||
|
||||
```js
|
||||
const paragraphs = document.querySelectorAll("main p");
|
||||
assert.isAtLeast(paragraphs.length, 2);
|
||||
```
|
||||
|
||||
Inside the second `p` element, you should have a `strong` element with the text `Movie Rating:`.
|
||||
|
||||
```js
|
||||
const strongEl = document.querySelector("main p:nth-of-type(2) strong");
|
||||
assert.match(strongEl?.innerText.trim(), /^Movie Rating:?$/);
|
||||
```
|
||||
|
||||
There should be a `span` element inside the rating paragraph.
|
||||
|
||||
```js
|
||||
const spanEl = document.querySelector("main p:nth-of-type(2) span");
|
||||
assert.isNotNull(spanEl);
|
||||
```
|
||||
|
||||
The `span` element inside the rating paragraph should have ten stars, either filled in (⭐) or empty (☆), followed by a numerical value in parentheses after the `span`.
|
||||
|
||||
```js
|
||||
const spanEl = document.querySelector("main p:nth-of-type(2) span");
|
||||
const fullRatingText = document.querySelector("main p:nth-of-type(2)")?.textContent.replace(/\s+/g, ' ').trim();
|
||||
|
||||
assert.match(spanEl?.innerText, /^[⭐☆]{10}$/);
|
||||
assert.match(fullRatingText, /Movie Rating:\s+[⭐☆]{10}\s+\(\d+(?:\.\d+)?\/10\)$/);
|
||||
```
|
||||
|
||||
The `span` element inside the rating paragraph should have an `aria-hidden` attribute set to `true`.
|
||||
|
||||
```js
|
||||
const spanEl = document.querySelector("main p:nth-of-type(2) span");
|
||||
assert.strictEqual(spanEl?.getAttribute("aria-hidden"), "true");
|
||||
```
|
||||
|
||||
You should have an `h2` element.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector("h2"));
|
||||
```
|
||||
|
||||
Your `h2` should come after your second `p` element.
|
||||
|
||||
```js
|
||||
const allParagraphs = document.querySelectorAll("p");
|
||||
assert.isAtLeast(allParagraphs.length, 2);
|
||||
|
||||
const h2 = document.querySelector("h2");
|
||||
const main = document.querySelector("main");
|
||||
|
||||
assert.exists(h2);
|
||||
assert.exists(main);
|
||||
|
||||
const elements = Array.from(main.querySelectorAll("*"));
|
||||
const lastPIndex = elements.indexOf(allParagraphs[1]);
|
||||
const h2Index = elements.indexOf(h2);
|
||||
|
||||
assert.isAbove(h2Index, lastPIndex);
|
||||
```
|
||||
|
||||
Your `h2` should have the text `Cast Members`.
|
||||
|
||||
```js
|
||||
const h2 = document.querySelector("h2");
|
||||
assert.equal(h2?.textContent, "Cast Members");
|
||||
```
|
||||
|
||||
You should have a `ul` element after the `h2`.
|
||||
|
||||
```js
|
||||
const ul = document.querySelector("main h2 + ul");
|
||||
assert.isNotNull(ul);
|
||||
```
|
||||
|
||||
The `ul` should contain multiple `li` elements.
|
||||
|
||||
```js
|
||||
const liItems = document.querySelectorAll("main ul li");
|
||||
assert.isAbove(liItems.length, 1);
|
||||
```
|
||||
|
||||
Each `li` should contain a `strong` element for the actor name followed by the corresponding character name preceded by the text `as`. (e.g., `James Holloway as Ethan Carter`).
|
||||
|
||||
```js
|
||||
const liItems = document.querySelectorAll("main ul li");
|
||||
assert.isNotEmpty(liItems);
|
||||
liItems.forEach(li => {
|
||||
const strong = li.querySelector("strong");
|
||||
assert.isNotNull(strong);
|
||||
const fullText = li.textContent.trim();
|
||||
const actorName = strong.textContent.trim();
|
||||
assert.isTrue(fullText.startsWith(actorName));
|
||||
const characterPart = fullText.slice(actorName.length).trim();
|
||||
assert.match(characterPart, /^as\s.+/);
|
||||
});
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Movie Review</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Movie Review</title>
|
||||
</head>
|
||||
<body>
|
||||
<main class="review">
|
||||
<h1>Movie Review: Rise Beyond</h1>
|
||||
<img
|
||||
src="https://cdn.freecodecamp.org/curriculum/labs/rise-beyond-2.png"
|
||||
alt="The Rise Beyond movie poster, starring Ethan Carter. A portrait of a young boy standing on a stage with his back toward the audience, holding a guitar at his side, staring at a backdrop of a cityscape with the sun rising behind its tall buildings."
|
||||
/>
|
||||
<p>
|
||||
Rise Beyond is an uplifting drama that tells the story of Ethan Carter,
|
||||
a young man from a small town who dreams of becoming a world-class
|
||||
musician. Facing financial struggles and self-doubt, Ethan embarks on a
|
||||
journey of resilience, guided by his mentor Professor Adams and
|
||||
childhood friend Lena Mitchell. Through setbacks, failures, and moments
|
||||
of triumph, Rise Beyond reminds us that our greatest potential lies
|
||||
beyond our fears.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Movie Rating:</strong>
|
||||
<span aria-hidden="true">⭐⭐⭐⭐⭐⭐⭐⭐⭐☆</span> (9.2/10)
|
||||
</p>
|
||||
|
||||
<h2>Cast Members</h2>
|
||||
<ul>
|
||||
<li><strong>James Holloway</strong> as Ethan Carter</li>
|
||||
<li><strong>Olivia Sterling</strong> as Lena Mitchell</li>
|
||||
<li><strong>William Lancaster</strong> as Professor Adams</li>
|
||||
<li>
|
||||
<strong>Maria Collins</strong> as Evelyn Carter (Ethan’s Mother)
|
||||
</li>
|
||||
</ul>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -110,6 +110,7 @@
|
||||
"dashedName": "lecture-importance-of-accessibility-and-good-html-structure"
|
||||
},
|
||||
{ "dashedName": "lab-checkout-page" },
|
||||
{ "dashedName": "lab-movie-review-page" },
|
||||
{ "dashedName": "lab-multimedia-player" },
|
||||
{ "dashedName": "review-html-accessibility" },
|
||||
{ "dashedName": "quiz-html-accessibility" }
|
||||
|
||||
Reference in New Issue
Block a user