@internetarchive/metadata-service 0.0.1-alpha.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/.editorconfig +29 -0
- package/.eslintrc.js +14 -0
- package/.github/workflows/ci.yml +26 -0
- package/LICENSE +661 -0
- package/README.md +64 -0
- package/demo/app-root.ts +80 -0
- package/demo/index.html +27 -0
- package/dist/demo/app-root.d.ts +11 -0
- package/dist/demo/app-root.js +71 -0
- package/dist/demo/app-root.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/src/backend/default-metadata-backend.d.ts +27 -0
- package/dist/src/backend/default-metadata-backend.js +101 -0
- package/dist/src/backend/default-metadata-backend.js.map +1 -0
- package/dist/src/backend/metadata-backend-interface.d.ts +20 -0
- package/dist/src/backend/metadata-backend-interface.js +2 -0
- package/dist/src/backend/metadata-backend-interface.js.map +1 -0
- package/dist/src/metadata-service-error.d.ts +11 -0
- package/dist/src/metadata-service-error.js +18 -0
- package/dist/src/metadata-service-error.js.map +1 -0
- package/dist/src/metadata-service-interface.d.ts +44 -0
- package/dist/src/metadata-service-interface.js +2 -0
- package/dist/src/metadata-service-interface.js.map +1 -0
- package/dist/src/metadata-service.d.ts +18 -0
- package/dist/src/metadata-service.js +43 -0
- package/dist/src/metadata-service.js.map +1 -0
- package/dist/src/models/file.d.ts +29 -0
- package/dist/src/models/file.js +95 -0
- package/dist/src/models/file.js.map +1 -0
- package/dist/src/models/metadata-fields/field-types/boolean.d.ts +5 -0
- package/dist/src/models/metadata-fields/field-types/boolean.js +8 -0
- package/dist/src/models/metadata-fields/field-types/boolean.js.map +1 -0
- package/dist/src/models/metadata-fields/field-types/byte.d.ts +13 -0
- package/dist/src/models/metadata-fields/field-types/byte.js +16 -0
- package/dist/src/models/metadata-fields/field-types/byte.js.map +1 -0
- package/dist/src/models/metadata-fields/field-types/date.d.ts +5 -0
- package/dist/src/models/metadata-fields/field-types/date.js +8 -0
- package/dist/src/models/metadata-fields/field-types/date.js.map +1 -0
- package/dist/src/models/metadata-fields/field-types/duration.d.ts +14 -0
- package/dist/src/models/metadata-fields/field-types/duration.js +17 -0
- package/dist/src/models/metadata-fields/field-types/duration.js.map +1 -0
- package/dist/src/models/metadata-fields/field-types/list.d.ts +25 -0
- package/dist/src/models/metadata-fields/field-types/list.js +34 -0
- package/dist/src/models/metadata-fields/field-types/list.js.map +1 -0
- package/dist/src/models/metadata-fields/field-types/mediatype.d.ts +5 -0
- package/dist/src/models/metadata-fields/field-types/mediatype.js +8 -0
- package/dist/src/models/metadata-fields/field-types/mediatype.js.map +1 -0
- package/dist/src/models/metadata-fields/field-types/number.d.ts +5 -0
- package/dist/src/models/metadata-fields/field-types/number.js +8 -0
- package/dist/src/models/metadata-fields/field-types/number.js.map +1 -0
- package/dist/src/models/metadata-fields/field-types/page-progression.d.ts +5 -0
- package/dist/src/models/metadata-fields/field-types/page-progression.js +8 -0
- package/dist/src/models/metadata-fields/field-types/page-progression.js.map +1 -0
- package/dist/src/models/metadata-fields/field-types/string.d.ts +5 -0
- package/dist/src/models/metadata-fields/field-types/string.js +8 -0
- package/dist/src/models/metadata-fields/field-types/string.js.map +1 -0
- package/dist/src/models/metadata-fields/metadata-field.d.ts +70 -0
- package/dist/src/models/metadata-fields/metadata-field.js +67 -0
- package/dist/src/models/metadata-fields/metadata-field.js.map +1 -0
- package/dist/src/models/metadata.d.ts +168 -0
- package/dist/src/models/metadata.js +618 -0
- package/dist/src/models/metadata.js.map +1 -0
- package/dist/src/models/review.d.ts +10 -0
- package/dist/src/models/review.js +43 -0
- package/dist/src/models/review.js.map +1 -0
- package/dist/src/models/speech-music-asr-entry.d.ts +10 -0
- package/dist/src/models/speech-music-asr-entry.js +2 -0
- package/dist/src/models/speech-music-asr-entry.js.map +1 -0
- package/dist/src/responses/metadata-response.d.ts +28 -0
- package/dist/src/responses/metadata-response.js +31 -0
- package/dist/src/responses/metadata-response.js.map +1 -0
- package/dist/test/default-metadata-backend.test.d.ts +1 -0
- package/dist/test/default-metadata-backend.test.js +91 -0
- package/dist/test/default-metadata-backend.test.js.map +1 -0
- package/dist/test/metadata-service.test.d.ts +1 -0
- package/dist/test/metadata-service.test.js +99 -0
- package/dist/test/metadata-service.test.js.map +1 -0
- package/dist/test/mock-response-generator.d.ts +3 -0
- package/dist/test/mock-response-generator.js +62 -0
- package/dist/test/mock-response-generator.js.map +1 -0
- package/dist/test/models/file.test.d.ts +1 -0
- package/dist/test/models/file.test.js +9 -0
- package/dist/test/models/file.test.js.map +1 -0
- package/dist/test/models/metadata-fields/list-field.test.d.ts +1 -0
- package/dist/test/models/metadata-fields/list-field.test.js +52 -0
- package/dist/test/models/metadata-fields/list-field.test.js.map +1 -0
- package/dist/test/models/metadata-fields/metadata-field.test.d.ts +1 -0
- package/dist/test/models/metadata-fields/metadata-field.test.js +121 -0
- package/dist/test/models/metadata-fields/metadata-field.test.js.map +1 -0
- package/dist/test/models/metadata.test.d.ts +1 -0
- package/dist/test/models/metadata.test.js +10 -0
- package/dist/test/models/metadata.test.js.map +1 -0
- package/index.ts +32 -0
- package/package.json +77 -0
- package/src/backend/default-metadata-backend.ts +141 -0
- package/src/backend/metadata-backend-interface.ts +25 -0
- package/src/metadata-service-error.ts +21 -0
- package/src/metadata-service-interface.ts +51 -0
- package/src/metadata-service.ts +63 -0
- package/src/models/file.ts +105 -0
- package/src/models/metadata-fields/field-types/boolean.ts +8 -0
- package/src/models/metadata-fields/field-types/byte.ts +16 -0
- package/src/models/metadata-fields/field-types/date.ts +8 -0
- package/src/models/metadata-fields/field-types/duration.ts +17 -0
- package/src/models/metadata-fields/field-types/list.ts +44 -0
- package/src/models/metadata-fields/field-types/mediatype.ts +8 -0
- package/src/models/metadata-fields/field-types/number.ts +8 -0
- package/src/models/metadata-fields/field-types/page-progression.ts +14 -0
- package/src/models/metadata-fields/field-types/string.ts +8 -0
- package/src/models/metadata-fields/metadata-field.ts +108 -0
- package/src/models/metadata.ts +457 -0
- package/src/models/review.ts +41 -0
- package/src/models/speech-music-asr-entry.ts +10 -0
- package/src/responses/metadata-response.ts +61 -0
- package/test/default-metadata-backend.test.ts +101 -0
- package/test/metadata-service.test.ts +150 -0
- package/test/mock-response-generator.ts +62 -0
- package/test/models/file.test.ts +10 -0
- package/test/models/metadata-fields/list-field.test.ts +64 -0
- package/test/models/metadata-fields/metadata-field.test.ts +151 -0
- package/test/models/metadata.test.ts +11 -0
- package/tsconfig.json +22 -0
- package/web-test-runner.config.mjs +7 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
import { expect } from '@open-wc/testing';
|
|
4
|
+
|
|
5
|
+
import { MockResponseGenerator } from './mock-response-generator';
|
|
6
|
+
import { MetadataResponse } from '../src/responses/metadata-response';
|
|
7
|
+
import { Result } from '@internetarchive/result-type';
|
|
8
|
+
import { MetadataBackendInterface } from '../src/backend/metadata-backend-interface';
|
|
9
|
+
import {
|
|
10
|
+
MetadataServiceError,
|
|
11
|
+
MetadataServiceErrorType,
|
|
12
|
+
} from '../src/metadata-service-error';
|
|
13
|
+
import { MetadataService } from '../src/metadata-service';
|
|
14
|
+
|
|
15
|
+
describe('MetadataService', () => {
|
|
16
|
+
it('can request metadata when requested', async () => {
|
|
17
|
+
class MockMetadataBackend implements MetadataBackendInterface {
|
|
18
|
+
async fetchMetadata(
|
|
19
|
+
identifier: string
|
|
20
|
+
): Promise<Result<MetadataResponse, MetadataServiceError>> {
|
|
21
|
+
const responseGenerator = new MockResponseGenerator();
|
|
22
|
+
const mockResponse =
|
|
23
|
+
responseGenerator.generateMockMetadataResponse(identifier);
|
|
24
|
+
return { success: mockResponse };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const backend = new MockMetadataBackend();
|
|
29
|
+
const service = new MetadataService(backend);
|
|
30
|
+
const result = await service.fetchMetadata('foo');
|
|
31
|
+
expect(result.success?.metadata.identifier).to.equal('foo');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('requestMetadataValue', async () => {
|
|
35
|
+
class MockMetadataBackend implements MetadataBackendInterface {
|
|
36
|
+
response: any;
|
|
37
|
+
async fetchMetadata(
|
|
38
|
+
identifier: string,
|
|
39
|
+
keypath?: string
|
|
40
|
+
): Promise<Result<any, MetadataServiceError>> {
|
|
41
|
+
return {
|
|
42
|
+
success: {
|
|
43
|
+
result: this.response,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
it('can request a metadata value', async () => {
|
|
50
|
+
const backend = new MockMetadataBackend();
|
|
51
|
+
const service = new MetadataService(backend);
|
|
52
|
+
|
|
53
|
+
let expectedResult: any = 'foo';
|
|
54
|
+
backend.response = expectedResult;
|
|
55
|
+
|
|
56
|
+
let result = await service.fetchMetadataValue<typeof expectedResult>(
|
|
57
|
+
'foo',
|
|
58
|
+
'metadata'
|
|
59
|
+
);
|
|
60
|
+
expect(result.success).to.equal(expectedResult);
|
|
61
|
+
|
|
62
|
+
expectedResult = { foo: 'bar' };
|
|
63
|
+
backend.response = expectedResult;
|
|
64
|
+
|
|
65
|
+
result = await service.fetchMetadataValue<typeof expectedResult>(
|
|
66
|
+
'foo',
|
|
67
|
+
'metadata'
|
|
68
|
+
);
|
|
69
|
+
expect(result.success).to.equal(expectedResult);
|
|
70
|
+
expect(result.success.foo).to.equal('bar');
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('returns an error result if the item is not found', async () => {
|
|
75
|
+
class MockSearchBackend implements MetadataBackendInterface {
|
|
76
|
+
async fetchMetadata(
|
|
77
|
+
identifier: string
|
|
78
|
+
): Promise<Result<MetadataResponse, MetadataServiceError>> {
|
|
79
|
+
// this is unfortunate.. instead of getting an http 404 error,
|
|
80
|
+
// we get an empty JSON object when an item is not found
|
|
81
|
+
return { success: {} as any };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const backend = new MockSearchBackend();
|
|
86
|
+
const service = new MetadataService(backend);
|
|
87
|
+
const result = await service.fetchMetadata('foo');
|
|
88
|
+
expect(result.error).to.not.equal(undefined);
|
|
89
|
+
expect(result.error?.type).to.equal(MetadataServiceErrorType.itemNotFound);
|
|
90
|
+
|
|
91
|
+
const valueResult = await service.fetchMetadataValue('foo', 'metadata');
|
|
92
|
+
expect(valueResult.error).to.not.equal(undefined);
|
|
93
|
+
expect(valueResult.error?.type).to.equal(
|
|
94
|
+
MetadataServiceErrorType.itemNotFound
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('returns the network error if one occurs', async () => {
|
|
99
|
+
class MockSearchBackend implements MetadataBackendInterface {
|
|
100
|
+
async fetchMetadata(
|
|
101
|
+
identifier: string
|
|
102
|
+
): Promise<Result<MetadataResponse, MetadataServiceError>> {
|
|
103
|
+
const error = new MetadataServiceError(
|
|
104
|
+
MetadataServiceErrorType.networkError,
|
|
105
|
+
'network error'
|
|
106
|
+
);
|
|
107
|
+
return { error };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const backend = new MockSearchBackend();
|
|
112
|
+
const service = new MetadataService(backend);
|
|
113
|
+
const metadataResult = await service.fetchMetadata('foo');
|
|
114
|
+
expect(metadataResult.error).to.not.equal(undefined);
|
|
115
|
+
expect(metadataResult.error?.type).to.equal(
|
|
116
|
+
MetadataServiceErrorType.networkError
|
|
117
|
+
);
|
|
118
|
+
expect(metadataResult.error?.message).to.equal('network error');
|
|
119
|
+
|
|
120
|
+
const metadataValueResult = await service.fetchMetadataValue('foo', 'bar');
|
|
121
|
+
expect(metadataValueResult.error).to.not.equal(undefined);
|
|
122
|
+
expect(metadataValueResult.error?.type).to.equal(
|
|
123
|
+
MetadataServiceErrorType.networkError
|
|
124
|
+
);
|
|
125
|
+
expect(metadataValueResult.error?.message).to.equal('network error');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('returns a decoding error if one occurs', async () => {
|
|
129
|
+
class MockSearchBackend implements MetadataBackendInterface {
|
|
130
|
+
async fetchMetadata(
|
|
131
|
+
identifier: string
|
|
132
|
+
): Promise<Result<MetadataResponse, MetadataServiceError>> {
|
|
133
|
+
const error = new MetadataServiceError(
|
|
134
|
+
MetadataServiceErrorType.decodingError,
|
|
135
|
+
'decoding error'
|
|
136
|
+
);
|
|
137
|
+
return { error };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const backend = new MockSearchBackend();
|
|
142
|
+
const service = new MetadataService(backend);
|
|
143
|
+
const metadataResult = await service.fetchMetadata('foo');
|
|
144
|
+
expect(metadataResult.error).to.not.equal(undefined);
|
|
145
|
+
expect(metadataResult.error?.type).to.equal(
|
|
146
|
+
MetadataServiceErrorType.decodingError
|
|
147
|
+
);
|
|
148
|
+
expect(metadataResult.error?.message).to.equal('decoding error');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
export class MockResponseGenerator {
|
|
3
|
+
generateMockMetadataResponse(identifier: string): any {
|
|
4
|
+
return {
|
|
5
|
+
created: 1586477049,
|
|
6
|
+
d1: 'ia600201.us.archive.org',
|
|
7
|
+
d2: 'ia800201.us.archive.org',
|
|
8
|
+
dir: '/27/items/rss-383924main_TWAN_09_04_09',
|
|
9
|
+
files: [
|
|
10
|
+
{
|
|
11
|
+
name: 'foo.jpg',
|
|
12
|
+
source: 'derivative',
|
|
13
|
+
format: 'Thumbnail',
|
|
14
|
+
original: 'foo.mp4',
|
|
15
|
+
md5: '48067b43a547d3e90cb433a04ba84d5d',
|
|
16
|
+
mtime: '1256675427',
|
|
17
|
+
size: '1135',
|
|
18
|
+
crc32: '40870038',
|
|
19
|
+
sha1: '6445c2a6f51c8314c1872ec1f7daf33c5cfabd06',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'bar.jpg',
|
|
23
|
+
source: 'derivative',
|
|
24
|
+
format: 'Thumbnail',
|
|
25
|
+
original: 'bar.mp4',
|
|
26
|
+
md5: '5bf69912d7b796fe309cde32e61230bc',
|
|
27
|
+
mtime: '1256675429',
|
|
28
|
+
size: '6329',
|
|
29
|
+
crc32: 'ba5f361a',
|
|
30
|
+
sha1: 'cddab0e2daab29978e5efdeff735240a44aa7c80',
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
files_count: 2,
|
|
34
|
+
item_last_updated: 1463797130,
|
|
35
|
+
item_size: 99872691,
|
|
36
|
+
metadata: {
|
|
37
|
+
feed_id:
|
|
38
|
+
'/0/rss_feeds/NASACast_Video/nasacast_video:sts128_landing/NASAcast_vodcast.rss',
|
|
39
|
+
mediatype: 'movies',
|
|
40
|
+
title: "NASA TV's This Week @NASA, September 4",
|
|
41
|
+
description: "NASA TV's This Week @NASA, September 4",
|
|
42
|
+
creator: 'NASA',
|
|
43
|
+
source: 'http://www.nasa.gov/multimedia/podcasting/twan_09_04_09.html',
|
|
44
|
+
date: '9/4/2009',
|
|
45
|
+
year: '2009',
|
|
46
|
+
rights: 'Public Domain',
|
|
47
|
+
language: 'en-us',
|
|
48
|
+
updater: 'BonnieReal',
|
|
49
|
+
updatedate: '2009-10-27 20:23:01',
|
|
50
|
+
identifier,
|
|
51
|
+
uploader: 'bonnie@archive.org',
|
|
52
|
+
addeddate: '2009-10-27 20:25:55',
|
|
53
|
+
publicdate: '2009-10-27 20:41:27',
|
|
54
|
+
collection: ['nasa', 'nasacastvideo'],
|
|
55
|
+
backup_location: 'ia903604_7',
|
|
56
|
+
},
|
|
57
|
+
server: 'ia800201.us.archive.org',
|
|
58
|
+
uniq: 162444403,
|
|
59
|
+
workable_servers: ['ia800201.us.archive.org', 'ia600201.us.archive.org'],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing';
|
|
2
|
+
|
|
3
|
+
import { File } from '../../src/models/file';
|
|
4
|
+
|
|
5
|
+
describe('File', () => {
|
|
6
|
+
it('can be instantiated with an object', async () => {
|
|
7
|
+
const file = new File({ name: 'foo.jpg' });
|
|
8
|
+
expect(file.name).to.equal('foo.jpg');
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing';
|
|
2
|
+
import {
|
|
3
|
+
NumberListField,
|
|
4
|
+
StringListField,
|
|
5
|
+
} from '../../../src/models/metadata-fields/field-types/list';
|
|
6
|
+
|
|
7
|
+
describe('List Field', () => {
|
|
8
|
+
describe('String List Field', () => {
|
|
9
|
+
it('can parse individual values', () => {
|
|
10
|
+
const stringListField = new StringListField('foo');
|
|
11
|
+
|
|
12
|
+
expect(stringListField.value).to.equal('foo');
|
|
13
|
+
expect(stringListField.values).to.deep.equal(['foo']);
|
|
14
|
+
expect(stringListField.rawValue).to.equal('foo');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('can parse lists', () => {
|
|
18
|
+
const stringListField = new StringListField('foo, bar, baz');
|
|
19
|
+
|
|
20
|
+
expect(stringListField.value).to.equal('foo');
|
|
21
|
+
expect(stringListField.values).to.deep.equal(['foo', 'bar', 'baz']);
|
|
22
|
+
expect(stringListField.rawValue).to.equal('foo, bar, baz');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('can parse lists of lists', () => {
|
|
26
|
+
const stringListField = new StringListField([
|
|
27
|
+
'foo, bar, baz',
|
|
28
|
+
'beep, boop, bop',
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
expect(stringListField.value).to.equal('foo');
|
|
32
|
+
expect(stringListField.values).to.deep.equal([
|
|
33
|
+
'foo',
|
|
34
|
+
'bar',
|
|
35
|
+
'baz',
|
|
36
|
+
'beep',
|
|
37
|
+
'boop',
|
|
38
|
+
'bop',
|
|
39
|
+
]);
|
|
40
|
+
expect(stringListField.rawValue).to.deep.equal([
|
|
41
|
+
'foo, bar, baz',
|
|
42
|
+
'beep, boop, bop',
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('NumberListField', () => {
|
|
48
|
+
it('can parse lists of numbers', () => {
|
|
49
|
+
const listField = new NumberListField('1, 2, 3');
|
|
50
|
+
|
|
51
|
+
expect(listField.value).to.equal(1);
|
|
52
|
+
expect(listField.values).to.deep.equal([1, 2, 3]);
|
|
53
|
+
expect(listField.rawValue).to.equal('1, 2, 3');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('can parse lists of lists', () => {
|
|
57
|
+
const listField = new NumberListField(['1, 2, 3', '4, 5, 6']);
|
|
58
|
+
|
|
59
|
+
expect(listField.value).to.equal(1);
|
|
60
|
+
expect(listField.values).to.deep.equal([1, 2, 3, 4, 5, 6]);
|
|
61
|
+
expect(listField.rawValue).to.deep.equal(['1, 2, 3', '4, 5, 6']);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FieldParserInterface,
|
|
3
|
+
FieldParserRawValue,
|
|
4
|
+
} from '@internetarchive/field-parsers';
|
|
5
|
+
import { expect } from '@open-wc/testing';
|
|
6
|
+
import { MetadataField } from '../../../src/models/metadata-fields/metadata-field';
|
|
7
|
+
|
|
8
|
+
describe('Metadata Field', () => {
|
|
9
|
+
it('can be properly instantiated with single value', () => {
|
|
10
|
+
class MockParser implements FieldParserInterface<string> {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
parseValue(rawValue: any): string {
|
|
13
|
+
return rawValue;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const parser = new MockParser();
|
|
18
|
+
const metadataField = new MetadataField(parser, 'foo');
|
|
19
|
+
|
|
20
|
+
expect(metadataField.rawValue).to.equal('foo');
|
|
21
|
+
expect(metadataField.value).to.equal('foo');
|
|
22
|
+
expect(metadataField.values).to.deep.equal(['foo']);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('can be properly instantiated with array value', () => {
|
|
26
|
+
class MockParser implements FieldParserInterface<string> {
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
parseValue(rawValue: any): string {
|
|
29
|
+
return rawValue;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const parser = new MockParser();
|
|
34
|
+
const metadataField = new MetadataField(parser, ['foo', 'bar', 'baz']);
|
|
35
|
+
|
|
36
|
+
expect(metadataField.rawValue).to.deep.equal(['foo', 'bar', 'baz']);
|
|
37
|
+
expect(metadataField.value).to.equal('foo');
|
|
38
|
+
expect(metadataField.values).to.deep.equal(['foo', 'bar', 'baz']);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('properly casts values to expected parser type for single values', () => {
|
|
42
|
+
class MockFloatParser implements FieldParserInterface<number> {
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
+
parseValue(rawValue: any): number {
|
|
45
|
+
return parseFloat(rawValue);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const parser = new MockFloatParser();
|
|
50
|
+
const metadataField = new MetadataField(parser, '1.3');
|
|
51
|
+
|
|
52
|
+
expect(metadataField.rawValue).to.equal('1.3');
|
|
53
|
+
expect(metadataField.value).to.equal(1.3);
|
|
54
|
+
expect(metadataField.values).to.deep.equal([1.3]);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('properly casts values to expected parser type for array values', () => {
|
|
58
|
+
class MockFloatParser implements FieldParserInterface<number> {
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
parseValue(rawValue: any): number {
|
|
61
|
+
return parseFloat(rawValue);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const parser = new MockFloatParser();
|
|
66
|
+
const metadataField = new MetadataField(parser, ['1.3', '2.4', '4.5']);
|
|
67
|
+
|
|
68
|
+
expect(metadataField.rawValue).to.deep.equal(['1.3', '2.4', '4.5']);
|
|
69
|
+
expect(metadataField.value).to.equal(1.3);
|
|
70
|
+
expect(metadataField.values).to.deep.equal([1.3, 2.4, 4.5]);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('has no value if a raw value was not passed in', () => {
|
|
74
|
+
class MockFloatParser implements FieldParserInterface<number> {
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
|
+
parseValue(rawValue: any): number {
|
|
77
|
+
return rawValue;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const parser = new MockFloatParser();
|
|
82
|
+
const metadataField = new MetadataField(parser);
|
|
83
|
+
|
|
84
|
+
expect(metadataField.rawValue).to.equal(undefined);
|
|
85
|
+
expect(metadataField.value).to.equal(undefined);
|
|
86
|
+
expect(metadataField.values).to.deep.equal([]);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('does not add value to values array if parsed value is undefined', () => {
|
|
90
|
+
class MockFloatParser implements FieldParserInterface<number> {
|
|
91
|
+
parseValue(rawValue: FieldParserRawValue): number | undefined {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const parser = new MockFloatParser();
|
|
97
|
+
const metadataField = new MetadataField(parser);
|
|
98
|
+
|
|
99
|
+
expect(metadataField.rawValue).to.equal(undefined);
|
|
100
|
+
expect(metadataField.value).to.equal(undefined);
|
|
101
|
+
expect(metadataField.values).to.deep.equal([]);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('handles falsy `0` return values properly', () => {
|
|
105
|
+
class MockFloatParser implements FieldParserInterface<number> {
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
107
|
+
parseValue(rawValue: any): number {
|
|
108
|
+
return rawValue;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const parser = new MockFloatParser();
|
|
113
|
+
const metadataField = new MetadataField(parser, 0);
|
|
114
|
+
|
|
115
|
+
expect(metadataField.rawValue).to.equal(0);
|
|
116
|
+
expect(metadataField.value).to.equal(0);
|
|
117
|
+
expect(metadataField.values).to.deep.equal([0]);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('handles falsy `false` return values properly', () => {
|
|
121
|
+
class MockFloatParser implements FieldParserInterface<number> {
|
|
122
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
123
|
+
parseValue(rawValue: any): number {
|
|
124
|
+
return rawValue;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const parser = new MockFloatParser();
|
|
129
|
+
const metadataField = new MetadataField(parser, false);
|
|
130
|
+
|
|
131
|
+
expect(metadataField.rawValue).to.equal(false);
|
|
132
|
+
expect(metadataField.value).to.equal(false);
|
|
133
|
+
expect(metadataField.values).to.deep.equal([false]);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('handles falsy empty string return values properly', () => {
|
|
137
|
+
class MockFloatParser implements FieldParserInterface<number> {
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
139
|
+
parseValue(rawValue: any): number {
|
|
140
|
+
return rawValue;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const parser = new MockFloatParser();
|
|
145
|
+
const metadataField = new MetadataField(parser, '');
|
|
146
|
+
|
|
147
|
+
expect(metadataField.rawValue).to.equal('');
|
|
148
|
+
expect(metadataField.value).to.equal('');
|
|
149
|
+
expect(metadataField.values).to.deep.equal(['']);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing';
|
|
2
|
+
|
|
3
|
+
import { Metadata } from '../../src/models/metadata';
|
|
4
|
+
|
|
5
|
+
describe('Metadata', () => {
|
|
6
|
+
it('properly instantiates metadata with identifier', async () => {
|
|
7
|
+
const json = { identifier: 'foo', collection: 'bar' };
|
|
8
|
+
const metadata = new Metadata(json);
|
|
9
|
+
expect(metadata.identifier).to.equal('foo');
|
|
10
|
+
});
|
|
11
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2018",
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"noEmitOnError": true,
|
|
7
|
+
"lib": ["es2017", "dom"],
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": false,
|
|
10
|
+
"allowSyntheticDefaultImports": true,
|
|
11
|
+
"experimentalDecorators": true,
|
|
12
|
+
"importHelpers": true,
|
|
13
|
+
"outDir": "dist",
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"inlineSources": true,
|
|
16
|
+
"declaration": true,
|
|
17
|
+
"rootDir": "./",
|
|
18
|
+
},
|
|
19
|
+
"include": [
|
|
20
|
+
"**/*.ts"
|
|
21
|
+
],
|
|
22
|
+
}
|