Skip to content

Commit

Permalink
Added '.rejects' and '.resolves' to tutorial 8
Browse files Browse the repository at this point in the history
  • Loading branch information
Nickname5862 committed Jul 29, 2024
1 parent cf31e4d commit 3739e8a
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 47 deletions.
2 changes: 2 additions & 0 deletions generateTutorialAndSolution.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ function generateTutorialAndSolutions() {
return [3 /*break*/, 2];
case 7: return [4 /*yield*/, fs.readdir(generatorFolder)];
case 8:
// These tests will not cause any failing, but are just nice to have.
// e.g. instead of removing excess whitespaces/newlines, we now just prevent them altogether.
filenames = (_d.sent()).filter(function (f) { return f.endsWith("test.ts"); }); // the names are the same in all three folders
_a = 0, filenames_2 = filenames;
_d.label = 9;
Expand Down
42 changes: 25 additions & 17 deletions generator/8 - utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -557,37 +557,40 @@ describe('utils', () => {
* This translates Promises directly to Sherlock concepts we have discussed already.
*/
it('`fromPromise()`', async () => {
// we initialize a Promise that will resolve, not reject, when handled
/**
* `.fromPromise()` returns an atom that is linked to the Promise it is based on.
* We initialize a Promise that will resolve, not reject, when handled
*/
let promise = Promise.resolve(15);
let myAtom$ = fromPromise(promise);

/**
* ** Your Turn **
* What do you think is the default state of an atom based on a Promise?
*/
expect(myAtom$.resolved).toBe(__YOUR_TURN__); // #QUESTION
expect(myAtom$.value).toBe(__YOUR_TURN__); // #QUESTION
expect(myAtom$.final).toBe(__YOUR_TURN__); // #QUESTION
expect(myAtom$.resolved).toBe(false); // #ANSWER
expect(myAtom$.value).toBe(undefined); // #ANSWER
expect(myAtom$.final).toBe(false); // #ANSWER

// Now we wait for the Promise to be handled (resolved).
await promise;

/**
* ** Your Turn **
* So, what will happen to `myAtom$` and `myMappedAtom$`?
* So, what will happen to `myAtom$`?
*/
expect(myAtom$.get()).toBe(__YOUR_TURN__); // #QUESTION
expect(myAtom$.value).toBe(__YOUR_TURN__); // #QUESTION
expect(myAtom$.final).toBe(__YOUR_TURN__); // #QUESTION
expect(myAtom$.get()).toBe(15); // #ANSWER
expect(myAtom$.value).toBe(15); // #ANSWER
expect(myAtom$.final).toBe(true); // #ANSWER

// Now we make a promise that is rejected when called.
promise = Promise.reject('Oh no, I messed up!');
myAtom$ = fromPromise(promise);

// We cannot await the Promise itself, as it would immediately throw.
await Promise.resolve();
// As expected, the promise gets rejected.
await expect(promise).rejects.toBe('Oh no, I messed up!');

/**
* ** Your Turn **
Expand All @@ -603,7 +606,7 @@ describe('utils', () => {

it('`.toPromise()`', async () => {
/**
* `.toPromise()` returns a promise that is linked to the atom it is based on (`myAtom$` here)
* `.toPromise()` returns a promise that is linked to the atom it is based on (`myAtom$` here). Note how this is the reverse of `fromPromise()`.
* If the atom has a value, the promise is resolved. If the atom errors, the promise is rejected using the same error.
* And it the atom is unresolved, the promise is pending.
*/
Expand All @@ -615,26 +618,31 @@ describe('utils', () => {
* What do you think will happen when we try to set the atom with a value?
*/
myAtom$.set('second value');
expect(await promise).toBe(__YOUR_TURN__); // #QUESTION
expect(await promise).toBe('initial value'); // `myAtom$` starts with a value ('initial value'), so the promise is immediately resolved // #ANSWER
// `.resolves` or `.rejects`? ↴
await expect(promise) /*__YOUR_TURN__*/ // #QUESTION
.toBe(__YOUR_TURN__); // #QUESTION
await expect(promise).resolves.toBe('initial value'); // `myAtom$` starts with a value ('initial value'), so the promise is immediately resolved // #ANSWER

myAtom$.unset(); // reset

myAtom$.unset();
promise = myAtom$.toPromise();

/**
* ** Your Turn **
* We set the atom to `unresolved`. What will now happen when we try to set the atom with a value?
*/
myAtom$.set('third value');
expect(await promise).toBe(__YOUR_TURN__); // #QUESTION
expect(await promise).toBe('third value'); // This is now the first value the atom obtains since the promise was created. // #ANSWER
// `.resolves` or `.rejects`? ↴
await expect(promise) /*__YOUR_TURN__*/ // #QUESTION
.toBe(__YOUR_TURN__); // #QUESTION
await expect(promise).resolves.toBe('third value'); // This is now the first value the atom obtains since the promise was created. // #ANSWER

// Whenever an atom is in an `unresolved` state, the corresponding Promise is pending.
// This means that the Promise can still become resolved or rejected depending on the atom's actions.

myAtom$.unset();
promise = myAtom$.toPromise();
myAtom$.unset(); // reset

promise = myAtom$.toPromise();
myAtom$.setError('Error.');

/**
Expand All @@ -658,7 +666,7 @@ describe('utils', () => {

/**
* ** Your Turn **
* We now let `myDerivable$` derive from `myAtom$`, and it will throw a normal error (not a custom Sherlock error).
* We now let `myDerivable$` derive from `myAtom$`, which will throw a normal error (not a custom Sherlock error).
* What will the error message be this time?
*/
try {
Expand Down
4 changes: 2 additions & 2 deletions solution/3 - reacting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { atom } from '@skunkteam/sherlock';

// xxx check my solutions with the actual solutions (https://github.com/skunkteam/sherlock/tree/tutorial-solutions/robin/tutorial)
// FIXME: remove all TODO: and FIXME:
// FIXME: check whether the generated tutorials and solutions actually work (e.g. are all solutions correct? No weird shenanigans?) - ALSO CHECK "Or, alternatively"!
// xxx check whether the generated tutorials and solutions actually work (e.g. are all solutions correct? No weird shenanigans?) -
// FIXME: ALSO CHECK "Or, alternatively"!
// FIXME: deze file niet linten / builden (voor automatische test). Tutorial ook niet. Maar solutions juist wel! OP EIND. (mag beide wel linten right?)
// FIXME: interne review document, mocht ik iets hebben om te laten zien! In Google Drive, zet het erin!
// xxx werkt `npm run tutorial` nog? > Nu wel.
// xxx PETER: "nu je toch met Sherlock bezig bent; zou je voor mij eens kunnen checken of de code voorbeelden in de README
// nog wel kloppen met de huidige API? Ik heb het gevoel dat dat niet zo is; volgens mij is er geen function "derivation()"
// en heet dat nu "derive()" bijvoorbeeld."
// FIXME: OOOOOOH JA, ik had eroverheen gepushed! Dat moet nog een PR met terugwerkende kracht worden... (of commits squashen, en dat ze dan maar de commit moeten reviewen?)

// FIXME: Add FromEventPattern + FromObservable
// xxx fix the generator for code blocks.
// FIXME: now check whether it did not remove excess lines or kept 2 empty lines where it should not. (I think it is good though.)
Expand Down
32 changes: 19 additions & 13 deletions solution/8 - utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,33 +505,36 @@ describe('utils', () => {
* This translates Promises directly to Sherlock concepts we have discussed already.
*/
it('`fromPromise()`', async () => {
// we initialize a Promise that will resolve, not reject, when handled
/**
* `.fromPromise()` returns an atom that is linked to the Promise it is based on.
* We initialize a Promise that will resolve, not reject, when handled
*/
let promise = Promise.resolve(15);
let myAtom$ = fromPromise(promise);

/**
* ** Your Turn **
* What do you think is the default state of an atom based on a Promise?
*/
expect(myAtom$.resolved).toBe(false);
expect(myAtom$.value).toBe(undefined);
expect(myAtom$.final).toBe(false);

// Now we wait for the Promise to be handled (resolved).
await promise;

/**
* ** Your Turn **
* So, what will happen to `myAtom$` and `myMappedAtom$`?
* So, what will happen to `myAtom$`?
*/
expect(myAtom$.get()).toBe(15);
expect(myAtom$.value).toBe(15);
expect(myAtom$.final).toBe(true);

// Now we make a promise that is rejected when called.
promise = Promise.reject('Oh no, I messed up!');
myAtom$ = fromPromise(promise);

// We cannot await the Promise itself, as it would immediately throw.
await Promise.resolve();
// As expected, the promise gets rejected.
await expect(promise).rejects.toBe('Oh no, I messed up!');

/**
* ** Your Turn **
Expand All @@ -544,7 +547,7 @@ describe('utils', () => {

it('`.toPromise()`', async () => {
/**
* `.toPromise()` returns a promise that is linked to the atom it is based on (`myAtom$` here)
* `.toPromise()` returns a promise that is linked to the atom it is based on (`myAtom$` here). Note how this is the reverse of `fromPromise()`.
* If the atom has a value, the promise is resolved. If the atom errors, the promise is rejected using the same error.
* And it the atom is unresolved, the promise is pending.
*/
Expand All @@ -556,24 +559,27 @@ describe('utils', () => {
* What do you think will happen when we try to set the atom with a value?
*/
myAtom$.set('second value');
expect(await promise).toBe('initial value'); // `myAtom$` starts with a value ('initial value'), so the promise is immediately resolved
// `.resolves` or `.rejects`? ↴
await expect(promise).resolves.toBe('initial value'); // `myAtom$` starts with a value ('initial value'), so the promise is immediately resolved

myAtom$.unset(); // reset

myAtom$.unset();
promise = myAtom$.toPromise();

/**
* ** Your Turn **
* We set the atom to `unresolved`. What will now happen when we try to set the atom with a value?
*/
myAtom$.set('third value');
expect(await promise).toBe('third value'); // This is now the first value the atom obtains since the promise was created.
// `.resolves` or `.rejects`? ↴
await expect(promise).resolves.toBe('third value'); // This is now the first value the atom obtains since the promise was created.

// Whenever an atom is in an `unresolved` state, the corresponding Promise is pending.
// This means that the Promise can still become resolved or rejected depending on the atom's actions.

myAtom$.unset();
promise = myAtom$.toPromise();
myAtom$.unset(); // reset

promise = myAtom$.toPromise();
myAtom$.setError('Error.');

/**
Expand All @@ -596,7 +602,7 @@ describe('utils', () => {

/**
* ** Your Turn **
* We now let `myDerivable$` derive from `myAtom$`, and it will throw a normal error (not a custom Sherlock error).
* We now let `myDerivable$` derive from `myAtom$`, which will throw a normal error (not a custom Sherlock error).
* What will the error message be this time?
*/
try {
Expand Down
4 changes: 2 additions & 2 deletions tutorial/3 - reacting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import { atom } from '@skunkteam/sherlock';
export const __YOUR_TURN__ = {} as any;
// xxx check my solutions with the actual solutions (https://github.com/skunkteam/sherlock/tree/tutorial-solutions/robin/tutorial)
// FIXME: remove all TODO: and FIXME:
// FIXME: check whether the generated tutorials and solutions actually work (e.g. are all solutions correct? No weird shenanigans?) - ALSO CHECK "Or, alternatively"!
// xxx check whether the generated tutorials and solutions actually work (e.g. are all solutions correct? No weird shenanigans?) -
// FIXME: ALSO CHECK "Or, alternatively"!
// FIXME: deze file niet linten / builden (voor automatische test). Tutorial ook niet. Maar solutions juist wel! OP EIND. (mag beide wel linten right?)
// FIXME: interne review document, mocht ik iets hebben om te laten zien! In Google Drive, zet het erin!
// xxx werkt `npm run tutorial` nog? > Nu wel.
// xxx PETER: "nu je toch met Sherlock bezig bent; zou je voor mij eens kunnen checken of de code voorbeelden in de README
// nog wel kloppen met de huidige API? Ik heb het gevoel dat dat niet zo is; volgens mij is er geen function "derivation()"
// en heet dat nu "derive()" bijvoorbeeld."
// FIXME: OOOOOOH JA, ik had eroverheen gepushed! Dat moet nog een PR met terugwerkende kracht worden... (of commits squashen, en dat ze dan maar de commit moeten reviewen?)

// FIXME: Add FromEventPattern + FromObservable
// xxx fix the generator for code blocks.
// FIXME: now check whether it did not remove excess lines or kept 2 empty lines where it should not. (I think it is good though.)
Expand Down
34 changes: 21 additions & 13 deletions tutorial/8 - utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,33 +517,36 @@ describe.skip('utils', () => {
* This translates Promises directly to Sherlock concepts we have discussed already.
*/
it('`fromPromise()`', async () => {
// we initialize a Promise that will resolve, not reject, when handled
/**
* `.fromPromise()` returns an atom that is linked to the Promise it is based on.
* We initialize a Promise that will resolve, not reject, when handled
*/
let promise = Promise.resolve(15);
let myAtom$ = fromPromise(promise);

/**
* ** Your Turn **
* What do you think is the default state of an atom based on a Promise?
*/
expect(myAtom$.resolved).toBe(__YOUR_TURN__);
expect(myAtom$.value).toBe(__YOUR_TURN__);
expect(myAtom$.final).toBe(__YOUR_TURN__);

// Now we wait for the Promise to be handled (resolved).
await promise;

/**
* ** Your Turn **
* So, what will happen to `myAtom$` and `myMappedAtom$`?
* So, what will happen to `myAtom$`?
*/
expect(myAtom$.get()).toBe(__YOUR_TURN__);
expect(myAtom$.value).toBe(__YOUR_TURN__);
expect(myAtom$.final).toBe(__YOUR_TURN__);

// Now we make a promise that is rejected when called.
promise = Promise.reject('Oh no, I messed up!');
myAtom$ = fromPromise(promise);

// We cannot await the Promise itself, as it would immediately throw.
await Promise.resolve();
// As expected, the promise gets rejected.
await expect(promise).rejects.toBe('Oh no, I messed up!');

/**
* ** Your Turn **
Expand All @@ -556,7 +559,7 @@ describe.skip('utils', () => {

it('`.toPromise()`', async () => {
/**
* `.toPromise()` returns a promise that is linked to the atom it is based on (`myAtom$` here)
* `.toPromise()` returns a promise that is linked to the atom it is based on (`myAtom$` here). Note how this is the reverse of `fromPromise()`.
* If the atom has a value, the promise is resolved. If the atom errors, the promise is rejected using the same error.
* And it the atom is unresolved, the promise is pending.
*/
Expand All @@ -568,24 +571,29 @@ describe.skip('utils', () => {
* What do you think will happen when we try to set the atom with a value?
*/
myAtom$.set('second value');
expect(await promise).toBe(__YOUR_TURN__);
// `.resolves` or `.rejects`? ↴
await expect(promise) /*__YOUR_TURN__*/
.toBe(__YOUR_TURN__);

myAtom$.unset(); // reset

myAtom$.unset();
promise = myAtom$.toPromise();

/**
* ** Your Turn **
* We set the atom to `unresolved`. What will now happen when we try to set the atom with a value?
*/
myAtom$.set('third value');
expect(await promise).toBe(__YOUR_TURN__);
// `.resolves` or `.rejects`? ↴
await expect(promise) /*__YOUR_TURN__*/
.toBe(__YOUR_TURN__);

// Whenever an atom is in an `unresolved` state, the corresponding Promise is pending.
// This means that the Promise can still become resolved or rejected depending on the atom's actions.

myAtom$.unset();
promise = myAtom$.toPromise();
myAtom$.unset(); // reset

promise = myAtom$.toPromise();
myAtom$.setError('Error.');

/**
Expand All @@ -608,7 +616,7 @@ describe.skip('utils', () => {

/**
* ** Your Turn **
* We now let `myDerivable$` derive from `myAtom$`, and it will throw a normal error (not a custom Sherlock error).
* We now let `myDerivable$` derive from `myAtom$`, which will throw a normal error (not a custom Sherlock error).
* What will the error message be this time?
*/
try {
Expand Down

0 comments on commit 3739e8a

Please sign in to comment.