Skip to content

Commit 44f55c4

Browse files
committed
fix(express): acceptShare type codec
Ticket: WP-6717
1 parent c82d952 commit 44f55c4

File tree

2 files changed

+95
-10
lines changed

2 files changed

+95
-10
lines changed

modules/express/src/typedRoutes/api/v1/acceptShare.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,17 @@ export const AcceptShareRequestBody = {
1313
/** New passphrase to encrypt the shared wallet's keys */
1414
newWalletPassphrase: optional(t.string),
1515
/** Optional encrypted private key to use instead of generating a new one */
16-
overrideEncryptedXprv: optional(t.string),
16+
overrideEncryptedPrv: optional(t.string),
1717
};
1818

19+
/** Response from accepting a wallet share */
20+
export const AcceptShareResponse = t.type({
21+
/** Indicates whether the share state was changed by this operation */
22+
changed: t.boolean,
23+
/** Current state of the wallet share */
24+
state: t.string,
25+
});
26+
1927
/**
2028
* Accept a Wallet Share
2129
* Allows users to accept a wallet share invitation from another user.
@@ -34,7 +42,7 @@ export const PostAcceptShare = httpRoute({
3442
}),
3543
response: {
3644
/** Successfully accepted wallet share */
37-
200: t.UnknownRecord,
45+
200: AcceptShareResponse,
3846
/** Error response */
3947
400: BitgoExpressError,
4048
},

modules/express/test/unit/typedRoutes/acceptShare.ts

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as t from 'io-ts';
33
import {
44
AcceptShareRequestParams,
55
AcceptShareRequestBody,
6+
AcceptShareResponse,
67
PostAcceptShare,
78
} from '../../../src/typedRoutes/api/v1/acceptShare';
89
import { assertDecode } from './common';
@@ -48,13 +49,13 @@ describe('AcceptShare codec tests', function () {
4849
const validBody = {
4950
userPassword: 'mySecurePassword',
5051
newWalletPassphrase: 'myNewPassphrase',
51-
overrideEncryptedXprv: 'encryptedXprvString',
52+
overrideEncryptedPrv: 'encryptedPrvString',
5253
};
5354

5455
const decoded = assertDecode(t.type(AcceptShareRequestBody), validBody);
5556
assert.strictEqual(decoded.userPassword, validBody.userPassword);
5657
assert.strictEqual(decoded.newWalletPassphrase, validBody.newWalletPassphrase);
57-
assert.strictEqual(decoded.overrideEncryptedXprv, validBody.overrideEncryptedXprv);
58+
assert.strictEqual(decoded.overrideEncryptedPrv, validBody.overrideEncryptedPrv);
5859
});
5960

