Sooooo, I got owned by a simple test in a NestJs Jest test because I honestly didn't know what I was doing. My favourite development strategy is brute force. I have no problem with this method since I realised it's a process of illumination where I try all that I know before I begin my hunt for answers on stack overflow and the rest of the big scary internet.
To understand how I messed this up, I decided to break down the function I was trying to test into smaller pieces.
But, enough about me.....for now.
The service
The service I was testing looked like this 👇🏿
this.service.lookup(reqUrl).pipe(map((res)=>res.map(.)));
Where the lookup function returned an Array wrapped in an RxJs Observable.
The service calls an endpoint to retrieve some data. Basic stuff right. Well from me trying to test this felt like I was stuck inside the upside-down without Jane (aka Eleven).
The first set of errors I got was the .map is not a function, which is the compiler's way of saying:
Array.map(): prototype of Array
'Yoooo, dude, this is not an Array, map won't work here.'
Observable.map(): imported from Rxjs
'Yoooo, dude, this is not an Observable, map won't work here.'
Array vs Observarble pipe
What are the differences between Array map and rxjs map
The error was confusing to me since I thought that the data being returned was an Array. Essentially this wasn't the main problem but I was led down a rabbit hole for 1.5 hours, which led me to write this article.
After my buddy, Toma, fixed it haha, thanks bro ✊🏿
Now time for the pipe dream
Since I can know HOW the service call is invoked and that it returns data, what I didn't understand was what .pipe does.
In a nutshell, .pipe takes what is being returned and passed that returned value to the next function in the chain.
func(args In): funcRes {} <-- our starter function
pipe( <- passes its response into the pipe function
func1(funcRes), <- func1 use it and returns a func1Res
func2(func1Res) <- func2 uses func1Res and returns func2Res
); = func2Res <- out comes our baby func2Res
Another way to break this up is to create a custom pipe function. TypeOfNan made a simple example of how to demonstrate what .pipe does.
// Input string = "Stranger Things Season 4 Episode 7"
// Custom Pipe
const pipe = (...args) => args.reduce((acc, el) => el(acc));
// Create our 3 functions transfer
const titleFunc1 = '10 Weird Facts About Dogs';
const toLowerCaseFunc2 = (str1) => str1.toLowerCase();
const addHyphensFunc3 = (str2) => str2.replace(/\s/g, '-');
const slug = pipe(titleFunc1, toLowerCaseFunc2, addHyphensFunc3);
console.log(slug);
// Return string = Stranger-things-season-4-episode-7
Now knowing that the pipe function plays 'hot potato' with the return values from the functions passed through it, I can focus on the next, small parts. Thanks for reading I hope this helps.
References
MDN Web docs - Array.prototype.map()
Rxjs - Pipe
Stack overflow - What are the differences between Array map and rxjs map?
TypeOfNan - How to use pipe, the pipeline operator in javascript
Top comments (0)