Skip to content

Commit

Permalink
Merge branch 'main' into bug/857-cached-link
Browse files Browse the repository at this point in the history
  • Loading branch information
SallyMcGrath authored Oct 23, 2024
2 parents 74170a0 + 38df5a5 commit b9eed24
Show file tree
Hide file tree
Showing 16 changed files with 719 additions and 158 deletions.
57 changes: 0 additions & 57 deletions common-content/en/module/js1/assembly/index.md

This file was deleted.

80 changes: 20 additions & 60 deletions common-content/en/module/js1/assertions/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ We now have 2 new concepts: **booleans** and **comparisons**. From these concept

> 🔑 An assertion is a _check_ that our code behaves in a particular way: this check can either succeed or fail.
So far we've used the log function `console.log`. We can write assertions using another function: [`console.assert`](https://developer.mozilla.org/en-US/docs/Web/API/console/assert). The documentation says that `console.assert` writes an error message to the console if the assertion is false. If the assertion is true, nothing happens. As `finalCharacter === "?"` evaluates to true, no message will be written to the console.
So far we've used the log function `console.log`. We can write assertions using another function: [`console.assert`](https://developer.mozilla.org/en-US/docs/Web/API/console/assert). The documentation says that `console.assert` writes an error message to the console if the assertion is false. If the assertion is true, nothing happens. As `10 + 32 === 42` evaluates to true, no message will be written to the console.

```js
const calculation = 10 + 32;
Expand All @@ -47,12 +47,13 @@ const result = 42;
console.assert(calculation === result);
```

Update the final character in the `sentence` variable string to make the assertion fail. Check the output you get in the console.
Change the value assigned to the `result` variable to make the assertion fail. Check the output you get in the console.

