Skip to content

Commit f0f369c

Browse files
fix the typescript client not properly handling get query params with an array value
1 parent 0ac2d0e commit f0f369c

File tree

2 files changed

+56
-20
lines changed

2 files changed

+56
-20
lines changed

src/DefaultRESTClient.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2020, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2019-2024, FusionAuth, All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -206,10 +206,18 @@ export default class DefaultRESTClient<RT, ERT> implements IRESTClient<RT, ERT>
206206
}
207207

208208
private getQueryString() {
209-
var queryString = '';
210-
for (let key in this.parameters) {
209+
let queryString = '';
210+
const appendParam = (key: string, param: string) => {
211211
queryString += (queryString.length === 0) ? '?' : '&';
212-
queryString += key + '=' + encodeURIComponent(this.parameters[key]);
212+
queryString += key + '=' + encodeURIComponent(param);
213+
}
214+
for (let key in this.parameters) {
215+
const value = this.parameters[key];
216+
if (Array.isArray(value)) {
217+
value.forEach(val => appendParam(key, val))
218+
} else {
219+
appendParam(key, value);
220+
}
213221
}
214222
return queryString;
215223
}

test/FusionAuthClientTest.ts

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2019-2024, FusionAuth, All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
1616

1717
'use strict';
1818

19-
import {ApplicationRequest, FusionAuthClient, GrantType} from '../index';
19+
import { ApplicationRequest, FusionAuthClient, GrantType, SearchResponse } from '../index';
2020
import * as chai from 'chai';
2121
import ClientResponse from "../src/ClientResponse";
2222

@@ -114,7 +114,7 @@ describe('#FusionAuthClient()', function () {
114114
}
115115
});
116116

117-
it('Create, Patch and Delete a User', async () => {
117+
it('Create, Patch, Search, and Delete a User', async () => {
118118
let clientResponse = await client.createUser(null, {
119119
user: {
120120
@@ -130,8 +130,10 @@ describe('#FusionAuthClient()', function () {
130130
chai.expect(clientResponse.response).to.have.property('user');
131131
chai.expect(clientResponse.response.user).to.have.property('id');
132132

133+
const userId = clientResponse.response.user.id;
134+
133135
// Patch the user
134-
clientResponse = await client.patchUser(clientResponse.response.user.id, {
136+
clientResponse = await client.patchUser(userId, {
135137
user: {
136138
firstName: "Jan"
137139
}
@@ -142,20 +144,46 @@ describe('#FusionAuthClient()', function () {
142144
chai.expect(clientResponse.response).to.have.property('user');
143145
chai.expect(clientResponse.response.user.firstName).to.equal("Jan");
144146

145-
clientResponse = await client.deleteUser(clientResponse.response.user.id);
146-
chai.assert.strictEqual(clientResponse.statusCode, 200);
147-
// Browser will return empty, node will return null, account for both scenarios
148-
if (clientResponse.response === null) {
149-
chai.assert.isNull(clientResponse.response);
150-
} else {
151-
chai.assert.isUndefined(clientResponse.response);
147+
// create a second user and search them both
148+
clientResponse = await client.createUser(null, {
149+
user: {
150+
151+
firstName: 'Joan',
152+
password: 'password'
153+
},
154+
skipVerification: true,
155+
sendSetPasswordEmail: false
156+
});
157+
158+
const secondUserId = clientResponse.response.user.id;
159+
const bothUsers = [userId, secondUserId];
160+
161+
const searchResp: ClientResponse<SearchResponse> = await client.searchUsersByIds(bothUsers);
162+
chai.assert.strictEqual(searchResp.statusCode, 200);
163+
chai.assert.strictEqual(searchResp.response.total, 2);
164+
// make sure each user was returned
165+
bothUsers.forEach(id => chai.assert.isNotNull(searchResp.response.users.find(user => user.id = id)));
166+
167+
// delete both users
168+
for (const id of bothUsers) {
169+
clientResponse = await client.deleteUser(id);
170+
chai.assert.strictEqual(clientResponse.statusCode, 200);
171+
// Browser will return empty, node will return null, account for both scenarios
172+
if (clientResponse.response === null) {
173+
chai.assert.isNull(clientResponse.response);
174+
} else {
175+
chai.assert.isUndefined(clientResponse.response);
176+
}
152177
}
153178

154-
try {
155-
await client.retrieveUserByEmail('[email protected]');
156-
chai.expect.fail("The user should have been deleted!");
157-
} catch (clientResponse) {
158-
chai.assert.strictEqual(clientResponse.statusCode, 404);
179+
// check that they are gone
180+
for (const email of ['[email protected]', '[email protected]']) {
181+
try {
182+
await client.retrieveUserByEmail(email);
183+
chai.expect.fail(`The user with ${email} should have been deleted!`);
184+
} catch (clientResponse) {
185+
chai.assert.strictEqual(clientResponse.statusCode, 404);
186+
}
159187
}
160188
});
161189

0 commit comments

Comments
 (0)