Skip to content

Commit 99179a3

Browse files
committed
More tests!
1 parent a6abcb8 commit 99179a3

File tree

3 files changed

+113
-57
lines changed

3 files changed

+113
-57
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
jest.mock("simple-oauth2", () => {
2+
return {
3+
ClientCredentials: jest.fn().mockImplementation(() => {
4+
return {
5+
getToken: jest.fn().mockResolvedValue({
6+
token: {
7+
access_token: "mocked-oauth-token",
8+
},
9+
expired: jest.fn().mockReturnValue(false),
10+
}),
11+
};
12+
}),
13+
};
14+
});

packages/sdk/src/server/__tests__/server.test.ts

Lines changed: 69 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,14 @@ import {
33
} from "../index";
44
import * as serverModule from "../index";
55
import fetchMock from "jest-fetch-mock";
6-
import {
7-
ClientCredentials, AccessToken,
8-
} from "simple-oauth2";
6+
import { ClientCredentials } from "simple-oauth2";
97

108
describe("ServerClient", () => {
119
let client: ServerClient;
1210

1311
beforeEach(() => {
14-
fetchMock.resetMocks(); // Reset fetch mocks before each test
15-
client = new ServerClient({
16-
publicKey: "test-public-key",
17-
secretKey: "test-secret-key",
18-
oauthClientId: "test-client-id",
19-
oauthClientSecret: "test-client-secret",
20-
});
12+
jest.clearAllMocks();
13+
fetchMock.resetMocks();
2114
});
2215

2316
describe("createClient", () => {
@@ -48,9 +41,14 @@ describe("ServerClient", () => {
4841
headers: {
4942
"Content-Type": "application/json",
5043
},
51-
}, // Add Content-Type header
44+
},
5245
);
5346

47+
client = new ServerClient({
48+
publicKey: "test-public-key",
49+
secretKey: "test-secret-key",
50+
});
51+
5452
const result = await client["_makeRequest"]("/test-path", {
5553
method: "GET",
5654
});
@@ -73,9 +71,14 @@ describe("ServerClient", () => {
7371
headers: {
7472
"Content-Type": "application/json",
7573
},
76-
}, // Add Content-Type header
74+
},
7775
);
7876

77+
client = new ServerClient({
78+
publicKey: "test-public-key",
79+
secretKey: "test-secret-key",
80+
});
81+
7982
const result = await client["_makeRequest"]("/test-path", {
8083
method: "POST",
8184
body: {
@@ -108,6 +111,11 @@ describe("ServerClient", () => {
108111
},
109112
});
110113

114+
client = new ServerClient({
115+
publicKey: "test-public-key",
116+
secretKey: "test-secret-key",
117+
});
118+
111119
await expect(client["_makeRequest"]("/bad-path")).rejects.toThrow("HTTP error! status: 404");
112120
expect(fetchMock).toHaveBeenCalledWith(
113121
"https://api.pipedream.com/v1/bad-path",
@@ -118,19 +126,29 @@ describe("ServerClient", () => {
118126

119127
describe("_makeApiRequest", () => {
120128
it("should include OAuth Authorization header and make an API request", async () => {
121-
const oauthToken = {
129+
// Create a mock oauthClient
130+
const getTokenMock = jest.fn().mockResolvedValue({
122131
token: {
123-
access_token: "oauth-token",
132+
access_token: "mocked-oauth-token",
124133
},
125134
expired: jest.fn().mockReturnValue(false),
126-
} as unknown as AccessToken;
127-
128-
client.oauthToken = oauthToken;
135+
});
129136

130-
client.oauthClient = {
131-
getToken: jest.fn().mockResolvedValue(oauthToken),
137+
const oauthClientMock = {
138+
getToken: getTokenMock,
132139
} as unknown as ClientCredentials;
133140

141+
// Inject the mock oauthClient into the ServerClient instance
142+
client = new ServerClient(
143+
{
144+
publicKey: "test-public-key",
145+
secretKey: "test-secret-key",
146+
oauthClientId: "test-client-id",
147+
oauthClientSecret: "test-client-secret",
148+
},
149+
oauthClientMock, // Inject mock oauthClient
150+
);
151+
134152
fetchMock.mockResponseOnce(
135153
JSON.stringify({
136154
success: true,
@@ -139,7 +157,7 @@ describe("ServerClient", () => {
139157
headers: {
140158
"Content-Type": "application/json",
141159
},
142-
}, // Add Content-Type header
160+
},
143161
);
144162

145163
const result = await client["_makeApiRequest"]("/test-path");
@@ -151,7 +169,7 @@ describe("ServerClient", () => {
151169
"https://api.pipedream.com/v1/test-path",
152170
expect.objectContaining({
153171
headers: expect.objectContaining({
154-
"Authorization": "Bearer oauth-token",
172+
"Authorization": "Bearer mocked-oauth-token",
155173
"Content-Type": "application/json",
156174
}),
157175
}),
@@ -170,9 +188,14 @@ describe("ServerClient", () => {
170188
headers: {
171189
"Content-Type": "application/json",
172190
},
173-
}, // Add Content-Type header
191+
},
174192
);
175193

194+
client = new ServerClient({
195+
publicKey: "test-public-key",
196+
secretKey: "test-secret-key",
197+
});
198+
176199
const result = await client.connectTokenCreate({
177200
app_slug: "test-app",
178201
external_user_id: "user-id",
@@ -212,9 +235,14 @@ describe("ServerClient", () => {
212235
headers: {
213236
"Content-Type": "application/json",
214237
},
215-
}, // Add Content-Type header
238+
},
216239
);
217240

241+
client = new ServerClient({
242+
publicKey: "test-public-key",
243+
secretKey: "test-secret-key",
244+
});
245+
218246
const result = await client.getAccounts({
219247
include_credentials: 1,
220248
});
@@ -234,24 +262,28 @@ describe("ServerClient", () => {
234262

235263
describe("invokeWorkflow", () => {
236264
it("should invoke a workflow with provided URL and body", async () => {
237-
const oauthToken = "oauth-token";
238-
239-
// Mock the OAuth token and client
240-
const oauthTokenObj = {
265+
// Create a mock oauthClient
266+
const getTokenMock = jest.fn().mockResolvedValue({
241267
token: {
242-
access_token: oauthToken,
268+
access_token: "mocked-oauth-token",
243269
},
244270
expired: jest.fn().mockReturnValue(false),
245-
} as unknown as AccessToken;
246-
247-
client.oauthToken = oauthTokenObj;
271+
});
248272

249-
client.oauthClient = {
250-
getToken: jest.fn().mockResolvedValue(oauthTokenObj),
273+
const oauthClientMock = {
274+
getToken: getTokenMock,
251275
} as unknown as ClientCredentials;
252276

253-
// Optionally, spy on the _oauthAuthorizationHeader method
254-
jest.spyOn(client, "_oauthAuthorizationHeader").mockResolvedValue(`Bearer ${oauthToken}`);
277+
// Inject the mock oauthClient into the ServerClient instance
278+
client = new ServerClient(
279+
{
280+
publicKey: "test-public-key",
281+
secretKey: "test-secret-key",
282+
oauthClientId: "test-client-id",
283+
oauthClientSecret: "test-client-secret",
284+
},
285+
oauthClientMock, // Inject mock oauthClient
286+
);
255287

256288
fetchMock.mockResponseOnce(
257289
JSON.stringify({
@@ -261,7 +293,7 @@ describe("ServerClient", () => {
261293
headers: {
262294
"Content-Type": "application/json",
263295
},
264-
}, // Add Content-Type header
296+
},
265297
);
266298

267299
const result = await client.invokeWorkflow("https://example.com/workflow", {
@@ -281,7 +313,7 @@ describe("ServerClient", () => {
281313
foo: "bar",
282314
}),
283315
headers: expect.objectContaining({
284-
"Authorization": `Bearer ${oauthToken}`,
316+
Authorization: "Bearer mocked-oauth-token",
285317
}),
286318
}),
287319
);

packages/sdk/src/server/index.ts

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -288,25 +288,35 @@ export function createClient(opts: CreateServerClientOpts) {
288288
* A client for interacting with the Pipedream Connect API on the server-side.
289289
*/
290290
export class ServerClient {
291-
secretKey?: string;
292-
publicKey?: string;
293-
oauthClient?: ClientCredentials;
294-
oauthToken?: AccessToken;
295-
baseURL: string;
291+
private secretKey?: string;
292+
private publicKey?: string;
293+
private oauthClient?: ClientCredentials;
294+
public oauthToken?: AccessToken;
295+
private baseURL: string;
296296

297297
/**
298298
* Constructs a new ServerClient instance.
299299
*
300300
* @param opts - The options for configuring the server client.
301+
* @param oauthClient - An optional OAuth client to use for authentication in tests
301302
*/
302-
constructor(opts: CreateServerClientOpts) {
303+
constructor(
304+
opts: CreateServerClientOpts,
305+
oauthClient?: ClientCredentials,
306+
) {
303307
this.secretKey = opts.secretKey;
304308
this.publicKey = opts.publicKey;
305309

306310
const { apiHost = "api.pipedream.com" } = opts;
307311
this.baseURL = `https://${apiHost}/v1`;
308312

309-
this._configureOauthClient(opts, this.baseURL);
313+
if (oauthClient) {
314+
// Use the provided OAuth client (useful for testing)
315+
this.oauthClient = oauthClient;
316+
} else {
317+
// Configure the OAuth client normally
318+
this._configureOauthClient(opts, this.baseURL);
319+
}
310320
}
311321

312322
private _configureOauthClient(
@@ -343,7 +353,7 @@ export class ServerClient {
343353
return `Basic ${encoded}`;
344354
}
345355

346-
async _oauthAuthorizationHeader(): Promise<string> {
356+
private async _oauthAuthorizationHeader(): Promise<string> {
347357
if (!this.oauthClient) {
348358
throw new Error("OAuth client not configured");
349359
}
@@ -364,7 +374,7 @@ export class ServerClient {
364374
* @returns A promise resolving to the API response.
365375
* @throws Will throw an error if the response status is not OK.
366376
*/
367-
async _makeRequest<T>(
377+
private async _makeRequest<T>(
368378
path: string,
369379
opts: RequestOptions = {},
370380
): Promise<T> {
@@ -446,7 +456,7 @@ export class ServerClient {
446456
* @returns A promise resolving to the API response.
447457
* @throws Will throw an error if the response status is not OK.
448458
*/
449-
async _makeApiRequest<T>(
459+
private async _makeApiRequest<T>(
450460
path: string,
451461
opts: RequestOptions = {},
452462
): Promise<T> {
@@ -470,7 +480,7 @@ export class ServerClient {
470480
* @returns A promise resolving to the API response.
471481
* @throws Will throw an error if the response status is not OK.
472482
*/
473-
async _makeConnectRequest<T>(
483+
private async _makeConnectRequest<T>(
474484
path: string,
475485
opts: RequestOptions = {},
476486
): Promise<T> {
@@ -501,7 +511,7 @@ typescript
501511
*
502512
503513
*/
504-
async connectTokenCreate(opts: ConnectTokenCreateOpts): Promise<ConnectTokenResponse> {
514+
public async connectTokenCreate(opts: ConnectTokenCreateOpts): Promise<ConnectTokenResponse> {
505515
const body = {
506516
external_id: opts.external_user_id,
507517
app_slug: opts.app_slug,
@@ -548,7 +558,7 @@ typescript
548558
*
549559
550560
*/
551-
async getAccount(accountId: string, params: ConnectParams = {}): Promise<Account> {
561+
public async getAccount(accountId: string, params: ConnectParams = {}): Promise<Account> {
552562
return this._makeConnectRequest<Account>(`/accounts/${accountId}`, {
553563
params,
554564
});
@@ -569,7 +579,7 @@ typescript
569579
*
570580
571581
*/
572-
async getAccountsByApp(appId: string, params: ConnectParams = {}): Promise<Account[]> {
582+
public async getAccountsByApp(appId: string, params: ConnectParams = {}): Promise<Account[]> {
573583
return this._makeConnectRequest<Account[]>(`/accounts/app/${appId}`, {
574584
params,
575585
});
@@ -590,7 +600,7 @@ typescript
590600
*
591601
592602
*/
593-
async getAccountsByExternalId(externalId: string, params: ConnectParams = {}): Promise<Account[]> {
603+
public async getAccountsByExternalId(externalId: string, params: ConnectParams = {}): Promise<Account[]> {
594604
return this._makeConnectRequest<Account[]>(`/accounts/external_id/${externalId}`, {
595605
params,
596606
});
@@ -610,7 +620,7 @@ typescript
610620
*
611621
612622
*/
613-
async deleteAccount(accountId: string): Promise<void> {
623+
public async deleteAccount(accountId: string): Promise<void> {
614624
await this._makeConnectRequest(`/accounts/${accountId}`, {
615625
method: "DELETE",
616626
});
@@ -630,7 +640,7 @@ typescript
630640
*
631641
632642
*/
633-
async deleteAccountsByApp(appId: string): Promise<void> {
643+
public async deleteAccountsByApp(appId: string): Promise<void> {
634644
await this._makeConnectRequest(`/accounts/app/${appId}`, {
635645
method: "DELETE",
636646
});
@@ -650,13 +660,13 @@ typescript
650660
*
651661
652662
*/
653-
async deleteExternalUser(externalId: string): Promise<void> {
663+
public async deleteExternalUser(externalId: string): Promise<void> {
654664
await this._makeConnectRequest(`/users/${externalId}`, {
655665
method: "DELETE",
656666
});
657667
}
658668

659-
async getProjectInfo(): Promise<ProjectInfoResponse> {
669+
public async getProjectInfo(): Promise<ProjectInfoResponse> {
660670
return this._makeConnectRequest<ProjectInfoResponse>("/projects/info", {
661671
method: "GET",
662672
});
@@ -693,7 +703,7 @@ typescript
693703
* },
694704
* );
695705
*/
696-
async invokeWorkflow(url: string, opts: RequestOptions = {}): Promise<unknown> {
706+
public async invokeWorkflow(url: string, opts: RequestOptions = {}): Promise<unknown> {
697707
const {
698708
body,
699709
headers = {},

0 commit comments

Comments
 (0)