Skip to content

Commit

Permalink
fix(processQueue): move callback on method level (#115)
Browse files Browse the repository at this point in the history
I think this the way it should have been done in the first place.

Queue should pass down args agnostically.
Methods should decide what to do with the args, whether it's a callback or not.

This change results in a better separation of concerns, and will allow
implementing callback in other methods without any arity constraint.
  • Loading branch information
tkrugg authored May 10, 2019
1 parent c02c178 commit 1ff8191
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 30 deletions.
12 changes: 12 additions & 0 deletions lib/__tests__/_cookieUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,16 @@ describe("cookieUtils", () => {
});
});
});
describe("getUserToken", () => {
it("should return the current userToken", () => {
const userToken = AlgoliaInsights.getUserToken();
expect(userToken).toEqual("007");
});
it("should accept a callback", () => {
AlgoliaInsights.getUserToken({}, (err, userToken) => {
expect(err).toEqual(null);
expect(userToken).toEqual("007");
});
});
});
});
25 changes: 12 additions & 13 deletions lib/__tests__/_processQueue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,37 +35,36 @@ describe("processQueue", () => {
});

it("should forward method calls that happen before the queue is processed", () => {
const callback = jest.fn();
globalObject.aa("init", { appID: "xxx", apiKey: "yyy" });
globalObject.aa("otherMethod", { objectIDs: ["1"] });
globalObject.aa("otherMethod", { objectIDs: ["1"] }, callback);

expect(insights.init).not.toHaveBeenCalled();
expect(insights.otherMethod).not.toHaveBeenCalled();

insights.processQueue(globalObject);

expect(insights.init).toHaveBeenCalledWith({ appID: "xxx", apiKey: "yyy" });
expect(insights.otherMethod).toHaveBeenCalledWith({ objectIDs: ["1"] });
expect(insights.otherMethod).toHaveBeenCalledWith(
{ objectIDs: ["1"] },
callback
);
});

it("should forward method calls that happen after the queue is processed", () => {
const callback = jest.fn();
insights.processQueue(globalObject);

expect(insights.init).not.toHaveBeenCalled();
expect(insights.otherMethod).not.toHaveBeenCalled();

globalObject.aa("init", { appID: "xxx", apiKey: "yyy" });
globalObject.aa("otherMethod", { objectIDs: ["1"] });

expect(insights.init).toHaveBeenCalledWith({ appID: "xxx", apiKey: "yyy" });
expect(insights.otherMethod).toHaveBeenCalledWith({ objectIDs: ["1"] });
});

it("should return method output in a callback", () => {
insights.processQueue(globalObject);

const callback = jest.fn();
globalObject.aa("otherMethod", { objectIDs: ["1"] }, callback);

expect(callback).toHaveBeenCalledWith(null, "otherMethodReturnedValue");
expect(insights.init).toHaveBeenCalledWith({ appID: "xxx", apiKey: "yyy" });
expect(insights.otherMethod).toHaveBeenCalledWith(
{ objectIDs: ["1"] },
callback
);
});
});
9 changes: 8 additions & 1 deletion lib/_cookieUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createUUID } from "./utils/uuid";
import { isFunction } from "./utils";

const COOKIE_KEY = "_ALGOLIA";

Expand Down Expand Up @@ -49,6 +50,12 @@ export function setUserToken(userToken: string | number): void {
}
}

export function getUserToken() {
export function getUserToken(
options?: any,
callback?: (err: any, userToken: string) => void
): string {
if (isFunction(callback)) {
callback(null, this._userToken);
}
return this._userToken;
}
21 changes: 6 additions & 15 deletions lib/_processQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,28 @@
*/
import { isFunction } from "./utils";

type QueueItemCallback = (err: any, res: any) => void;
type QueueItem = [string, any, QueueItemCallback?];

export function processQueue(globalObject) {
// Set pointer which allows renaming of the script
const pointer = globalObject["AlgoliaAnalyticsObject"] as string;

// Check if there is a queue
if (pointer) {
const queue: QueueItem[] = globalObject[pointer].queue || [];
const queue: IArguments[] = globalObject[pointer].queue || [];

// Loop queue and execute functions in the queue
queue.forEach(([functionName, functionArguments, functionCallback]) => {
queue.forEach((args: IArguments) => {
const [functionName, ...functionArguments] = [].slice.call(args);
if (functionName && isFunction((this as any)[functionName])) {
const output: any = this[functionName](functionArguments);
if (isFunction(functionCallback)) {
functionCallback(null, output);
}
this[functionName](...functionArguments);
}
});

// Reassign pointer
globalObject[pointer] = (
functionName: string,
functionArguments: any,
functionCallback: QueueItemCallback
...functionArguments: any[]
) => {
const output = (this as any)[functionName](functionArguments);
if (isFunction(functionCallback)) {
functionCallback(null, output);
}
(this as any)[functionName](...functionArguments);
};
}
}
5 changes: 4 additions & 1 deletion lib/insights.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ class AlgoliaAnalytics {

public ANONYMOUS_USER_TOKEN: string;
public setUserToken: (userToken: string) => void;
public getUserToken: () => string;
public getUserToken: (
options?: any,
callback?: (err: any, userToken: string) => void
) => string;

public clickedObjectIDsAfterSearch: (
params?: InsightsSearchClickEvent
Expand Down

0 comments on commit 1ff8191

Please sign in to comment.