Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding lots of new tests for the tutorial and solution #64

Draft
wants to merge 31 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1d2cf7b
Added sinon and chai back to devDependencies
untio11 Nov 7, 2023
e18daad
Added tutorial folder from politie-sherlock
untio11 Nov 7, 2023
c57801a
Made the tests runnable with jest
untio11 Nov 9, 2023
89b4d83
Got test 1 in working order
untio11 Nov 9, 2023
5c15c5e
Got test 2 in working order
untio11 Nov 9, 2023
d377fa0
Got test 3 in working order
untio11 Nov 9, 2023
a20df39
Got test 4 in working order (I think)
untio11 Nov 10, 2023
c35c5eb
Got test 5 in working order
untio11 Nov 10, 2023
7f7ff7d
Fixed weird import issues when running tutorials
untio11 Nov 15, 2023
8957c53
Got tutorial 7 in a working state
untio11 Nov 15, 2023
a198244
Got tutorial 8 in working state
untio11 Nov 17, 2023
dfc094f
Got tutorial 9 in working state
untio11 Nov 17, 2023
8a60b74
Updated some comments
untio11 Nov 17, 2023
bfec2d7
Added placeholder code for tutorial 6
untio11 Nov 17, 2023
8526f94
Finalized tutorial 1
untio11 Nov 17, 2023
9468e19
Finalized tutorial 2
untio11 Nov 17, 2023
077a3f8
Finalized tutorial 3
untio11 Nov 20, 2023
0883841
Finalized tutorial 4
untio11 Nov 21, 2023
feec43d
Finalized tutorial 5
untio11 Nov 21, 2023
03b5aa0
Finalized tutorial 7
untio11 Nov 22, 2023
748978d
Finalized tutorial 8
untio11 Nov 22, 2023
ec2aac7
Finalized tutorial 9
untio11 Nov 22, 2023
eef2e33
Added lots of content to the tutorials
Nickname5862 Jul 16, 2024
bf9c621
added a tutorial-and-solution-generator; added tons of tests
Nickname5862 Jul 18, 2024
cf31e4d
Added more tests; renamed the folders; improved the generator; README…
Nickname5862 Jul 25, 2024
3739e8a
Added '.rejects' and '.resolves' to tutorial 8
Nickname5862 Jul 29, 2024
ef9b79a
All content has now been added.
Nickname5862 Sep 26, 2024
0ee30de
Merge branch 'main' into tutorial-base
Nickname5862 Sep 26, 2024
571e046
Moved generator file
Nickname5862 Sep 26, 2024
6216e85
Small ReadMe update
Nickname5862 Sep 26, 2024
cd8caee
Update to `npm run generate` command
Nickname5862 Sep 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
"source.fixAll": true
"source.organizeImports": "explicit",
"source.fixAll": "explicit"
},
"json.schemas": [
{
Expand Down
29 changes: 20 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ let currentPageNumber$ = atom(0);

// We simply use a lambda function to define currentPage$ as a derivation of currentBook$
// and currentFontSize$ using calculatePages. Sherlock automatically records all dependencies.
let currentPages$ = derivation(() => calculatePages(currentBook$.get(), currentFontSize$.get()));
let currentPages$ = derive(() => calculatePages(currentBook$.get(), currentFontSize$.get()));

// currentPage$ is always equal to the element in currentPages$ at position currentPageNumber$.
let currentPage$ = currentPages$.pluck(currentPageNumber$);
Expand Down Expand Up @@ -145,28 +145,39 @@ There are three types of Derivables:
```typescript
const isBrilliant$ = name$.derive(name => name === 'Sherlock');

isBrilliant$.get(); // false
isBrilliant$.get(); // => false

name$.set('Sherlock');

isBrilliant$.get(); // true
isBrilliant$.get(); // => true
```

Derivations can also be created with the generic `derivation` function as seen earlier. This function can be used to do an arbitrary calculation on any number of derivables. `@skunkteam/sherlock` automatically records which derivable is dependent on which other derivable to be able to update derived state when needed.
Derivations can also be created with the generic `derive` function as seen earlier. This function can be used to do an arbitrary calculation on any number of derivables. `@skunkteam/sherlock` automatically records which derivable is dependent on which other derivable to be able to update derived state when needed.

## Reactors

To execute side effects, you can react to changes on any derivable as seen in an earlier example.
To execute side effects, you can react to changes on any derivable as seen in an earlier example. This can be done using the `#react` method that is present on all derivables.

_More documentation coming soon_
```typescript
const normalEffect = atom('');
let sideEffect = '';

## Transactions
normalEffect.react(v => {
sideEffect = v.replace('effect', 'side-effect');
});

_More documentation coming soon_
normalEffect.set('Watch this effect');
sideEffect; // => 'Watch this side-effect'
```

## Interoperability with RxJS out of the box

_Coming soon_
RxJS is another popular reactive library. However, RxJS can become quite complicated and user-unfriendly when your application becomes big. This was the main reason why Sherlock was developed. As Angular uses RxJS, and we use Angualr, our Sherlock library needs to be compatible with RxJS. The `fromObservable()` and `toObservable()` functions are used for this. However, the `from()` function in RxJS has become a succesful alternative to `toObservable()`.
`fromObservable()` can be used to map an `Observable` to a `Derivable`, and the `from()` function in RxJS can be used to map a `Derivable` to a `Derivable`.

## Transactions

_More documentation coming soon_

## Proxies using sherlock-proxies

Expand Down
153 changes: 153 additions & 0 deletions generator/1 - intro.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { atom } from '@skunkteam/sherlock';

// #QUESTION-BLOCK-START
/**
* ** Your Turn **
* If you see this variable, you should do something about it. :-)
*/
export const __YOUR_TURN__ = {} as any;
// #QUESTION-BLOCK-END
/**
* Welcome to the `@skunkteam/sherlock` tutorial.
*
* It is set up as a collection of specs, with the goal of getting all the specs
* to pass. The `expect()`s and basic setup are there, you just need to get it
* to work.
*
* All specs are set to `.skip`. Remove this to start on
* that part of the tutorial.
*
* Start the tutorial by running:
* `npm run tutorial`.
*
* To not manually re-enter the command, use:
* `npm run tutorial -- --watch`
* This will automatically rerun the tests when a file change has been detected.
*
* *Hint: most methods and functions are fairly well documented in jsDoc,
* which is easily accessed through TypeScript*
*
* If you cannot figure it out or are curious to the intended answers, you can
* read the answers in the `solution` folder.
*/

/**
* ** Your Turn **
* Your first task: remove this `.skip`.
* */
describe('intro', () => {
it(`

--- Welcome to the tutorial! ---

Please look in \`./tutorial/1 - intro.test.ts\` to see what to do next.`, () => {
// At the start of the spec, there will be some setup.
let bool = false;

// Sometimes including an expectation, to show the current state.
expect(bool).toBeFalse();

/**
* If ** Your Turn ** is shown in a comment, there is work for you to do.
* This can also be indicated with the `__YOUR_TURN__` variable.
*
* It should be clear what to do here... */
bool = __YOUR_TURN__; // #QUESTION
bool = true; // #ANSWER
expect(bool).toBeTrue();
// We use expectations like this to verify the result.
});
});

/**
* Let's start with the `Derivable` basics.
*
* ** Your Turn **
* Remove the `.skip` so this part of the tutorial will run.
*/
describe('the basics', () => {
/**
* The `Atom` is the basic building block of `@skunkteam/sherlock`.
* It holds a value which you can `get()` and `set()`.
*/
it('the `Atom`', () => {
// An `Atom` can be created with the `atom()` function. The parameter
// of this function is used as the initial value of the `Atom`.
const myValue$ = atom(1);
// Variables containing `Atom`s or any other `Derivable` are usually
// postfixed with a `$` to indicate this. Hence `myValue$`.

// The `.get()` method can be used to get the current value of
// the `Atom`.
expect(myValue$.get()).toEqual(1);

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

/**
* The `Atom` is a `Derivable`. This means it can be used to create a
* derived value. This derived value stays up to date with the original
* `Atom`.
*
* The easiest way to do this, is to call `.derive()` on another
* `Derivable`.
*
* Let's try this.
*/
it('the `Derivable`', () => {
const myValue$ = atom(1);
expect(myValue$.get()).toEqual(1);

/**
* ** Your Turn **
*
* We want to create a new `Derivable` that outputs the inverse (from a
* 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__); // #QUESTION
const myInverse$ = myValue$.derive(val => -val); // #ANSWER
expect(myInverse$.get()).toEqual(-1);
// So if we set `myValue$` to -2:
myValue$.set(-2);
// `myInverse$` will change accordingly.
expect(myInverse$.get()).toEqual(2);
});

/**
* Of course, `Derivable`s are not only meant to get, set and derive state.
* You can also listen to the changes.
*
* This is done with the `.react()` method.
* This method is given a function that is executed every time the value of
* the `Derivable` changes.
*/
it('reacting to `Derivable`s', () => {
const myCounter$ = atom(0);
let reacted = 0;

/**
* ** Your Turn **
*
* Now react to `myCounter$`. In every `react()`.
* Increase the `reacted` variable by one. */
myCounter$.react(() => __YOUR_TURN__); // #QUESTION
myCounter$.react(() => reacted++); // #ANSWER
expect(reacted).toEqual(1);
// `react()` will react immediately, more on that later.

/**
* And then we set the `Atom` a couple of times
* to make the `Derivable` react.
* */
for (let i = 0; i <= 100; i++) {
// Set the value of the `Atom`.
myCounter$.set(i);
}

expect(reacted).toEqual(101);
});
});
Loading
Loading