Skip to content

Commit 2362b9c

Browse files
author
Fil Maj
authored
fix: do not proxy then. fixes #107 (#108)
1 parent 26fcdd6 commit 2362b9c

File tree

2 files changed

+50
-18
lines changed

2 files changed

+50
-18
lines changed

src/api-proxy.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { BaseSlackAPIClient } from "./base-client.ts";
22
import { BaseResponse, SlackAPIClient, SlackAPIMethodArgs } from "./types.ts";
33

4+
const DO_NOT_PROXY = ["then"];
5+
46
type APICallback = {
57
(method: string, payload?: SlackAPIMethodArgs): Promise<BaseResponse>;
68
};
@@ -46,7 +48,10 @@ export const APIProxy = (
4648
const proxy = new Proxy(objectToProxy, {
4749
get(obj, prop) {
4850
// We're attempting to access a property that doesn't exist, so create a new nested proxy
49-
if (typeof prop === "string" && !(prop in obj)) {
51+
if (
52+
typeof prop === "string" && !DO_NOT_PROXY.includes(prop) &&
53+
!(prop in obj)
54+
) {
5055
return APIProxy(null, apiCallback, ...path, prop);
5156
}
5257

src/api-proxy_test.ts

+44-17
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,57 @@ import { BaseSlackAPIClient } from "./base-client.ts";
33
import { SlackAPIMethodArgs } from "./types.ts";
44
import { assertSpyCall, spy } from "./dev_deps.ts";
55

6-
Deno.test("APIProxy", async () => {
6+
Deno.test("APIProxy", async (t) => {
77
const baseClient = new BaseSlackAPIClient("test-token");
8-
const clientToProxy = {
9-
apiCall: baseClient.apiCall.bind(baseClient),
10-
response: baseClient.response.bind(baseClient),
11-
};
8+
const generateClientProxy = (client: BaseSlackAPIClient) => ({
9+
apiCall: client.apiCall.bind(client),
10+
response: client.response.bind(client),
11+
});
12+
13+
await t.step("should proxy legit Slack API calls", async () => {
14+
const clientToProxy = generateClientProxy(baseClient);
15+
16+
const apiCallHandler = (_method: string, _payload?: SlackAPIMethodArgs) => {
17+
return Promise.resolve({
18+
ok: true,
19+
toFetchResponse: () => new Response(),
20+
});
21+
};
22+
const apiCallHandlerSpy = spy(apiCallHandler);
1223

13-
const apiCallHandler = (_method: string, _payload?: SlackAPIMethodArgs) => {
14-
return Promise.resolve({ ok: true, toFetchResponse: () => new Response() });
15-
};
16-
const apiCallHandlerSpy = spy(apiCallHandler);
24+
const client = APIProxy(clientToProxy, apiCallHandlerSpy);
1725

18-
const client = APIProxy(clientToProxy, apiCallHandlerSpy);
26+
const payload = { text: "proxied call", channel: "" };
27+
await client.chat.postMessage(payload);
1928

20-
const payload = { text: "proxied call", channel: "" };
21-
await client.chat.postMessage(payload);
29+
assertSpyCall(apiCallHandlerSpy, 0, {
30+
args: ["chat.postMessage", payload],
31+
});
2232

23-
assertSpyCall(apiCallHandlerSpy, 0, {
24-
args: ["chat.postMessage", payload],
33+
await client.admin.apps.approved.list();
34+
35+
assertSpyCall(apiCallHandlerSpy, 1, {
36+
args: ["admin.apps.approved.list", undefined],
37+
});
2538
});
2639

27-
await client.admin.apps.approved.list();
40+
await t.step("should not proxy Promise methods like `then`", () => {
41+
const clientToProxy = generateClientProxy(baseClient);
42+
43+
const apiCallHandler = (_method: string, _payload?: SlackAPIMethodArgs) => {
44+
return Promise.resolve({
45+
ok: true,
46+
toFetchResponse: () => new Response(),
47+
});
48+
};
49+
const apiCallHandlerSpy = spy(apiCallHandler);
50+
51+
const client = APIProxy(clientToProxy, apiCallHandlerSpy);
2852

29-
assertSpyCall(apiCallHandlerSpy, 1, {
30-
args: ["admin.apps.approved.list", undefined],
53+
// re: https://github.com/slackapi/deno-slack-api/issues/107
54+
// @ts-expect-error client does not have `then` but thenable feature detection at runtime may invoke or test for the method
55+
if (client.then) {
56+
throw new Error("APIProxy should have no `then`!");
57+
}
3158
});
3259
});

0 commit comments

Comments
 (0)