Skip to content

Commit 69c180b

Browse files
committed
address comments, add DataConnect.executeQuery() and DataConnect.executeMutation() unit tests
1 parent 5d4cbab commit 69c180b

File tree

5 files changed

+239
-12
lines changed

5 files changed

+239
-12
lines changed

src/data-connect/data-connect.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ export class DataConnect {
186186
* Optionally, you may provide auth impersonation.
187187
*
188188
* @param name - The name of the defined query to execute.
189-
* @param options - The GraphQL options, must include operationName and impersonation details.
190189
* @param variables - The variables for the query. May be optional if the query's variables are optional.
190+
* @param options - The GraphQL options, must include operationName and impersonation details.
191191
* @returns A promise that fulfills with the GraphQL response.
192192
*/
193193
public executeQuery<Data, Variables>(
@@ -222,8 +222,8 @@ export class DataConnect {
222222
* Optionally, you may provide auth impersonation.
223223
*
224224
* @param name - The name of the defined mutation to execute.
225-
* @param options - The GraphQL options, must include operationName and impersonation details.
226225
* @param variables - The variables for the mutation. May be optional if the mutation's variables are optional.
226+
* @param options - The GraphQL options, must include operationName and impersonation details.
227227
* @returns A promise that fulfills with the GraphQL response.
228228
*/
229229
public executeMutation<Data, Variables>(

test/integration/data-connect.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ describe('getDataConnect()', () => {
495495
undefined,
496496
optsUnauthorizedClaims
497497
).should.eventually.be.rejected.and.have.property('code', 'data-connect/not-found');
498-
})
498+
});
499499

500500
it('should execute a query with variables', async () => {
501501
const resp = await getDataConnect(connectorConfig).executeQuery<GetUserResponse, GetUserVariables>(
@@ -504,7 +504,7 @@ describe('getDataConnect()', () => {
504504
);
505505
expect(resp.data.user).to.not.be.empty;
506506
expect(resp.data.user).to.deep.equal(fredUser);
507-
})
507+
});
508508

509509
describe('with unauthenticated impersonation', () => {
510510
it('should successfully execute a query with @auth(level: PUBLIC)', async () => {
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
import * as sinon from 'sinon';
2+
import * as mocks from '../../resources/mocks';
3+
import { ConnectorConfig, DataConnect, getDataConnect, OperationOptions } from '../../../src/data-connect';
4+
import { expect } from 'chai';
5+
import { DataConnectApiClient } from '../../../src/data-connect/data-connect-api-client-internal';
6+
import { FirebaseApp } from '../../../src/app/firebase-app';
7+
import * as appIndex from '../../../src/app/lifecycle';
8+
9+
describe('DataConnect', () => {
10+
const mockOptions = {
11+
credential: new mocks.MockCredential(),
12+
projectId: 'test-project',
13+
};
14+
const connectorConfig: ConnectorConfig = {
15+
location: 'us-west2',
16+
serviceId: 'my-service',
17+
connector: 'my-connector',
18+
};
19+
let mockApp: FirebaseApp;
20+
let dc: DataConnect;
21+
22+
interface RequiredVariables {
23+
limit: number;
24+
}
25+
26+
type OptionalVariables = Partial<RequiredVariables> | undefined;
27+
28+
interface Data {
29+
data: number;
30+
}
31+
32+
const operationName = 'operation';
33+
const requiredVariables: RequiredVariables = { limit: 1 };
34+
const optionalVariables: OptionalVariables = { limit: 2 };
35+
const options: OperationOptions = { impersonate: { unauthenticated: true } };
36+
const data: Data = { data: 99 };
37+
38+
let executeQueryStub: sinon.SinonStub;
39+
let executeMutationStub: sinon.SinonStub;
40+
let getAppStub: sinon.SinonStub;
41+
42+
beforeEach(() => {
43+
mockApp = mocks.appWithOptions(mockOptions);
44+
getAppStub = sinon.stub(appIndex, 'getApp').returns(mockApp);
45+
executeQueryStub = sinon
46+
.stub(DataConnectApiClient.prototype, 'executeQuery')
47+
.resolves(data);
48+
executeMutationStub = sinon
49+
.stub(DataConnectApiClient.prototype, 'executeMutation')
50+
.resolves(data);
51+
dc = getDataConnect(connectorConfig);
52+
});
53+
54+
afterEach(() => {
55+
executeQueryStub.restore();
56+
executeMutationStub.restore();
57+
getAppStub.restore();
58+
return mockApp.delete();
59+
});
60+
61+
describe('executeQuery()', () => {
62+
describe('should handle method and argument overload correctly', async () => {
63+
describe('with required variables', () => {
64+
describe('with a Variable type parameter provided', () => {
65+
describe('with variables provided', () => {
66+
it('with options provided', async () => {
67+
await dc.executeQuery<Data, RequiredVariables>(operationName, requiredVariables, options);
68+
expect(executeQueryStub.calledOnceWithExactly(operationName, requiredVariables, options)).to.be.true;
69+
});
70+
71+
it('WITHOUT options provided', async () => {
72+
await dc.executeQuery<Data, RequiredVariables>(operationName, requiredVariables);
73+
expect(executeQueryStub.calledOnceWithExactly(operationName, requiredVariables, undefined)).to.be.true;
74+
});
75+
});
76+
});
77+
78+
describe('WITHOUT a Variable type parameter provided', () => {
79+
describe('with variables provided', () => {
80+
it('with options provided', async () => {
81+
await dc.executeQuery(operationName, requiredVariables, options);
82+
expect(executeQueryStub.calledOnceWithExactly(operationName, requiredVariables, options)).to.be.true;
83+
});
84+
85+
it('WITHOUT options provided', async () => {
86+
await dc.executeQuery(operationName, requiredVariables);
87+
expect(executeQueryStub.calledOnceWithExactly(operationName, requiredVariables, undefined)).to.be.true;
88+
});
89+
});
90+
});
91+
});
92+
93+
describe('with optional variables', () => {
94+
describe('with a Variable type parameter provided', () => {
95+
describe('with variables provided', () => {
96+
it('with options provided', async () => {
97+
await dc.executeQuery<Data, OptionalVariables>(operationName, optionalVariables, options);
98+
expect(executeQueryStub.calledOnceWithExactly(operationName, optionalVariables, options)).to.be.true;
99+
});
100+
101+
it('WITHOUT options provided', async () => {
102+
await dc.executeQuery<Data, OptionalVariables>(operationName, optionalVariables);
103+
expect(executeQueryStub.calledOnceWithExactly(operationName, optionalVariables, undefined)).to.be.true;
104+
});
105+
});
106+
107+
describe('WITHOUT variables provided', () => {
108+
it('with options provided', async () => {
109+
await dc.executeQuery<Data, OptionalVariables>(operationName, undefined, options);
110+
expect(executeQueryStub.calledOnceWithExactly(operationName, undefined, options)).to.be.true;
111+
});
112+
113+
it('WITHOUT options provided', async () => {
114+
await dc.executeQuery<Data, OptionalVariables>(operationName, undefined);
115+
expect(executeQueryStub.calledOnceWithExactly(operationName, undefined, undefined)).to.be.true;
116+
});
117+
});
118+
});
119+
120+
describe('WITHOUT a Variable type parameter provided', () => {
121+
describe('with variables provided', async () => {
122+
it('with options provided', async () => {
123+
await dc.executeQuery(operationName, optionalVariables, options);
124+
expect(executeQueryStub.calledOnceWithExactly(operationName, optionalVariables, options)).to.be.true;
125+
});
126+
127+
it('WITHOUT options provided', async () => {
128+
await dc.executeQuery(operationName, optionalVariables);
129+
expect(executeQueryStub.calledOnceWithExactly(operationName, optionalVariables, undefined)).to.be.true;
130+
});
131+
});
132+
133+
describe('WITHOUT variables provided', async () => {
134+
it('WITHOUT options provided', async () => {
135+
await dc.executeQuery(operationName);
136+
expect(executeQueryStub.calledOnceWithExactly(operationName, undefined, undefined)).to.be.true;
137+
});
138+
});
139+
});
140+
});
141+
});
142+
});
143+
144+
describe('executeMutation()', () => {
145+
describe('should handle method and argument overload correctly', async () => {
146+
describe('with required variables', () => {
147+
describe('with a Variable type parameter provided', () => {
148+
describe('with variables provided', () => {
149+
it('with options provided', async () => {
150+
await dc.executeMutation<Data, RequiredVariables>(operationName, requiredVariables, options);
151+
expect(executeMutationStub.calledOnceWithExactly(operationName, requiredVariables, options)).to.be.true;
152+
});
153+
154+
it('WITHOUT options provided', async () => {
155+
await dc.executeMutation<Data, RequiredVariables>(operationName, requiredVariables);
156+
expect(executeMutationStub.calledOnceWithExactly(operationName, requiredVariables, undefined)).to.be.true;
157+
});
158+
});
159+
});
160+
161+
describe('WITHOUT a Variable type parameter provided', () => {
162+
describe('with variables provided', () => {
163+
it('with options provided', async () => {
164+
await dc.executeMutation(operationName, requiredVariables, options);
165+
expect(executeMutationStub.calledOnceWithExactly(operationName, requiredVariables, options)).to.be.true;
166+
});
167+
168+
it('WITHOUT options provided', async () => {
169+
await dc.executeMutation(operationName, requiredVariables);
170+
expect(executeMutationStub.calledOnceWithExactly(operationName, requiredVariables, undefined)).to.be.true;
171+
});
172+
});
173+
});
174+
});
175+
176+
describe('with optional variables', () => {
177+
describe('with a Variable type parameter provided', () => {
178+
describe('with variables provided', () => {
179+
it('with options provided', async () => {
180+
await dc.executeMutation<Data, OptionalVariables>(operationName, optionalVariables, options);
181+
expect(executeMutationStub.calledOnceWithExactly(operationName, optionalVariables, options)).to.be.true;
182+
});
183+
184+
it('WITHOUT options provided', async () => {
185+
await dc.executeMutation<Data, OptionalVariables>(operationName, optionalVariables);
186+
expect(executeMutationStub.calledOnceWithExactly(operationName, optionalVariables, undefined)).to.be.true;
187+
});
188+
});
189+
190+
describe('WITHOUT variables provided', () => {
191+
it('with options provided', async () => {
192+
await dc.executeMutation<Data, OptionalVariables>(operationName, undefined, options);
193+
expect(executeMutationStub.calledOnceWithExactly(operationName, undefined, options)).to.be.true;
194+
});
195+
196+
it('WITHOUT options provided', async () => {
197+
await dc.executeMutation<Data, OptionalVariables>(operationName, undefined);
198+
expect(executeMutationStub.calledOnceWithExactly(operationName, undefined, undefined)).to.be.true;
199+
});
200+
});
201+
});
202+
203+
describe('WITHOUT a Variable type parameter provided', () => {
204+
describe('with variables provided', async () => {
205+
it('with options provided', async () => {
206+
await dc.executeMutation(operationName, optionalVariables, options);
207+
expect(executeMutationStub.calledOnceWithExactly(operationName, optionalVariables, options)).to.be.true;
208+
});
209+
210+
it('WITHOUT options provided', async () => {
211+
await dc.executeMutation(operationName, optionalVariables);
212+
expect(executeMutationStub.calledOnceWithExactly(operationName, optionalVariables, undefined)).to.be.true;
213+
});
214+
});
215+
216+
describe('WITHOUT variables provided', async () => {
217+
it('WITHOUT options provided', async () => {
218+
await dc.executeMutation(operationName);
219+
expect(executeMutationStub.calledOnceWithExactly(operationName, undefined, undefined)).to.be.true;
220+
});
221+
});
222+
});
223+
});
224+
});
225+
});
226+
});

test/unit/data-connect/validate-admin-args.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@ describe('validateAdminArgs()', () => {
7777
});
7878

7979
it('should successfully parse the provided options', () => {
80-
const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateAdminArgs<object>(
80+
const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateAdminArgs(
8181
connectorConfig, options
8282
);
8383
expect(dcInstance).to.deep.equal(stubDcInstance);
8484
expect(inputVars).to.be.undefined;
85-
expect(inputOpts).to.be.deep.equal(options);
85+
expect(inputOpts).to.deep.equal(options);
8686
});
8787
});
8888

@@ -93,7 +93,7 @@ describe('validateAdminArgs()', () => {
9393
);
9494
expect(dcInstance).to.deep.equal(providedDcInstance);
9595
expect(inputVars).to.be.undefined;
96-
expect(inputOpts).to.be.deep.equal(options);
96+
expect(inputOpts).to.deep.equal(options);
9797
});
9898
});
9999

@@ -184,7 +184,7 @@ describe('validateAdminArgs()', () => {
184184
connectorConfig, providedDcInstance, variables, undefined, true, true
185185
);
186186
expect(dcInstance).to.deep.equal(providedDcInstance);
187-
expect(inputVars).to.deep.equal(inputVars);
187+
expect(inputVars).to.deep.equal(variables);
188188
expect(inputOpts).to.be.undefined;
189189
}).to.not.throw(invalidVariablesError);
190190
});
@@ -195,7 +195,7 @@ describe('validateAdminArgs()', () => {
195195
connectorConfig, variables, undefined, undefined, true, true
196196
);
197197
expect(dcInstance).to.deep.equal(stubDcInstance);
198-
expect(inputVars).to.deep.equal(inputVars);
198+
expect(inputVars).to.deep.equal(variables);
199199
expect(inputOpts).to.be.undefined;
200200
}).to.not.throw(invalidVariablesError);
201201
});
@@ -238,7 +238,7 @@ describe('validateAdminArgs()', () => {
238238
connectorConfig, variables, undefined, undefined, true, false
239239
);
240240
expect(dcInstance).to.deep.equal(stubDcInstance);
241-
expect(inputVars).to.deep.equal(inputVars);
241+
expect(inputVars).to.deep.equal(variables);
242242
expect(inputOpts).to.be.undefined;
243243
});
244244
});
@@ -250,7 +250,7 @@ describe('validateAdminArgs()', () => {
250250
connectorConfig, providedDcInstance, undefined, undefined, true, false
251251
);
252252
expect(dcInstance).to.deep.equal(providedDcInstance);
253-
expect(inputVars).to.deep.equal(inputVars);
253+
expect(inputVars).to.deep.equal(variables);
254254
expect(inputOpts).to.be.undefined;
255255
}).to.not.throw(invalidVariablesError);
256256
});

test/unit/index.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,5 @@ import './extensions/extensions-api-client-internal.spec';
121121
// Data Connect
122122
import './data-connect/index.spec';
123123
import './data-connect/data-connect-api-client-internal.spec';
124-
// import './data-connect/validate-admin-args.spec';
124+
import './data-connect/data-connect.spec';
125+
import './data-connect/validate-admin-args.spec';

0 commit comments

Comments
 (0)