6061
it('should validate empty body since all fields are optional', function () {
@@ -63,7 +64,7 @@ describe('AcceptShare codec tests', function () {
6364
const decoded = assertDecode(t.type(AcceptShareRequestBody), validBody);
6465
assert.strictEqual(decoded.userPassword, undefined);
6566
assert.strictEqual(decoded.newWalletPassphrase, undefined);
66-
assert.strictEqual(decoded.overrideEncryptedXprv, undefined);
67+
assert.strictEqual(decoded.overrideEncryptedPrv, undefined);
6768
});
6869

6970
it('should reject body with non-string optional fields', function () {
@@ -103,13 +104,13 @@ describe('AcceptShare codec tests', function () {
103104
const body = {
104105
userPassword: '',
105106
newWalletPassphrase: '',
106-
overrideEncryptedXprv: '',
107+
overrideEncryptedPrv: '',
107108
};
108109

109110
const decoded = assertDecode(t.type(AcceptShareRequestBody), body);
110111
assert.strictEqual(decoded.userPassword, '');
111112
assert.strictEqual(decoded.newWalletPassphrase, '');
112-
assert.strictEqual(decoded.overrideEncryptedXprv, '');
113+
assert.strictEqual(decoded.overrideEncryptedPrv, '');
113114
});
114115

115116
it('should handle additional unknown properties', function () {
@@ -126,14 +127,79 @@ describe('AcceptShare codec tests', function () {
126127
});
127128
});
128129

130+
describe('AcceptShareResponse', function () {
131+
it('should validate valid response with all fields', function () {
132+
const validResponse = {
133+
changed: true,
134+
state: 'accepted',
135+
};
136+
137+
const decoded = assertDecode(AcceptShareResponse, validResponse);
138+
assert.strictEqual(decoded.changed, validResponse.changed);
139+
assert.strictEqual(decoded.state, validResponse.state);
140+
});
141+
142+
it('should validate response with changed=false', function () {
143+
const validResponse = {
144+
changed: false,
145+
state: 'pending',
146+
};
147+
148+
const decoded = assertDecode(AcceptShareResponse, validResponse);
149+
assert.strictEqual(decoded.changed, false);
150+
assert.strictEqual(decoded.state, 'pending');
151+
});
152+
153+
it('should reject response without changed field', function () {
154+
const invalidResponse = {
155+
state: 'accepted',
156+
};
157+
158+
assert.throws(() => {
159+
assertDecode(AcceptShareResponse, invalidResponse);
160+
});
161+
});
162+
163+
it('should reject response without state field', function () {
164+
const invalidResponse = {
165+
changed: true,
166+
};
167+
168+
assert.throws(() => {
169+
assertDecode(AcceptShareResponse, invalidResponse);
170+
});
171+
});
172+
173+
it('should reject response with non-boolean changed field', function () {
174+
const invalidResponse = {
175+
changed: 'true',
176+
state: 'accepted',
177+
};
178+
179+
assert.throws(() => {
180+
assertDecode(AcceptShareResponse, invalidResponse);
181+
});
182+
});
183+
184+
it('should reject response with non-string state field', function () {
185+
const invalidResponse = {
186+
changed: true,
187+
state: 123,
188+
};
189+
190+
assert.throws(() => {
191+
assertDecode(AcceptShareResponse, invalidResponse);
192+
});
193+
});
194+
});
195+
129196
describe('Supertest Integration Tests', function () {
130197
const agent = setupAgent();
131198
const shareId = 'share123456789abcdef';
132199

133200
const mockAcceptShareResponse = {
134201
state: 'accepted',
135202
changed: true,
136-
walletId: 'wallet123',
137203
};
138204

139205
afterEach(function () {
@@ -144,7 +210,7 @@ describe('AcceptShare codec tests', function () {
144210
const requestBody = {
145211
userPassword: 'mySecurePassword',
146212
newWalletPassphrase: 'myNewPassphrase',
147-
overrideEncryptedXprv: 'encryptedXprvString',
213+
overrideEncryptedPrv: 'encryptedPrvString',
148214
};
149215

150216
const acceptShareStub = sinon.stub().resolves(mockAcceptShareResponse);
@@ -163,13 +229,18 @@ describe('AcceptShare codec tests', function () {
163229
assert.strictEqual(result.status, 200);
164230
assert.ok(result.body);
165231

232+
// Validate response structure
233+
const decodedResponse = assertDecode(AcceptShareResponse, result.body);
234+
assert.strictEqual(typeof decodedResponse.changed, 'boolean');
235+
assert.strictEqual(typeof decodedResponse.state, 'string');
236+
166237
// Verify the method was called with correct params
167238
sinon.assert.calledOnce(acceptShareStub);
168239
const callArgs = acceptShareStub.firstCall.args[0];
169240
assert.strictEqual(callArgs.walletShareId, shareId);
170241
assert.strictEqual(callArgs.userPassword, requestBody.userPassword);
171242
assert.strictEqual(callArgs.newWalletPassphrase, requestBody.newWalletPassphrase);
172-
assert.strictEqual(callArgs.overrideEncryptedXprv, requestBody.overrideEncryptedXprv);
243+
assert.strictEqual(callArgs.overrideEncryptedPrv, requestBody.overrideEncryptedPrv);
173244
});
174245

175246
it('should successfully accept share with empty body', async function () {
@@ -191,6 +262,9 @@ describe('AcceptShare codec tests', function () {
191262
assert.strictEqual(result.status, 200);
192263
assert.ok(result.body);
193264

265+
// Validate response structure
266+
assertDecode(AcceptShareResponse, result.body);
267+
194268
sinon.assert.calledOnce(acceptShareStub);
195269
const callArgs = acceptShareStub.firstCall.args[0];
196270
assert.strictEqual(callArgs.walletShareId, shareId);
@@ -217,6 +291,9 @@ describe('AcceptShare codec tests', function () {
217291
assert.strictEqual(result.status, 200);
218292
assert.ok(result.body);
219293

294+
// Validate response structure
295+
assertDecode(AcceptShareResponse, result.body);
296+
220297
sinon.assert.calledOnce(acceptShareStub);
221298
const callArgs = acceptShareStub.firstCall.args[0];
222299
assert.strictEqual(callArgs.walletShareId, shareId);

0 commit comments

Comments
 (0)