Question
Answered step-by-step

i want help to understand the questions below-

/*******************************************************************************

 * Problem 0: learn how to implement code to pass unit tests.

 *

 * Welcome to Assignment 1! In this assignment, you're going to be practicing lots

 * of new JavaScript programming techniques.  Before you dive in let's spend a

 * minute helping you learn how to read this code, and how to understand the

 * tests that go with it.

 *

 * In addition to this file, please also open the src/problem-00.test.js file.

 * Start by reading the comment at the top of that file, then come back here and

 * continue.

 *

 * Make sure you have completed the necessary Setup (install node.js, run `npm install`

 * before continuing).  The rest of the instructions assume that you have done this.

 *

 * After you finish reading src/problem-00.test.js, it's time to try running

 * the tests.  To run the tests, go to your terminal and type the following command:

 *

 *   npm test

 *

 * You have to run this command in the root of your project (i.e., in the same

 * directory as src/ and package.json).  When you do, you will see a lot of failures.

 * That's expected, since we haven't written any solution code yet.

 *

 * You can also run tests for only this problem instead of everything.  To do that:

 *

 *   npm test problem-00

 *

 * This will look for tests that are part of the problem-00.test.js file, and only

 * run those.  Doing so should result in 1 failed and 1 passed test.

 *

 * The first test passes:

 *

 *  ✓ greeting should be a function (2ms)

 *

 * But the second one failed:

 *

 * ✕ greeting should  return the correct string output (3ms)

 *

 * ● Problem 0 - greeting() function › greeting should  return the correct string output

 *

 *   expect(received).toBe(expected) // Object.is equality

 *

 *   Expected: "Hello WEB222 Student!"

 *   Received: "Hello WEB222 Student"

 *

 *     63 |   test('greeting should return the correct string output', function() {

 *     64 |     let result = greeting('WEB222 Student');

 *   > 65 |     expect(result).toBe('Hello WEB222 Student!');

 *        |                    ^

 *     66 |   });

 *     67 |

 *     68 |   /**

 *

 * We can see that the test 'greeting should say "Hello Name!"' is failing.

 * It's failing on line 65 of src/problem-00.test.js.  In particular, it's failing

 * because it expected to get the String "Hello WEB222 Student!" but instead

 * it actually received the String "Hello WEB222 Student".

 *

 * It looks like we have a small typo in our code below, and we are missing

 * the final "!"" character.  Try adding it below, save this file, and re-run the

 * tests again:

 *

 * npm test problem-00

 * PASS  src/problem-00.test.js

 *  Problem 0 - greeting() function

 *   ✓ greeting should be a function (2ms)

 *   ✓ greeting should return the correct string output

 *

 * Test Suites: 1 passed, 1 total

 * Tests:       2 passed, 2 total

 *

 * Excellent! At this point you're ready to move on to Problem 1. As you do,

 * read both the information in the Problem's comment, and also read the tests

 * to understand what they expect from your code's implementation.

 *

 * One final word about these comments.  You'll see comments like this one:

 *

 * @p..;@returns {string}

 *

 * These are specially formatted comments that define parameters to functions,

 * and tell us the type {string} or {number}, and also the parameter's name.

 * We also indicate the return type for functions.

 *

 * Finally, we also explain a bit about how the parameter is used, and what

 * data it will have, whether it's optional, etc.

 ******************************************************************************/


function greeting(name) {

  return `Hello ${name}!`;

}


/*******************************************************************************

 * Problem 1: replace all internal whitespace in a string value with dashes ('-'),

 * and make it UPPERCASE.

 *

 * We want to be able to convert a string to Upper Kebab Case style, so that it

 * contains no spaces, tabs, or dots, and all letters are upper case.

 *

 * The kebab() function should work like this:

 *

 * kebab('ABC') --> returns 'ABC' (all Upper Case, the string is unchanged)

 * kebab(' ABC ') --> returns 'ABC' (all Upper Case, leading/trailing whitespace removed)

 * kebab('abc') --> returns 'ABC' (the string was converted to upper case)

 * kebab('A BC') --> returns 'A-BC' (uppercase, single space replaced with -)

 * kebab('A BC') --> returns 'A-BC' (uppercase, single space replaced with -)

 * kebab('A   BC') --> returns 'A-BC' (uppercase, multiple spaces replaced with -)

 * kebab('A.BC') --> returns 'A-BC' (uppercase, period replaced with -)

 * kebab('A..  BC') --> returns 'A-BC' (uppercase, periods/spaces replaced with -)

 *

 * @p..;@return {string}

 ******************************************************************************/


function kebab(value) {

 

  return `${value}`;+

}


/*******************************************************************************

 * Problem 2: create an HTML <img> element for the given url and alt text.

 *

 * In HTML, we use markup syntax to indicate how browsers should format elements

 * of a web page.  For example, here is a URL to a cat picture:

 *

 * https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500

 *

 * Try navigating to it in your browser.  In order for a web page to know how to

 * interpret this URL (e.g., should we show the text of the URL itself, or use

 * it to load an image?), we have to use special markup.  The <img> element

 * is how we specify that a URL is to be interpreted as an image, see:

 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img

 *

 * Here is how we might use HTML to markup this image:

 *

 * <img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">

 *

 * Our <img> has two attributes:

 *

 * - src: the URL to use when downloading this image's data

 * - alt: the alternative text to display in non-visual browsing environments (e.g., screen readers)

 *

 * Write the createImg() function to accept a URL and alt text, and return the

 * properly formatted img element.  For example:

 *

 * createImg('https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500', 'Cat with ears down')

 *

 * should return the following string of HTML:

 *

 * '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">'

 *

 * An <img> can also optionally contain a width attribute, for example:

 *

 * <img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down" width="300">

 *

 * In this case, the <img> element should use 300 pixels for its width.  Therefore,

 * your createImg() function should also accept a third argument, width:

 *

 * // No width given

 * createImg('https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500', 'Cat with ears down')

 * // Width of 300 given

 * createImg('https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500', 'Cat with ears down', 300)

 *

 * The returned <img> HTML string should be formatted as follows:

 *

 * - Remove leading/trailing whitespace from src and alt values before you use them

 * - The src and alt attribute values should be wrapped in double-quotes (e.g., src="...")

 * - There should be a single space between the end of one attribute and start of the next (e.g., src="..." alt="...")

 * - The width attribute should only be added if a valid integer value (number or string) is passed

 *   for the third argument.  Otherwise ignore it.

 *

 * @param {string} src - the src URL for the img

 * @p..;@param {string|number} width - (optional) the width of the img. Must be a valid integer

 * @returns {string}

 ******************************************************************************/


function createImg(src, alt, width) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 3: extract Date from date string

 *

 * A date string is expected to be formatted as follows:

 *

 * YYYY-DD-MM

 *

 * Meaning, Year (4 digits), Day (2 digits), Month (2 digits).

 *

 * January 1, 2021 would therefore be the following date string:

 *

 * 2021-01-01

 *

 * Similarly, September 29, 2021 would be:

 *

 * 2021-29-09

 *

 * Write a function, parseDateString() that accepts a date string of the format

 * specified above, and returns a Date object, set to the correct day.

 *

 * To help developers using your function, you are asked to provide detailed error

 * messages when the date string is formatted incorrectly.  We will use the throw

 * statement to throw an error when a particular value is not what we expect, see:

 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw

 *

 * For example: parseDateString('01-01-01') should fail, because the year is

 * not 4 digits.  Similarly, parseDateString('2021-1-01') should fail because

 * the day is not 2 digits, and parseDateString('2021-01-1') should fail because

 * the month is not 2 digits.  Also, a totally invalid date string should also

 * cause an exception to be thrown, for example parseDateString(null) or

 * parseDateString("this is totally wrong").

 *

 * @p..;@returns {Date}

 ******************************************************************************/