👉🏿 [Keep Going](#predict-explain-check-2)
{{</tab>}}

{{<tab name="Exercise 2">}}

{{<note type="exercise" title="Exercise 2">}}
Let's look at an example using `formatAs12HourClock`:

```js
Expand All @@ -62,8 +63,6 @@ console.assert(formatAs12HourClock("08:00") === "08:00 am");

Predict and explain if the assertion will succeed or fail. Pay particular attention to the return value of `formatAs12HourClock`.

{{</note>}}

{{</tab>}}

{{</tabs>}}
Expand All @@ -84,7 +83,7 @@ console.assert(
Let's break down these arguments to make sense of what's going on:

1. **first argument** - `formatAs12HourClock("08:00") === "08:00 am"` - the condition we're checking
2. **second argument** - `current output: ${formatAs12HourClock("08:00")}, target output: 08:00 am` - a message string that will be logged to the console if the condition is false.
2. **second argument** - `` `current output: ${formatAs12HourClock("08:00")}, target output: 08:00 am` `` - a message string that will be logged to the console if the condition is false.

#### 🧹 Refactor

Expand All @@ -109,13 +108,13 @@ Assertion failed: current output: undefined, target output: 08:00 am

## 🧰 Implementing the functionality

On line 4, the function is being passed a single argument `"08:00"`. But our function ignores it - it doesn't declare any parameters. We can parameterise the function and label the input as `time`:
On line 3, the function is being passed a single argument `"08:00"`. But our function ignores it: it doesn't declare any parameters. We can parameterise the function and label the input as `time`:

```js
function formatAs12HourClock(time) {}
```

According to our assertion, when we call our function with an input of `"08:00"` we need to create an output of `"08:00 am"`. We can add `"am"` to the `time` to get the target output. We can update our function with a template literal, set the return value and then _re-run_ our code including our assertion to check the function is returning the correct value.
According to our assertion, when we call our function with an input of `"08:00"` we need to create an output of `"08:00 am"`. If we add `"am"` to the `time`, we'll get the target output. We can update our function with a template literal, set the return value and then _re-run_ our code including our assertion to check the function is returning the correct value.

📓 We can and should continually check our assertions to see if our function’s current output meets our target output.

Expand All @@ -140,49 +139,21 @@ Create a javascript file on your local machine and execute the code above. Doubl

## 💼 Checking different cases

So far we’ve only created assertions that check the function’s behaviour for times _after midnight and before midday_. In these cases, there is a pattern: take the current time and add `"am"` to the end.
So far we’ve only created assertions that check the function’s behaviour for times _between midnight and midday_. In these cases, there is a pattern: take the current time and add `" am"` to the end.

Now we need to assert that the function behaves correctly when the time is later than midday. Let’s create an assertion for our function when passed an input of `"23:00"`:
But this isn't the pattern we need to follow for _all_ times. To make sure our function works for all times, we need to write more assertions.

```js {linenos=table,linenostart=1}
function formatAs12HourClock(time) {
return `${time} am`;
}
We need to assert that the function behaves correctly when the time is later than midday.

const currentOutput = formatAs12HourClock("08:00");
const targetOutput = "08:00 am";
console.assert(
currentOutput === targetOutput,
`current output: ${currentOutput}, target output: ${targetOutput}`
);
Before we think about any code, we should think about our problem. Separating _problem_ and _code_ lets us focus better. First we can focus on the data. Then we can focus on the code.

const currentOutput = formatAs12HourClock("23:00");
const targetOutput = "11:00 pm";
console.assert(
currentOutput === targetOutput,
`current output: ${currentOutput}, target output: ${targetOutput}`
);
```
First, let's think of an example time in 24 hour clock - we'll pick `23:00`.

## 🔄 Reusing variable names
Next, let's work out what we expect our example time to be in 12 hour clock: `11:00 pm`.

When we run the file with Node, we get an error in the console:
Now that we've thought about the problem, we can write the code. Let's create an assertion for our function when passed an input of `"23:00"`:

```bash
SyntaxError: Identifier 'currentOutput' has already been declared
```

In this case, identifier means name of a variable, so in a variable declaration like

```js
const currentOutput = formatAs12HourClock("08:23");
```

`currentOutput` is the **identifier**.

When an error is thrown, it means the execution of the program stops at this point and an error report is sent to the user. However, we want to do multiple assertions.

```js title="problem.js"
```js {linenos=table,linenostart=1}
function formatAs12HourClock(time) {
return `${time} am`;
}
Expand All @@ -194,23 +165,12 @@ console.assert(
`current output: ${currentOutput}, target output: ${targetOutput}`
);

// ❌ this assertion now fails
const currentOutput2 = formatAs12HourClock("23:00");
const targetOutput2 = "11:00 pm";
const currentOutput = formatAs12HourClock("23:00");
const targetOutput = "11:00 pm";
console.assert(
currentOutput2 === targetOutput2,
`current output: ${currentOutput2}, target output: ${targetOutput2}`
currentOutput === targetOutput,
`current output: ${currentOutput}, target output: ${targetOutput}`
);
```

Now the second assertion fails with the following message:

```bash
Assertion failed: current output: 23:00 am, target output: 11:00 pm
```

{{<note type="exercise" title="Exercise 2">}}

✏️ Write another assertion that checks `formatAs12HourClock` returns the target output when passed another _time input in the afternoon._

{{</note>}}
Save this code to a file. Before you run it in Node, write down what you think will happen. Then run it with Node - compare what you saw with what you predicted.
6 changes: 3 additions & 3 deletions common-content/en/module/js1/clocks/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ We use the notation "HH:MM". HH is our stand-in for the hours value. MM is our s

Let's pose a problem: given any time in 24 hour clock, we want to format it as a 12 hour clock time. To achieve this goal, we're going to implement a function `formatAs12HourClock`.

_Given_ a time in 24 hour clock
_When_ we call `formatAs12HourClock`
_Then_ we get back a string representing the same time in 12 hour clock
_Given_ a time in 24 hour clock
_When_ we call `formatAs12HourClock`
_Then_ we get back a string representing the same time in 12 hour clock.

### 🧪 Our tests:

Expand Down
2 changes: 1 addition & 1 deletion common-content/en/module/js1/comparison/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ b) the 🎯 target output?

We have learned how to log values to the console. We can also **compare** two values. We check that a function produces some target output with a comparison.

We compare the current output of `formatAs12HourClock("08:00")` with the target output of `"08:00 am"` and ask: **are these two values the same?**. We use a comparison operator to compare two expressions and check if they evaluate to the same value. We use the strict equality operator `===` to check if two values are the same.
We compare the current output of `formatAs12HourClock("08:00")` with the target output of `"08:00 am"` and ask: **are these two values the same?** We use a comparison operator to compare two expressions and check if they evaluate to the same value. We use the strict equality operator `===` to check if two values are the same.

### Left equals Right

Expand Down
68 changes: 68 additions & 0 deletions common-content/en/module/js1/identifying-missing-tests/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
+++
title = '🔬 Identifying missing tests'

time = 30
facilitation = false
emoji= '🔬'
[objectives]
1='Define groups of input'
2='Define edge cases'
3='Identify groups of input for a function'
4='Identify edge cases for a function'
[build]
render = 'never'
list = 'local'
publishResources = false

+++

