Skip to content

Commit

Permalink
Reported better error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
maneesht committed Jul 19, 2024
1 parent 7cc2b9c commit ba8dba2
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 12 deletions.
15 changes: 13 additions & 2 deletions packages/data-connect/src/network/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,15 @@ export function dcFetch<T, U>(
} catch (e) {
throw new DataConnectError(Code.OTHER, JSON.stringify(e));
}
const message = getMessage(jsonResponse);
if (response.status >= 400) {
logError(
'Error while performing request: ' + JSON.stringify(jsonResponse)
);
if(response.status === 401) {
throw new DataConnectError(Code.UNAUTHORIZED, JSON.stringify(jsonResponse));
throw new DataConnectError(Code.UNAUTHORIZED, message);
}
throw new DataConnectError(Code.OTHER, JSON.stringify(jsonResponse));
throw new DataConnectError(Code.OTHER, message);
}
return jsonResponse;
})
Expand All @@ -84,3 +85,13 @@ export function dcFetch<T, U>(
return res as { data: T; errors: Error[] };
});
}
interface MessageObject {
message?: string;
}
function getMessage(obj: MessageObject) : string {
if ('message' in obj) {
console.log('message')
return obj.message;
}
return JSON.stringify(obj);
}
6 changes: 6 additions & 0 deletions packages/data-connect/test/post.gql
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ query listPosts @auth(level: PUBLIC) {
content
}
}
query listPosts2 {
posts {
id,
content
}
}

16 changes: 11 additions & 5 deletions packages/data-connect/test/queries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const SEEDED_DATA = [
content: 'task 2'
}
];
const REAL_DATA = SEEDED_DATA.map(obj => ({ ...obj, id: obj.id.replace(/-/g, '')}))
function seedDatabase(instance: DataConnect): Promise<void> {
// call mutation query that adds SEEDED_DATA to database
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -100,7 +101,7 @@ describe('DataConnect Tests', async () => {
const taskListQuery = queryRef<TaskListResponse>(dc, 'listPosts');
const taskListRes = await executeQuery(taskListQuery);
expect(taskListRes.data).to.deep.eq({
posts: SEEDED_DATA
posts: REAL_DATA
});
});
it(`instantly executes a query if one hasn't been subscribed to`, async () => {
Expand All @@ -121,7 +122,7 @@ describe('DataConnect Tests', async () => {
);
const res = await promise;
expect(res.data).to.deep.eq({
posts: SEEDED_DATA
posts: REAL_DATA
});
expect(res.source).to.eq(SOURCE_SERVER);
});
Expand All @@ -138,7 +139,7 @@ describe('DataConnect Tests', async () => {
const result = await waitForFirstEvent(taskListQuery);
const serializedRef: SerializedRef<TaskListResponse, undefined> = {
data: {
posts: SEEDED_DATA
posts: REAL_DATA
},
fetchTime: Date.now().toLocaleString(),
refInfo: {
Expand All @@ -149,7 +150,7 @@ describe('DataConnect Tests', async () => {
name: taskListQuery.name,
variables: undefined
},
source: SOURCE_SERVER
source: SOURCE_CACHE
};
expect(result.toJSON()).to.deep.eq(serializedRef);
expect(result.source).to.deep.eq(SOURCE_CACHE);
Expand All @@ -163,10 +164,15 @@ describe('DataConnect Tests', async () => {
});
connectDataConnectEmulator(fakeInstance, 'localhost', Number(0));
const taskListQuery = queryRef<TaskListResponse>(dc, 'listPosts');
expect(await executeQuery(taskListQuery)).to.eventually.be.rejectedWith(
expect(executeQuery(taskListQuery)).to.eventually.be.rejectedWith(
'ECONNREFUSED'
);
});
it('throws an error with just the message when the server responds with an error', async () => {
const invalidTaskListQuery = queryRef<TaskListResponse>(dc, 'listPosts2');
const message = 'unauthorized: you are not authorized to perform this operation';
await expect(executeQuery(invalidTaskListQuery)).to.eventually.be.rejectedWith(message);
})
});
async function waitForFirstEvent<Data, Variables>(
query: QueryRef<Data, Variables>
Expand Down
4 changes: 2 additions & 2 deletions packages/data-connect/test/unit/dataconnect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { expect } from "chai";

describe('Data Connect Test', () => {
it('should throw an error if `projectId` is not provided', () => {
const app = initializeApp({});
expect(() => getDataConnect({ connector: 'c', location: 'l', service: 's'})).to.throw('Project ID must be provided. Did you pass in a proper projectId to initializeApp?');
const app = initializeApp({projectId: undefined}, 'a');
expect(() => getDataConnect(app,{ connector: 'c', location: 'l', service: 's'})).to.throw('Project ID must be provided. Did you pass in a proper projectId to initializeApp?');
deleteApp(app);
});
it('should not throw an error if `projectId` is provided', () => {
Expand Down
39 changes: 39 additions & 0 deletions packages/data-connect/test/unit/fetch.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { expect, use } from 'chai';
import { dcFetch, initializeFetch } from '../../src/network/fetch';
import chaiAsPromised from 'chai-as-promised';
import * as sinon from 'sinon';
use(chaiAsPromised);
function mockFetch(json: any) {
const fakeFetchImpl = sinon.stub().returns(
Promise.resolve({
json: () => {
return Promise.resolve(json);
},
status: 401
} as Response)
);
initializeFetch(fakeFetchImpl);
}
describe('fetch', () => {
it('should throw an error with just the message when the server responds with an error with a message property in the body', async () => {
const message = 'Failed to connect to Postgres instance';
mockFetch({
code: 401,
message
});
await expect(
dcFetch('http://localhost', {}, {} as AbortController, null)
).to.eventually.be.rejectedWith(message);
});
it('should throw a stringified message when the server responds with an error without a message property in the body', async () => {
const message = 'Failed to connect to Postgres instance';
const json = {
code: 401,
message1: message
}
mockFetch(json);
await expect(
dcFetch('http://localhost', {}, {} as AbortController, null)
).to.eventually.be.rejectedWith(JSON.stringify(json));
});
});
6 changes: 3 additions & 3 deletions packages/data-connect/test/unit/queries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe('Queries', () => {
const rt = new RESTTransport(options, undefined, authProvider);
await expect(
rt.invokeQuery('test', null)
).to.eventually.be.rejectedWith(JSON.stringify(json));
).to.eventually.be.rejectedWith(json.message);
expect(fakeFetchImpl.callCount).to.eq(2);
});
it('[MUTATION] should retry auth whenever the fetcher returns with unauthorized', async () => {
Expand All @@ -63,7 +63,7 @@ describe('Queries', () => {
const rt = new RESTTransport(options, undefined, authProvider);
await expect(
rt.invokeMutation('test', null)
).to.eventually.be.rejectedWith(JSON.stringify(json));
).to.eventually.be.rejectedWith(json.message);
expect(fakeFetchImpl.callCount).to.eq(2);
});
it("should not retry auth whenever the fetcher returns with unauthorized and the token doesn't change", async () => {
Expand All @@ -73,7 +73,7 @@ describe('Queries', () => {
rt._setLastToken('initial token');
await expect(
rt.invokeQuery('test', null) as Promise<any>
).to.eventually.be.rejectedWith(JSON.stringify(json));
).to.eventually.be.rejectedWith(json.message);
expect(fakeFetchImpl.callCount).to.eq(1);
});
});

0 comments on commit ba8dba2

Please sign in to comment.