Write two functions that decide whether to call fn by counting the calls to the function they return.
before(n, fn) returns a function that calls fn while it has been called fewer than n times, so for the first n - 1 calls. From the nth call on, it stops calling fn and returns the result of the last call that did, or undefined if none did.
after(n, fn) returns a function that does nothing and returns undefined for the first n - 1 calls, then calls fn on the nth call and on every call after it.
Whenever fn runs, it gets the caller's this and arguments, and its result is returned. Every returned function counts its own calls.
const twice = before(3, (x) => x * 2);
twice(1); // 2
twice(2); // 4
twice(3); // 4: fn isn't called any more
const done = after(3, () => "all loaded");
done(); // undefined
done(); // undefined
done(); // "all loaded"
done(); // "all loaded"
const fn = spy();
const limited = before(3, fn);
limited();
limited();
expect(fn).toHaveBeenCalledTimes(2);
limited();
limited();
expect(fn).toHaveBeenCalledTimes(2);
const double = before(3, (x) => x * 2);
expect(double(1)).toBe(2);
expect(double(2)).toBe(4);
expect(double(3)).toBe(4);
expect(double(10)).toBe(4);
const fn = spy(() => "ran");
const never = before(1, fn);
expect(never()).toBeUndefined();
expect(never()).toBeUndefined();
expect(fn).not.toHaveBeenCalled();
const fn = spy();
const done = after(3, fn);
done();
done();
expect(fn).not.toHaveBeenCalled();
done();
expect(fn).toHaveBeenCalledTimes(1);
done();
expect(fn).toHaveBeenCalledTimes(2);
const ready = after(2, (x) => x + 1);
expect(ready(1)).toBeUndefined();
expect(ready(5)).toBe(6);
expect(ready(7)).toBe(8);
const fn = spy();
const always = after(1, fn);
always();
always();
expect(fn).toHaveBeenCalledTimes(2);
const early = spy();
const late = spy();
const obj = { early: before(2, early), late: after(1, late) };
obj.early("a", 1);
obj.late("b", 2);
expect(early.calls[0].this).toBe(obj);
expect(early).toHaveBeenCalledWith("a", 1);
expect(late.calls[0].this).toBe(obj);
expect(late).toHaveBeenCalledWith("b", 2);
const fn = spy();
const first = after(2, fn);
const second = after(2, fn);
first();
second();
expect(fn).not.toHaveBeenCalled();
first();
expect(fn).toHaveBeenCalledTimes(1);
const other = spy();
const one = before(2, other);
const two = before(2, other);
one();
two();
expect(other).toHaveBeenCalledTimes(2);
Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.
Ctrl + Enter runs the tests (⌘ + Enter on a Mac).
I'm here to help with Before and after. I give hints, never the solution, so you get to solve it yourself. Ask for a hint, select code to ask about it, or press Ask Tuto why on a failing test.
Your first 3 answers need no account. for free to keep asking.