bcchapi 1.0.0 → 1.0.2
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/LICENSE +7 -0
- package/README.md +12 -12
- 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/client.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import * as querystring from 'node:querystring';
|
|
2
2
|
import * as assert from 'node:assert/strict';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
parseSearchSeriesResponse,
|
|
9
|
-
ApiResponse,
|
|
10
|
-
} from './response';
|
|
11
|
-
import { isValidDate } from './helpers';
|
|
12
|
-
|
|
13
|
-
export type ClientConfig = {
|
|
3
|
+
import { GetSeriesResponse, SearchSeriesResponse, ApiResponse } from './types';
|
|
4
|
+
import { parseGetSeriesResponse, parseSearchSeriesResponse } from './helpers/parsers';
|
|
5
|
+
import isValidDate from './helpers/is-valid-date';
|
|
6
|
+
|
|
7
|
+
export interface ClientConfig {
|
|
14
8
|
/**
|
|
15
9
|
* Client username (registered email).
|
|
16
10
|
*/
|
|
@@ -19,33 +13,20 @@ export type ClientConfig = {
|
|
|
19
13
|
* Client password.
|
|
20
14
|
*/
|
|
21
15
|
pass: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type GetSeriesInput = {
|
|
25
|
-
/**
|
|
26
|
-
* Series identifier.
|
|
27
|
-
*/
|
|
28
|
-
series: string;
|
|
29
|
-
/**
|
|
30
|
-
* First date of the range to fetch.
|
|
31
|
-
*/
|
|
32
|
-
since?: string | Date;
|
|
33
|
-
/**
|
|
34
|
-
* Last date of the range to fetch.
|
|
35
|
-
*/
|
|
36
|
-
until?: string | Date;
|
|
37
|
-
};
|
|
16
|
+
}
|
|
38
17
|
|
|
39
|
-
export
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
18
|
+
export enum Frequency {
|
|
19
|
+
Daily = 'DAILY',
|
|
20
|
+
Monthly = 'MONTHLY',
|
|
21
|
+
Quarterly = 'QUARTERLY',
|
|
22
|
+
Annual = 'ANNUAL',
|
|
23
|
+
}
|
|
45
24
|
|
|
46
25
|
export class Client {
|
|
47
26
|
static apiURL = 'https://si3.bcentral.cl/SieteRestWS/SieteRestWS.ashx';
|
|
27
|
+
|
|
48
28
|
private username: string;
|
|
29
|
+
|
|
49
30
|
private password: string;
|
|
50
31
|
|
|
51
32
|
constructor(config: ClientConfig) {
|
|
@@ -53,59 +34,77 @@ export class Client {
|
|
|
53
34
|
this.password = config.pass;
|
|
54
35
|
}
|
|
55
36
|
|
|
56
|
-
async request(
|
|
57
|
-
const
|
|
37
|
+
async request(query: Record<string, string>): Promise<ApiResponse> {
|
|
38
|
+
const queryString = querystring.stringify({
|
|
58
39
|
user: this.username,
|
|
59
40
|
pass: this.password,
|
|
60
|
-
...
|
|
41
|
+
...query,
|
|
61
42
|
});
|
|
62
43
|
|
|
63
|
-
return (await fetch(`${Client.apiURL}?${
|
|
44
|
+
return (await fetch(`${Client.apiURL}?${queryString}`)).json() as Promise<ApiResponse>;
|
|
64
45
|
}
|
|
65
46
|
|
|
66
47
|
/**
|
|
67
48
|
* Fetches the list of observed values for a given series.
|
|
68
49
|
*/
|
|
69
|
-
async getSeries(
|
|
70
|
-
|
|
50
|
+
async getSeries(params: {
|
|
51
|
+
/**
|
|
52
|
+
* Series identifier.
|
|
53
|
+
*/
|
|
54
|
+
series: string;
|
|
55
|
+
/**
|
|
56
|
+
* First date of the range to fetch.
|
|
57
|
+
*/
|
|
58
|
+
since?: string | Date;
|
|
59
|
+
/**
|
|
60
|
+
* Last date of the range to fetch.
|
|
61
|
+
*/
|
|
62
|
+
until?: string | Date;
|
|
63
|
+
}): Promise<GetSeriesResponse> {
|
|
64
|
+
const { series, since, until } = params;
|
|
71
65
|
|
|
72
66
|
assert.ok(series && typeof series === 'string', 'series must be a non-empty string');
|
|
73
67
|
|
|
74
|
-
const
|
|
68
|
+
const query: Record<string, string> = {
|
|
75
69
|
timeseries: series,
|
|
76
70
|
function: 'GetSeries',
|
|
77
71
|
};
|
|
78
72
|
|
|
79
73
|
if (since) {
|
|
80
74
|
assert.ok(isValidDate(since), '"since" is not a valid date string or Date object');
|
|
81
|
-
|
|
75
|
+
query.firstdate = typeof since === 'string' ? since : since.toISOString().slice(0, 10);
|
|
82
76
|
}
|
|
83
77
|
|
|
84
78
|
if (until) {
|
|
85
79
|
assert.ok(isValidDate(until), '"until" is not a valid date string or Date object');
|
|
86
|
-
|
|
80
|
+
query.lastdate = typeof until === 'string' ? until : until.toISOString().slice(0, 10);
|
|
87
81
|
}
|
|
88
82
|
|
|
89
|
-
if (
|
|
90
|
-
assert.ok(
|
|
83
|
+
if (query.firstdate && query.lastdate) {
|
|
84
|
+
assert.ok(query.firstdate <= query.lastdate, 'invalid date range');
|
|
91
85
|
}
|
|
92
86
|
|
|
93
|
-
return this.request(
|
|
87
|
+
return this.request(query).then(parseGetSeriesResponse);
|
|
94
88
|
}
|
|
95
89
|
|
|
96
90
|
/**
|
|
97
91
|
* Fetches the list of available series by frequency and their metadata.
|
|
98
92
|
*/
|
|
99
|
-
async searchSeries(
|
|
100
|
-
|
|
101
|
-
|
|
93
|
+
async searchSeries(params: {
|
|
94
|
+
/**
|
|
95
|
+
* Frequency for which you want to consult the catalog of available series.
|
|
96
|
+
*/
|
|
97
|
+
frequency: Frequency;
|
|
98
|
+
}): Promise<SearchSeriesResponse> {
|
|
99
|
+
const { frequency } = params;
|
|
100
|
+
|
|
102
101
|
assert.ok(frequency && typeof frequency === 'string', 'frequency must be a non-empty string');
|
|
103
|
-
|
|
104
|
-
const
|
|
102
|
+
|
|
103
|
+
const query: Record<string, string> = {
|
|
105
104
|
frequency,
|
|
106
105
|
function: 'SearchSeries',
|
|
107
106
|
};
|
|
108
107
|
|
|
109
|
-
return this.request(
|
|
108
|
+
return this.request(query).then(parseSearchSeriesResponse);
|
|
110
109
|
}
|
|
111
|
-
}
|
|
110
|
+
}
|
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