Skip to content

Commit

Permalink
My solutions for the tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
untio11 committed Nov 23, 2023
1 parent ec2aac7 commit 80f3171
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 150 deletions.
9 changes: 5 additions & 4 deletions tutorial/1 - intro.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('intro', () => {
* This can also be indicated with the `__YOUR_TURN__` variable.
*
* It should be clear what to do here... */
bool = __YOUR_TURN__;
bool = true;
expect(bool).toBeTrue();
// We use expectations like this to verify the result.
});
Expand All @@ -55,7 +55,7 @@ describe('intro', () => {
* ** Your Turn **
* Remove the `.skip` so this part of the tutorial will run.
*/
describe.skip('the basics', () => {
describe('the basics', () => {
/**
* The `Atom` is the basic building block of `@skunkteam/sherlock`.
* It holds a value which you can `get()` and `set()`.
Expand All @@ -73,6 +73,7 @@ describe.skip('the basics', () => {

// ** Your Turn **
// Use the `.set(<newValue>)` method to change the value of the `Atom`.
myValue$.set(2);
expect(myValue$.get()).toEqual(2);
});

Expand All @@ -97,7 +98,7 @@ describe.skip('the basics', () => {
* negative to a positive number and vice versa) of the original `Atom`.
*/
// Use `myValue$.derive(val => ...)` to implement `myInverse$`.
const myInverse$ = myValue$.derive(__YOUR_TURN__ => __YOUR_TURN__);
const myInverse$ = myValue$.derive(val => -val);
expect(myInverse$.get()).toEqual(-1);
// So if we set `myValue$` to -2:
myValue$.set(-2);
Expand All @@ -122,7 +123,7 @@ describe.skip('the basics', () => {
*
* Now react to `myCounter$`. In every `react()`.
* Increase the `reacted` variable by one. */
myCounter$.react(() => __YOUR_TURN__);
myCounter$.react(() => reacted++);
expect(reacted).toEqual(1);
// `react()` will react immediately, more on that later.

Expand Down
34 changes: 20 additions & 14 deletions tutorial/2 - deriving.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe.skip('deriving', () => {
*/

// We can combine txt with `repeat$.get()` here.
const lyric$ = text$.derive(txt => txt /* __YOUR_TURN__ */);
const lyric$ = text$.derive(txt => txt.repeat(repeat$.get()));

expect(lyric$.get()).toEqual(`It won't be long`);

Expand Down Expand Up @@ -74,12 +74,18 @@ describe.skip('deriving', () => {
*/

// Should return 'Fizz' when `myCounter$` is a multiple of 3 and '' otherwise.
const fizz$: Derivable<string> = myCounter$.derive(__YOUR_TURN__);
const fizz$: Derivable<string> = myCounter$.derive(value => {
return value % 3 ? '' : 'Fizz';
});

// Should return 'Buzz' when `myCounter$` is a multiple of 5 and '' otherwise.
const buzz$: Derivable<string> = myCounter$.derive(__YOUR_TURN__);
const buzz$: Derivable<string> = myCounter$.derive(value => {
return value % 5 ? '' : 'Buzz';
});

const fizzBuzz$: Derivable<string | number> = derive(__YOUR_TURN__);
const fizzBuzz$: Derivable<string | number> = derive(() => {
return fizz$.get() + buzz$.get() || myCounter$.get();
});

expect(fizz$.get()).toEqual('');
expect(buzz$.get()).toEqual('');
Expand Down Expand Up @@ -153,9 +159,9 @@ describe.skip('deriving', () => {
const tweetCount = pastTweets.length;
const lastTweet = pastTweets[tweetCount - 1];

expect(tweetCount).toEqual(__YOUR_TURN__); // Is there a new tweet?
expect(lastTweet).toContain(__YOUR_TURN__); // Who sent it? Donald? Or Barack?
expect(lastTweet).toContain(__YOUR_TURN__); // What did he tweet?
expect(tweetCount).toEqual(3); // Is there a new tweet?
expect(lastTweet).toContain('Donald'); // Who sent it? Donald? Or Barack?
expect(lastTweet).toContain('politics'); // What did he tweet?

/**
* As you can see, this is something to look out for.
Expand Down Expand Up @@ -200,17 +206,17 @@ describe.skip('deriving', () => {
*/
const fizz$ = myCounter$
.derive(count => count % 3)
.is(__YOUR_TURN__)
.and(__YOUR_TURN__)
.or(__YOUR_TURN__) as Derivable<string>;
.is(0)
.and('Fizz')
.or('') as Derivable<string>;

const buzz$ = myCounter$
.derive(count => count % 5)
.is(__YOUR_TURN__)
.and(__YOUR_TURN__)
.or(__YOUR_TURN__) as Derivable<string>;
.is(0)
.and('Buzz')
.or('') as Derivable<string>;

const fizzBuzz$ = derive(() => fizz$.get() + buzz$.get()).or(__YOUR_TURN__);
const fizzBuzz$ = derive(() => fizz$.get() + buzz$.get()).or(myCounter$);

for (let count = 1; count <= 100; count++) {
// Set the value of the `Atom`,
Expand Down
41 changes: 27 additions & 14 deletions tutorial/3 - reacting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ describe.skip('reacting', () => {
* Time to react to `myAtom$` with the `reactor()` function defined
* above.
*/

myAtom$.react(reactor);
expectReact(1, 'initial value');

// Now set a 'new value' to `myAtom$`.

myAtom$.set('new value');
expectReact(2, 'new value');
});

Expand All @@ -99,7 +99,7 @@ describe.skip('reacting', () => {
*
* catch the returned `stopper` in a variable
*/
myAtom$.react(reactor);
let stopper = myAtom$.react(reactor);

expectReact(1, 'initial value');

Expand All @@ -108,7 +108,7 @@ describe.skip('reacting', () => {
*
* Call the `stopper`.
*/

stopper();
myAtom$.set('new value');

// And the reaction stopped.
Expand All @@ -130,9 +130,9 @@ describe.skip('reacting', () => {
* In the reaction below, use the stopper callback to stop the
* reaction
*/
myAtom$.react((val, __YOUR_TURN___) => {
myAtom$.react((val, stop) => {
reactor(val);
__YOUR_TURN___;
stop();
});

expectReact(1, 'initial value');
Expand Down Expand Up @@ -185,7 +185,7 @@ describe.skip('reacting', () => {
*
* Try giving `boolean$` as `until` option.
*/
string$.react(reactor, __YOUR_TURN__);
string$.react(reactor, { until: boolean$ });

// It should react directly as usual.
expectReact(1, 'Value');
Expand Down Expand Up @@ -233,7 +233,13 @@ describe.skip('reacting', () => {
* Use `!string$.get()` to return `true` when the `string` is
* empty.
*/
string$.react(reactor, __YOUR_TURN__);
let stringEmpty = function () {
return !string$.get();
};

string$.react(reactor, {
until: stringEmpty,
});

// It should react as usual:
string$.set('New value');
Expand Down Expand Up @@ -261,7 +267,7 @@ describe.skip('reacting', () => {
* Try using the first parameter of the `until` function to do
* the same as above.
*/
string$.react(reactor, __YOUR_TURN__);
string$.react(reactor, { until: parent$ => !parent$.get() });

// It should react as usual.
string$.set('New value');
Expand Down Expand Up @@ -305,7 +311,7 @@ describe.skip('reacting', () => {
*
* *Hint: remember the `.is()` method from tutorial 2?*
*/
sherlock$.react(reactor, __YOUR_TURN__);
sherlock$.react(reactor, { from: parent$ => parent$.is('dear') });

expectReact(0);
['Elementary,', 'my', 'dear', 'Watson'].forEach(txt => sherlock$.set(txt));
Expand Down Expand Up @@ -334,7 +340,7 @@ describe.skip('reacting', () => {
* Now, let's react to all even numbers.
* Except 4, we don't want to make it too easy now.
*/
count$.react(reactor, __YOUR_TURN__);
count$.react(reactor, { when: parent$ => parent$.derive(value => value % 2 == 0 && value != 4) });

expectReact(1, 0);

Expand All @@ -361,7 +367,7 @@ describe.skip('reacting', () => {
*
* Say you want to react when `done$` is true. But not right away..
*/
done$.react(reactor, __YOUR_TURN__);
done$.react(reactor, { skipFirst: true });
expectReact(0);

done$.set(true);
Expand All @@ -387,7 +393,10 @@ describe.skip('reacting', () => {
*
* *Hint: you will need to combine `once` with another option*
*/
finished$.react(reactor, __YOUR_TURN__);
finished$.react(reactor, {
once: true,
skipFirst: true,
});
expectReact(0);

// When finished it should react once.
Expand All @@ -414,7 +423,11 @@ describe.skip('reacting', () => {
* `connected$` indicates the current connection status.
* This should be possible with three simple ReactorOptions
*/
connected$.react(reactor, __YOUR_TURN__);
connected$.react(reactor, {
skipFirst: true,
once: true,
from: parent$ => parent$,
});

// It starts as 'not connected'
expectReact(0);
Expand Down
50 changes: 25 additions & 25 deletions tutorial/4 - inner workings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const __YOUR_TURN__ = {} as any;
/**
* Time to dive a bit deeper into the inner workings of `@skunkteam/sherlock`.
*/
describe.skip('inner workings', () => {
describe('inner workings', () => {
/**
* What if there is a derivation that reads from one of two `Derivable`s
* dynamically? Will both of those `Derivable`s be tracked for changes?
Expand Down Expand Up @@ -43,8 +43,8 @@ describe.skip('inner workings', () => {
*
* What do you expect?
*/
expect(reacted).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(reacted).toHaveBeenLastCalledWith(__YOUR_TURN__, expect.toBeFunction());
expect(reacted).toHaveBeenCalledTimes(1);
expect(reacted).toHaveBeenLastCalledWith(1, expect.toBeFunction());

// `switch$` is still set to true (number)
number$.set(2);
Expand All @@ -54,8 +54,8 @@ describe.skip('inner workings', () => {
*
* What do you expect?
*/
expect(reacted).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(reacted).toHaveBeenLastCalledWith(__YOUR_TURN__, expect.toBeFunction());
expect(reacted).toHaveBeenCalledTimes(2);
expect(reacted).toHaveBeenLastCalledWith(2, expect.toBeFunction());

// Now let's reset the mock function, so the call count should
// be 0 again.
Expand All @@ -71,8 +71,8 @@ describe.skip('inner workings', () => {
*
* What do you expect now?
*/
expect(reacted).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(reacted).toHaveBeenLastCalledWith(__YOUR_TURN__, expect.toBeFunction());
expect(reacted).toHaveBeenCalledTimes(1);
expect(reacted).toHaveBeenLastCalledWith('two', expect.toBeFunction());
});

/**
Expand All @@ -98,17 +98,17 @@ describe.skip('inner workings', () => {
*/

// Well, what do you expect?
expect(hasDerived).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasDerived).toHaveBeenCalledTimes(0);

myDerivation$.get();

// And after a `.get()`?
expect(hasDerived).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasDerived).toHaveBeenCalledTimes(1);

myDerivation$.get();

// And after the second `.get()`? Is there an extra call?
expect(hasDerived).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasDerived).toHaveBeenCalledTimes(2);

/**
* The state of any `Derivable` can change at any moment.
Expand Down Expand Up @@ -147,27 +147,27 @@ describe.skip('inner workings', () => {
*
* Ok, it's your turn to complete the expectations.
*/
expect(hasDerived).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasDerived).toHaveBeenCalledTimes(1);

myDerivation$.get();

expect(hasDerived).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasDerived).toHaveBeenCalledTimes(1);

myAtom$.set(false);

expect(hasDerived).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasDerived).toHaveBeenCalledTimes(2);

myDerivation$.get();

expect(hasDerived).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasDerived).toHaveBeenCalledTimes(2);

stopper();

expect(hasDerived).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasDerived).toHaveBeenCalledTimes(2);

myDerivation$.get();

expect(hasDerived).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasDerived).toHaveBeenCalledTimes(3);

/**
* Since the `.react()` already listens to the value(changes) there is
Expand Down Expand Up @@ -212,23 +212,23 @@ describe.skip('inner workings', () => {
// Note that this is the same value as it was initialized with
myAtom$.set(1);

expect(first).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(second).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(first).toHaveBeenCalledTimes(1);
expect(second).toHaveBeenCalledTimes(1);

myAtom$.set(2);

expect(first).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(second).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(first).toHaveBeenCalledTimes(2);
expect(second).toHaveBeenCalledTimes(1);

myAtom$.set(3);

expect(first).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(second).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(first).toHaveBeenCalledTimes(3);
expect(second).toHaveBeenCalledTimes(2);

myAtom$.set(4);

expect(first).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(second).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(first).toHaveBeenCalledTimes(4);
expect(second).toHaveBeenCalledTimes(2);

/**
* Can you explain the behavior above?
Expand Down Expand Up @@ -265,7 +265,7 @@ describe.skip('inner workings', () => {
* The `Atom` is set with exactly the same object as before. Will the
* `.react()` fire?
*/
expect(hasReacted).toHaveBeenCalledTimes(__YOUR_TURN__);
expect(hasReacted).toHaveBeenCalledTimes(1);

/**
* But what if you use an object, that can be easily compared through a
Expand Down
Loading

0 comments on commit 80f3171

Please sign in to comment.