We started off writing one test for our code - checking that it correctly handled the input `08:00`. We wrote an implementation that passed all our (1) tests!

Then we realised there was a bug - it didn't handle times after midday correctly. So we wrote another test - for the input `23:00`. We saw our implementation failed that test. And we fixed it. And we had an implementation that passed all our (2) tests!

> When will we be happy that our implementation works for all possible inputs? When do we have enough tests?
### Groups of input

One way to approach this is to think about what _groups_ of input our problem may have.

We've already identified two examples of groups of input to the problem of converting 24 hour clocks to 12 hour clocks: Times before midday and times after midday.

One way to find extra cases to consider (and extra tests to write) is to try to think of different groups of input.

For example, some times are exactly on the hour (end in `:00`) and other times have a non-zero number of minutes.

{{<note type="exercise">}}
Set a timer for 5 minutes. Write down as many groups of input to this problem as you can. Write an example assertion for each one.

If you find any bugs in the implementation, go fix them!
{{</note>}}

### Edge cases

Another way to consider this question is to think about what _edge cases_ there are in the problem.

{{<note type="definition" title="Definition: edge case">}}
An edge case is an unusual value which may need special treatment.

Some examples are: the minimum value, the maximum value, and the boundary between two groups of input.
{{</note>}}

Some example edge cases for this problem are:
`00:00`
: The minimum time, which is `12:00 am` in 12 hour clock.
This is also the only hour that is _bigger_ in 12 hour clock than 24 hour clock.

`24:00`
: The maximum time.

`12:00`
: Where time changes from am to pm. The edge between morning times and afternoon times.

Often these edge cases are where bugs happen.

{{<note type="exercise">}}
Set a timer for 5 minutes. Write down as many edge cases of input to this problem as you can. Write an example assertion for each one.

If you find any bugs in the implementation, go fix them!
{{</note>}}
101 changes: 101 additions & 0 deletions common-content/en/module/js1/interpreting-errors/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
+++
title = '🔎 Interpreting errors'

time = 20
facilitation = false
emoji= '🔎'
[objectives]
1='Interpret an error trace to identify which line in which file caused the error'
2="Identify an error message from an error trace"
[build]
render = 'never'
list = 'local'
publishResources = false

+++

## An error is thrown

When we run the file with Node, we get an error in the console:

```console
% node clock-example.js
/Users/dwh/CYF/clock-example.js:12
const currentOutput = formatAs12HourClock("23:00");
^

SyntaxError: Identifier 'currentOutput' has already been declared
at wrapSafe (node:internal/modules/cjs/loader:1383:18)
at Module._compile (node:internal/modules/cjs/loader:1412:20)
at Module._extensions..js (node:internal/modules/cjs/loader:1551:10)
at Module.load (node:internal/modules/cjs/loader:1282:32)
at Module._load (node:internal/modules/cjs/loader:1098:12)
at TracingChannel.traceSync (node:diagnostics_channel:315:14)
at wrapModuleLoad (node:internal/modules/cjs/loader:215:24)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:158:5)
at node:internal/main/run_main_module:30:49

Node.js v22.4.1
```

When an error is thrown, the program stops and an error report is sent to the user.

As programmers, we will see a lot of errors. It's useful for us to be able to read them.

### Interpreting the output

Each line of output here tells us something useful.

The first line is:

```
/Users/dwh/CYF/clock-example.js:12
```

Your output was probably different. But it will have the same parts. Some text, then a colon (`:`), then a number.

{{<note type="exercise" title="Exercise">}}

Work out what the parts of this line mean.

Why are they different on my computer than yours?

How can we use both pieces of information?

{{</note>}}

Often, looking at one line of a file is enough to understand what's wrong. So the message also shows us a copy of the line that caused the problem:

```
const currentOutput = formatAs12HourClock("23:00");
```

Then the output tells us the error message:

```
SyntaxError: Identifier 'currentOutput' has already been declared
```

We may not know what this means yet, but it's something we can learn about.

{{<note type="exercise" title="Exercise">}}
Write down three ways you could find out what this means.
{{</note>}}

Each line starting with "at" is showing us a "Stack trace". We'll skip over this for now. In the future we'll see how it can be useful to us.

Finally, we have this line:

```
Node.js v22.4.1
```

{{<note type="exercise" title="Exercise">}}

What does this line mean?

Why might it be useful to know this information?

Add your answer to your spaced repetition calendar. Your understanding of this will grow over time. Answer the question again in the future, and compare it to your previous answer.

{{</note>}}
Loading

0 comments on commit b9eed24

Please sign in to comment.