function parseDateString(value) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 4: convert Date to date string with specified format.

 *

 * As above, a date string is expected to be formatted as follows:

 *

 * YYYY-DD-MM

 *

 * Meaning, Year (4 digits), Day (2 digits), Month (2 digits).

 *

 * Write a function, toDateString() that accepts a Date object, and returns a

 * date string formatted according to the specification above. Make sure your

 * day and month values are padded with a leading '0' if necessary (e.g., 03 vs. 3).

 *

 * NOTE: it should be possible to use parseDateString() from the previous question

 * and toDateString() to reverse each other. For example:

 *

 * toDateString(parseDateString('2021-29-01)) should return '2021-29-01'

 *

 * @p..;@returns {string}

 ******************************************************************************/


function toDateString(value) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 5: validate a coordinate

 *

 * Coordinates are defined as numeric, decimal values of Latitude and Longitude.

 * A example, the Seneca College Newnham campus is located at:

 *

 * Latitude: 43.7955 (positive number means North)

 * Longitude: -79.3496 (negative number means West)

 *

 * Write a function, validateCoord(), which accepts a latitude and longitude,

 * and returns true if they are both valid, or false if one or both are invalid.

 *

 * Valid Latitude values are decimal numbers between -90 and 90.

 *

 * Valid Longitude values are decimal numbers between -180 and 180.

 *

 * @param {number} lat - the latitude

 * @p..;@returns {boolean}

 ******************************************************************************/


function validateCoord(lat, lng) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 6, Part 1: format a coordinate as a string

 *

 * As above, coordinates are defined as numeric, decimal values of Latitude and Longitude.

 *

 * Write a function, formatCoord(), which accepts a latitude and longitude,

 * and returns a string formatted as follows:

 *

 * (lat, lng)

 *

 * For example:

 *

 * formatCoord(43.7955, -79.3496) should return the string '43.7955,-79.3496'.

 *

 * An optional third param, includeBrackets, determines whether or not to include

 * parenthesis around the formatted coordinate:

 *

 * formatCoord(43.7955, -79.3496) should return the string '43.7955,-79.3496'.

 * formatCoord(43.7955, -79.3496, true) should return the string '[43.7955,-79.3496]'.

 *

 * Use your validateCoord() function from Problem 5 to determine if the coordinate

 * is valid before you attempt to format it.  If the coordinate is not valid, throw

 * an exception.

 *

 * @param {number} lat - the latitude

 * @param {number} lng - the longitude

 * @p..;@returns {string}

 ******************************************************************************/


function formatCoord(lat, lng, includeBrackets) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 6, Part 2: format any number of coordinates as a string

 *

 * Similar to Problem 6 Part 1, you are asked to format lat, lng coordinates

 * into a string. However, where formatCoord() formats a single lat, lng pair,

 * the formatCoords() function (note the `s` suffix) is able to format any

 * number of lag, lng pairs.

 *

 * For example:

 *

 * formatCoords(43.7955, -79.3496) should return '[[43.7955,-79.3496]]'

 * formatCoords(43.7955, -79.3496, 43.7953, -79.3491) should return '[[43.7955,-79.3496], [43.7953,-79.3491]]'

 *

 * In your solution for formatCoords, use the formatCoord function you wrote above.

 *

 * The formatCoords() function can take any number of arguments, but they must all be numbers,

 * there must be an even number of them, and all lat, lng pairs should be valid.

 *

 * If any of these conditions are not met, throw an exception.

 *

 * @p..;@returns {string}

 ******************************************************************************/


function formatCoords(...values) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 7: determine MIME type from filename extension

 *

 * Web browsers and servers exchange streams of bytes, which must be interpreted

 * by the receiver based on their type.  For example, an HTML web page is

 * plain text, while a JPG image is a binary sequence.

 *

 * The Content-Type header contains information about a resource's MIME type, see:

 * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type

 *

 * The MIME type is made-up of a `type` and a `subtype` separated by a `/` character.

 * The type is general, for example, 'text' or 'video'.  The subtype is more

 * specific, indicating the specific type of text, image, video, etc.  See:

 * https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types

 *

 * A number of common types are used in web development:

 *

 * mimeFromFilename('/User/Documents/readme.txt') --> returns 'text/plain'

 *

 * Your mimeFromFilename() function should support all of the following extensions

 * with and without the leading '.':

 *

 * - .html, .htm --> text/html

 * - .css --> text/css

 * - .js --> text/javascript

 * - .jpg, .jpeg --> image/jpeg

 * - .gif --> image/gif

 * - .bmp --> image/bmp

 * - .ico, .cur --> image/x-icon

 * - .png --> image/png

 * - .svg --> image/svg+xml

 * - .webp --> image/webp

 * - .mp3 --> audio/mp3

 * - .wav --> audio/wav

 * - .mp4 --> video/mp4

 * - .webm --> video/webm

 * - .json --> application/json

 *

 * NOTE: any other extension should use the `application/octet-stream` MIME type,

 * to indicate that it is an unknown stream of bytes (e.g., binary file). You should

 * also use `application/octet-stream` if the file has no extension.

 *

 * @p..;@returns {string}

 ******************************************************************************/


function mimeFromFilename(filename) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 8, Part 1: generate license text and link from license code.

 *

 * Images, videos, and other resources on the web are governed by copyright.

 * Everything you find on the web is copyright to its creator automatically, and

 * you cannot reuse it unless you are granted a license to do so.

 *

 * Different licenses exist to allow creators to share their work. For example,

 * the Creative Commons licenses are a popular way to allow people to reuse

 * copyright material, see https://creativecommons.org/licenses/.

 *

 * Below is a list of license codes, and the associated license text explaining the code:

 *

 * CC-BY: Creative Commons Attribution License

 * CC-BY-NC: Creative Commons Attribution-NonCommercial License

 * CC-BY-SA: Creative Commons Attribution-ShareAlike License

 * CC-BY-ND: Creative Commons Attribution-NoDerivs License

 * CC-BY-NC-SA: Creative Commons Attribution-NonCommercial-ShareAlike License

 * CC-BY-NC-ND: Creative Commons Attribution-NonCommercial-NoDerivs License

 *

 * NOTE: any other licenseCode should use the URL https://choosealicense.com/no-permission/

 * and the explanation text, "All Rights Reserved"

 *

 * Write a function, generateLicenseLink(), which takes a license code, and returns

 * an HTML link to the appropriate license URL, and including the explanation text.

 *

 * For example:

 *

 * generateLicenseLink('CC-BY-NC') should return the following HTML string:

 *

 * '<a href="https://creativecommons.org/licenses/by-nc/4.0/">Creative Commons Attribution-NonCommercial License</a>'

 *

 * The URL is generated based on the license code:

 *

 * - remove the `CC-` prefix

 * - convert to lower case

 * - place formatted license code within URL https://creativecommons.org/licenses/[...here]/4.0/

 *

 * You can read more about HTML links at https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a

 *

 * @p..;@returns {string}

 ******************************************************************************/


function generateLicenseLink(licenseCode) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 9 Part 1: create a pure Boolean true/false value from a dataset

 *

 * A dataset contains fields that indicate a value is true or false.  However,

 * users have entered data in various formats over the years, for example:

 *

 * Yes, yes, YES, Y, t, TRUE, true, True, 1

 * No, no, NO, N, n, f, FALSE, false, False, 0, null, undefined, -1

 *

 * Write a function pureBool() which takes a String, Number, Boolean,

 * null, or undefined and attempts to convert it into a pure Boolean value.

 *

 * If the value is not one of the values above, throw an error with the error

 * message, 'invalid boolean value'.

 *

 * @p..;@returns {bool}

 ******************************************************************************/


function pureBool(value) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 9 Part 2: checking for all True or all False values in a normalized list

 *

 * Using your normalizeBoolean() function, create two new functions to check

 * if a list of arguments are all normalized True or normalized False values:

 *

 * all('Y', 'yes', 1) --> returns true

 * some('Y', 'no', 1) --> returns true

 * none('Y', 'invalid', 1) --> returns false

 *

 * allFalse('N', 'no', 0) --> returns true

 * allFalse('N', 'no', 0) --> returns false

 * allFalse('Y', 'invalid', 1) --> returns false (i.e., does not throw)

 *

 * Use try/catch syntax to avoid having allTrue() and allFalse() throw errors

 * when normalizeBoolean() throws on invalid data.

 ******************************************************************************/


function all() {

  // Replace this comment with your code...

}


function none() {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 10 - build a URL to query the iNaturalist Web API

 *

 * One of the data sources we'll be exploring in future assignments is

 * https://www.inaturalist.org.  Using iNaturalist, both hobbyist and professional

 * scientists can share sightings and help identify plants and animals in their

 * local area.

 *

 * As a web developer, you have access to this tremendous database of scientific

 * observations via the iNaturalist Web API (application programming interface):

 *

 * https://www.inaturalist.org/pages/api+reference#get-observations

 *

 * Querying the iNaturalist dataset for information involves formatting a URL

 * in a particular way.  As we know from week 1, a URL can contain optional

 * name=value pairs, see: https://web222.ca/weeks/week01/#urls

 *

 * For example:

 *

 *   https://www.store.com/search?q=dog includes q=dog

 *

 *   https://www.store.com?_encoding=UTF8&node=18521080011 includes

 *   both _encoding=UTF8 and also node=18521080011, separated by &

 *

 * We will write a buildUrl() function to build a URL for the iNaturalist API

 * based on arguments passed by the caller.

 *

 * The buildUrl() function accepts the following arguments:

 *

 * - q: a search string, for example "butterfly" or "Horse-chestnut"

 * - per_page: a number from 1 to 200, indicating how many results to return per page

 * - order: a string indicating sort order, with possible values of `asc` or `desc`

 * - license: a string indicating which items to return (e.g., which license they use). Possible

 *   values include: none, any, cc-by, cc-by-nc, cc-by-sa, cc-by-nd, cc-by-nc-sa, cc-by-nc-nd

 * - lat: a number, indicating the latitude to use for results

 * - lng: a number, indicating the longitude to use for results.

 *

 * Write an implementation of buildUrl() that accepts arguments for all of the above

 * parameters, validates them (e.g., perPage must be between 1 and 200, lat and lng

 * must be a valid coord, etc), and returns a properly formatted URL.

 *

 * For example:

 *

 * buildUrl('butterfly', 50, 'asc', 'cc-by', 43.7955, -79.3496) should return

 * the following URL:

 *

 * https://api.inaturalist.org/v1/observations?q=butterfly&per_page=50&order=asc&license=cc-by&lat=43.7955&lng=-79.3496

 *

 * NOTE: if any of the values passed to buildUrl() are invalid, an exception should be thrown.

 *

 * NOTE: make sure you properly encode the q value, since URLs can't

 * contain spaces or certain other characters. HINT: use the encodeURIComponent()

 * function to do this, see:

 *

 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

 *

 * @param {string} q the query to use. Must be properly URI encoded

 * @param {number} perPage the number of results per page, must be 1-200

 * @param {string} order the sort order to use, must be one of asc or desc

 * @param {string} license the license to use, must be one of none, any, cc-by, cc-by-nc, cc-by-sa, cc-by-nd, cc-by-nc-sa, cc-by-nc-nd

 * @param {number} lat the latitude to use, must be a valid latitude (use validateCoord() function)

 * @p..;@returns {string} the properly formatted iNaturalist URL

 ******************************************************************************/


function buildUrl(q, perPage, order, license, lat, lng) {

  // Replace this comment with your code...

}


// Our unit test files need to access the functions we defined

// above, so we export them here.

exports.greeting = greeting;

exports.kebab = kebab;

exports.createImg = createImg;

exports.parseDateString = parseDateString;

exports.toDateString = toDateString;

exports.validateCoord = validateCoord;

exports.formatCoord = formatCoord;

exports.formatCoords = formatCoords;

exports.mimeFromFilename = mimeFromFilename;

exports.generateLicenseLink = generateLicenseLink;

exports.pureBool = pureBool;

exports.all = all;

exports.none = none;

exports.buildUrl = buildUrl;




problem00-

/**

 * Welcome to the Problem 0 Unit Tests! The problem test files are code that

 * has already been written for you, you don't need to do anything

 * in them except read what's here.  They include tests for the assignment's

 * functions, and will help you know if your coding is working or not.

 *

 * A Unit Test is a piece of code that tests a "unit" of code, for example, a

 * function. We call them Unit Tests, because we try to have our tests test the

 * smallest possible unit of code that we can.

 *

 * These tests have been written using a Testing Framework called Jest.

 * Jest was created by Facebook, and helps developers write code with

 * fewer bugs. You can read more about it at https://jestjs.io/

 *

 * Each of the problems that you need to solve in src/solutions.js

 * has an associated file with unit tests, Problem 1's tests are in

 * the file problem-01.test.js, and so on. These tests define the

 * expected behaviour of your code.  If you write your tests correctly,

 * all the tests should PASS.  If you make a mistake, one or more of them

 * will FAIL.

 *

 * Your goal is get all of the tests in this assignment to PASS.

 * It's like a video game, except instead of using a gamepad, you'll be writing

 * JavaScript!

 *

 * Some of what these tests do is more complex than what you know how to

 * do yourself at this point.  Don't worry about that.  Remember, you don't

 * have to write the tests, only get your code to pass.

 *

 * To help you, we'll document and explain everything in this file as we go.

 * This first line is getting the `greeting` function from the file solutions.js.

 * Don't worry about this for the moment, but if you're curious, you can read more

 * at https://nodejs.org/en/knowledge/getting-started/what-is-require/

 */

const { greeting } = require('./solutions');


/**

 * Next, we use one of Jest's functions called describe().  It allows

 * us to describe our tests for a particular feature, and give them a name.

 * Doing so makes it a bit easier to see what's going on when we run our tests.

 * We also define a function() {...} to contain our tests.  When the Problem 0

 * tests are run, this function will be called.

 */

describe('Problem 0 - greeting() function', function () {

  /**

   * Now we come to the individual tests.  We try to keep our tests

   * small, and only test 1 thing at a time.  This makes it easier to implement

   * our code and slowly make progress.  You can write a bit of the functionality,

   * and get some of the tests to pass.  As you add more, and deal with new cases,

   * more of the tests should pass.  You also want to avoid having passing tests

   * suddenly start failing--meaning you've introduced a bug.

   *

   * Our first test makes sure that the variable named `greeting` is really

   * a function.  We're using Jest's expect() function, which let's us

   * compare an actual value (something returned by running our code) to an

   * expected value (something we define in advance in our test).  You don't need

   * to spend too much time on this, but if you're interested, you can read more

   * about expect() at https://jestjs.io/docs/en/expect.

   */

  test('greeting should be a function', function () {

    // This is like saying: if(typeof greeting === 'function')

    expect(typeof greeting).toBe('function');

  });


  /**

   * Our final test for greeting() checks to make sure that if you pass in

   * a name (i.e., a String), that it returns a new String formatted in the right way.

   */

  test('greeting should return the correct string output', function () {

    let result = greeting('WEB222 Student');

    expect(result).toBe('Hello WEB222 Student!');

  });


  /**

   * OK, now you're ready to go back to src/solutions.js and continue solving

   * Problem 1.

   */

});



Problem 01-


const { kebab } = require('./solutions');


describe('Problem 1 - kebab() function', function () {

  test('returns string unmodified if it is already kebabed', function () {

    let result = kebab('ABC');

    expect(result).toBe('ABC');

  });


  test('returns string with leading whitespace removed', function () {

    let result = kebab(' ABC');

    expect(result).toBe('ABC');

  });


  test('returns string with trailing whitespace removed', function () {

    let result = kebab('ABC ');

    expect(result).toBe('ABC');

  });


  test('returns string with all uppercase letters', function () {

    let result = kebab('abc');

    expect(result).toBe('ABC');

  });


  test('returns string with spaces removed', function () {

    let result = kebab(' A B C                ');

    expect(result).toBe('A-B-C');

  });


  test('returns string with tabs removed', function () {

    let result = kebab('tAtBtCt');

    expect(result).toBe('A-B-C');

  });


  test('returns string with tabs and spaces removed', function () {

    let result = kebab(' A Bt C ');

    expect(result).toBe('A-B-C');

  });


  test('returns string with periods removed', function () {

    let result = kebab('A.B..............................C');

    expect(result).toBe('A-B-C');

  });


  test('returns string with periods, tabs, and spaces removed', function () {

    let result = kebab('A. b. . . . . . . ttt  ....t. . . . .   ......c..     ....');

    expect(result).toBe('A-B-C-');

  });

});



Problem02-


const { createImg } = require('./solutions');


describe('Problem 2 - createImg() function', function () {

  test('<img> is correct for given src and alt values', function () {

    let src = 'https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500';

    let alt = 'Cat with ears down';

    let result = createImg(src, alt);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">'

    );

  });


  test('<img> HTML is correct for src and alt values that need to be trimmed', function () {

    let src = '   https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500  ';

    let alt = 'Cat with ears down  ';

    let result = createImg(src, alt);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">'

    );

  });


  test('<img> HTML is correct when valid width Number is included', function () {

    let src = 'https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500';

    let alt = 'Cat with ears down';

    let width = 300;

    let result = createImg(src, alt, width);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down" width="300">'

    );

  });


  test('<img> HTML is correct when valid width string is included', function () {

    let src = 'https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500';

    let alt = 'Cat with ears down';

    let width = '300';

    let result = createImg(src, alt, width);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down" width="300">'

    );

  });


  test('<img> HTML is correct when invalid width is included', function () {

    let src = 'https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500';

    let alt = 'Cat with ears down';

    let width = 'three-hundred';

    let result = createImg(src, alt, width);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">'

    );

  });

});




