fix(curriculum): improve prose consistency in cargo manifest validator lab (#69246)

Co-authored-by: sembauke <sembauke@users.noreply.github.com>
This commit is contained in:
Sem Bauke
2026-08-06 01:43:50 +02:00
committed by GitHub
parent c966671345
commit f4b07d54ac
@@ -14,7 +14,7 @@ Each cargo manifest will be represented as an object with the following properti
- `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).
- `unit`: a string describing the unit of 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:
@@ -35,8 +35,8 @@ Example cargo manifest object:
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.
- 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.
@@ -52,11 +52,12 @@ Example cargo manifest object:
```
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 valid, `Validation success: ${containerId}` and then the manifest's `weight` in kilograms, in the form `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.
**Note:** Neither `normalizeUnits`, `validateManifest`, nor `processManifest` should be declared using `const`, since the tests need to reassign them.
**Note:** Each of these two cases should have two `console.log()` calls.
**Note:** Do not declare `normalizeUnits`, `validateManifest`, or `processManifest` using `const`, since the tests need to reassign them.
# --before-each--
@@ -120,7 +121,7 @@ console.log = () => {};
# --hints--
Neither `normalizeUnits`, `validateManifest`, nor `processManifest` should be declared using `const`, since the tests need to reassign them.
You should not declare `normalizeUnits`, `validateManifest`, or `processManifest` using `const`, since the tests need to reassign them.
```js
assert.doesNotThrow(() => {
@@ -140,12 +141,12 @@ assert.equal(params.length, 1);
assert.equal(params[0].toString(), '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.
Your `normalizeUnits` function should return the new object `{ containerId: 68, destination: "Salinas", weight: 45.45, unit: "kg", hazmat: true }` when called with `{ containerId: 68, destination: "Salinas", weight: 101, unit: "lb", hazmat: true }`, without mutating the original.
```js
const testObj = {
containerId: 68,
destination: "Salinas",
destination: "Salinas",
weight: 101,
unit: "lb",
hazmat: true
@@ -161,7 +162,7 @@ const expected = {
const copy = normalizeUnits(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "normalizeUnits() did not return the expected normalized object");
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.");
@@ -171,13 +172,13 @@ 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.
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");
assert.isObject(result, "normalizeUnits() should return an object.");
assert.notStrictEqual(result, obj, "normalizeUnits() should return a new object, not mutate the original.");
const expectedWeight = obj.unit === "lb" ? obj.weight * 0.45 : obj.weight;
const expected = {
...obj,
@@ -188,12 +189,12 @@ _validManifests.forEach((obj, i) => {
assert.deepEqual(
result,
expected,
`normalizeUnits did not return the expected normalized object for manifest at index ${i}`
`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.
Your `normalizeUnits` function should return a new copy of the input manifest object without mutating the original.
```js
const original = {
@@ -231,12 +232,12 @@ assert.equal(params.length, 1);
assert.equal(params[0].toString(), 'manifest');
```
Calling `validateManifest()` with `{ containerId: 1, destination: "Santa Cruz", weight: 304, unit: "kg", hazmat: false }` should return the new object `{}`.
Your `validateManifest` function should return a new, empty object `{}` when called with `{ containerId: 1, destination: "Santa Cruz", weight: 304, unit: "kg", hazmat: false }`.
```js
const testObj = {
containerId: 1,
destination: "Santa Cruz",
destination: "Santa Cruz",
weight: 304,
unit: "kg",
hazmat: false
@@ -246,16 +247,16 @@ 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");
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 `{}`.
Your `validateManifest` function should return an empty object `{}` if the input manifest object is valid.
```js
const solution = {};
@@ -268,7 +269,7 @@ for (const obj of _validManifests) {
}
```
Calling `validateManifest()` with `{}` should return the new object `{ containerId: "Missing", destination: "Missing", weight: "Missing", unit: "Missing", hazmat: "Missing" }` without mutating the source input.
Your `validateManifest` function should return the new object `{ containerId: "Missing", destination: "Missing", weight: "Missing", unit: "Missing", hazmat: "Missing" }` when called with `{}`, without mutating the original.
```js
const testObj = {};
@@ -283,12 +284,12 @@ const expected = {
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");
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: null, destination: "Santa Cruz", weight: 304, unit: "kg", hazmat: false }` should return the new object `{ containerId: "Invalid" }` without mutating the source input.
Your `validateManifest` function should return the new object `{ containerId: "Invalid" }` when called with `{ containerId: null, destination: "Santa Cruz", weight: 304, unit: "kg", hazmat: false }`, without mutating the original.
```js
const testObj = {
@@ -305,11 +306,11 @@ const expected = {
const copy = validateManifest(testObj);
assert.isObject(copy);
assert.deepEqual(copy, expected, "validateManifest() did not return the expected object for null containerId");
assert.notStrictEqual(copy, testObj, "validateManifest() should return a new object, not mutate the original");
assert.deepEqual(copy, expected, "validateManifest() did not return the expected object for null containerId.");
assert.notStrictEqual(copy, testObj, "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.
Your `validateManifest` function should return the new object `{ containerId: "Invalid", destination: "Invalid", weight: "Invalid", unit: "Invalid", hazmat: "Invalid" }` when called with `{ containerId: 0, destination: 405, weight: -84, unit: "pounds", hazmat: "no" }`, without mutating the original.
```js
const testObj = {
@@ -330,16 +331,16 @@ const expected = {
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");
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.
Your `validateManifest` function should return the new object `{ containerId: "Invalid", destination: "Missing", weight: "Missing", unit: "Missing", hazmat: "Missing" }` when called with `{ containerId: -2 }`, without mutating the original.
```js
const testObj = {
@@ -356,13 +357,13 @@ const expected = {
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");
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.
Your `validateManifest` function should return the new object `{ containerId: "Invalid", destination: "Missing", weight: "Missing", unit: "Missing", hazmat: "Missing" }` when called with `{ containerId: 3.50 }`, without mutating the original. You can use `Number.isInteger()` to validate integer values.
```js
const testObj = {
@@ -379,13 +380,13 @@ const expected = {
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");
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.
Your `validateManifest` function should return the new object `{ containerId: "Missing", destination: "Invalid", weight: "Missing", unit: "Missing", hazmat: "Missing" }` when called with `{ destination: " " }`, without mutating the original. You can use `.trim()` to remove whitespace from a string.
```js
const testObj = {
@@ -402,13 +403,13 @@ const expected = {
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");
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.
Your `validateManifest` function should return the new object `{ containerId: "Missing", destination: "Missing", weight: "Invalid", unit: "Missing", hazmat: "Missing" }` when called with `{ weight: NaN }`, without mutating the original. You can use `Number.isNaN()` to validate `NaN` values.
```js
const testObj = {
@@ -425,13 +426,13 @@ const expected = {
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");
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.
Your `validateManifest` function should return an object describing missing and/or invalid properties if the input manifest object is not valid.
```js
const solutions = [
@@ -504,7 +505,7 @@ assert.equal(params.length, 1);
assert.equal(params[0].toString(), '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"`.
Your `processManifest` function should first log `Validation success: 55` and then log `Total weight: 180 kg` when called with `{ containerId: 55, destination: "Carmel", weight: 400, unit: "lb", hazmat: false }`.
```js
const testObj = {
@@ -524,8 +525,8 @@ try {
["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");
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);
@@ -534,7 +535,7 @@ try {
}
```
If the input manifest object is valid, your `processManifest` function should first log the success message, `Validation success: ${containerId}`.
Your `processManifest` function should first log the success message, `Validation success: ${containerId}`, if the input manifest object is valid.
```js
const testObj = {
@@ -562,7 +563,7 @@ try {
}
```
If the input manifest object is valid, your `processManifest` function should normalize it to kilograms using `normalizeUnits()` and then log: `Total weight: ${weight} kg`.
Your `processManifest` function should normalize a valid input manifest object to kilograms using `normalizeUnits()` and then log `Total weight: ${weight} kg`.
```js
const testObj = {
@@ -590,7 +591,7 @@ try {
}
```
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.
Your `processManifest` function should log a success message with the object's `containerId`, and then log the object's `weight` in kilograms, if the input manifest object is valid. You should use `normalizeUnits()` for the conversion, and this should involve two `console.log()` calls.
```js
const originalNormalize = normalizeUnits;
@@ -605,7 +606,7 @@ try {
assert.isTrue(
called,
"processManifest should call normalizeUnits() when the manifest is valid"
"processManifest() should call normalizeUnits() when the manifest is valid."
);
} catch (err) {
@@ -635,7 +636,7 @@ try {
}
```
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" }`.
Your `processManifest` function should first log `Validation error: -88` and then log the object `{ containerId: "Invalid", weight: "Invalid", unit: "Missing", hazmat: "Missing" }` when called with `{ containerId: -88, destination: "Soledad", weight: NaN }`.
```js
const testObj = {
@@ -658,8 +659,8 @@ try {
}]
];
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");
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);
@@ -668,7 +669,7 @@ try {
}
```
Calling `processManifest()` with `{ destination: "Watsonville", hazmat: true }` should first log `Validation error: undefined` and then log the object `{ containerId: "Missing", weight: "Missing", unit: "Missing" }`.
Your `processManifest` function should first log `Validation error: undefined` and then log the object `{ containerId: "Missing", weight: "Missing", unit: "Missing" }` when called with `{ destination: "Watsonville", hazmat: true }`.
```js
const testObj = {
@@ -689,8 +690,8 @@ try {
}]
];
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");
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);
@@ -699,7 +700,7 @@ try {
}
```
If the input manifest object is not valid, your `processManifest` function should first log the error message, `Validation error: ${containerId}`.
Your `processManifest` function should first log the error message, `Validation error: ${containerId}`, if the input manifest object is not valid.
```js
const spy = __helpers.spyOn(console, "log");
@@ -718,13 +719,13 @@ try {
assert.deepEqual(spy.calls[0], expectedCalls[0]);
} catch (err) {
assert.fail(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.
Your `processManifest` function should also log the object returned by calling `validateManifest()` with the original manifest object if the input manifest object is not valid. Call `console.log()` directly with the returned object.
```js
const originalValidate = validateManifest;
@@ -740,7 +741,7 @@ try {
assert.isTrue(
called,
"processManifest should call validateManifest() when the manifest is invalid"
"processManifest() should call validateManifest() when the manifest is invalid."
);
} catch (err) {
@@ -765,13 +766,13 @@ try {
assert.deepEqual(spy.calls[1], expectedCalls[1]);
} catch (err) {
assert.fail(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.
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, if the input manifest object is not valid. This should involve two `console.log()` calls.
```js
const originalValidate = validateManifest;
@@ -787,7 +788,7 @@ try {
assert.isTrue(
called,
"processManifest should call validateManifest() when the manifest is invalid"
"processManifest() should call validateManifest() when the manifest is invalid."
);
} catch (err) {
@@ -812,7 +813,7 @@ try {
assert.deepEqual(spy.calls, expectedCalls);
} catch (err) {
assert.fail(err);
assert.fail(err);
} finally {
spy.restore();
}