From 342ee3f653f492d3b07ac9b467eba55f0d02b3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Gorej?= Date: Fri, 1 Mar 2024 11:54:03 +0100 Subject: [PATCH] feat(core): add support for RefElement and LinkElement (#3884) Refs #3882 --- packages/@types/minim.d.ts | 16 +++---- .../transformers/serializers/value/index.ts | 14 +++++++ .../test/transformers/serializers/value.ts | 42 +++++++++++++++++++ .../apidom-core/test/traversal/visitor.ts | 35 +++++++++++++++- 4 files changed, 98 insertions(+), 9 deletions(-) diff --git a/packages/@types/minim.d.ts b/packages/@types/minim.d.ts index c55c4efca6..9e53641f74 100644 --- a/packages/@types/minim.d.ts +++ b/packages/@types/minim.d.ts @@ -169,23 +169,23 @@ declare module 'minim' { } export class LinkElement extends Element { - constructor(content?: Array, meta?: Meta, attributes?: Attributes); + constructor(content?: unknown, meta?: Meta, attributes?: Attributes); - get relation(): unknown; + get relation(): string; - set relation(relation: unknown); + set relation(relation: string); - get href(): unknown; + get href(): string; - set href(key: unknown); + set href(key: string); } export class RefElement extends Element { - constructor(content?: Array, meta?: Meta, attributes?: Attributes); + constructor(content?: unknown, meta?: Meta, attributes?: Attributes); - get path(): unknown; + get path(): string; - set path(path: unknown); + set path(path: string); } export class ArraySlice { diff --git a/packages/apidom-core/src/transformers/serializers/value/index.ts b/packages/apidom-core/src/transformers/serializers/value/index.ts index a0e1dc5f0e..d49e67dfa6 100644 --- a/packages/apidom-core/src/transformers/serializers/value/index.ts +++ b/packages/apidom-core/src/transformers/serializers/value/index.ts @@ -7,6 +7,8 @@ import { ObjectElement, MemberElement, NullElement, + RefElement, + LinkElement, } from 'minim'; import { visit } from './visitor'; @@ -82,9 +84,21 @@ class Visitor { public NullElement() { return null; } + + public RefElement(element: RefElement): unknown { + return element.toValue(); + } + + public LinkElement(element: LinkElement): string { + if (isStringElement(element.href)) { + return element.href.toValue(); + } + return ''; + } } type ShortCutElementTypes = StringElement | NumberElement | BooleanElement | NullElement; + const serializer = (element: T): any => { if (!isElement(element)) return element; diff --git a/packages/apidom-core/test/transformers/serializers/value.ts b/packages/apidom-core/test/transformers/serializers/value.ts index 0955b27a70..69c65a0c85 100644 --- a/packages/apidom-core/test/transformers/serializers/value.ts +++ b/packages/apidom-core/test/transformers/serializers/value.ts @@ -7,6 +7,8 @@ import { NullElement, ObjectElement, ArrayElement, + RefElement, + LinkElement, } from '../../../src'; import serializer from '../../../src/transformers/serializers/value'; @@ -134,6 +136,46 @@ describe('serializers', function () { }); }); + context('given RefElement', function () { + specify('should serialize to JavaScript value', function () { + const ref = new RefElement('id'); + const serialized = serializer(ref); + + assert.strictEqual(serialized, 'id'); + }); + + context('and nested inside ObjectElement', function () { + specify('should serialize to JavaScript value', function () { + const object = new ObjectElement({ + ref: new RefElement('id'), + }); + const serialized = serializer(object); + + assert.deepEqual(serialized, { ref: 'id' }); + }); + }); + }); + + context('given LinkElement', function () { + specify('should serialize to JavaScript value', function () { + const ref = new LinkElement(); + const serialized = serializer(ref); + + assert.strictEqual(serialized, ''); + }); + + context('and nested inside ObjectElement', function () { + specify('should serialize to JavaScript value', function () { + const object = new ObjectElement({ + link: new LinkElement(undefined, undefined, { relation: 'foo', href: '/bar' }), + }); + const serialized = serializer(object); + + assert.deepEqual(serialized, { link: '/bar' }); + }); + }); + }); + context('given primitive value', function () { specify('should acts as identify function', function () { assert.strictEqual(serializer(1 as any), 1); diff --git a/packages/apidom-core/test/traversal/visitor.ts b/packages/apidom-core/test/traversal/visitor.ts index 55568ff5ae..fbcacfa192 100644 --- a/packages/apidom-core/test/traversal/visitor.ts +++ b/packages/apidom-core/test/traversal/visitor.ts @@ -1,11 +1,14 @@ import { assert } from 'chai'; +import sinon from 'sinon'; import { ObjectElement, ArrayElement, StringElement, - visit, MemberElement, + RefElement, + LinkElement, + visit, toValue, } from '../../src'; @@ -92,5 +95,35 @@ describe('traversal', function () { assert.deepEqual(toValue(newArrayElement), [1]); }); + + context('given RefElement', function () { + specify('should call RefElement visitor hook', function () { + const objectElement = new ObjectElement({ + ref: new RefElement('id'), + }); + const visitor = { + RefElement: sinon.spy(), + }; + + visit(objectElement, visitor); + + assert.isTrue(visitor.RefElement.calledOnce); + }); + }); + + context('given LinkElement', function () { + specify('should call LinkElement visitor hook', function () { + const objectElement = new ObjectElement({ + ref: new LinkElement(), + }); + const visitor = { + LinkElement: sinon.spy(), + }; + + visit(objectElement, visitor); + + assert.isTrue(visitor.LinkElement.calledOnce); + }); + }); }); });