Problem03-


const { parseDateString } = require('./solutions');


describe('Problem 3 - parseDateString() function', function () {

  // Checks that a date uses the given year, month, day values

  function assertDate(d, year, month, day) {

    return d && d.getFullYear() === year && d.getMonth() === month - 1 && d.getDate() === day;

  }


  test('not passing a date string throws an Error', function () {

    // null

    expect(() => parseDateString(null)).toThrow();

    // undefined

    expect(() => parseDateString()).toThrow();

    // empty string

    expect(() => parseDateString('')).toThrow();

  });


  test('passing an invalid date string format throws an Error', function () {

    // 2-digit year

    expect(() => parseDateString('20-03-12')).toThrow();

    // 1-digit month

    expect(() => parseDateString('2020-3-12')).toThrow();

    // using spaces vs. dashes

    expect(() => parseDateString('2020 03 12')).toThrow();

    // using slashes vs dashes

    expect(() => parseDateString('2020/03/12')).toThrow();

    // string, but not a date string

    expect(() => parseDateString('invalid string')).toThrow();

  });


  test('passing a valid date string results in correct date', function () {

    let result = parseDateString('2021-01-01');

    expect(assertDate(result, 2021, 1, 1)).toBe(true);

  });


  test('passing a valid date string results in correct month and day', function () {

    let result = parseDateString('2021-29-01');

    expect(assertDate(result, 2021, 1, 29)).toBe(true);

  });

});




Problem04-


const { toDateString, parseDateString } = require('./solutions');


// Returns true if two dates have same year, month, day (ignoring time)

function compareDates(a, b) {

  return (

    a.getFullYear() === b.getFullYear() &&

    a.getMonth() === b.getMonth() &&

    a.getDate() === b.getDate()

  );

}


describe('Problem 4 - toDateString() function', function () {

  test('a date is correctly converted to a date string', function () {

    let date = new Date('December 10, 2021');

    let result = toDateString(date);

    expect(result).toBe('2021-10-12');

  });


  test('a date is correctly converted to a date string with expected month and day', function () {

    let date = new Date('December 17, 2021');

    let result = toDateString(date);

    expect(result).toBe('2021-17-12');

  });


  test('a date is correctly converted to a date string, with padded month', function () {

    let date = new Date('January 10, 2021');

    let result = toDateString(date);

    expect(result).toBe('2021-10-01');

  });


  test('a date is correctly converted to a date string, with padded day', function () {

    let date = new Date('December 01, 2021');

    let result = toDateString(date);

    expect(result).toBe('2021-01-12');

  });


  test('toDateString and parseDateString are reversible', function () {

    let date = new Date('December 01, 2021');

    let dateString = '2021-01-12';


    expect(compareDates(parseDateString(toDateString(date)), date)).toBe(true);

    expect(toDateString(parseDateString(dateString))).toBe(dateString);

  });

});





Problem 05-


const { validateCoord } = require('./solutions');


