From 0bcf5c340f8f5115b1a7310a38de2a2bfe63c9c8 Mon Sep 17 00:00:00 2001 From: Juunini Date: Thu, 12 Oct 2023 23:59:42 +0900 Subject: [PATCH] fix test cases --- README.md | 43 +++--- package.json | 2 +- src/reader/JsonLDReader.test.ts | 245 ++++++++++++++++++++++++++++++++ src/reader/JsonLDReader.ts | 12 +- src/reader/reader.test.ts | 192 ------------------------- 5 files changed, 275 insertions(+), 219 deletions(-) create mode 100644 src/reader/JsonLDReader.test.ts delete mode 100644 src/reader/reader.test.ts diff --git a/README.md b/README.md index 96a3319..2fe8f10 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ When receive JSON-LD, { "@context": "https://www.w3.org/ns/activitystreams", "name": "juunini", + "type": "Person", "id": "juunini" } ``` @@ -30,6 +31,7 @@ is equals { "@context": "https://www.w3.org/ns/activitystreams", "as:name": "juunini", + "type": "Person", "@id": "juunini" } ``` @@ -44,7 +46,12 @@ and it also equals "@value": "juunini" } ], - "@id": "juunini" + "@id": "juunini", + "https://www.w3.org/ns/activitystreams#type": [ + { + "@value": "Person" + } + ] } ] ``` @@ -79,23 +86,22 @@ const jsonld = await JsonLDReader.parse({ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers" } ], - "as:id": "https://mastodon.social/users/juunini", + "@id": "https://mastodon.social/users/juunini", "as:type": "Person", - "as:url": "https://mastodon.social/@juunini", + "url": "https://mastodon.social/@juunini", "as:image": { - "as:type": "Image", + "@type": "Image", "as:mediaType": "image/png", "url": "https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png" }, - "as:manuallyApprovesFollowers": "true" + "manuallyApprovesFollowers": "true" }) -const imageURL = jsonld - .setNamespace({ as: 'https://www.w3.org/ns/activitystreams' }) - .read('as', 'image') - .read('as', 'url') - .stringOrThrow() -// https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png +const imageType = jsonld + .read('image') + .read('mediaType') + .stringOrElse('') +// image/png const imageURL = jsonld .read('image') @@ -103,21 +109,16 @@ const imageURL = jsonld .stringOrThrow() // https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png -const id = jsonld.read('@id').get() -// https://mastodon.social/users/juunini - const id = jsonld.read('id').get() +const id = jsonld.read('@id').get() // https://mastodon.social/users/juunini -const type = jsonld.read('@type').get() -// Person - const type = jsonld.read('type').get() +const type = jsonld.read('@type').get() // Person const manuallyApprovesFollowers = jsonld - .setNamespace({ as: 'https://www.w3.org/ns/activitystreams' }) - .read('as', 'manuallyApprovesFollowers') + .read('manuallyApprovesFollowers') .booleanOrElse(false) // true ``` @@ -130,8 +131,8 @@ JsonLDReader.parse (value: object | object[], options?: Options.Expand): Promise .value [readonly]: unknown .length [readonly]: number -.read (key: string | number): JsonLDReader -.read (namespace: string, key: string): JsonLDReader +.read (key: string): JsonLDReader +.read (index: number): JsonLDReader .get (): unknown .getOrThrow (error?: Error): unknown diff --git a/package.json b/package.json index 85442bc..3b64840 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cloudmatelabs/jsonld-helper", - "version": "1.2.3", + "version": "1.3.0", "description": "JSON-LD Helper", "homepage": "/~https://github.com/cloudmatelabs/jsonld-helper-ts", "repository": "cloudmatelabs/jsonld-helper-ts", diff --git a/src/reader/JsonLDReader.test.ts b/src/reader/JsonLDReader.test.ts new file mode 100644 index 0000000..23444be --- /dev/null +++ b/src/reader/JsonLDReader.test.ts @@ -0,0 +1,245 @@ +import { describe, it, expect } from 'bun:test' + +import { JsonLDReader } from './JsonLDReader' + +describe('get', () => { + describe('when given key can not find', () => { + const givenKey = 'notFoundKey' + + it('should return null', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(jsonld.read(givenKey).get()).toBeNull() + expect(jsonld.read(0).read(givenKey).get()).toBeNull() + }) + }) + + describe('when given index, result is object', () => { + it('should return null', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(jsonld.read(0).read(0).get()).toBeNull() + }) + }) + + describe('when given key can find', () => { + const givenKey = 'name' + + it('should return value', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(jsonld.read(givenKey).get()).toBe('지상 최강의 개발자 쥬니니') + expect(jsonld.read(0).read(givenKey).get()).toBe('지상 최강의 개발자 쥬니니') + }) + }) + + describe('when given key is preDefined key', () => { + it('should return value', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(jsonld.read('id').get()).toBe('acct:juunini@snippet.cloudmt.co.kr') + expect(jsonld.read('@id').get()).toBe('acct:juunini@snippet.cloudmt.co.kr') + expect(jsonld.read('type').get()).toBe('Person') + expect(jsonld.read('@type').get()).toBe('Person') + expect(jsonld.read(0).read('id').get()).toBe('acct:juunini@snippet.cloudmt.co.kr') + expect(jsonld.read(0).read('@id').get()).toBe('acct:juunini@snippet.cloudmt.co.kr') + expect(jsonld.read(0).read('type').get()).toBe('Person') + expect(jsonld.read(0).read('@type').get()).toBe('Person') + }) + }) + + describe('when given index and key can find', () => { + it('should return value', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(jsonld.read('attachment').read(0).read('value').get()).toBe('juunini') + }) + }) +}) + +describe('getOrElse', () => { + describe('when given key can not find', () => { + const givenKey = 'notFoundKey' + const givenDefaultValue = 'defaultValue' + + it('should return default value', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(jsonld.read(givenKey).getOrElse(givenDefaultValue)).toBe(givenDefaultValue) + expect(jsonld.read(0).read(givenKey).getOrElse(givenDefaultValue)).toBe(givenDefaultValue) + }) + }) + + describe('when given key can find', () => { + const givenKey = 'name' + const givenDefaultValue = 'defaultValue' + + it('should return value', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(jsonld.read(givenKey).getOrElse(givenDefaultValue)).toBe('지상 최강의 개발자 쥬니니') + expect(jsonld.read(0).read(givenKey).getOrElse(givenDefaultValue)).toBe('지상 최강의 개발자 쥬니니') + }) + }) + + describe('when given index can not find', () => { + const givenIndex = 1 + const givenDefaultValue = 'defaultValue' + + it('should return default value', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(jsonld.read(givenIndex).getOrElse(givenDefaultValue)).toBe(givenDefaultValue) + expect(jsonld.read(0).read(0).getOrElse(givenDefaultValue)).toBe(givenDefaultValue) + }) + }) +}) + +describe('getOrThrow', () => { + describe('when given key can not find', () => { + const givenKey = 'notFoundKey' + + it('should throw error', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(() => jsonld.read(givenKey).getOrThrow()).toThrow('Not found key: notFoundKey') + expect(() => jsonld.read(0).read(givenKey).getOrThrow()).toThrow('Not found key: notFoundKey') + }) + }) + + describe('when given key can find', () => { + const givenKey = 'name' + + it('should return value', async () => { + const jsonld = await JsonLDReader.parse(givenJsonLD, options) + + expect(jsonld.read(givenKey).getOrThrow()).toBe('지상 최강의 개발자 쥬니니') + expect(jsonld.read(0).read(givenKey).getOrThrow()).toBe('지상 최강의 개발자 쥬니니') + }) + }) +}) + +describe('readme JSON-LD test', () => { + it('should return value', async () => { + const jsonld = await JsonLDReader.parse(readmeJsonLD, options) + + expect(jsonld.read('id').get()).toBe('https://mastodon.social/users/juunini') + expect(jsonld.read('@id').get()).toBe('https://mastodon.social/users/juunini') + expect(jsonld.read('type').get()).toBe('Person') + expect(jsonld.read('@type').get()).toBe('Person') + expect(jsonld.read('url').get()).toBe('https://mastodon.social/@juunini') + expect(jsonld.read('image').read('type').get()).toBe('Image') + expect(jsonld.read('image').read('@type').get()).toBe('Image') + expect(jsonld.read('image').read('mediaType').get()).toBe('image/png') + expect(jsonld.read('image').read('url').get()).toBe('https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png') + expect(jsonld.read('manuallyApprovesFollowers').get()).toBe('true') + }) +}) + +const options = { + documentLoader: async (url: string) => { + if (url === 'https://www.w3.org/ns/activitystreams') { + return { + document: activitystream, + documentUrl: url + } + } + + if (url === 'http://schema.org') { + return { + document: schema, + documentUrl: url + } + } + + return { + documentUrl: url, + document: {} + } + } +} + +const givenJsonLD = { + '@context': [ + 'https://www.w3.org/ns/activitystreams', + { + schema: 'http://schema.org#', + PropertyValue: 'schema:PropertyValue', + value: 'schema:value' + } + ], + 'as:type': 'Person', + '@id': 'acct:juunini@snippet.cloudmt.co.kr', + name: '지상 최강의 개발자 쥬니니', + attachment: [ + { + type: 'PropertyValue', + name: 'GitHub', + value: 'juunini' + } + ] +} + +const readmeJsonLD = { + '@context': [ + 'https://www.w3.org/ns/activitystreams', + { + manuallyApprovesFollowers: 'as:manuallyApprovesFollowers' + } + ], + '@id': 'https://mastodon.social/users/juunini', + 'as:type': 'Person', + url: 'https://mastodon.social/@juunini', + 'as:image': { + '@type': 'Image', + 'as:mediaType': 'image/png', + url: 'https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png' + }, + manuallyApprovesFollowers: 'true' +} + +const activitystream = { + '@context': { + '@vocab': '_:', + xsd: 'http://www.w3.org/2001/XMLSchema#', + as: 'https://www.w3.org/ns/activitystreams#', + ldp: 'http://www.w3.org/ns/ldp#', + vcard: 'http://www.w3.org/2006/vcard/ns#', + id: '@id', + type: '@type', + attachment: { + '@id': 'as:attachment', + '@type': '@id' + }, + url: { + '@id': 'as:url', + '@type': '@id' + }, + mediaType: 'as:mediaType', + name: 'as:name', + Image: 'as:Image', + Person: 'as:Person' + } +} + +const schema = { + '@context': { + rdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + rdfs: 'http://www.w3.org/2000/01/rdf-schema#', + schema: 'https://schema.org/' + }, + '@graph': [ + { + '@id': 'schema:value', + '@type': 'rdf:Property' + }, + { + '@id': 'schema:name', + '@type': 'rdf:Property' + }, + { + '@id': 'schema:PropertyValue', + '@type': 'rdfs:Class' + } + ] +} diff --git a/src/reader/JsonLDReader.ts b/src/reader/JsonLDReader.ts index a0cb2a0..d8a1c44 100644 --- a/src/reader/JsonLDReader.ts +++ b/src/reader/JsonLDReader.ts @@ -46,14 +46,16 @@ export class JsonLDReader { return JsonLDReader.of(data) } - public strict (): JsonLDReader { - return JsonLDReader.of(this.value) - } - /** - * @param keyOrIndex + * @param key key of parsed JSON-LD value + * @returns JsonLDReader instance. if key is not found, returns `Nothing` instance. + */ + public read (key: string): JsonLDReader + /** + * @param index index of parsed JSON-LD value * @returns JsonLDReader instance. if key is not found, returns `Nothing` instance. */ + public read (index: number): JsonLDReader public read (keyOrIndex: string | number): JsonLDReader { return read({ jsonld: this.value, diff --git a/src/reader/reader.test.ts b/src/reader/reader.test.ts deleted file mode 100644 index cba4a00..0000000 --- a/src/reader/reader.test.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { describe, it, expect } from 'bun:test' - -import { JsonLDReader } from './JsonLDReader' - -describe('read', () => { - describe('when given key is not found', () => { - it('should changes type Nothing', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect(() => jsonld.read('uid').getOrThrow()).toThrow('Not found key: uid') - }) - }) - - describe('when given key is string, but value is not object', () => { - it('should changes type Nothing', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect(() => jsonld.read('id').read('@context').getOrThrow()).toThrow('Not an object') - }) - }) - - describe('when given key is number, but value is not array', () => { - it('should changes type Nothing', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect(() => jsonld.read(0).read(0).getOrThrow()).toThrow('Not an array') - }) - }) - - describe('when error case and given throw error', () => { - it('should throws given error', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect(() => jsonld.read('uid').getOrThrow(new Error('test'))).toThrow('test') - }) - }) - - describe('when given key is string, find key', () => { - it('should return value', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect( - jsonld - .read('outbox') - .getOrThrow() - ).toBe('https://mastodon.social/users/juunini/outbox') - }) - }) - - describe('when not given namespace, find key', () => { - it('should return value', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect(jsonld.read('outbox').get()).toBe('https://mastodon.social/users/juunini/outbox') - }) - }) - - describe('when given key is preDefined key', () => { - it('should return value', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect(jsonld.read('@id').get()).toBe('https://mastodon.social/users/juunini') - expect(jsonld.read('id').get()).toBe('https://mastodon.social/users/juunini') - expect(jsonld.read('@type').get()).toBe('Person') - expect(jsonld.read('type').get()).toBe('Person') - }) - }) -}) - -describe('stringOrThrow', () => { - describe('when given value is string', () => { - it('should return value', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect( - jsonld - .read('image') - .read('url') - .stringOrThrow() - ).toBe('https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png') - }) - }) - - describe('when given value is not string', () => { - it('should throws error', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect( - jsonld - .read('manuallyApprovesFollowers') - .stringOrThrow() - ).toBe('false') - }) - }) -}) - -describe('numberOrThrow', () => { - describe('when given value is number', () => { - it('should return value', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect( - jsonld - .read('accuracy') - .numberOrThrow() - ).toBe(1) - }) - }) - - describe('when given value is not number', () => { - it('should throws error', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect(() => jsonld.read('@id').numberOrThrow()).toThrow('Not a number') - }) - }) -}) - -describe('booleanOrThrow', () => { - describe('when given value is boolean', () => { - it('should return value', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect( - jsonld - .read('closed') - .booleanOrThrow() - ).toBe(true) - }) - }) - - describe('when given value is not boolean', () => { - it('should throws error', async () => { - const jsonld = await JsonLDReader.parse(givenJSONLD) - expect(() => jsonld.read('@id').booleanOrThrow()).toThrow('Not a boolean') - }) - }) -}) - -describe('booleanOrElse', () => { - const givenJsonLD = { - '@context': [ - 'https://www.w3.org/ns/activitystreams', - { - manuallyApprovesFollowers: 'as:manuallyApprovesFollowers' - } - ], - 'as:id': 'https://mastodon.social/users/juunini', - 'as:type': 'Person', - 'as:url': 'https://mastodon.social/@juunini', - 'as:image': { - 'as:type': 'Image', - 'as:mediaType': 'image/png', - url: 'https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png' - }, - 'as:manuallyApprovesFollowers': 'true' - } - - it('should return value', async () => { - const jsonld = await JsonLDReader.parse(givenJsonLD) - - const manuallyApprovesFollowers = jsonld - .read('manuallyApprovesFollowers') - .booleanOrElse(false) - - expect(manuallyApprovesFollowers).toBe(true) - }) -}) - -const givenJSONLD = { - '@context': [ - 'https://www.w3.org/ns/activitystreams', - { - manuallyApprovesFollowers: 'as:manuallyApprovesFollowers' - } - ], - accuracy: 1, - '@id': 'https://mastodon.social/users/juunini', - 'as:type': 'Person', - following: 'https://mastodon.social/users/juunini/following', - followers: 'https://mastodon.social/users/juunini/followers', - inbox: 'https://mastodon.social/users/juunini/inbox', - outbox: 'https://mastodon.social/users/juunini/outbox', - preferredUsername: 'juunini', - name: '지상 최강의 개발자 쥬니니', - summary: '', - url: 'https://mastodon.social/@juunini', - manuallyApprovesFollowers: false, - closed: 'true', - published: '2022-11-26T00:00:00Z', - endpoints: { - sharedInbox: 'https://mastodon.social/inbox' - }, - icon: { - type: 'Image', - mediaType: 'image/jpeg', - url: 'https://files.mastodon.social/accounts/avatars/109/408/471/076/954/889/original/aa381e203bb80bb7.jpg' - }, - image: { - type: 'Image', - mediaType: 'image/png', - url: 'https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png' - } -}