feat(curriculum): add Cargo Manifest Validator Lab to JavaScript v9 (#66197)

Co-authored-by: LGH831 <luishernandez1@csumb.edu>
Co-authored-by: Ilenia M <nethleen@gmail.com>
This commit is contained in:
Luis
2026-03-18 06:16:53 -07:00
committed by GitHub
parent 6469794530
commit 32f20a1ba9
4 changed files with 882 additions and 0 deletions

View File

@@ -4829,6 +4829,12 @@
"In these lectures, you will learn the fundamentals of JavaScript objects, including how to create them, access their properties, and understand the difference between primitive and non-primitive data types."
]
},
"lab-cargo-manifest-validator": {
"title": "Build a Cargo Manifest Validator",
"intro": [
"In this lab, you will use JavaScript to normalize and validate cargo manifests."
]
},
"lecture-working-with-json": {
"title": "Working with JSON",
"intro": [

View File

@@ -0,0 +1,861 @@
---
id: 69a56b5069ca99f7317e6e19
title: Build a Cargo Manifest Validator
challengeType: 26
dashedName: lab-cargo-manifest-validator
---
# --description--
In this lab, you will use JavaScript to normalize and validate cargo manifests. A cargo manifest is a document that typically lists goods being transported (for example, by ship or train) and includes details about those goods.
Each cargo manifest will be represented as an object with the following properties:
- `containerId`: a positive integer identifying the associated cargo container.
- `destination`: a non-empty string (after trimming whitespace) denoting the cargo's target destination.
- `weight`: a positive number representing the cargo's weight.
- `unit`: a string describing the units for the cargo's weight property (either `"kg"` for kilograms or `"lb"` for pounds).
- `hazmat`: a boolean value indicating whether hazardous material handling is needed.
Example cargo manifest object:
```js
{
containerId: 1,
destination: "Monterey, California, USA",
weight: 831,
unit: "lb",
hazmat: false
}
```
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
**User Stories:**
1. You should implement a function named `normalizeUnits` with a `manifest` parameter.
- The function must not mutate the original manifest object and must always return a new object where `weight` is normalized to kilograms and `unit` is set to `"kg"`.
- If the weight of the manifest object is expressed in pounds (`unit: "lb"`), the function should convert the `weight` to kilograms using the approximate conversion, 1 lb = 0.45 kg, and update the `unit` accordingly.
- If the weight is already expressed in kilograms (`unit: "kg"`), the `weight` and `unit` should remain unchanged.
2. You should implement a function named `validateManifest` with a `manifest` parameter.
- The function must not mutate the original manifest object and must always return a new object.
- If the input manifest is valid (no missing or invalid properties), the function should return an empty object.
- If the input manifest is not valid, the function should return an object containing entries for each missing or invalid property. Missing properties should have the value `"Missing"` and invalid properties should have the value `"Invalid"`.
Example return value where the input object is missing the `destination` property and has an invalid `weight` property:
```js
{
destination: "Missing",
weight: "Invalid"
}
```
3. You should implement a function named `processManifest` with a `manifest` parameter. The function should log:
- If the manifest object is valid, `Validation success: ${containerId}` and then the manifest's weight in kilograms as such, `Total weight: ${weight} kg`. Use `normalizeUnits()` for this conversion.
- If the manifest object is not valid, `Validation error: ${containerId}` and then the object returned by calling `validateManifest()` with the manifest object.
**Note:** each of these two cases should have two `console.log()` calls.
# --before-each--
```js
const _validManifests = [
{
containerId: 4,
destination: "Monterey, California, USA",
weight: 831,
unit: "lb",
hazmat: false
},
{
containerId: 5,
destination: "Montreal, Quebec, Canada",
weight: 151,
unit: "kg",
hazmat: false
}
];
const _invalidManifests = [
{
containerId: -6,
destination: 123,
weight: 0,
unit: "pounds",
hazmat: true
},
{
containerId: 0,
weight: -21,
unit: "KG"
},
{
containerId: "eight",
destination: "Guadalajara, Jalisco, Mexico",
weight: 9001,
hazmat: "no"
},
{
destination: " ",
weight: NaN,
unit: "kg",
hazmat: 1
},
{
containerId: 10,
destination: " ",
},
];
const _testObj = {
containerId: 1.51,
destination: "Lavender Town",
weight: NaN,
};
console.log = () => {};
```
# --hints--
You should have a function named `normalizeUnits` with a `manifest` parameter.
```js
assert.isFunction(normalizeUnits);
const funcString = normalizeUnits.toString();
const params = __helpers.getFunctionParams(funcString);
assert.equal(params.length, 1);
assert.equal(params[0].name, 'manifest');
```
Calling `normalizeUnits()` with `{ containerId: 68, destination: "Salinas", weight: 101, unit: "lb", hazmat: true }` should return the new object `{ containerId: 68, destination: "Salinas", weight: 45.45, unit: "kg", hazmat: true }` without mutating the source input.
```js
const testObj = {
containerId: 68,
destination: "Salinas",
weight: 101,
unit: "lb",
hazmat: true
};
const expected = {
containerId: 68,
destination: "Salinas",
weight: 45.45,
unit: "kg",
hazmat: true
};
const copy = normalizeUnits(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "normalizeUnits() did not return the expected normalized object");
assert.notStrictEqual(copy, testObj, "normalizeUnits() should return a new object.");
assert.strictEqual(testObj.containerId, 68, "Original object should not be mutated.");
assert.strictEqual(testObj.destination, "Salinas", "Original object should not be mutated.");
assert.strictEqual(testObj.weight, 101, "Original object should not be mutated.");
assert.strictEqual(testObj.unit, "lb", "Original object should not be mutated.");
assert.strictEqual(testObj.hazmat, true, "Original object should not be mutated.");
assert.equal(Object.keys(testObj).length, 5, "Original object should not be mutated.");
```
Your `normalizeUnits` function should return a copy of the input manifest object with its `weight` normalized to kilograms and its `unit` set to `"kg"`. Use the approximate conversion `1 lb = 0.45 kg` for the weight conversion.
```js
_validManifests.forEach((obj, i) => {
const result = normalizeUnits(obj);
assert.isObject(result, "normalizeUnits should return an object");
assert.notStrictEqual(result, obj, "normalizeUnits must return a new object, not modify the original");
const expectedWeight = obj.unit === "lb" ? obj.weight * 0.45 : obj.weight;
const expected = {
...obj,
weight: expectedWeight,
unit: "kg"
};
assert.deepEqual(
result,
expected,
`normalizeUnits did not return the expected normalized object for manifest at index ${i}`
);
});
```
Your `normalizeUnits` function should return a new copy of the input `manifest` object without mutating the original.
```js
const original = {
containerId: 151,
destination: "Saffron City",
weight: 151,
unit: "lb",
hazmat: false
};
const expected = {
containerId: 151,
destination: "Saffron City",
weight: 67.95,
unit: "kg",
hazmat: false
};
const copy = normalizeUnits(original);
assert.isObject(copy);
assert.deepEqual(copy, expected);
assert.notStrictEqual(copy, original, "normalizeUnits() should return a new object.");
assert.strictEqual(original.weight, 151, "Original object should not be mutated.");
assert.strictEqual(original.unit, "lb", "Original object should not be mutated.");
assert.equal(Object.keys(original).length, 5, "Original object should not be mutated.");
```
You should have a function named `validateManifest` with a `manifest` parameter.
```js
assert.isFunction(validateManifest);
const funcString = validateManifest.toString();
const params = __helpers.getFunctionParams(funcString);
assert.equal(params.length, 1);
assert.equal(params[0].name, 'manifest');
```
Calling `validateManifest()` with `{ containerId: 1, destination: "Santa Cruz", weight: 304, unit: "kg", hazmat: false }` should return the new object `{}`.
```js
const testObj = {
containerId: 1,
destination: "Santa Cruz",
weight: 304,
unit: "kg",
hazmat: false
};
const expected = {};
const copy = validateManifest(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "validateManifest() did not return the expected object for a valid manifest");
assert.notStrictEqual(copy, testObj, "validateManifest() should return a new object, not mutate the original");
assert.strictEqual(testObj.containerId, 1, "Original object should not be mutated");
assert.strictEqual(testObj.destination, "Santa Cruz", "Original object should not be mutated");
assert.strictEqual(testObj.weight, 304, "Original object should not be mutated");
assert.strictEqual(testObj.unit, "kg", "Original object should not be mutated");
assert.strictEqual(testObj.hazmat, false, "Original object should not be mutated");
```
If the input manifest object is valid, your `validateManifest` function should return an empty object `{}`.
```js
const solution = {}
for (const obj of _validManifests) {
assert.deepEqual(
validateManifest(obj),
solution,
"validateManifest() should return an empty object for valid manifests."
);
}
```
Calling `validateManifest()` with `{}` should return the new object `{ containerId: "Missing", destination: "Missing", weight: "Missing", unit: "Missing", hazmat: "Missing" }` without mutating the source input.
```js
const testObj = {
};
const expected = {
containerId: "Missing",
destination: "Missing",
weight: "Missing",
unit: "Missing",
hazmat: "Missing"
};
const copy = validateManifest(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "validateManifest() did not return the expected object for missing properties");
assert.notStrictEqual(copy, testObj, "validateManifest() should return a new object, not mutate the original");
assert.equal(Object.keys(testObj).length, 0, "validateManifest() should return a new object, not mutate the original")
```
Calling `validateManifest()` with `{ containerId: 0, destination: 405, weight: -84, unit: "pounds", hazmat: "no" }` should return the new object `{ containerId: "Invalid", destination: "Invalid", weight: "Invalid", unit: "Invalid", hazmat: "Invalid" }` without mutating the source input.
```js
const testObj = {
containerId: 0,
destination: 405,
weight: -84,
unit: "pounds",
hazmat: "no"
};
const expected = {
containerId: "Invalid",
destination: "Invalid",
weight: "Invalid",
unit: "Invalid",
hazmat: "Invalid"
};
const copy = validateManifest(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "validateManifest() did not return the expected object for invalid properties");
assert.notStrictEqual(copy, testObj, "validateManifest() should return a new object, not mutate the original");
assert.strictEqual(testObj.containerId, 0, "Original object should not be mutated");
assert.strictEqual(testObj.destination, 405, "Original object should not be mutated");
assert.strictEqual(testObj.weight, -84, "Original object should not be mutated");
assert.strictEqual(testObj.unit, "pounds", "Original object should not be mutated");
assert.strictEqual(testObj.hazmat, "no", "Original object should not be mutated");
```
Calling `validateManifest()` with `{ containerId: -2 }` should return the new object `{ containerId: "Invalid", destination: "Missing", weight: "Missing", unit: "Missing", hazmat: "Missing" }` without mutating the source input.
```js
const testObj = {
containerId: -2,
};
const expected = {
containerId: "Invalid",
destination: "Missing",
weight: "Missing",
unit: "Missing",
hazmat: "Missing"
};
const copy = validateManifest(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "validateManifest() did not return the expected object for invalid and missing properties");
assert.notStrictEqual(copy, testObj, "validateManifest() should return a new object, not mutate the original");
assert.strictEqual(testObj.containerId, -2, "Original object should not be mutated");
assert.equal(Object.keys(testObj).length, 1, "Original object should not be mutated");
```
Calling `validateManifest()` with `{ containerId: 3.50 }` should return the new object `{ containerId: "Invalid", destination: "Missing", weight: "Missing", unit: "Missing", hazmat: "Missing" }` without mutating the source input. You can use `Number.isInteger()` to validate integer values.
```js
const testObj = {
containerId: 3.50,
};
const expected = {
containerId: "Invalid",
destination: "Missing",
weight: "Missing",
unit: "Missing",
hazmat: "Missing"
};
const copy = validateManifest(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "validateManifest() did not return the expected object for invalid and missing properties");
assert.notStrictEqual(copy, testObj, "validateManifest() should return a new object, not mutate the original");
assert.strictEqual(testObj.containerId, 3.50, "Original object should not be mutated");
assert.equal(Object.keys(testObj).length, 1, "Original object should not be mutated");
```
Calling `validateManifest()` with `{ destination: " " }` should return the new object `{ containerId: "Missing", destination: "Invalid", weight: "Missing", unit: "Missing", hazmat: "Missing" }` without mutating the source input. You can use `String.trim()` to remove whitespace from a string.
```js
const testObj = {
destination: " ",
};
const expected = {
containerId: "Missing",
destination: "Invalid",
weight: "Missing",
unit: "Missing",
hazmat: "Missing"
};
const copy = validateManifest(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "validateManifest() did not return the expected object for invalid and missing properties");
assert.notStrictEqual(copy, testObj, "validateManifest() should return a new object, not mutate the original");
assert.strictEqual(testObj.destination, " ", "Original object should not be mutated");
assert.equal(Object.keys(testObj).length, 1, "Original object should not be mutated");
```
Calling `validateManifest()` with `{ weight: NaN }` should return the new object `{ containerId: "Missing", destination: "Missing", weight: "Invalid", unit: "Missing", hazmat: "Missing" }` without mutating the source input. You can use `Number.isNaN()` to validate NaN values.
```js
const testObj = {
weight: NaN,
};
const expected = {
containerId: "Missing",
destination: "Missing",
weight: "Invalid",
unit: "Missing",
hazmat: "Missing"
};
const copy = validateManifest(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "validateManifest() did not return the expected object for invalid and missing properties");
assert.notStrictEqual(copy, testObj, "validateManifest() should return a new object, not mutate the original");
assert.ok(Number.isNaN(testObj.weight), "Original object should not be mutated");
assert.equal(Object.keys(testObj).length, 1, "Original object should not be mutated");
```
If the input manifest object is not valid, your `validateManifest` function should return an object describing missing and/or invalid properties.
```js
const solutions = [
{ containerId: 'Invalid', destination: 'Invalid', weight: 'Invalid', unit: 'Invalid' },
{ containerId: 'Invalid', destination: 'Missing', weight: 'Invalid', unit: 'Invalid', hazmat: 'Missing' },
{ containerId: 'Invalid', unit: 'Missing', hazmat: 'Invalid' },
{ containerId: 'Missing', destination: 'Invalid', weight: 'Invalid', hazmat: 'Invalid' },
{ destination: 'Invalid', weight: 'Missing', unit: 'Missing', hazmat: 'Missing' }
];
let i = 0;
for (const obj of _invalidManifests) {
const result = validateManifest(obj);
assert.deepEqual(
result,
solutions[i],
"validateManifest() should return an object with errors for invalid manifests."
);
i += 1;
}
```
Your `validateManifest` function should return a new object without mutating the original.
```js
const invalidOriginal = {
containerId: -151,
destination: "",
weight: -151,
unit: "kilograms",
hazmat: "idk"
};
const validOriginal = {
containerId: 151,
destination: "Pallet Town",
weight: 151,
unit: "kg",
hazmat: false
};
const res0 = validateManifest(invalidOriginal);
assert.isObject(res0);
assert.notStrictEqual(res0, invalidOriginal, "validateManifest() should return a new object.");
assert.strictEqual(invalidOriginal.containerId, -151, "Original object should not be mutated.");
assert.strictEqual(invalidOriginal.destination, "", "Original object should not be mutated.");
assert.strictEqual(invalidOriginal.weight, -151, "Original object should not be mutated.");
assert.strictEqual(invalidOriginal.unit, "kilograms", "Original object should not be mutated.");
assert.strictEqual(invalidOriginal.hazmat, "idk", "Original object should not be mutated.");
assert.equal(Object.keys(invalidOriginal).length, 5, "Original object should not be mutated.");
const res1 = validateManifest(validOriginal);
assert.isObject(res1);
assert.notStrictEqual(res1, validOriginal, "validateManifest() should return a new object.");
assert.strictEqual(validOriginal.containerId, 151, "Original object should not be mutated.");
assert.strictEqual(validOriginal.destination, "Pallet Town", "Original object should not be mutated.");
assert.strictEqual(validOriginal.weight, 151, "Original object should not be mutated.");
assert.strictEqual(validOriginal.unit, "kg", "Original object should not be mutated.");
assert.strictEqual(validOriginal.hazmat, false, "Original object should not be mutated.");
assert.equal(Object.keys(validOriginal).length, 5, "Original object should not be mutated.");
```
You should have a function named `processManifest` with a `manifest` parameter.
```js
assert.isFunction(processManifest);
const funcString = processManifest.toString();
const params = __helpers.getFunctionParams(funcString);
assert.equal(params.length, 1);
assert.equal(params[0].name, 'manifest');
```
Calling `processManifest()` with `{ containerId: 55, destination: "Carmel", weight: 400, unit: "lb", hazmat: false }` should first log `"Validation success: 55"` and then log `"Total weight: 180 kg"`.
```js
const testObj = {
containerId: 55,
destination: "Carmel",
weight: 400,
unit: "lb",
hazmat: false
};
const spy = __helpers.spyOn(console, "log");
try {
processManifest(testObj);
const expectedCalls = [
["Validation success: 55"],
["Total weight: 180 kg"]
];
assert.deepEqual(spy.calls[0], expectedCalls[0], "First log should be the validation success message");
assert.deepEqual(spy.calls[1], expectedCalls[1], "Second log should be the normalized weight in kg");
} catch (err) {
assert.fail(err);
} finally {
spy.restore();
}
```
If the input manifest object is valid, your `processManifest` function should first log the success message, `Validation success: ${containerId}`.
```js
const testObj = {
containerId: 97,
destination: "Cerulean City",
weight: 200,
unit: "lb",
hazmat: false
}
const spy = __helpers.spyOn(console, "log");
try {
processManifest(testObj);
const expectedCalls = [
["Validation success: 97"],
["Total weight: 90 kg"],
]
assert.deepEqual(spy.calls[0], expectedCalls[0]);
} catch (err) {
assert.fail(err);
} finally {
spy.restore();
}
```
If the input manifest object is valid, your `processManifest` function should normalize it to kilograms using `normalizeUnits()` and then log: `Total weight: ${weight} kg`.
```js
const testObj = {
containerId: 97,
destination: "Cerulean City",
weight: 200,
unit: "lb",
hazmat: false
}
const spy = __helpers.spyOn(console, "log");
try {
processManifest(testObj);
const expectedCalls = [
["Validation success: 97"],
["Total weight: 90 kg"],
]
assert.deepEqual(spy.calls[1], expectedCalls[1]);
} catch (err) {
assert.fail(err);
} finally {
spy.restore();
}
```
If the input manifest object is valid, your `processManifest` function should log a success message with the object's `containerId`, and then log the object's `weight` in kilograms. You should use `normalizeUnits()` for the conversion and have two `console.log()` calls.
```js
const originalNormalize = normalizeUnits;
let called = false;
try {
normalizeUnits = function (...args) {
called = true;
return originalNormalize(...args);
};
processManifest(_validManifests[0]);
assert.isTrue(
called,
"processManifest should call normalizeUnits() when the manifest is valid"
);
} catch (err) {
assert.fail(err);
} finally {
normalizeUnits = originalNormalize;
}
const spy = __helpers.spyOn(console, "log");
try {
for (const obj of _validManifests) {
processManifest(obj);
}
const expectedCalls = [
["Validation success: 4"],
["Total weight: 373.95 kg"],
["Validation success: 5"],
["Total weight: 151 kg"],
]
assert.deepEqual(spy.calls, expectedCalls);
} catch (err) {
assert.fail(err);
} finally {
spy.restore();
}
```
Calling `processManifest()` with `{ containerId: -88, destination: "Soledad", weight: NaN }` should first log `Validation error: -88` and then log the object `{ containerId: "Invalid", weight: "Invalid", unit: "Missing", hazmat: "Missing" }`.
```js
const testObj = {
containerId: -88,
destination: "Soledad",
weight: NaN
};
const spy = __helpers.spyOn(console, "log");
try {
processManifest(testObj);
const expectedCalls = [
["Validation error: -88"],
[{
containerId: "Invalid",
weight: "Invalid",
unit: "Missing",
hazmat: "Missing"
}]
];
assert.deepEqual(spy.calls[0], expectedCalls[0], "First log should be the validation error message");
assert.deepEqual(spy.calls[1], expectedCalls[1], "Second log should be the validation result object");
} catch (err) {
assert.fail(err);
} finally {
spy.restore();
}
```
Calling `processManifest()` with `{ destination: "Watsonville", hazmat: true }` should first log `Validation error: undefined` and then log the object `{ containerId: "Missing", weight: "Missing", unit: "Missing" }`.
```js
const testObj = {
destination: "Watsonville",
hazmat: true
};
const spy = __helpers.spyOn(console, "log");
try {
processManifest(testObj);
const expectedCalls = [
["Validation error: undefined"],
[{
containerId: "Missing",
weight: "Missing",
unit: "Missing"
}]
];
assert.deepEqual(spy.calls[0], expectedCalls[0], "First log should be the validation error message");
assert.deepEqual(spy.calls[1], expectedCalls[1], "Second log should be the validation result object");
} catch (err) {
assert.fail(err);
} finally {
spy.restore();
}
```
If the input manifest object is not valid, your `processManifest` function should first log the error message, `Validation error: ${containerId}`.
```js
const spy = __helpers.spyOn(console, "log");
try {
processManifest(_testObj);
const expectedCalls = [
["Validation error: 1.51"],
[{
containerId: "Invalid",
weight: "Invalid",
unit: "Missing",
hazmat: "Missing"
}]
];
assert.deepEqual(spy.calls[0], expectedCalls[0]);
} catch (err) {
assert.fail(err);
} finally {
spy.restore();
}
```
If the input manifest object is not valid, your `processManifest` function should also log the object returned by calling `validateManifest()` with the original manifest object. Call `console.log()` directly with the returned object.
```js
const originalValidate = validateManifest;
let called = false;
try {
validateManifest = function (...args) {
called = true;
return originalValidate(...args);
};
processManifest(_invalidManifests[0]);
assert.isTrue(
called,
"processManifest should call validateManifest() when the manifest is invalid"
);
} catch (err) {
assert.fail(err);
} finally {
validateManifest = originalValidate;
}
const spy = __helpers.spyOn(console, "log");
try {
processManifest(_testObj);
const expectedCalls = [
["Validation error: 1.51"],
[{
containerId: "Invalid",
weight: "Invalid",
unit: "Missing",
hazmat: "Missing"
}]
];
assert.deepEqual(spy.calls[1], expectedCalls[1]);
} catch (err) {
assert.fail(err);
} finally {
spy.restore();
}
```
If the input manifest object is not valid, your `processManifest` function should log an error message with the object's `containerId`, and then log the object returned by calling `validateManifest()` with the input object. This should involve two `console.log()` calls.
```js
const originalValidate = validateManifest;
let called = false;
try {
validateManifest = function (...args) {
called = true;
return originalValidate(...args);
};
processManifest(_invalidManifests[0]);
assert.isTrue(
called,
"processManifest should call validateManifest() when the manifest is invalid"
);
} catch (err) {
assert.fail(err);
} finally {
validateManifest = originalValidate;
}
const spy = __helpers.spyOn(console, "log");
try {
processManifest(_testObj);
const expectedCalls = [
["Validation error: 1.51"],
[{
containerId: "Invalid",
weight: "Invalid",
unit: "Missing",
hazmat: "Missing"
}]
];
assert.deepEqual(spy.calls, expectedCalls);
} catch (err) {
assert.fail(err);
} finally {
spy.restore();
}
```
# --seed--
## --seed-contents--
```js
```
# --solutions--
```js
function normalizeUnits(manifest) {
const normalized = {
...manifest
}
if (normalized.unit === "lb") {
normalized.weight = normalized.weight * 0.45;
normalized.unit = "kg";
}
return normalized;
}
function validateManifest(manifest) {
const result = {}
if (manifest.containerId === undefined) {
result.containerId = "Missing";
} else if (
typeof manifest.containerId !== "number" ||
!Number.isInteger(manifest.containerId) ||
manifest.containerId <= 0
) {
result.containerId = "Invalid";
}
if (manifest.destination === undefined) {
result.destination = "Missing";
} else if (typeof manifest.destination !== "string" || manifest.destination.trim() === "") {
result.destination = "Invalid";
}
if (manifest.weight === undefined) {
result.weight = "Missing";
} else if (typeof manifest.weight !== "number" || manifest.weight <= 0 || Number.isNaN(manifest.weight)) {
result.weight = "Invalid";
}
if (manifest.unit === undefined) {
result.unit = "Missing";
} else if (manifest.unit !== "kg" && manifest.unit !== "lb") {
result.unit = "Invalid";
}
if (manifest.hazmat === undefined) {
result.hazmat = "Missing";
} else if (typeof manifest.hazmat !== "boolean") {
result.hazmat = "Invalid";
}
return result;
}
function processManifest(manifest) {
const validation = validateManifest(manifest);
if (Object.keys(validation).length > 0) {
console.log(`Validation error: ${manifest.containerId}`);
console.log(validation);
} else {
const normalized = normalizeUnits(manifest);
console.log(`Validation success: ${manifest.containerId}`);
console.log(`Total weight: ${normalized.weight} kg`);
}
}
```

View File

@@ -0,0 +1,14 @@
{
"isUpcomingChange": false,
"dashedName": "lab-cargo-manifest-validator",
"helpCategory": "JavaScript",
"blockLayout": "link",
"challengeOrder": [
{
"id": "69a56b5069ca99f7317e6e19",
"title": "Build a Cargo Manifest Validator"
}
],
"blockLabel": "lab",
"usesMultifileEditor": true
}

View File

@@ -82,6 +82,7 @@
"dashedName": "javascript-objects",
"blocks": [
"lecture-introduction-to-javascript-objects-and-their-properties",
"lab-cargo-manifest-validator",
"lecture-working-with-json",
"lecture-working-with-optional-chaining-and-object-destructuring",
"workshop-recipe-tracker",