bcchapi 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +3 -0
- package/.eslintrc.json +21 -0
- package/.prettierrc.json +17 -0
- package/.vscode/extensions.json +3 -0
- package/.vscode/settings.json +4 -0
- package/dist/client.d.ts +50 -0
- package/dist/client.js +93 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +37 -0
- package/dist/helpers/is-valid-date.d.ts +1 -0
- package/dist/helpers/is-valid-date.js +12 -0
- package/dist/helpers/parsers.d.ts +3 -0
- package/dist/helpers/parsers.js +51 -0
- package/dist/helpers/reverse-date.d.ts +1 -0
- package/dist/helpers/reverse-date.js +6 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +11 -0
- package/dist/types.d.ts +109 -0
- package/dist/types.js +2 -0
- package/package.json +10 -2
- package/src/client.ts +51 -52
- package/src/errors.ts +2 -2
- package/src/helpers/is-valid-date.ts +9 -0
- package/src/helpers/parsers.ts +56 -0
- package/src/helpers/reverse-date.ts +3 -0
- package/src/index.ts +8 -3
- package/src/types.ts +113 -0
- package/test/client.test.ts +89 -59
- package/test/fixtures/index.ts +1 -1
- package/test/fixtures/responses/credentials.invalid.json +1 -1
- package/test/fixtures/responses/getseries.invalid.json +1 -1
- package/test/fixtures/responses/getseries.success.json +1 -1
- package/test/fixtures/responses/searchseries.invalid.json +1 -1
- package/test/fixtures/responses/searchseries.success.json +13 -11
- package/test/{helpers.test.ts → helpers/is-valid-date.test.ts} +3 -12
- package/test/helpers/parse-get-series.test.ts +45 -0
- package/test/helpers/parse-search-series.test.ts +48 -0
- package/test/helpers/reverse-date.test.ts +11 -0
- package/test/mocks/fetch.mock.ts +18 -13
- package/tsconfig.eslint.json +5 -0
- package/tsconfig.json +1 -1
- package/src/helpers.ts +0 -13
- package/src/response.ts +0 -175
- package/test/response.test.ts +0 -71
package/src/errors.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ErrorResponse } from './
|
|
1
|
+
import { ErrorResponse } from './types';
|
|
2
2
|
|
|
3
3
|
export enum ErrorCodes {
|
|
4
4
|
InvalidCredentials = -5,
|
|
@@ -33,4 +33,4 @@ export class InvalidSeriesError extends WebServiceError {
|
|
|
33
33
|
constructor(response?: ErrorResponse) {
|
|
34
34
|
super(response, 'Invalid series id');
|
|
35
35
|
}
|
|
36
|
-
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import reverseDate from './reverse-date';
|
|
2
|
+
import {
|
|
3
|
+
ErrorCodes,
|
|
4
|
+
InvalidFrequencyError,
|
|
5
|
+
InvalidCredentialsError,
|
|
6
|
+
InvalidSeriesError,
|
|
7
|
+
WebServiceError,
|
|
8
|
+
} from '../errors';
|
|
9
|
+
import { ApiResponse, ErrorResponse, GetSeriesResponse, SearchSeriesResponse } from '../types';
|
|
10
|
+
|
|
11
|
+
export function parseGetSeriesResponse<T extends ApiResponse>(response: T): GetSeriesResponse {
|
|
12
|
+
if (response.Codigo !== 0) {
|
|
13
|
+
switch (response.Codigo) {
|
|
14
|
+
case ErrorCodes.InvalidCredentials:
|
|
15
|
+
throw new InvalidCredentialsError();
|
|
16
|
+
case ErrorCodes.InvalidSeries:
|
|
17
|
+
throw new InvalidSeriesError();
|
|
18
|
+
default:
|
|
19
|
+
throw new WebServiceError(response as ApiResponse as ErrorResponse);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
seriesId: response.Series.seriesId || '',
|
|
25
|
+
description: response.Series.descripIng || '',
|
|
26
|
+
data: (response.Series.Obs || []).map((obs) => ({
|
|
27
|
+
date: reverseDate(obs.indexDateString),
|
|
28
|
+
value: parseFloat(obs.value),
|
|
29
|
+
})),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function parseSearchSeriesResponse<T extends ApiResponse>(
|
|
34
|
+
response: T,
|
|
35
|
+
): SearchSeriesResponse {
|
|
36
|
+
if (response.Codigo !== 0) {
|
|
37
|
+
switch (response.Codigo) {
|
|
38
|
+
case ErrorCodes.InvalidCredentials:
|
|
39
|
+
throw new InvalidCredentialsError();
|
|
40
|
+
case ErrorCodes.InvalidFrequency:
|
|
41
|
+
throw new InvalidFrequencyError();
|
|
42
|
+
default:
|
|
43
|
+
throw new WebServiceError(response as ApiResponse as ErrorResponse);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return response.SeriesInfos.map((series) => ({
|
|
48
|
+
seriesId: series.seriesId,
|
|
49
|
+
frequency: series.frequencyCode,
|
|
50
|
+
title: series.englishTitle,
|
|
51
|
+
firstObservedAt: reverseDate(series.firstObservation),
|
|
52
|
+
lastObservedAt: reverseDate(series.lastObservation),
|
|
53
|
+
updatedAt: reverseDate(series.updatedAt),
|
|
54
|
+
createdAt: reverseDate(series.createdAt),
|
|
55
|
+
}));
|
|
56
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
export { Client, ClientConfig,
|
|
2
|
-
export { ApiResponse, ErrorResponse,
|
|
3
|
-
export {
|
|
1
|
+
export { Client, ClientConfig, Frequency } from './client';
|
|
2
|
+
export { ApiResponse, ErrorResponse, GetSeriesResponse, SearchSeriesResponse } from './types';
|
|
3
|
+
export {
|
|
4
|
+
WebServiceError,
|
|
5
|
+
InvalidCredentialsError,
|
|
6
|
+
InvalidFrequencyError,
|
|
7
|
+
InvalidSeriesError,
|
|
8
|
+
} from './errors';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
interface SeriesValue {
|
|
2
|
+
/**
|
|
3
|
+
* Series observed date in DD-MM-YYYY format.
|
|
4
|
+
*/
|
|
5
|
+
indexDateString: string;
|
|
6
|
+
/**
|
|
7
|
+
* Series observed value.
|
|
8
|
+
*/
|
|
9
|
+
value: string;
|
|
10
|
+
/**
|
|
11
|
+
* Series observed value status code (ND = no data recorded).
|
|
12
|
+
*/
|
|
13
|
+
statusCode: 'OK' | 'ND';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface SeriesHistory {
|
|
17
|
+
/**
|
|
18
|
+
* Series identifier.
|
|
19
|
+
*/
|
|
20
|
+
seriesId: string;
|
|
21
|
+
/**
|
|
22
|
+
* Series name in Spanish.
|
|
23
|
+
*/
|
|
24
|
+
descripEsp: string;
|
|
25
|
+
/**
|
|
26
|
+
* Series name in English.
|
|
27
|
+
*/
|
|
28
|
+
descripIng: string;
|
|
29
|
+
/**
|
|
30
|
+
* List of series observed values.
|
|
31
|
+
*/
|
|
32
|
+
Obs: SeriesValue[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type NullSeries = {
|
|
36
|
+
[key in keyof SeriesHistory]: null;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
interface SeriesMetadata {
|
|
40
|
+
/**
|
|
41
|
+
* Series identifier.
|
|
42
|
+
*/
|
|
43
|
+
seriesId: string;
|
|
44
|
+
/**
|
|
45
|
+
* Series frequency.
|
|
46
|
+
*/
|
|
47
|
+
frequencyCode: string;
|
|
48
|
+
/**
|
|
49
|
+
* Series name in Spanish.
|
|
50
|
+
*/
|
|
51
|
+
spanishTitle: string;
|
|
52
|
+
/**
|
|
53
|
+
* Series name in English.
|
|
54
|
+
*/
|
|
55
|
+
englishTitle: string;
|
|
56
|
+
/**
|
|
57
|
+
* Date of first observation in DD-MM-YYYY format.
|
|
58
|
+
*/
|
|
59
|
+
firstObservation: string;
|
|
60
|
+
/**
|
|
61
|
+
* Date of last observation in DD-MM-YYYY format.
|
|
62
|
+
*/
|
|
63
|
+
lastObservation: string;
|
|
64
|
+
/**
|
|
65
|
+
* Date of last update in DD-MM-YYYY format.
|
|
66
|
+
*/
|
|
67
|
+
updatedAt: string;
|
|
68
|
+
/**
|
|
69
|
+
* Date of creation in DD-MM-YYYY format.
|
|
70
|
+
*/
|
|
71
|
+
createdAt: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface ApiResponse {
|
|
75
|
+
/**
|
|
76
|
+
* Response status code.
|
|
77
|
+
*/
|
|
78
|
+
Codigo: number;
|
|
79
|
+
/**
|
|
80
|
+
* Response status message.
|
|
81
|
+
*/
|
|
82
|
+
Descripcion: string;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Series historic information.
|
|
86
|
+
*/
|
|
87
|
+
Series: SeriesHistory | NullSeries;
|
|
88
|
+
/**
|
|
89
|
+
* Series metadata information.
|
|
90
|
+
*/
|
|
91
|
+
SeriesInfos: SeriesMetadata[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface ErrorResponse extends ApiResponse {
|
|
95
|
+
Series: NullSeries;
|
|
96
|
+
SeriesInfos: never[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface GetSeriesResponse {
|
|
100
|
+
seriesId: string;
|
|
101
|
+
description: string;
|
|
102
|
+
data: ReadonlyArray<{ date: string; value: number }>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export type SearchSeriesResponse = ReadonlyArray<{
|
|
106
|
+
seriesId: string;
|
|
107
|
+
frequency: string;
|
|
108
|
+
title: string;
|
|
109
|
+
firstObservedAt: string;
|
|
110
|
+
lastObservedAt: string;
|
|
111
|
+
updatedAt: string;
|
|
112
|
+
createdAt: string;
|
|
113
|
+
}>;
|
package/test/client.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { expect, describe, it, vi, afterEach,
|
|
2
|
-
import { Client } from '../src';
|
|
1
|
+
import { expect, describe, it, vi, afterEach, beforeEach } from 'vitest';
|
|
3
2
|
import {
|
|
3
|
+
Client,
|
|
4
4
|
Frequency,
|
|
5
5
|
InvalidCredentialsError,
|
|
6
6
|
InvalidSeriesError,
|
|
@@ -8,9 +8,8 @@ import {
|
|
|
8
8
|
} from '../src';
|
|
9
9
|
import fetchMock from './mocks/fetch.mock';
|
|
10
10
|
import fixtures from './fixtures';
|
|
11
|
-
import
|
|
11
|
+
import reverseDate from '../src/helpers/reverse-date';
|
|
12
12
|
|
|
13
|
-
// global.fetch = vi.fn().mockImplementation(fetchMock);
|
|
14
13
|
const fetchSpy = vi.spyOn(global, 'fetch').mockImplementation(fetchMock);
|
|
15
14
|
|
|
16
15
|
describe('Client', () => {
|
|
@@ -23,7 +22,7 @@ describe('Client', () => {
|
|
|
23
22
|
user: '',
|
|
24
23
|
pass: '',
|
|
25
24
|
});
|
|
26
|
-
|
|
25
|
+
|
|
27
26
|
it('should create a Client instance', () => {
|
|
28
27
|
expect(client).toBeInstanceOf(Client);
|
|
29
28
|
});
|
|
@@ -37,46 +36,62 @@ describe('Client', () => {
|
|
|
37
36
|
});
|
|
38
37
|
|
|
39
38
|
it('should throw an error if series is not a non-empty string', async () => {
|
|
40
|
-
await expect(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
await expect(
|
|
40
|
+
client.getSeries({
|
|
41
|
+
series: undefined as unknown as string,
|
|
42
|
+
}),
|
|
43
|
+
).rejects.toThrow('series must be a non-empty string');
|
|
44
|
+
await expect(
|
|
45
|
+
client.getSeries({
|
|
46
|
+
series: '',
|
|
47
|
+
}),
|
|
48
|
+
).rejects.toThrow('series must be a non-empty string');
|
|
46
49
|
|
|
47
50
|
expect(fetchSpy).not.toHaveBeenCalled();
|
|
48
51
|
});
|
|
49
52
|
|
|
50
53
|
it('should throw an error if date range is invalid', async () => {
|
|
51
|
-
await expect(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
await expect(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
54
|
+
await expect(
|
|
55
|
+
client.getSeries({
|
|
56
|
+
series: 'TEST',
|
|
57
|
+
since: 'invalid',
|
|
58
|
+
}),
|
|
59
|
+
).rejects.toThrow('"since" is not a valid date string or Date object');
|
|
60
|
+
await expect(
|
|
61
|
+
client.getSeries({
|
|
62
|
+
series: 'TEST',
|
|
63
|
+
since: new Date('invalid'),
|
|
64
|
+
}),
|
|
65
|
+
).rejects.toThrow('"since" is not a valid date string or Date object');
|
|
66
|
+
|
|
67
|
+
await expect(
|
|
68
|
+
client.getSeries({
|
|
69
|
+
series: 'TEST',
|
|
70
|
+
until: 'invalid',
|
|
71
|
+
}),
|
|
72
|
+
).rejects.toThrow('"until" is not a valid date string or Date object');
|
|
73
|
+
await expect(
|
|
74
|
+
client.getSeries({
|
|
75
|
+
series: 'TEST',
|
|
76
|
+
until: new Date('invalid'),
|
|
77
|
+
}),
|
|
78
|
+
).rejects.toThrow('"until" is not a valid date string or Date object');
|
|
79
|
+
|
|
80
|
+
await expect(
|
|
81
|
+
client.getSeries({
|
|
82
|
+
series: 'TEST',
|
|
83
|
+
since: new Date(2020, 0, 1),
|
|
84
|
+
until: new Date(2000, 0, 1),
|
|
85
|
+
}),
|
|
86
|
+
).rejects.toThrow('invalid date range');
|
|
74
87
|
|
|
75
88
|
expect(fetchSpy).not.toHaveBeenCalled();
|
|
76
89
|
});
|
|
77
90
|
|
|
78
91
|
it('should throw error if credentials are invalid', async () => {
|
|
79
|
-
await expect(invalidClient.getSeries({ series: 'TEST' })).rejects.toThrow(
|
|
92
|
+
await expect(invalidClient.getSeries({ series: 'TEST' })).rejects.toThrow(
|
|
93
|
+
InvalidCredentialsError,
|
|
94
|
+
);
|
|
80
95
|
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
81
96
|
});
|
|
82
97
|
|
|
@@ -89,16 +104,20 @@ describe('Client', () => {
|
|
|
89
104
|
const series = await client.getSeries({ series: 'TEST' });
|
|
90
105
|
|
|
91
106
|
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
92
|
-
|
|
107
|
+
|
|
93
108
|
expect(series).toBeDefined();
|
|
94
109
|
expect(series.seriesId).toBe('TEST');
|
|
95
110
|
expect(series.description).toBe('Test');
|
|
96
111
|
expect(series.data).toBeInstanceOf(Array);
|
|
97
112
|
expect(series.data).toHaveLength(15);
|
|
98
|
-
|
|
113
|
+
|
|
99
114
|
for (let i = 0; i < series.data.length; i += 1) {
|
|
100
|
-
expect(reverseDate(series.data[i].date)).toBe(
|
|
101
|
-
|
|
115
|
+
expect(reverseDate(series.data[i].date)).toBe(
|
|
116
|
+
fixtures.response.getSeriesSuccess.Series.Obs[i].indexDateString,
|
|
117
|
+
);
|
|
118
|
+
expect(series.data[i].value.toFixed(2)).toBe(
|
|
119
|
+
fixtures.response.getSeriesSuccess.Series.Obs[i].value,
|
|
120
|
+
);
|
|
102
121
|
|
|
103
122
|
if (Number.isNaN(series.data[i].value)) {
|
|
104
123
|
expect(fixtures.response.getSeriesSuccess.Series.Obs[i].statusCode).toBe('ND');
|
|
@@ -111,7 +130,7 @@ describe('Client', () => {
|
|
|
111
130
|
series: 'TEST',
|
|
112
131
|
until: '2020-12-05',
|
|
113
132
|
});
|
|
114
|
-
|
|
133
|
+
|
|
115
134
|
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
116
135
|
|
|
117
136
|
expect(series).toBeDefined();
|
|
@@ -119,10 +138,14 @@ describe('Client', () => {
|
|
|
119
138
|
expect(series.description).toBe('Test');
|
|
120
139
|
expect(series.data).toBeInstanceOf(Array);
|
|
121
140
|
expect(series.data).toHaveLength(5);
|
|
122
|
-
|
|
141
|
+
|
|
123
142
|
for (let i = 0; i < series.data.length; i += 1) {
|
|
124
|
-
expect(reverseDate(series.data[i].date)).toBe(
|
|
125
|
-
|
|
143
|
+
expect(reverseDate(series.data[i].date)).toBe(
|
|
144
|
+
fixtures.response.getSeriesSuccess.Series.Obs[i].indexDateString,
|
|
145
|
+
);
|
|
146
|
+
expect(series.data[i].value.toFixed(2)).toBe(
|
|
147
|
+
fixtures.response.getSeriesSuccess.Series.Obs[i].value,
|
|
148
|
+
);
|
|
126
149
|
|
|
127
150
|
if (Number.isNaN(series.data[i].value)) {
|
|
128
151
|
expect(fixtures.response.getSeriesSuccess.Series.Obs[i].statusCode).toBe('ND');
|
|
@@ -137,14 +160,13 @@ describe('Client', () => {
|
|
|
137
160
|
});
|
|
138
161
|
|
|
139
162
|
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
140
|
-
|
|
163
|
+
|
|
141
164
|
expect(series).toBeDefined();
|
|
142
165
|
expect(series.seriesId).toBe('TEST');
|
|
143
166
|
expect(series.description).toBe('Test');
|
|
144
167
|
expect(series.data).toBeInstanceOf(Array);
|
|
145
168
|
expect(series.data).toHaveLength(0);
|
|
146
169
|
});
|
|
147
|
-
|
|
148
170
|
});
|
|
149
171
|
|
|
150
172
|
describe('searchSeries', () => {
|
|
@@ -156,28 +178,36 @@ describe('Client', () => {
|
|
|
156
178
|
});
|
|
157
179
|
|
|
158
180
|
it('should throw an error if frequency is not a non-empty string', async () => {
|
|
159
|
-
await expect(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
181
|
+
await expect(
|
|
182
|
+
client.searchSeries({
|
|
183
|
+
frequency: undefined as unknown as Frequency,
|
|
184
|
+
}),
|
|
185
|
+
).rejects.toThrow('frequency must be a non-empty string');
|
|
186
|
+
await expect(
|
|
187
|
+
client.searchSeries({
|
|
188
|
+
frequency: '' as Frequency,
|
|
189
|
+
}),
|
|
190
|
+
).rejects.toThrow('frequency must be a non-empty string');
|
|
165
191
|
|
|
166
192
|
expect(fetchSpy).not.toHaveBeenCalled();
|
|
167
193
|
});
|
|
168
194
|
|
|
169
195
|
it('should throw error if credentials are invalid', async () => {
|
|
170
|
-
await expect(
|
|
171
|
-
|
|
172
|
-
|
|
196
|
+
await expect(
|
|
197
|
+
invalidClient.searchSeries({
|
|
198
|
+
frequency: Frequency.Daily,
|
|
199
|
+
}),
|
|
200
|
+
).rejects.toThrow(InvalidCredentialsError);
|
|
173
201
|
|
|
174
202
|
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
175
203
|
});
|
|
176
204
|
|
|
177
205
|
it('should throw error if frequency is invalid', async () => {
|
|
178
|
-
await expect(
|
|
179
|
-
|
|
180
|
-
|
|
206
|
+
await expect(
|
|
207
|
+
client.searchSeries({
|
|
208
|
+
frequency: 'invalid' as Frequency,
|
|
209
|
+
}),
|
|
210
|
+
).rejects.toThrow(InvalidFrequencyError);
|
|
181
211
|
|
|
182
212
|
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
183
213
|
});
|
|
@@ -188,9 +218,9 @@ describe('Client', () => {
|
|
|
188
218
|
});
|
|
189
219
|
|
|
190
220
|
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
191
|
-
|
|
221
|
+
|
|
192
222
|
expect(series).toBeInstanceOf(Array);
|
|
193
223
|
expect(series).toHaveLength(1);
|
|
194
224
|
});
|
|
195
225
|
});
|
|
196
|
-
});
|
|
226
|
+
});
|
package/test/fixtures/index.ts
CHANGED
|
@@ -7,14 +7,16 @@
|
|
|
7
7
|
"seriesId": null,
|
|
8
8
|
"Obs": null
|
|
9
9
|
},
|
|
10
|
-
"SeriesInfos": [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
10
|
+
"SeriesInfos": [
|
|
11
|
+
{
|
|
12
|
+
"seriesId": "TEST",
|
|
13
|
+
"frequencyCode": "DAILY",
|
|
14
|
+
"spanishTitle": "Test",
|
|
15
|
+
"englishTitle": "Test",
|
|
16
|
+
"firstObservation": "01-12-2020",
|
|
17
|
+
"lastObservation": "15-12-2020",
|
|
18
|
+
"updatedAt": "19-01-2024",
|
|
19
|
+
"createdAt": "19-01-2024"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import
|
|
2
|
+
import isValidDate from '../../src/helpers/is-valid-date';
|
|
3
3
|
|
|
4
|
-
describe('
|
|
5
|
-
it('should reverse correctly a date in DD-MM-YYYY format', () => {
|
|
6
|
-
const date = '01-02-2020';
|
|
7
|
-
const reversed = reverseDate(date);
|
|
8
|
-
|
|
9
|
-
expect(reversed).toBe('2020-02-01');
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
describe('helpers: isValidDate', () => {
|
|
4
|
+
describe('isValidDate', () => {
|
|
14
5
|
it('should return true if the date is valid', () => {
|
|
15
6
|
expect(isValidDate('2020-01-01')).toBe(true);
|
|
16
7
|
expect(isValidDate(new Date())).toBe(true);
|
|
@@ -23,4 +14,4 @@ describe('helpers: isValidDate', () => {
|
|
|
23
14
|
expect(isValidDate(null)).toBe(false);
|
|
24
15
|
expect(isValidDate(new Date('invalid'))).toBe(false);
|
|
25
16
|
});
|
|
26
|
-
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import * as Errors from '../../src/errors';
|
|
3
|
+
import { parseGetSeriesResponse } from '../../src/helpers/parsers';
|
|
4
|
+
import { ApiResponse } from '../../src/types';
|
|
5
|
+
import fixtures from '../fixtures';
|
|
6
|
+
|
|
7
|
+
describe('parseGetSeriesResponse', () => {
|
|
8
|
+
it('should parse correctly a valid response', () => {
|
|
9
|
+
const parsed = parseGetSeriesResponse(
|
|
10
|
+
fixtures.response.getSeriesSuccess as unknown as ApiResponse,
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
expect(parsed).toBeDefined();
|
|
14
|
+
expect(parsed.seriesId).toBe(fixtures.response.getSeriesSuccess.Series.seriesId);
|
|
15
|
+
expect(parsed.description).toBe(fixtures.response.getSeriesSuccess.Series.descripIng);
|
|
16
|
+
expect(parsed.data).toHaveLength(fixtures.response.getSeriesSuccess.Series.Obs.length);
|
|
17
|
+
|
|
18
|
+
for (let i = 0; i < parsed.data.length; i += 1) {
|
|
19
|
+
expect(parsed.data[i].date).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
20
|
+
expect(parsed.data[i].value.toFixed(2)).toBe(
|
|
21
|
+
fixtures.response.getSeriesSuccess.Series.Obs[i].value,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
if (Number.isNaN(parsed.data[i].value)) {
|
|
25
|
+
expect(fixtures.response.getSeriesSuccess.Series.Obs[i].statusCode).toBe('ND');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should throw an InvalidCredentialsError if the response code is -5', () => {
|
|
31
|
+
expect(() =>
|
|
32
|
+
parseGetSeriesResponse(fixtures.response.credentialsInvalid as unknown as ApiResponse),
|
|
33
|
+
).toThrow(Errors.InvalidCredentialsError);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should throw an InvalidSeriesError if the response code is -50', () => {
|
|
37
|
+
expect(() =>
|
|
38
|
+
parseGetSeriesResponse(fixtures.response.getSeriesInvalid as unknown as ApiResponse),
|
|
39
|
+
).toThrow(Errors.InvalidSeriesError);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should throw a ResponseError if the response code is unknown', () => {
|
|
43
|
+
expect(() => parseGetSeriesResponse({} as ApiResponse)).toThrow(Errors.WebServiceError);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import * as Errors from '../../src/errors';
|
|
3
|
+
import { ApiResponse } from '../../src/types';
|
|
4
|
+
import { parseSearchSeriesResponse } from '../../src/helpers/parsers';
|
|
5
|
+
import fixtures from '../fixtures';
|
|
6
|
+
|
|
7
|
+
describe('parseSearchSeriesResponse', () => {
|
|
8
|
+
it('should parse correctly a valid response', () => {
|
|
9
|
+
const parsed = parseSearchSeriesResponse(
|
|
10
|
+
fixtures.response.searchSeriesSuccess as unknown as ApiResponse,
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
expect(parsed).toBeInstanceOf(Array);
|
|
14
|
+
expect(parsed).toHaveLength(fixtures.response.searchSeriesSuccess.SeriesInfos.length);
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < parsed.length; i += 1) {
|
|
17
|
+
expect(parsed[i].seriesId).toBe(
|
|
18
|
+
fixtures.response.searchSeriesSuccess.SeriesInfos[i].seriesId,
|
|
19
|
+
);
|
|
20
|
+
expect(parsed[i].frequency).toBe(
|
|
21
|
+
fixtures.response.searchSeriesSuccess.SeriesInfos[i].frequencyCode,
|
|
22
|
+
);
|
|
23
|
+
expect(parsed[i].title).toBe(
|
|
24
|
+
fixtures.response.searchSeriesSuccess.SeriesInfos[i].englishTitle,
|
|
25
|
+
);
|
|
26
|
+
expect(parsed[i].firstObservedAt).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
27
|
+
expect(parsed[i].lastObservedAt).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
28
|
+
expect(parsed[i].updatedAt).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
29
|
+
expect(parsed[i].createdAt).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should throw an InvalidCredentialsError if the response code is -5', () => {
|
|
34
|
+
expect(() =>
|
|
35
|
+
parseSearchSeriesResponse(fixtures.response.credentialsInvalid as unknown as ApiResponse),
|
|
36
|
+
).toThrow(Errors.InvalidCredentialsError);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should throw an InvalidFrequencyError if the response code is -1', () => {
|
|
40
|
+
expect(() =>
|
|
41
|
+
parseSearchSeriesResponse(fixtures.response.searchSeriesInvalid as unknown as ApiResponse),
|
|
42
|
+
).toThrow(Errors.InvalidFrequencyError);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should throw a ResponseError if the response code is unknown', () => {
|
|
46
|
+
expect(() => parseSearchSeriesResponse({} as ApiResponse)).toThrow(Errors.WebServiceError);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import reverseDate from '../../src/helpers/reverse-date';
|
|
3
|
+
|
|
4
|
+
describe('reverseDate', () => {
|
|
5
|
+
it('should reverse correctly a date in DD-MM-YYYY format', () => {
|
|
6
|
+
const date = '01-02-2020';
|
|
7
|
+
const reversed = reverseDate(date);
|
|
8
|
+
|
|
9
|
+
expect(reversed).toBe('2020-02-01');
|
|
10
|
+
});
|
|
11
|
+
});
|