AniUI Academy

Build a spy that records its calls

mediumFunctions & Closures+250 XPPractice

When you assert that a component called onSelect with the right row, you are using a spy. It is a wrapper that passes everything through and keeps a log on the side, and it is about fifteen lines of closure.

Implement createSpy(fn). It returns a spy function that forwards its arguments to fn and returns fn's return value, while recording: spy.calls, an array holding one array of arguments per call, in call order; spy.results, an array of the values returned by each call, in the same order; and spy.callCount, the number of calls. All three start empty or at zero. spy.reset() clears calls and results back to empty arrays and callCount back to 0. createSpy() may also be called with no function at all, in which case the spy records calls as usual and returns undefined.

Arguments

fnFunction | undefined
Optional function to proxy. If omitted, the spy records calls and returns undefined.

Returns

Function & { calls: any[][]; results: any[]; callCount: number; reset(): void } — A spy that behaves like fn while exposing a call log and a reset() method.

Examples

const spy = createSpy((a, b) => a + b);

spy(1, 2);        // 3
spy(10, 20);      // 30
spy.calls;        // [[1, 2], [10, 20]]
spy.results;      // [3, 30]
spy.callCount;    // 2
const noop = createSpy();
noop("hi");
noop.calls;    // [["hi"]]
noop.callCount; // 1 — recording still works with no fn to wrap

What it has to do

  • spy.calls holds one array of arguments per call, in order.
  • spy.results holds each call's return value, in order.
  • spy.callCount matches the number of calls, and the spy returns fn's value.
  • spy.reset() empties calls and results and zeroes callCount.
  • With no function to wrap, the spy still records and returns undefined.

Notes

  • A rest parameter already gives you the arguments as an array to push — no need to copy from arguments.
  • reset() has to reassign to fresh arrays, not call .length = 0: references the test holds to the old arrays would otherwise mutate underneath them.

Stuck? The javascript course covers everything this challenge needs.

Try it yourself
Loading playground...
5 tests · +250 XP

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.