--- id: 669e2f60e83c011754f711f9 title: Build a Travel Agency Page challengeType: 25 dashedName: build-a-travel-agency-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 `DOCTYPE` declaration. 1. You should have an `html` element with `lang` set to `en`. 1. You should have a `head` element containing a `meta` void element with `charset` set to `utf-8` and a `title` with the text `Travel Agency Page`. 1. You should have a `meta` tag in your `head` element that contains a short description of your website for SEO. 1. You should have an `h1` element to present your travel destinations. 1. You should have a paragraph below the `h1` element introducing the travel opportunities. 1. You should have an `h2` element with the text `Packages`. 1. You should have a `p` element introducing briefly the various packages. 1. You should have an unordered list element with two list items. The two list items should have the text `Group Travels` and `Private Tours`, respectively. The text of each list item should be enclosed by an anchor element. 1. You should have an `h2` element with the text `Top Itineraries`. 1. You should have at least three `figure` elements, each containing an anchor element and a `figcaption` element. 1. The three anchor elements should have an `img` element with an appropriate `alt` attribute and a `src` attribute set to a valid image as their content. You can use `https://cdn.freecodecamp.org/curriculum/labs/colosseo.jpg`, `https://cdn.freecodecamp.org/curriculum/labs/alps.jpg`, and `https://cdn.freecodecamp.org/curriculum/labs/sea.jpg` if you would like. 1. All your five anchor elements should have an `href` attribute with the value of `https://www.freecodecamp.org/learn` and a `target` attribute with the value of `_blank`. # --hints-- Your travel agency page should have a `!DOCTYPE html` declaration. ```js assert.match(code, //i); ``` You should have an `html` element with `lang` set to `en`. ```js assert.match(code, /[\s\S]*<\/\s*html\s*>/i); ``` You should have a `head` element within the `html` element. ```js assert.match( code, /[\s\S]*<\s*head\s*>[\s\S]*<\/\s*head\s*>[\s\S]*<\/\s*html\s*>/i ); ``` You should have two `meta` elements within your `head` element. ```js assert.match(code, /<\s*head\s*>[\s\S]*(<\s*meta[\s\S]*>[\s\S]*){2,}<\/\s*head\s*>/i); ``` One `meta` element should have a `name` attribute with value of `description` and a non-empty `content` attribute. ```js assert.match(code, /<\s*meta\s+[^>]*name\s*=\s*["']description["'][^>]*content\s*=\s*["'][^"']+?["'][^>]*>/i, ); ``` One `meta` element should have its `charset` attribute set to `UTF-8`. ```js assert.match(code, /<\s*meta[\s\S]+?charset\s*=\s*('|")UTF-8\1/i); ``` You should have `title` element within your `head` element. ```js assert.match( code, /<\s*head\s*>[\s\S]*<\s*title\s*>[\s\S]*<\/\s*title\s*>[\s\S]*<\/\s*head\s*>/i ); ``` Your `title` element should have your travel agency name. ```js assert.isAbove(document.querySelector('title')?.innerText.trim().length, 0); ``` You should have a `body` element within your `html` element. ```js assert.match( code, /<\s*html[\s\S]*>[\s\S]*<\s*head\s*>[\s\S]*<\/\s*head\s*>[\s\S]*<\s*body\s*>[\s\S]*<\/\s*body\s*>[\s\S]*<\/\s*html\s*>/i ); ``` You should have an `h1` element to present your travel destinations. ```js assert.isAbove(document.querySelector('h1')?.innerText.length, 0); ``` You should only have one `h1` element. ```js assert.lengthOf(document.querySelectorAll('h1'), 1); ``` You should have a `p` element below the `h1` element. ```js assert.strictEqual( document.querySelector('h1')?.nextElementSibling.tagName, 'P' ); ``` Your first `p` element should introduce the travel opportunities. ```js assert.isNotEmpty(document.querySelector('p')?.textContent?.trim()); ``` Your first `h2` element should have the text `Packages`. ```js assert.equal(document.querySelectorAll('h2')[0]?.innerText.trim(), 'Packages'); ``` You should have a `p` element below your first `h2` element. ```js assert.strictEqual( document.querySelector('h2')?.nextElementSibling.tagName, 'P' ); ``` Your second `p` element should introduce briefly the various packages. ```js assert.isNotEmpty(document.querySelectorAll('p')?.[1]?.textContent?.trim()); ``` You should have an unordered list element below your second `p` element. ```js assert.strictEqual( document.querySelectorAll('p')?.[1]?.nextElementSibling?.tagName, 'UL' ); ``` You should have two items in your unordered list. ```js assert.lengthOf(document.querySelectorAll('p + ul li'), 2); ``` Both your list items should contain an anchor element. ```js const listItems = document.querySelectorAll('p + ul li'); assert.isNotEmpty(listItems); for (let e of listItems) { assert.strictEqual(e.children[0].tagName, 'A'); assert.lengthOf(e.children, 1); } ``` The anchor element of your first list item should wrap the text `Group Travels`. ```js assert.equal(document.querySelectorAll('li > a')[0]?.innerText.trim(), 'Group Travels'); ``` The anchor element of your second list item should wrap the text `Private Tours`. ```js assert.equal(document.querySelectorAll('li > a')[1]?.innerText.trim(), 'Private Tours'); ``` You should have an `h2` element after your unordered list. ```js assert.strictEqual( document.querySelectorAll('h2')[1]?.previousElementSibling.tagName, 'UL' ); ``` Your second `h2` element should have the text `Top Itineraries`. ```js assert.equal(document.querySelectorAll('h2')[1]?.innerText.trim(), 'Top Itineraries'); ``` You should have at least three `figure` elements. ```js assert.isAtLeast(document.querySelectorAll('figure').length, 3); ``` Each `figure` element should contain an anchor element as its first nested element. ```js const figures = document.querySelectorAll('figure'); assert.isNotEmpty(figures); for (let figure of figures) { assert.equal(figure.children[0].tagName, 'A'); } ``` Each `figure` element should contain a `figcaption` element as its second nested element. ```js const figures = document.querySelectorAll('figure'); assert.isNotEmpty(figures); for (let figure of figures) { assert.equal(figure.children[1]?.tagName, 'FIGCAPTION'); } ``` Each `figcaption` should contain some text. ```js const figcaptionEls = document.querySelectorAll('figcaption'); assert.isNotEmpty(figcaptionEls); figcaptionEls.forEach((figcaption => assert.isNotEmpty(figcaption.innerText))); ``` Each of the `a` elements nested in your `figure` elements should contain an image. ```js const anchors = document.querySelectorAll('figure > a'); assert.isNotEmpty(anchors); for (let anchor of anchors) { assert.equal(anchor.children[0]?.tagName, 'IMG'); } ``` Each `img` element should have a valid `src` attribute. ```js const images = document.querySelectorAll('img'); assert.isNotEmpty(images); for (let image of images) { assert.isAbove(image.src.trim().length, 0); } ``` Each `img` element should have an `alt` attribute with an appropriate value. ```js const images = document.querySelectorAll('img'); assert.isNotEmpty(images); for (let image of images) { assert.isAbove(image.alt.trim().length, 0); } ``` Each `a` element should have an `href` attribute with the value of `https://www.freecodecamp.org/learn`. Don't forget the links in the list items. ```js const anchors = document.querySelectorAll('a'); assert.isNotEmpty(anchors); for (let anchor of anchors) { assert.equal(anchor.href, 'https://www.freecodecamp.org/learn'); } ``` Each `a` element should have a `target` attribute with the value of `_blank`. Don't forget the links in the list items. ```js const anchors = document.querySelectorAll('a'); assert.isNotEmpty(anchors); for (let anchor of anchors) { assert.equal(anchor.target, '_blank'); } ``` # --seed-- ## --seed-contents-- ```html ``` # --solutions-- ```html
Art, folklore, food, nature, and more. Choose among our wide selection of guided tours and excursions, and live an unforgettable experience exploring Italy.
We offer an extensive range of holiday solutions to accommodate the needs of all our clients. From daily excursions in the most beautiful cities, to thorough tours of hidden villages and medieval towns to discover Italy's lesser-known sides.