describe('Problem 5 - validateCoord() function', function () {

  test('valid lat, lng coord returns true', function () {

    let lat = 43.7955;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('valid lat at 90 returns true', function () {

    let lat = 90;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('valid lat at -90 returns true', function () {

    let lat = -90;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('invalid lat < -90 returns false', function () {

    let lat = -90.01;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(false);

  });


  test('valid lng at 180 returns false', function () {

    let lat = 43.7955;

    let lng = 180;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('valid lng at -180 returns false', function () {

    let lat = 43.7955;

    let lng = -180;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('invalid lat > 90 returns false', function () {

    let lat = 90.01;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(false);

  });


  test('invalid lng < -180 returns false', function () {

    let lat = 43.7955;

    let lng = -180.00001;

    expect(validateCoord(lat, lng)).toBe(false);

  });


  test('invalid lng > 180 returns false', function () {

    let lat = 43.7955;

    let lng = 180.00001;

    expect(validateCoord(lat, lng)).toBe(false);

  });


  test('invalid lat and lng returns false', function () {

    let lat = 90.00001;

    let lng = 180.00001;

    expect(validateCoord(lat, lng)).toBe(false);

  });

});




Problem06-


const { formatCoord, formatCoords } = require('./solutions');


describe('Problem 6', function () {

  describe('formatCoord() function', function () {

    test('valid lat, lng coord should be formatted correctly', function () {

      let result = formatCoord(43.7955, -79.3496);

      expect(result).toBe('43.7955,-79.3496');

    });


    test('valid lat, lng coord should be formatted correctly with includeBrackets', function () {

      let result = formatCoord(43.7955, -79.3496, true);

      expect(result).toBe('[43.7955,-79.3496]');

    });


    test('invalid lat in coord should throw', function () {

      expect(() => formatCoord(365, -79.3496)).toThrowError();

    });


    test('invalid lng in coord should throw', function () {

      expect(() => formatCoord(43.7955, 366)).toThrowError();

    });

  });


  describe('formatCoords() function', function () {

    test('valid lat, lng coord should be formatted correctly', function () {

      let result = formatCoords(43.7955, -79.3496);

      expect(result).toBe('[[43.7955,-79.3496]]');

    });


    test('multiple valid lat, lng coord should be formatted correctly', function () {

      let result = formatCoords(43.7955, -79.3496, 43.7955, -79.3496, 43.7955, -79.3496);

      expect(result).toBe('[[43.7955,-79.3496], [43.7955,-79.3496], [43.7955,-79.3496]]');

    });


    test('invalid lat coord should throw', function () {

      expect(() => formatCoords(10000, -79.3496)).toThrowError();

    });


    test('invalid lng coord should throw', function () {

      expect(() => formatCoords(43.7955, -1234134134)).toThrowError();

    });


    test('invalid number of lat, lng pairs should throw', function () {

      expect(() => formatCoords(43.7955, -79.3496, 43.7955)).toThrowError();

    });

  });

});


 


Problem07-


const { mimeFromFilename } = require('./solutions');


describe('Problem 7 - mimeFromFilename() function', function () {

  test('correct mime type for HTML extensions', function () {

    expect(mimeFromFilename('index.html')).toEqual('text/html');

    expect(mimeFromFilename('index.htm')).toEqual('text/html');

  });


  test('correct mime type for CSS extension', function () {

    expect(mimeFromFilename('styles.css')).toEqual('text/css');

  });


  test('correct mime type for JS extension', function () {

    expect(mimeFromFilename('index.js')).toEqual('text/javascript');

  });


  test('correct mime type for JPEG extensions', function () {

    expect(mimeFromFilename('photo.jpg')).toEqual('image/jpeg');

    expect(mimeFromFilename('photo.jpeg')).toEqual('image/jpeg');

  });


  test('correct mime type for GIF extension', function () {

    expect(mimeFromFilename('animation.gif')).toEqual('image/gif');

  });


  test('correct mime type for BMP extension', function () {

    expect(mimeFromFilename('graphic.bmp')).toEqual('image/bmp');

  });


  test('correct mime type for Icon extensions', function () {

    expect(mimeFromFilename('favicon.ico')).toEqual('image/x-icon');

    expect(mimeFromFilename('cursor.cur')).toEqual('image/x-icon');

  });


  test('correct mime type for PNG extension', function () {

    expect(mimeFromFilename('photo.png')).toEqual('image/png');

  });


  test('correct mime type for SVG extension', function () {

    expect(mimeFromFilename('chart.svg')).toEqual('image/svg+xml');

  });


  test('correct mime type for WEBP extension', function () {

    expect(mimeFromFilename('photo.webp')).toEqual('image/webp');

  });


  test('correct mime type for MP3 extension', function () {

    expect(mimeFromFilename('music.mp3')).toEqual('audio/mp3');

  });


  test('correct mime type for WAV extension', function () {

    expect(mimeFromFilename('sound.wav')).toEqual('audio/wav');

  });


  test('correct mime type for MP4 extension', function () {

    expect(mimeFromFilename('video.mp4')).toEqual('video/mp4');

  });


  test('correct mime type for WEBM extension', function () {

    expect(mimeFromFilename('video.webm')).toEqual('video/webm');

  });


  test('correct mime type for JSON extension', function () {

    expect(mimeFromFilename('data.json')).toEqual('application/json');

  });


  test('correct mime type for unknown extensions', function () {

    expect(mimeFromFilename('file.exe')).toEqual('application/octet-stream');

    expect(mimeFromFilename('library.dll')).toEqual('application/octet-stream');

    expect(mimeFromFilename('file.xht')).toEqual('application/octet-stream');

    expect(mimeFromFilename('file.m')).toEqual('application/octet-stream');

  });


  test('absolute Unix file paths give correct mime type', function () {

    expect(mimeFromFilename('/public/site/www/index.html')).toEqual('text/html');

  });


  test('absolute Windows file paths give correct mime type', function () {

    expect(mimeFromFilename('C:\Documents\Seneca\WEB222\index.html')).toEqual('text/html');

  });


  test('spaces in path give correct mime type', function () {

    expect(mimeFromFilename('/this path/has quite a/few spaces/index.html')).toEqual('text/html');

  });


  test('periods in path give correct mime type', function () {

    expect(mimeFromFilename('/this.path/has.quite.a/few.periods/index.html')).toEqual('text/html');

  });


  test('filename with no extension should give correct mime type', function () {

    expect(mimeFromFilename('/this/file/has/no/extension')).toEqual('application/octet-stream');

  });

});




Problem 08-


const { generateLicenseLink } = require('./solutions');


describe('Problem 8 - generateLicenseLink() function', function () {

  test('CC-BY license code produces correct link', function () {

    let licenseCode = 'CC-BY';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution License</a>'

    );

  });


  test('CC-BY-NC license code produces correct link', function () {

    let licenseCode = 'CC-BY-NC';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-nc/4.0/">Creative Commons Attribution-NonCommercial License</a>'

    );

  });


  test('CC-BY-SA license code produces correct link', function () {

    let licenseCode = 'CC-BY-SA';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike License</a>'

    );

  });


  test('CC-BY-ND license code produces correct link', function () {

    let licenseCode = 'CC-BY-ND';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-nd/4.0/">Creative Commons Attribution-NoDerivs License</a>'

    );

  });


  test('CC-BY-NC-SA license code produces correct link', function () {

    let licenseCode = 'CC-BY-NC-SA';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike License</a>'

    );

  });


  test('CC-BY-NC-ND license code produces correct link', function () {

    let licenseCode = 'CC-BY-NC-ND';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-nc-nd/4.0/">Creative Commons Attribution-NonCommercial-NoDerivs License</a>'

    );

  });


  test('Unknown license codes produces correct link', function () {

    expect(generateLicenseLink(null)).toBe(

      '<a href="https://choosealicense.com/no-permission/">All Rights Reserved</a>'

    );


    expect(generateLicenseLink()).toBe(

      '<a href="https://choosealicense.com/no-permission/">All Rights Reserved</a>'

    );


    expect(generateLicenseLink('copyright')).toBe(

      '<a href="https://choosealicense.com/no-permission/">All Rights Reserved</a>'

    );


    expect(generateLicenseLink('Unknown')).toBe(

      '<a href="https://choosealicense.com/no-permission/">All Rights Reserved</a>'

    );

  });

});




Problem 09-


const { pureBool, all, none } = require('./solutions');


describe('Problem 9 - pureBool(), all(), none() functions', function () {

  describe('pureBool()', function () {

    test('pure boolean values work as expected', function () {

      expect(pureBool(true)).toBe(true);

      expect(pureBool(false)).toBe(false);

    });


    test('various forms of Yes should return true', function () {

      expect(pureBool('Yes')).toBe(true);

      expect(pureBool('yes')).toBe(true);

      expect(pureBool('YES')).toBe(true);

      expect(pureBool('YeS')).toBe(true);

      expect(pureBool('YEs')).toBe(true);

      expect(pureBool('Y')).toBe(true);

      expect(pureBool('y')).toBe(true);

    });


    test('various forms of No should return false', function () {

      expect(pureBool('No')).toBe(false);

      expect(pureBool('no')).toBe(false);

      expect(pureBool('nO')).toBe(false);

      expect(pureBool('n')).toBe(false);

      expect(pureBool('N')).toBe(false);

    });


    test('various forms of True should return true', function () {

      expect(pureBool('True')).toBe(true);

      expect(pureBool('true')).toBe(true);

      expect(pureBool('TRUE')).toBe(true);

      expect(pureBool('TruE')).toBe(true);

      expect(pureBool('TRuE')).toBe(true);

      expect(pureBool('TRue')).toBe(true);

      expect(pureBool('trUE')).toBe(true);

      expect(pureBool('truE')).toBe(true);

      expect(pureBool('t')).toBe(true);

      expect(pureBool('T')).toBe(true);

    });


    test('various forms of False should return false', function () {

      expect(pureBool('False')).toBe(false);

      expect(pureBool('false')).toBe(false);

      expect(pureBool('FALSE')).toBe(false);

      expect(pureBool('FALSe')).toBe(false);

      expect(pureBool('FALSe')).toBe(false);

      expect(pureBool('FALse')).toBe(false);

      expect(pureBool('FAlse')).toBe(false);

      expect(pureBool('falsE')).toBe(false);

      expect(pureBool('falSE')).toBe(false);

      expect(pureBool('faLSE')).toBe(false);

      expect(pureBool('fALSE')).toBe(false);

      expect(pureBool('f')).toBe(false);

      expect(pureBool('F')).toBe(false);

    });


    test('the number 1 should be true', function () {

      expect(pureBool(1)).toBe(true);

    });

    test('the number -1 should be false', function () {

      expect(pureBool(-1)).toBe(false);

    });


    test('various non-values should be false', function () {

      expect(pureBool(undefined)).toBe(false);

      expect(pureBool()).toBe(false);

      expect(pureBool(null)).toBe(false);

      expect(pureBool(NaN)).toBe(false);

    });

  });


  describe('all()', function () {

    test('lists of normalized true values results in true', function () {

      expect(all('Yes', 'yes', 'YES', 'Y', 't', 'TRUE', true, 'True', 1)).toBe(true);

    });


    test('lists of mostly normalized true values results in false', function () {

      expect(all('Yes', 'yes', 'YES', 'Y', 't', 'TRUE', true, 'True', 1)).toBe(true);

      // Last value switched to false

      expect(all('Yes', 'yes', 'YES', 'Y', 't', 'TRUE', true, 'True', 0)).toBe(false);

    });

  });


  describe('none()', function () {

    test('lists of normalized false values results in true', function () {

      expect(

        none('No', 'no', 'NO', 'N', 'n', 'f', 'FALSE', false, 'False', 0, null, undefined, -1)

      ).toBe(true);

    });


    test('lists of mostly normalized false values results in false', function () {

      expect(

        none('No', 'no', 'NO', 'N', 'n', 'f', 'FALSE', false, 'False', 0, null, undefined, -1)

      ).toBe(true);

      // Last value switched to true

      expect(

        none('No', 'no', 'NO', 'N', 'n', 'f', 'FALSE', false, 'False', 0, null, undefined, 1)

      ).toBe(false);

    });

  });

});




Problem 10-


const { buildUrl } = require('./solutions');


describe('Problem 10 - buildUrl() function', function () {

  function assertUrl(urlString, q, perPage, order, license, lat, lng) {

    let url = new URL(urlString);

    expect(url.origin).toBe('https://api.inaturalist.org');

    expect(url.pathname).toBe('/v1/observations');

    expect(url.searchParams.get('q')).toEqual(q);

    expect(url.searchParams.get('per_page')).toEqual(String(perPage));

    expect(url.searchParams.get('order')).toEqual(order);

    expect(url.searchParams.get('license')).toEqual(license);

    expect(url.searchParams.get('lat')).toEqual(String(lat));

    expect(url.searchParams.get('lng')).toEqual(String(lng));

  }


  test('correct values produce an expected url', function () {

    let url = buildUrl('butterfly', 50, 'asc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 50, 'asc', 'cc-by', 43.7955, -79.3496);

  });


  test('q values are properly encoded on url', function () {

    let url = buildUrl(

      'butterfly with special characters:/\{}<>[]}`"',

      50,

      'asc',

      'cc-by',

      43.7955,

      -79.3496

    );

    expect(typeof url).toEqual('string');

    assertUrl(

      url,

      'butterfly with special characters:/\{}<>[]}`"',

      50,

      'asc',

      'cc-by',

      43.7955,

      -79.3496

    );

  });


  test('perPage below 1 throws but 1 works', function () {

    expect(() => buildUrl('butterfly', 0, 'asc', 'cc-by', 43.7955, -79.3496)).toThrowError();


    let url = buildUrl('butterfly', 1, 'asc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 1, 'asc', 'cc-by', 43.7955, -79.3496);

  });


  test('perPage above 200 throws but 200 works', function () {

    expect(() => buildUrl('butterfly', 201, 'asc', 'cc-by', 43.7955, -79.3496)).toThrowError();


    let url = buildUrl('butterfly', 200, 'asc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 200, 'asc', 'cc-by', 43.7955, -79.3496);

  });


  test('order can be asc', function () {

    let url = buildUrl('butterfly', 200, 'asc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 200, 'asc', 'cc-by', 43.7955, -79.3496);

  });


  test('order can be desc', function () {

    let url = buildUrl('butterfly', 200, 'desc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 200, 'desc', 'cc-by', 43.7955, -79.3496);

  });


  test('order other than asc/desc throws', function () {

    expect(() => buildUrl('butterfly', 200, '', 'cc-by', 43.7955, -79.3496)).toThrowError();

  });


  test('license must be one of the expected values', function () {

    [

      'none',

      'any',

      'cc-by',

      'cc-by-nc',

      'cc-by-sa',

      'cc-by-nd',

      'cc-by-nc-sa',

      'cc-by-nc-nd'

    ].forEach((license) => {

      let url = buildUrl('butterfly', 200, 'desc', license, 43.7955, -79.3496);

      expect(typeof url).toEqual('string');

      assertUrl(url, 'butterfly', 200, 'desc', license, 43.7955, -79.3496);

    });

  });


  test('license other than the expected values will throw', function () {

    expect(() => buildUrl('butterfly', 200, 'asc', '', 43.7955, -79.3496)).toThrowError();

  });


  test('invalid lat will throw', function () {

    expect(() => buildUrl('butterfly', 200, 'asc', '', -90.01, -79.3496)).toThrowError();

    expect(() => buildUrl('butterfly', 200, 'asc', '', 90.01, -79.3496)).toThrowError();

  });


  test('invalid lng will throw', function () {

    expect(() => buildUrl('butterfly', 200, 'asc', '', 43.7955, -180.01)).toThrowError();

    expect(() => buildUrl('butterfly', 200, 'asc', '', 43.7955, 180.01)).toThrowError();

  });

});


/**

 * WEB222 - Assignment 1

 *

 * I declare that this assignment is my own work in accordance with

 * Seneca Academic Policy. No part of this assignment has been copied

 * manually or electronically from any other source (including web sites)

 * or distributed to other students.

 *

 * Please update the following with your information:

 *

 *      Name: rishabh bhola

 *      Student ID: 148149198

 *      Date: <SUBMISSION_DATE>

 *

 * Please see all unit tests in the files problem-00.test.js, problem-01.test.js, etc.

 */


/*******************************************************************************

 * Problem 0: learn how to implement code to pass unit tests.

 *

 * Welcome to Assignment 1! In this assignment, you're going to be practicing lots

 * of new JavaScript programming techniques.  Before you dive in let's spend a

 * minute helping you learn how to read this code, and how to understand the

 * tests that go with it.

 *

 * In addition to this file, please also open the src/problem-00.test.js file.

 * Start by reading the comment at the top of that file, then come back here and

 * continue.

 *

 * Make sure you have completed the necessary Setup (install node.js, run `npm install`

 * before continuing).  The rest of the instructions assume that you have done this.

 *

 * After you finish reading src/problem-00.test.js, it's time to try running

 * the tests.  To run the tests, go to your terminal and type the following command:

 *

 *   npm test

 *

 * You have to run this command in the root of your project (i.e., in the same

 * directory as src/ and package.json).  When you do, you will see a lot of failures.

 * That's expected, since we haven't written any solution code yet.

 *

 * You can also run tests for only this problem instead of everything.  To do that:

 *

 *   npm test problem-00

 *

 * This will look for tests that are part of the problem-00.test.js file, and only

 * run those.  Doing so should result in 1 failed and 1 passed test.

 *

 * The first test passes:

 *

 *  ✓ greeting should be a function (2ms)

 *

 * But the second one failed:

 *

 * ✕ greeting should  return the correct string output (3ms)

 *

 * ● Problem 0 - greeting() function › greeting should  return the correct string output

 *

 *   expect(received).toBe(expected) // Object.is equality

 *

 *   Expected: "Hello WEB222 Student!"

 *   Received: "Hello WEB222 Student"

 *

 *     63 |   test('greeting should return the correct string output', function() {

 *     64 |     let result = greeting('WEB222 Student');

 *   > 65 |     expect(result).toBe('Hello WEB222 Student!');

 *        |                    ^

 *     66 |   });

 *     67 |

 *     68 |   /**

 *

 * We can see that the test 'greeting should say "Hello Name!"' is failing.

 * It's failing on line 65 of src/problem-00.test.js.  In particular, it's failing

 * because it expected to get the String "Hello WEB222 Student!" but instead

 * it actually received the String "Hello WEB222 Student".

 *

 * It looks like we have a small typo in our code below, and we are missing

 * the final "!"" character.  Try adding it below, save this file, and re-run the

 * tests again:

 *

 * npm test problem-00

 * PASS  src/problem-00.test.js

 *  Problem 0 - greeting() function

 *   ✓ greeting should be a function (2ms)

 *   ✓ greeting should return the correct string output

 *

 * Test Suites: 1 passed, 1 total

 * Tests:       2 passed, 2 total

 *

 * Excellent! At this point you're ready to move on to Problem 1. As you do,

 * read both the information in the Problem's comment, and also read the tests

 * to understand what they expect from your code's implementation.

 *

 * One final word about these comments.  You'll see comments like this one:

 *

 * @p..;@returns {string}

 *

 * These are specially formatted comments that define parameters to functions,

 * and tell us the type {string} or {number}, and also the parameter's name.

 * We also indicate the return type for functions.

 *

 * Finally, we also explain a bit about how the parameter is used, and what

 * data it will have, whether it's optional, etc.

 ******************************************************************************/


function greeting(name) {

  return `Hello ${name}!`;

}


/*******************************************************************************

 * Problem 1: replace all internal whitespace in a string value with dashes ('-'),

 * and make it UPPERCASE.

 *

 * We want to be able to convert a string to Upper Kebab Case style, so that it

 * contains no spaces, tabs, or dots, and all letters are upper case.

 *

 * The kebab() function should work like this:

 *

 * kebab('ABC') --> returns 'ABC' (all Upper Case, the string is unchanged)

 * kebab(' ABC ') --> returns 'ABC' (all Upper Case, leading/trailing whitespace removed)

 * kebab('abc') --> returns 'ABC' (the string was converted to upper case)

 * kebab('A BC') --> returns 'A-BC' (uppercase, single space replaced with -)

 * kebab('A BC') --> returns 'A-BC' (uppercase, single space replaced with -)

 * kebab('A   BC') --> returns 'A-BC' (uppercase, multiple spaces replaced with -)

 * kebab('A.BC') --> returns 'A-BC' (uppercase, period replaced with -)

 * kebab('A..  BC') --> returns 'A-BC' (uppercase, periods/spaces replaced with -)

 *

 * @p..;@return {string}

 ******************************************************************************/


function kebab(value) {

 

  return `${value}`;+

}


/*******************************************************************************

 * Problem 2: create an HTML <img> element for the given url and alt text.

 *

 * In HTML, we use markup syntax to indicate how browsers should format elements

 * of a web page.  For example, here is a URL to a cat picture:

 *

 * https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500

 *

 * Try navigating to it in your browser.  In order for a web page to know how to

 * interpret this URL (e.g., should we show the text of the URL itself, or use

 * it to load an image?), we have to use special markup.  The <img> element

 * is how we specify that a URL is to be interpreted as an image, see:

 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img

 *

 * Here is how we might use HTML to markup this image:

 *

 * <img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">

 *

 * Our <img> has two attributes:

 *

 * - src: the URL to use when downloading this image's data

 * - alt: the alternative text to display in non-visual browsing environments (e.g., screen readers)

 *

 * Write the createImg() function to accept a URL and alt text, and return the

 * properly formatted img element.  For example:

 *

 * createImg('https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500', 'Cat with ears down')

 *

 * should return the following string of HTML:

 *

 * '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">'

 *

 * An <img> can also optionally contain a width attribute, for example:

 *

 * <img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down" width="300">

 *

 * In this case, the <img> element should use 300 pixels for its width.  Therefore,

 * your createImg() function should also accept a third argument, width:

 *

 * // No width given

 * createImg('https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500', 'Cat with ears down')

 * // Width of 300 given

 * createImg('https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500', 'Cat with ears down', 300)

 *

 * The returned <img> HTML string should be formatted as follows:

 *

 * - Remove leading/trailing whitespace from src and alt values before you use them

 * - The src and alt attribute values should be wrapped in double-quotes (e.g., src="...")

 * - There should be a single space between the end of one attribute and start of the next (e.g., src="..." alt="...")

 * - The width attribute should only be added if a valid integer value (number or string) is passed

 *   for the third argument.  Otherwise ignore it.

 *

 * @param {string} src - the src URL for the img

 * @p..;@param {string|number} width - (optional) the width of the img. Must be a valid integer

 * @returns {string}

 ******************************************************************************/


function createImg(src, alt, width) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 3: extract Date from date string

 *

 * A date string is expected to be formatted as follows:

 *

 * YYYY-DD-MM

 *

 * Meaning, Year (4 digits), Day (2 digits), Month (2 digits).

 *

 * January 1, 2021 would therefore be the following date string:

 *

 * 2021-01-01

 *

 * Similarly, September 29, 2021 would be:

 *

 * 2021-29-09

 *

 * Write a function, parseDateString() that accepts a date string of the format

 * specified above, and returns a Date object, set to the correct day.

 *

 * To help developers using your function, you are asked to provide detailed error

 * messages when the date string is formatted incorrectly.  We will use the throw

 * statement to throw an error when a particular value is not what we expect, see:

 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw

 *

 * For example: parseDateString('01-01-01') should fail, because the year is

 * not 4 digits.  Similarly, parseDateString('2021-1-01') should fail because

 * the day is not 2 digits, and parseDateString('2021-01-1') should fail because

 * the month is not 2 digits.  Also, a totally invalid date string should also

 * cause an exception to be thrown, for example parseDateString(null) or

 * parseDateString("this is totally wrong").

 *

 * @p..;@returns {Date}

 ******************************************************************************/


function parseDateString(value) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 4: convert Date to date string with specified format.

 *

 * As above, a date string is expected to be formatted as follows:

 *

 * YYYY-DD-MM

 *

 * Meaning, Year (4 digits), Day (2 digits), Month (2 digits).

 *

 * Write a function, toDateString() that accepts a Date object, and returns a

 * date string formatted according to the specification above. Make sure your

 * day and month values are padded with a leading '0' if necessary (e.g., 03 vs. 3).

 *

 * NOTE: it should be possible to use parseDateString() from the previous question

 * and toDateString() to reverse each other. For example:

 *

 * toDateString(parseDateString('2021-29-01)) should return '2021-29-01'

 *

 * @p..;@returns {string}

 ******************************************************************************/


function toDateString(value) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 5: validate a coordinate

 *

 * Coordinates are defined as numeric, decimal values of Latitude and Longitude.

 * A example, the Seneca College Newnham campus is located at:

 *

 * Latitude: 43.7955 (positive number means North)

 * Longitude: -79.3496 (negative number means West)

 *

 * Write a function, validateCoord(), which accepts a latitude and longitude,

 * and returns true if they are both valid, or false if one or both are invalid.

 *

 * Valid Latitude values are decimal numbers between -90 and 90.

 *

 * Valid Longitude values are decimal numbers between -180 and 180.

 *

 * @param {number} lat - the latitude

 * @p..;@returns {boolean}

 ******************************************************************************/


function validateCoord(lat, lng) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 6, Part 1: format a coordinate as a string

 *

 * As above, coordinates are defined as numeric, decimal values of Latitude and Longitude.

 *

 * Write a function, formatCoord(), which accepts a latitude and longitude,

 * and returns a string formatted as follows:

 *

 * (lat, lng)

 *

 * For example:

 *

 * formatCoord(43.7955, -79.3496) should return the string '43.7955,-79.3496'.

 *

 * An optional third param, includeBrackets, determines whether or not to include

 * parenthesis around the formatted coordinate:

 *

 * formatCoord(43.7955, -79.3496) should return the string '43.7955,-79.3496'.

 * formatCoord(43.7955, -79.3496, true) should return the string '[43.7955,-79.3496]'.

 *

 * Use your validateCoord() function from Problem 5 to determine if the coordinate

 * is valid before you attempt to format it.  If the coordinate is not valid, throw

 * an exception.

 *

 * @param {number} lat - the latitude

 * @param {number} lng - the longitude

 * @p..;@returns {string}

 ******************************************************************************/


function formatCoord(lat, lng, includeBrackets) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 6, Part 2: format any number of coordinates as a string

 *

 * Similar to Problem 6 Part 1, you are asked to format lat, lng coordinates

 * into a string. However, where formatCoord() formats a single lat, lng pair,

 * the formatCoords() function (note the `s` suffix) is able to format any

 * number of lag, lng pairs.

 *

 * For example:

 *

 * formatCoords(43.7955, -79.3496) should return '[[43.7955,-79.3496]]'

 * formatCoords(43.7955, -79.3496, 43.7953, -79.3491) should return '[[43.7955,-79.3496], [43.7953,-79.3491]]'

 *

 * In your solution for formatCoords, use the formatCoord function you wrote above.

 *

 * The formatCoords() function can take any number of arguments, but they must all be numbers,

 * there must be an even number of them, and all lat, lng pairs should be valid.

 *

 * If any of these conditions are not met, throw an exception.

 *

 * @p..;@returns {string}

 ******************************************************************************/


function formatCoords(...values) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 7: determine MIME type from filename extension

 *

 * Web browsers and servers exchange streams of bytes, which must be interpreted

 * by the receiver based on their type.  For example, an HTML web page is

 * plain text, while a JPG image is a binary sequence.

 *

 * The Content-Type header contains information about a resource's MIME type, see:

 * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type

 *

 * The MIME type is made-up of a `type` and a `subtype` separated by a `/` character.

 * The type is general, for example, 'text' or 'video'.  The subtype is more

 * specific, indicating the specific type of text, image, video, etc.  See:

 * https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types

 *

 * A number of common types are used in web development:

 *

 * mimeFromFilename('/User/Documents/readme.txt') --> returns 'text/plain'

 *

 * Your mimeFromFilename() function should support all of the following extensions

 * with and without the leading '.':

 *

 * - .html, .htm --> text/html

 * - .css --> text/css

 * - .js --> text/javascript

 * - .jpg, .jpeg --> image/jpeg

 * - .gif --> image/gif

 * - .bmp --> image/bmp

 * - .ico, .cur --> image/x-icon

 * - .png --> image/png

 * - .svg --> image/svg+xml

 * - .webp --> image/webp

 * - .mp3 --> audio/mp3

 * - .wav --> audio/wav

 * - .mp4 --> video/mp4

 * - .webm --> video/webm

 * - .json --> application/json

 *

 * NOTE: any other extension should use the `application/octet-stream` MIME type,

 * to indicate that it is an unknown stream of bytes (e.g., binary file). You should

 * also use `application/octet-stream` if the file has no extension.

 *

 * @p..;@returns {string}

 ******************************************************************************/


function mimeFromFilename(filename) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 8, Part 1: generate license text and link from license code.

 *

 * Images, videos, and other resources on the web are governed by copyright.

 * Everything you find on the web is copyright to its creator automatically, and

 * you cannot reuse it unless you are granted a license to do so.

 *

 * Different licenses exist to allow creators to share their work. For example,

 * the Creative Commons licenses are a popular way to allow people to reuse

 * copyright material, see https://creativecommons.org/licenses/.

 *

 * Below is a list of license codes, and the associated license text explaining the code:

 *

 * CC-BY: Creative Commons Attribution License

 * CC-BY-NC: Creative Commons Attribution-NonCommercial License

 * CC-BY-SA: Creative Commons Attribution-ShareAlike License

 * CC-BY-ND: Creative Commons Attribution-NoDerivs License

 * CC-BY-NC-SA: Creative Commons Attribution-NonCommercial-ShareAlike License

 * CC-BY-NC-ND: Creative Commons Attribution-NonCommercial-NoDerivs License

 *

 * NOTE: any other licenseCode should use the URL https://choosealicense.com/no-permission/

 * and the explanation text, "All Rights Reserved"

 *

 * Write a function, generateLicenseLink(), which takes a license code, and returns

 * an HTML link to the appropriate license URL, and including the explanation text.

 *

 * For example:

 *

 * generateLicenseLink('CC-BY-NC') should return the following HTML string:

 *

 * '<a href="https://creativecommons.org/licenses/by-nc/4.0/">Creative Commons Attribution-NonCommercial License</a>'

 *

 * The URL is generated based on the license code:

 *

 * - remove the `CC-` prefix

 * - convert to lower case

 * - place formatted license code within URL https://creativecommons.org/licenses/[...here]/4.0/

 *

 * You can read more about HTML links at https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a

 *

 * @p..;@returns {string}

 ******************************************************************************/


function generateLicenseLink(licenseCode) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 9 Part 1: create a pure Boolean true/false value from a dataset

 *

 * A dataset contains fields that indicate a value is true or false.  However,

 * users have entered data in various formats over the years, for example:

 *

 * Yes, yes, YES, Y, t, TRUE, true, True, 1

 * No, no, NO, N, n, f, FALSE, false, False, 0, null, undefined, -1

 *

 * Write a function pureBool() which takes a String, Number, Boolean,

 * null, or undefined and attempts to convert it into a pure Boolean value.

 *

 * If the value is not one of the values above, throw an error with the error

 * message, 'invalid boolean value'.

 *

 * @p..;@returns {bool}

 ******************************************************************************/


function pureBool(value) {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 9 Part 2: checking for all True or all False values in a normalized list

 *

 * Using your normalizeBoolean() function, create two new functions to check

 * if a list of arguments are all normalized True or normalized False values:

 *

 * all('Y', 'yes', 1) --> returns true

 * some('Y', 'no', 1) --> returns true

 * none('Y', 'invalid', 1) --> returns false

 *

 * allFalse('N', 'no', 0) --> returns true

 * allFalse('N', 'no', 0) --> returns false

 * allFalse('Y', 'invalid', 1) --> returns false (i.e., does not throw)

 *

 * Use try/catch syntax to avoid having allTrue() and allFalse() throw errors

 * when normalizeBoolean() throws on invalid data.

 ******************************************************************************/


function all() {

  // Replace this comment with your code...

}


function none() {

  // Replace this comment with your code...

}


/*******************************************************************************

 * Problem 10 - build a URL to query the iNaturalist Web API

 *

 * One of the data sources we'll be exploring in future assignments is

 * https://www.inaturalist.org.  Using iNaturalist, both hobbyist and professional

 * scientists can share sightings and help identify plants and animals in their

 * local area.

 *

 * As a web developer, you have access to this tremendous database of scientific

 * observations via the iNaturalist Web API (application programming interface):

 *

 * https://www.inaturalist.org/pages/api+reference#get-observations

 *

 * Querying the iNaturalist dataset for information involves formatting a URL

 * in a particular way.  As we know from week 1, a URL can contain optional

 * name=value pairs, see: https://web222.ca/weeks/week01/#urls

 *

 * For example:

 *

 *   https://www.store.com/search?q=dog includes q=dog

 *

 *   https://www.store.com?_encoding=UTF8&node=18521080011 includes

 *   both _encoding=UTF8 and also node=18521080011, separated by &

 *

 * We will write a buildUrl() function to build a URL for the iNaturalist API

 * based on arguments passed by the caller.

 *

 * The buildUrl() function accepts the following arguments:

 *

 * - q: a search string, for example "butterfly" or "Horse-chestnut"

 * - per_page: a number from 1 to 200, indicating how many results to return per page

 * - order: a string indicating sort order, with possible values of `asc` or `desc`

 * - license: a string indicating which items to return (e.g., which license they use). Possible

 *   values include: none, any, cc-by, cc-by-nc, cc-by-sa, cc-by-nd, cc-by-nc-sa, cc-by-nc-nd

 * - lat: a number, indicating the latitude to use for results

 * - lng: a number, indicating the longitude to use for results.

 *

 * Write an implementation of buildUrl() that accepts arguments for all of the above

 * parameters, validates them (e.g., perPage must be between 1 and 200, lat and lng

 * must be a valid coord, etc), and returns a properly formatted URL.

 *

 * For example:

 *

 * buildUrl('butterfly', 50, 'asc', 'cc-by', 43.7955, -79.3496) should return

 * the following URL:

 *

 * https://api.inaturalist.org/v1/observations?q=butterfly&per_page=50&order=asc&license=cc-by&lat=43.7955&lng=-79.3496

 *

 * NOTE: if any of the values passed to buildUrl() are invalid, an exception should be thrown.

 *

 * NOTE: make sure you properly encode the q value, since URLs can't

 * contain spaces or certain other characters. HINT: use the encodeURIComponent()

 * function to do this, see:

 *

 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

 *

 * @param {string} q the query to use. Must be properly URI encoded

 * @param {number} perPage the number of results per page, must be 1-200

 * @param {string} order the sort order to use, must be one of asc or desc

 * @param {string} license the license to use, must be one of none, any, cc-by, cc-by-nc, cc-by-sa, cc-by-nd, cc-by-nc-sa, cc-by-nc-nd

 * @param {number} lat the latitude to use, must be a valid latitude (use validateCoord() function)

 * @p..;@returns {string} the properly formatted iNaturalist URL

 ******************************************************************************/


function buildUrl(q, perPage, order, license, lat, lng) {

  // Replace this comment with your code...

}


// Our unit test files need to access the functions we defined

// above, so we export them here.

exports.greeting = greeting;

exports.kebab = kebab;

exports.createImg = createImg;

exports.parseDateString = parseDateString;

exports.toDateString = toDateString;

exports.validateCoord = validateCoord;

exports.formatCoord = formatCoord;

exports.formatCoords = formatCoords;

exports.mimeFromFilename = mimeFromFilename;

exports.generateLicenseLink = generateLicenseLink;

exports.pureBool = pureBool;

exports.all = all;

exports.none = none;

exports.buildUrl = buildUrl;




problem00-

/**

 * Welcome to the Problem 0 Unit Tests! The problem test files are code that

 * has already been written for you, you don't need to do anything

 * in them except read what's here.  They include tests for the assignment's

 * functions, and will help you know if your coding is working or not.

 *

 * A Unit Test is a piece of code that tests a "unit" of code, for example, a

 * function. We call them Unit Tests, because we try to have our tests test the

 * smallest possible unit of code that we can.

 *

 * These tests have been written using a Testing Framework called Jest.

 * Jest was created by Facebook, and helps developers write code with

 * fewer bugs. You can read more about it at https://jestjs.io/

 *

 * Each of the problems that you need to solve in src/solutions.js

 * has an associated file with unit tests, Problem 1's tests are in

 * the file problem-01.test.js, and so on. These tests define the

 * expected behaviour of your code.  If you write your tests correctly,

 * all the tests should PASS.  If you make a mistake, one or more of them

 * will FAIL.

 *

 * Your goal is get all of the tests in this assignment to PASS.

 * It's like a video game, except instead of using a gamepad, you'll be writing

 * JavaScript!

 *

 * Some of what these tests do is more complex than what you know how to

 * do yourself at this point.  Don't worry about that.  Remember, you don't

 * have to write the tests, only get your code to pass.

 *

 * To help you, we'll document and explain everything in this file as we go.

 * This first line is getting the `greeting` function from the file solutions.js.

 * Don't worry about this for the moment, but if you're curious, you can read more

 * at https://nodejs.org/en/knowledge/getting-started/what-is-require/

 */

const { greeting } = require('./solutions');


/**

 * Next, we use one of Jest's functions called describe().  It allows

 * us to describe our tests for a particular feature, and give them a name.

 * Doing so makes it a bit easier to see what's going on when we run our tests.

 * We also define a function() {...} to contain our tests.  When the Problem 0

 * tests are run, this function will be called.

 */

describe('Problem 0 - greeting() function', function () {

  /**

   * Now we come to the individual tests.  We try to keep our tests

   * small, and only test 1 thing at a time.  This makes it easier to implement

   * our code and slowly make progress.  You can write a bit of the functionality,

   * and get some of the tests to pass.  As you add more, and deal with new cases,

   * more of the tests should pass.  You also want to avoid having passing tests

   * suddenly start failing--meaning you've introduced a bug.

   *

   * Our first test makes sure that the variable named `greeting` is really

   * a function.  We're using Jest's expect() function, which let's us

   * compare an actual value (something returned by running our code) to an

   * expected value (something we define in advance in our test).  You don't need

   * to spend too much time on this, but if you're interested, you can read more

   * about expect() at https://jestjs.io/docs/en/expect.

   */

  test('greeting should be a function', function () {

    // This is like saying: if(typeof greeting === 'function')

    expect(typeof greeting).toBe('function');

  });


  /**

   * Our final test for greeting() checks to make sure that if you pass in

   * a name (i.e., a String), that it returns a new String formatted in the right way.

   */

  test('greeting should return the correct string output', function () {

    let result = greeting('WEB222 Student');

    expect(result).toBe('Hello WEB222 Student!');

  });


  /**

   * OK, now you're ready to go back to src/solutions.js and continue solving

   * Problem 1.

   */

});



Problem 01-


const { kebab } = require('./solutions');


describe('Problem 1 - kebab() function', function () {

  test('returns string unmodified if it is already kebabed', function () {

    let result = kebab('ABC');

    expect(result).toBe('ABC');

  });


  test('returns string with leading whitespace removed', function () {

    let result = kebab(' ABC');

    expect(result).toBe('ABC');

  });


  test('returns string with trailing whitespace removed', function () {

    let result = kebab('ABC ');

    expect(result).toBe('ABC');

  });


  test('returns string with all uppercase letters', function () {

    let result = kebab('abc');

    expect(result).toBe('ABC');

  });


  test('returns string with spaces removed', function () {

    let result = kebab(' A B C                ');

    expect(result).toBe('A-B-C');

  });


  test('returns string with tabs removed', function () {

    let result = kebab('tAtBtCt');

    expect(result).toBe('A-B-C');

  });


  test('returns string with tabs and spaces removed', function () {

    let result = kebab(' A Bt C ');

    expect(result).toBe('A-B-C');

  });


  test('returns string with periods removed', function () {

    let result = kebab('A.B..............................C');

    expect(result).toBe('A-B-C');

  });


  test('returns string with periods, tabs, and spaces removed', function () {

    let result = kebab('A. b. . . . . . . ttt  ....t. . . . .   ......c..     ....');

    expect(result).toBe('A-B-C-');

  });

});



Problem02-


const { createImg } = require('./solutions');


describe('Problem 2 - createImg() function', function () {

  test('<img> is correct for given src and alt values', function () {

    let src = 'https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500';

    let alt = 'Cat with ears down';

    let result = createImg(src, alt);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">'

    );

  });


  test('<img> HTML is correct for src and alt values that need to be trimmed', function () {

    let src = '   https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500  ';

    let alt = 'Cat with ears down  ';

    let result = createImg(src, alt);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">'

    );

  });


  test('<img> HTML is correct when valid width Number is included', function () {

    let src = 'https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500';

    let alt = 'Cat with ears down';

    let width = 300;

    let result = createImg(src, alt, width);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down" width="300">'

    );

  });


  test('<img> HTML is correct when valid width string is included', function () {

    let src = 'https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500';

    let alt = 'Cat with ears down';

    let width = '300';

    let result = createImg(src, alt, width);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down" width="300">'

    );

  });


  test('<img> HTML is correct when invalid width is included', function () {

    let src = 'https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500';

    let alt = 'Cat with ears down';

    let width = 'three-hundred';

    let result = createImg(src, alt, width);

    expect(result).toBe(

      '<img src="https://images.unsplash.com/photo-1513451713350-dee890297c4a?width=500" alt="Cat with ears down">'

    );

  });

});




Problem03-


const { parseDateString } = require('./solutions');


describe('Problem 3 - parseDateString() function', function () {

  // Checks that a date uses the given year, month, day values

  function assertDate(d, year, month, day) {

    return d && d.getFullYear() === year && d.getMonth() === month - 1 && d.getDate() === day;

  }


  test('not passing a date string throws an Error', function () {

    // null

    expect(() => parseDateString(null)).toThrow();

    // undefined

    expect(() => parseDateString()).toThrow();

    // empty string

    expect(() => parseDateString('')).toThrow();

  });


  test('passing an invalid date string format throws an Error', function () {

    // 2-digit year

    expect(() => parseDateString('20-03-12')).toThrow();

    // 1-digit month

    expect(() => parseDateString('2020-3-12')).toThrow();

    // using spaces vs. dashes

    expect(() => parseDateString('2020 03 12')).toThrow();

    // using slashes vs dashes

    expect(() => parseDateString('2020/03/12')).toThrow();

    // string, but not a date string

    expect(() => parseDateString('invalid string')).toThrow();

  });


  test('passing a valid date string results in correct date', function () {

    let result = parseDateString('2021-01-01');

    expect(assertDate(result, 2021, 1, 1)).toBe(true);

  });


  test('passing a valid date string results in correct month and day', function () {

    let result = parseDateString('2021-29-01');

    expect(assertDate(result, 2021, 1, 29)).toBe(true);

  });

});




Problem04-


const { toDateString, parseDateString } = require('./solutions');


// Returns true if two dates have same year, month, day (ignoring time)

function compareDates(a, b) {

  return (

    a.getFullYear() === b.getFullYear() &&

    a.getMonth() === b.getMonth() &&

    a.getDate() === b.getDate()

  );

}


describe('Problem 4 - toDateString() function', function () {

  test('a date is correctly converted to a date string', function () {

    let date = new Date('December 10, 2021');

    let result = toDateString(date);

    expect(result).toBe('2021-10-12');

  });


  test('a date is correctly converted to a date string with expected month and day', function () {

    let date = new Date('December 17, 2021');

    let result = toDateString(date);

    expect(result).toBe('2021-17-12');

  });


  test('a date is correctly converted to a date string, with padded month', function () {

    let date = new Date('January 10, 2021');

    let result = toDateString(date);

    expect(result).toBe('2021-10-01');

  });


  test('a date is correctly converted to a date string, with padded day', function () {

    let date = new Date('December 01, 2021');

    let result = toDateString(date);

    expect(result).toBe('2021-01-12');

  });


  test('toDateString and parseDateString are reversible', function () {

    let date = new Date('December 01, 2021');

    let dateString = '2021-01-12';


    expect(compareDates(parseDateString(toDateString(date)), date)).toBe(true);

    expect(toDateString(parseDateString(dateString))).toBe(dateString);

  });

});





Problem 05-


const { validateCoord } = require('./solutions');


describe('Problem 5 - validateCoord() function', function () {

  test('valid lat, lng coord returns true', function () {

    let lat = 43.7955;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('valid lat at 90 returns true', function () {

    let lat = 90;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('valid lat at -90 returns true', function () {

    let lat = -90;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('invalid lat < -90 returns false', function () {

    let lat = -90.01;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(false);

  });


  test('valid lng at 180 returns false', function () {

    let lat = 43.7955;

    let lng = 180;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('valid lng at -180 returns false', function () {

    let lat = 43.7955;

    let lng = -180;

    expect(validateCoord(lat, lng)).toBe(true);

  });


  test('invalid lat > 90 returns false', function () {

    let lat = 90.01;

    let lng = -79.3496;

    expect(validateCoord(lat, lng)).toBe(false);

  });


  test('invalid lng < -180 returns false', function () {

    let lat = 43.7955;

    let lng = -180.00001;

    expect(validateCoord(lat, lng)).toBe(false);

  });


  test('invalid lng > 180 returns false', function () {

    let lat = 43.7955;

    let lng = 180.00001;

    expect(validateCoord(lat, lng)).toBe(false);

  });


  test('invalid lat and lng returns false', function () {

    let lat = 90.00001;

    let lng = 180.00001;

    expect(validateCoord(lat, lng)).toBe(false);

  });

});




Problem06-


const { formatCoord, formatCoords } = require('./solutions');


describe('Problem 6', function () {

  describe('formatCoord() function', function () {

    test('valid lat, lng coord should be formatted correctly', function () {

      let result = formatCoord(43.7955, -79.3496);

      expect(result).toBe('43.7955,-79.3496');

    });


    test('valid lat, lng coord should be formatted correctly with includeBrackets', function () {

      let result = formatCoord(43.7955, -79.3496, true);

      expect(result).toBe('[43.7955,-79.3496]');

    });


    test('invalid lat in coord should throw', function () {

      expect(() => formatCoord(365, -79.3496)).toThrowError();

    });


    test('invalid lng in coord should throw', function () {

      expect(() => formatCoord(43.7955, 366)).toThrowError();

    });

  });


  describe('formatCoords() function', function () {

    test('valid lat, lng coord should be formatted correctly', function () {

      let result = formatCoords(43.7955, -79.3496);

      expect(result).toBe('[[43.7955,-79.3496]]');

    });


    test('multiple valid lat, lng coord should be formatted correctly', function () {

      let result = formatCoords(43.7955, -79.3496, 43.7955, -79.3496, 43.7955, -79.3496);

      expect(result).toBe('[[43.7955,-79.3496], [43.7955,-79.3496], [43.7955,-79.3496]]');

    });


    test('invalid lat coord should throw', function () {

      expect(() => formatCoords(10000, -79.3496)).toThrowError();

    });


    test('invalid lng coord should throw', function () {

      expect(() => formatCoords(43.7955, -1234134134)).toThrowError();

    });


    test('invalid number of lat, lng pairs should throw', function () {

      expect(() => formatCoords(43.7955, -79.3496, 43.7955)).toThrowError();

    });

  });

});


 


Problem07-


const { mimeFromFilename } = require('./solutions');


describe('Problem 7 - mimeFromFilename() function', function () {

  test('correct mime type for HTML extensions', function () {

    expect(mimeFromFilename('index.html')).toEqual('text/html');

    expect(mimeFromFilename('index.htm')).toEqual('text/html');

  });


  test('correct mime type for CSS extension', function () {

    expect(mimeFromFilename('styles.css')).toEqual('text/css');

  });


  test('correct mime type for JS extension', function () {

    expect(mimeFromFilename('index.js')).toEqual('text/javascript');

  });


  test('correct mime type for JPEG extensions', function () {

    expect(mimeFromFilename('photo.jpg')).toEqual('image/jpeg');

    expect(mimeFromFilename('photo.jpeg')).toEqual('image/jpeg');

  });


  test('correct mime type for GIF extension', function () {

    expect(mimeFromFilename('animation.gif')).toEqual('image/gif');

  });


  test('correct mime type for BMP extension', function () {

    expect(mimeFromFilename('graphic.bmp')).toEqual('image/bmp');

  });


  test('correct mime type for Icon extensions', function () {

    expect(mimeFromFilename('favicon.ico')).toEqual('image/x-icon');

    expect(mimeFromFilename('cursor.cur')).toEqual('image/x-icon');

  });


  test('correct mime type for PNG extension', function () {

    expect(mimeFromFilename('photo.png')).toEqual('image/png');

  });


  test('correct mime type for SVG extension', function () {

    expect(mimeFromFilename('chart.svg')).toEqual('image/svg+xml');

  });


  test('correct mime type for WEBP extension', function () {

    expect(mimeFromFilename('photo.webp')).toEqual('image/webp');

  });


  test('correct mime type for MP3 extension', function () {

    expect(mimeFromFilename('music.mp3')).toEqual('audio/mp3');

  });


  test('correct mime type for WAV extension', function () {

    expect(mimeFromFilename('sound.wav')).toEqual('audio/wav');

  });


  test('correct mime type for MP4 extension', function () {

    expect(mimeFromFilename('video.mp4')).toEqual('video/mp4');

  });


  test('correct mime type for WEBM extension', function () {

    expect(mimeFromFilename('video.webm')).toEqual('video/webm');

  });


  test('correct mime type for JSON extension', function () {

    expect(mimeFromFilename('data.json')).toEqual('application/json');

  });


  test('correct mime type for unknown extensions', function () {

    expect(mimeFromFilename('file.exe')).toEqual('application/octet-stream');

    expect(mimeFromFilename('library.dll')).toEqual('application/octet-stream');

    expect(mimeFromFilename('file.xht')).toEqual('application/octet-stream');

    expect(mimeFromFilename('file.m')).toEqual('application/octet-stream');

  });


  test('absolute Unix file paths give correct mime type', function () {

    expect(mimeFromFilename('/public/site/www/index.html')).toEqual('text/html');

  });


  test('absolute Windows file paths give correct mime type', function () {

    expect(mimeFromFilename('C:\Documents\Seneca\WEB222\index.html')).toEqual('text/html');

  });


  test('spaces in path give correct mime type', function () {

    expect(mimeFromFilename('/this path/has quite a/few spaces/index.html')).toEqual('text/html');

  });


  test('periods in path give correct mime type', function () {

    expect(mimeFromFilename('/this.path/has.quite.a/few.periods/index.html')).toEqual('text/html');

  });


  test('filename with no extension should give correct mime type', function () {

    expect(mimeFromFilename('/this/file/has/no/extension')).toEqual('application/octet-stream');

  });

});




Problem 08-


const { generateLicenseLink } = require('./solutions');


describe('Problem 8 - generateLicenseLink() function', function () {

  test('CC-BY license code produces correct link', function () {

    let licenseCode = 'CC-BY';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution License</a>'

    );

  });


  test('CC-BY-NC license code produces correct link', function () {

    let licenseCode = 'CC-BY-NC';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-nc/4.0/">Creative Commons Attribution-NonCommercial License</a>'

    );

  });


  test('CC-BY-SA license code produces correct link', function () {

    let licenseCode = 'CC-BY-SA';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike License</a>'

    );

  });


  test('CC-BY-ND license code produces correct link', function () {

    let licenseCode = 'CC-BY-ND';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-nd/4.0/">Creative Commons Attribution-NoDerivs License</a>'

    );

  });


  test('CC-BY-NC-SA license code produces correct link', function () {

    let licenseCode = 'CC-BY-NC-SA';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike License</a>'

    );

  });


  test('CC-BY-NC-ND license code produces correct link', function () {

    let licenseCode = 'CC-BY-NC-ND';

    let result = generateLicenseLink(licenseCode);

    expect(result).toBe(

      '<a href="https://creativecommons.org/licenses/by-nc-nd/4.0/">Creative Commons Attribution-NonCommercial-NoDerivs License</a>'

    );

  });


  test('Unknown license codes produces correct link', function () {

    expect(generateLicenseLink(null)).toBe(

      '<a href="https://choosealicense.com/no-permission/">All Rights Reserved</a>'

    );


    expect(generateLicenseLink()).toBe(

      '<a href="https://choosealicense.com/no-permission/">All Rights Reserved</a>'

    );


    expect(generateLicenseLink('copyright')).toBe(

      '<a href="https://choosealicense.com/no-permission/">All Rights Reserved</a>'

    );


    expect(generateLicenseLink('Unknown')).toBe(

      '<a href="https://choosealicense.com/no-permission/">All Rights Reserved</a>'

    );

  });

});




Problem 09-


const { pureBool, all, none } = require('./solutions');


describe('Problem 9 - pureBool(), all(), none() functions', function () {

  describe('pureBool()', function () {

    test('pure boolean values work as expected', function () {

      expect(pureBool(true)).toBe(true);

      expect(pureBool(false)).toBe(false);

    });


    test('various forms of Yes should return true', function () {

      expect(pureBool('Yes')).toBe(true);

      expect(pureBool('yes')).toBe(true);

      expect(pureBool('YES')).toBe(true);

      expect(pureBool('YeS')).toBe(true);

      expect(pureBool('YEs')).toBe(true);

      expect(pureBool('Y')).toBe(true);

      expect(pureBool('y')).toBe(true);

    });


    test('various forms of No should return false', function () {

      expect(pureBool('No')).toBe(false);

      expect(pureBool('no')).toBe(false);

      expect(pureBool('nO')).toBe(false);

      expect(pureBool('n')).toBe(false);

      expect(pureBool('N')).toBe(false);

    });


    test('various forms of True should return true', function () {

      expect(pureBool('True')).toBe(true);

      expect(pureBool('true')).toBe(true);

      expect(pureBool('TRUE')).toBe(true);

      expect(pureBool('TruE')).toBe(true);

      expect(pureBool('TRuE')).toBe(true);

      expect(pureBool('TRue')).toBe(true);

      expect(pureBool('trUE')).toBe(true);

      expect(pureBool('truE')).toBe(true);

      expect(pureBool('t')).toBe(true);

      expect(pureBool('T')).toBe(true);

    });


    test('various forms of False should return false', function () {

      expect(pureBool('False')).toBe(false);

      expect(pureBool('false')).toBe(false);

      expect(pureBool('FALSE')).toBe(false);

      expect(pureBool('FALSe')).toBe(false);

      expect(pureBool('FALSe')).toBe(false);

      expect(pureBool('FALse')).toBe(false);

      expect(pureBool('FAlse')).toBe(false);

      expect(pureBool('falsE')).toBe(false);

      expect(pureBool('falSE')).toBe(false);

      expect(pureBool('faLSE')).toBe(false);

      expect(pureBool('fALSE')).toBe(false);

      expect(pureBool('f')).toBe(false);

      expect(pureBool('F')).toBe(false);

    });


    test('the number 1 should be true', function () {

      expect(pureBool(1)).toBe(true);

    });

    test('the number -1 should be false', function () {

      expect(pureBool(-1)).toBe(false);

    });


    test('various non-values should be false', function () {

      expect(pureBool(undefined)).toBe(false);

      expect(pureBool()).toBe(false);

      expect(pureBool(null)).toBe(false);

      expect(pureBool(NaN)).toBe(false);

    });

  });


  describe('all()', function () {

    test('lists of normalized true values results in true', function () {

      expect(all('Yes', 'yes', 'YES', 'Y', 't', 'TRUE', true, 'True', 1)).toBe(true);

    });


    test('lists of mostly normalized true values results in false', function () {

      expect(all('Yes', 'yes', 'YES', 'Y', 't', 'TRUE', true, 'True', 1)).toBe(true);

      // Last value switched to false

      expect(all('Yes', 'yes', 'YES', 'Y', 't', 'TRUE', true, 'True', 0)).toBe(false);

    });

  });


  describe('none()', function () {

    test('lists of normalized false values results in true', function () {

      expect(

        none('No', 'no', 'NO', 'N', 'n', 'f', 'FALSE', false, 'False', 0, null, undefined, -1)

      ).toBe(true);

    });


    test('lists of mostly normalized false values results in false', function () {

      expect(

        none('No', 'no', 'NO', 'N', 'n', 'f', 'FALSE', false, 'False', 0, null, undefined, -1)

      ).toBe(true);

      // Last value switched to true

      expect(

        none('No', 'no', 'NO', 'N', 'n', 'f', 'FALSE', false, 'False', 0, null, undefined, 1)

      ).toBe(false);

    });

  });

});




Problem 10-


const { buildUrl } = require('./solutions');


describe('Problem 10 - buildUrl() function', function () {

  function assertUrl(urlString, q, perPage, order, license, lat, lng) {

    let url = new URL(urlString);

    expect(url.origin).toBe('https://api.inaturalist.org');

    expect(url.pathname).toBe('/v1/observations');

    expect(url.searchParams.get('q')).toEqual(q);

    expect(url.searchParams.get('per_page')).toEqual(String(perPage));

    expect(url.searchParams.get('order')).toEqual(order);

    expect(url.searchParams.get('license')).toEqual(license);

    expect(url.searchParams.get('lat')).toEqual(String(lat));

    expect(url.searchParams.get('lng')).toEqual(String(lng));

  }


  test('correct values produce an expected url', function () {

    let url = buildUrl('butterfly', 50, 'asc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 50, 'asc', 'cc-by', 43.7955, -79.3496);

  });


  test('q values are properly encoded on url', function () {

    let url = buildUrl(

      'butterfly with special characters:/\{}<>[]}`"',

      50,

      'asc',

      'cc-by',

      43.7955,

      -79.3496

    );

    expect(typeof url).toEqual('string');

    assertUrl(

      url,

      'butterfly with special characters:/\{}<>[]}`"',

      50,

      'asc',

      'cc-by',

      43.7955,

      -79.3496

    );

  });


  test('perPage below 1 throws but 1 works', function () {

    expect(() => buildUrl('butterfly', 0, 'asc', 'cc-by', 43.7955, -79.3496)).toThrowError();


    let url = buildUrl('butterfly', 1, 'asc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 1, 'asc', 'cc-by', 43.7955, -79.3496);

  });


  test('perPage above 200 throws but 200 works', function () {

    expect(() => buildUrl('butterfly', 201, 'asc', 'cc-by', 43.7955, -79.3496)).toThrowError();


    let url = buildUrl('butterfly', 200, 'asc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 200, 'asc', 'cc-by', 43.7955, -79.3496);

  });


  test('order can be asc', function () {

    let url = buildUrl('butterfly', 200, 'asc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 200, 'asc', 'cc-by', 43.7955, -79.3496);

  });


  test('order can be desc', function () {

    let url = buildUrl('butterfly', 200, 'desc', 'cc-by', 43.7955, -79.3496);

    expect(typeof url).toEqual('string');

    assertUrl(url, 'butterfly', 200, 'desc', 'cc-by', 43.7955, -79.3496);

  });


  test('order other than asc/desc throws', function () {

    expect(() => buildUrl('butterfly', 200, '', 'cc-by', 43.7955, -79.3496)).toThrowError();

  });


  test('license must be one of the expected values', function () {

    [

      'none',

      'any',

      'cc-by',

      'cc-by-nc',

      'cc-by-sa',

      'cc-by-nd',

      'cc-by-nc-sa',

      'cc-by-nc-nd'

    ].forEach((license) => {

      let url = buildUrl('butterfly', 200, 'desc', license, 43.7955, -79.3496);

      expect(typeof url).toEqual('string');

      assertUrl(url, 'butterfly', 200, 'desc', license, 43.7955, -79.3496);

    });

  });


  test('license other than the expected values will throw', function () {

    expect(() => buildUrl('butterfly', 200, 'asc', '', 43.7955, -79.3496)).toThrowError();

  });


  test('invalid lat will throw', function () {

    expect(() => buildUrl('butterfly', 200, 'asc', '', -90.01, -79.3496)).toThrowError();

    expect(() => buildUrl('butterfly', 200, 'asc', '', 90.01, -79.3496)).toThrowError();

  });


  test('invalid lng will throw', function () {

    expect(() => buildUrl('butterfly', 200, 'asc', '', 43.7955, -180.01)).toThrowError();

    expect(() => buildUrl('butterfly', 200, 'asc', '', 43.7955, 180.01)).toThrowError();

  });

});

Answer & Explanation
Verified Solved by verified expert

m ipsum dolor si

gue

ac, dictum vitae odio. Donec aliquet. Lorem ipsum dolor sit amet, consectetur a

gue

gue

consectetur adipiscing elit. Nam lacinia pulvinar tortor nec facilisis. Pellentesque dap


gue

trices ac magna. Fusce dui lectus, congue vel laoreet ac, dictum vitae odio. Donec

Unlock full access to Course Hero

Explore over 16 million step-by-step answers from our library

Subscribe to view answer
Step-by-step explanation

ec aliquet. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam lacinia pulvinar tortor nec facilisis. Pellentesque dapibus efficitur laoreet. Nam risus ante, dapibus a molestie consequat, ultrices ac magna. Fusce dui le

sum dolor sit amet, consectetur adipiscing elit. Nam lacinia pulvinar tortor nec facilisis. Pellen