Skip to content

Commit cc4f2b5

Browse files
authored
Fix throwing a Promise object instead of Error (#1826)
1 parent 31438c1 commit cc4f2b5

File tree

6 files changed

+182
-99
lines changed

6 files changed

+182
-99
lines changed

packages/installations/src/api/create-installation.test.ts

Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { FirebaseError } from '@firebase/util';
1819
import { expect } from 'chai';
1920
import { SinonStub, stub } from 'sinon';
2021
import { CreateInstallationResponse } from '../interfaces/api-response';
@@ -35,7 +36,7 @@ import { createInstallation } from './create-installation';
3536

3637
const FID = 'defenders-of-the-faith';
3738

38-
describe('api', () => {
39+
describe('createInstallation', () => {
3940
let appConfig: AppConfig;
4041
let fetchSpy: SinonStub<[RequestInfo, RequestInit?], Promise<Response>>;
4142
let inProgressInstallationEntry: InProgressInstallationEntry;
@@ -48,53 +49,79 @@ describe('api', () => {
4849
registrationStatus: RequestStatus.IN_PROGRESS,
4950
registrationTime: Date.now()
5051
};
52+
});
5153

52-
const response: CreateInstallationResponse = {
53-
refreshToken: 'refreshToken',
54-
authToken: {
55-
token:
56-
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCeKKF2QT4fwpMeJf36POk6yJV_adQssw5c',
57-
expiresIn: '604800s'
58-
}
59-
};
54+
describe('successful request', () => {
55+
beforeEach(() => {
56+
const response: CreateInstallationResponse = {
57+
refreshToken: 'refreshToken',
58+
authToken: {
59+
token:
60+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCeKKF2QT4fwpMeJf36POk6yJV_adQssw5c',
61+
expiresIn: '604800s'
62+
}
63+
};
6064

61-
fetchSpy = stub(self, 'fetch').resolves(
62-
new Response(JSON.stringify(response))
63-
);
64-
});
65+
fetchSpy = stub(self, 'fetch').resolves(
66+
new Response(JSON.stringify(response))
67+
);
68+
});
69+
70+
it('registers a pending InstallationEntry', async () => {
71+
const registeredInstallationEntry = await createInstallation(
72+
appConfig,
73+
inProgressInstallationEntry
74+
);
75+
expect(registeredInstallationEntry.registrationStatus).to.equal(
76+
RequestStatus.COMPLETED
77+
);
78+
});
79+
80+
it('calls the createInstallation server API with correct parameters', async () => {
81+
const expectedHeaders = new Headers({
82+
'Content-Type': 'application/json',
83+
Accept: 'application/json',
84+
'x-goog-api-key': 'apiKey'
85+
});
86+
const expectedBody = {
87+
fid: FID,
88+
authVersion: INTERNAL_AUTH_VERSION,
89+
appId: appConfig.appId,
90+
sdkVersion: PACKAGE_VERSION
91+
};
92+
const expectedRequest: RequestInit = {
93+
method: 'POST',
94+
headers: expectedHeaders,
95+
body: JSON.stringify(expectedBody)
96+
};
97+
const expectedEndpoint = `${INSTALLATIONS_API_URL}/projects/projectId/installations`;
6598

66-
it('registers a pending InstallationEntry', async () => {
67-
const registeredInstallationEntry = await createInstallation(
68-
appConfig,
69-
inProgressInstallationEntry
70-
);
71-
expect(registeredInstallationEntry.registrationStatus).to.equal(
72-
RequestStatus.COMPLETED
73-
);
99+
await createInstallation(appConfig, inProgressInstallationEntry);
100+
expect(fetchSpy).to.be.calledOnceWith(expectedEndpoint, expectedRequest);
101+
const actualHeaders = fetchSpy.lastCall.lastArg.headers;
102+
compareHeaders(expectedHeaders, actualHeaders);
103+
});
74104
});
75105

76-
it('calls the createInstallation server API with correct parameters', async () => {
77-
const expectedHeaders = new Headers({
78-
'Content-Type': 'application/json',
79-
Accept: 'application/json',
80-
'x-goog-api-key': 'apiKey'
106+
describe('failed request', () => {
107+
beforeEach(() => {
108+
const response = {
109+
error: {
110+
code: 409,
111+
message: 'Requested entity already exists',
112+
status: 'ALREADY_EXISTS'
113+
}
114+
};
115+
116+
fetchSpy = stub(self, 'fetch').resolves(
117+
new Response(JSON.stringify(response), { status: 409 })
118+
);
81119
});
82-
const expectedBody = {
83-
fid: FID,
84-
authVersion: INTERNAL_AUTH_VERSION,
85-
appId: appConfig.appId,
86-
sdkVersion: PACKAGE_VERSION
87-
};
88-
const expectedRequest: RequestInit = {
89-
method: 'POST',
90-
headers: expectedHeaders,
91-
body: JSON.stringify(expectedBody)
92-
};
93-
const expectedEndpoint = `${INSTALLATIONS_API_URL}/projects/projectId/installations`;
94120

95-
await createInstallation(appConfig, inProgressInstallationEntry);
96-
expect(fetchSpy).to.be.calledOnceWith(expectedEndpoint, expectedRequest);
97-
const actualHeaders = fetchSpy.lastCall.lastArg.headers;
98-
compareHeaders(expectedHeaders, actualHeaders);
121+
it('throws a FirebaseError with the error information from the server', async () => {
122+
await expect(
123+
createInstallation(appConfig, inProgressInstallationEntry)
124+
).to.be.rejectedWith(FirebaseError);
125+
});
99126
});
100127
});

packages/installations/src/api/create-installation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,6 @@ export async function createInstallation(
6161
};
6262
return registeredInstallationEntry;
6363
} else {
64-
throw getErrorFromResponse('Create Installation', response);
64+
throw await getErrorFromResponse('Create Installation', response);
6565
}
6666
}

packages/installations/src/api/delete-installation.test.ts

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { FirebaseError } from '@firebase/util';
1819
import { expect } from 'chai';
1920
import { SinonStub, stub } from 'sinon';
2021
import { AppConfig } from '../interfaces/app-config';
@@ -49,27 +50,53 @@ describe('deleteInstallation', () => {
4950
requestStatus: RequestStatus.NOT_STARTED
5051
}
5152
};
52-
53-
fetchSpy = stub(self, 'fetch').resolves(new Response());
5453
});
5554

56-
it('calls the deleteInstallation server API with correct parameters', async () => {
57-
const expectedHeaders = new Headers({
58-
'Content-Type': 'application/json',
59-
Accept: 'application/json',
60-
Authorization: `${INTERNAL_AUTH_VERSION} refreshToken`,
61-
'x-goog-api-key': 'apiKey'
55+
describe('successful request', () => {
56+
beforeEach(() => {
57+
fetchSpy = stub(self, 'fetch').resolves(new Response());
6258
});
63-
const expectedRequest: RequestInit = {
64-
method: 'DELETE',
65-
headers: expectedHeaders
66-
};
67-
const expectedEndpoint = `${INSTALLATIONS_API_URL}/projects/projectId/installations/${FID}`;
6859

69-
await deleteInstallation(appConfig, registeredInstallationEntry);
60+
it('calls the deleteInstallation server API with correct parameters', async () => {
61+
const expectedHeaders = new Headers({
62+
'Content-Type': 'application/json',
63+
Accept: 'application/json',
64+
Authorization: `${INTERNAL_AUTH_VERSION} refreshToken`,
65+
'x-goog-api-key': 'apiKey'
66+
});
67+
const expectedRequest: RequestInit = {
68+
method: 'DELETE',
69+
headers: expectedHeaders
70+
};
71+
const expectedEndpoint = `${INSTALLATIONS_API_URL}/projects/projectId/installations/${FID}`;
72+
73+
await deleteInstallation(appConfig, registeredInstallationEntry);
74+
75+
expect(fetchSpy).to.be.calledOnceWith(expectedEndpoint, expectedRequest);
76+
const actualHeaders = fetchSpy.lastCall.lastArg.headers;
77+
compareHeaders(expectedHeaders, actualHeaders);
78+
});
79+
});
80+
81+
describe('failed request', () => {
82+
beforeEach(() => {
83+
const response = {
84+
error: {
85+
code: 409,
86+
message: 'Requested entity already exists',
87+
status: 'ALREADY_EXISTS'
88+
}
89+
};
7090

71-
expect(fetchSpy).to.be.calledOnceWith(expectedEndpoint, expectedRequest);
72-
const actualHeaders = fetchSpy.lastCall.lastArg.headers;
73-
compareHeaders(expectedHeaders, actualHeaders);
91+
fetchSpy = stub(self, 'fetch').resolves(
92+
new Response(JSON.stringify(response), { status: 409 })
93+
);
94+
});
95+
96+
it('throws a FirebaseError with the error information from the server', async () => {
97+
await expect(
98+
deleteInstallation(appConfig, registeredInstallationEntry)
99+
).to.be.rejectedWith(FirebaseError);
100+
});
74101
});
75102
});

packages/installations/src/api/delete-installation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export async function deleteInstallation(
3737

3838
const response = await fetch(endpoint, request);
3939
if (!response.ok) {
40-
throw getErrorFromResponse('Delete Installation', response);
40+
throw await getErrorFromResponse('Delete Installation', response);
4141
}
4242
}
4343

packages/installations/src/api/generate-auth-token.test.ts

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { FirebaseError } from '@firebase/util';
1819
import { expect } from 'chai';
1920
import { SinonStub, stub } from 'sinon';
2021
import { GenerateAuthTokenResponse } from '../interfaces/api-response';
@@ -52,49 +53,77 @@ describe('generateAuthToken', () => {
5253
requestStatus: RequestStatus.NOT_STARTED
5354
}
5455
};
56+
});
5557

56-
const response: GenerateAuthTokenResponse = {
57-
token:
58-
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCeKKF2QT4fwpMeJf36POk6yJV_adQssw5c',
59-
expiresIn: '604800s'
60-
};
58+
describe('successful request', () => {
59+
beforeEach(() => {
60+
const response: GenerateAuthTokenResponse = {
61+
token:
62+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCeKKF2QT4fwpMeJf36POk6yJV_adQssw5c',
63+
expiresIn: '604800s'
64+
};
6165

62-
fetchSpy = stub(self, 'fetch').resolves(
63-
new Response(JSON.stringify(response))
64-
);
65-
});
66+
fetchSpy = stub(self, 'fetch').resolves(
67+
new Response(JSON.stringify(response))
68+
);
69+
});
6670

67-
it('fetches a new Authentication Token', async () => {
68-
const completedAuthToken: CompletedAuthToken = await generateAuthToken(
69-
appConfig,
70-
registeredInstallationEntry
71-
);
72-
expect(completedAuthToken.requestStatus).to.equal(RequestStatus.COMPLETED);
73-
});
71+
it('fetches a new Authentication Token', async () => {
72+
const completedAuthToken: CompletedAuthToken = await generateAuthToken(
73+
appConfig,
74+
registeredInstallationEntry
75+
);
76+
expect(completedAuthToken.requestStatus).to.equal(
77+
RequestStatus.COMPLETED
78+
);
79+
});
80+
81+
it('calls the generateAuthToken server API with correct parameters', async () => {
82+
const expectedHeaders = new Headers({
83+
'Content-Type': 'application/json',
84+
Accept: 'application/json',
85+
Authorization: `${INTERNAL_AUTH_VERSION} refreshToken`,
86+
'x-goog-api-key': 'apiKey'
87+
});
88+
const expectedBody = {
89+
installation: {
90+
sdkVersion: PACKAGE_VERSION
91+
}
92+
};
93+
const expectedRequest: RequestInit = {
94+
method: 'POST',
95+
headers: expectedHeaders,
96+
body: JSON.stringify(expectedBody)
97+
};
98+
const expectedEndpoint = `${INSTALLATIONS_API_URL}/projects/projectId/installations/${FID}/authTokens:generate`;
99+
100+
await generateAuthToken(appConfig, registeredInstallationEntry);
74101

75-
it('calls the generateAuthToken server API with correct parameters', async () => {
76-
const expectedHeaders = new Headers({
77-
'Content-Type': 'application/json',
78-
Accept: 'application/json',
79-
Authorization: `${INTERNAL_AUTH_VERSION} refreshToken`,
80-
'x-goog-api-key': 'apiKey'
102+
expect(fetchSpy).to.be.calledOnceWith(expectedEndpoint, expectedRequest);
103+
const actualHeaders = fetchSpy.lastCall.lastArg.headers;
104+
compareHeaders(expectedHeaders, actualHeaders);
81105
});
82-
const expectedBody = {
83-
installation: {
84-
sdkVersion: PACKAGE_VERSION
85-
}
86-
};
87-
const expectedRequest: RequestInit = {
88-
method: 'POST',
89-
headers: expectedHeaders,
90-
body: JSON.stringify(expectedBody)
91-
};
92-
const expectedEndpoint = `${INSTALLATIONS_API_URL}/projects/projectId/installations/${FID}/authTokens:generate`;
106+
});
93107

94-
await generateAuthToken(appConfig, registeredInstallationEntry);
108+
describe('failed request', () => {
109+
beforeEach(() => {
110+
const response = {
111+
error: {
112+
code: 409,
113+
message: 'Requested entity already exists',
114+
status: 'ALREADY_EXISTS'
115+
}
116+
};
95117

96-
expect(fetchSpy).to.be.calledOnceWith(expectedEndpoint, expectedRequest);
97-
const actualHeaders = fetchSpy.lastCall.lastArg.headers;
98-
compareHeaders(expectedHeaders, actualHeaders);
118+
fetchSpy = stub(self, 'fetch').resolves(
119+
new Response(JSON.stringify(response), { status: 409 })
120+
);
121+
});
122+
123+
it('throws a FirebaseError with the error information from the server', async () => {
124+
await expect(
125+
generateAuthToken(appConfig, registeredInstallationEntry)
126+
).to.be.rejectedWith(FirebaseError);
127+
});
99128
});
100129
});

packages/installations/src/api/generate-auth-token.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export async function generateAuthToken(
5656
);
5757
return completedAuthToken;
5858
} else {
59-
throw getErrorFromResponse('Generate Auth Token', response);
59+
throw await getErrorFromResponse('Generate Auth Token', response);
6060
}
6161
}
6262

0 commit comments

Comments
 (0)