From 3a2e5ded94d309cf38058b1ea93227e0fd987a22 Mon Sep 17 00:00:00 2001 From: mmelko Date: Fri, 29 Nov 2024 14:07:30 +0100 Subject: [PATCH] reflect PR comments --- packages/ui/src/hooks/entities.test.tsx | 69 +------------------ packages/ui/src/hooks/entities.ts | 11 --- .../__snapshots__/camel-resource.test.ts.snap | 28 ++++++++ .../models/camel/camel-k-resource-factory.ts | 5 +- .../ui/src/models/camel/camel-k-resource.ts | 2 - .../models/camel/camel-resource-factory.ts | 14 ++-- .../src/models/camel/camel-resource.test.ts | 2 +- .../models/camel/camel-route-resource.test.ts | 20 +++--- .../src/models/camel/camel-route-resource.ts | 5 +- .../src/models/camel/kamelet-resource.test.ts | 6 +- .../ui/src/models/camel/kamelet-resource.ts | 2 +- .../yaml-camel-resource-serializer.test.ts | 32 +++++++++ .../yaml-camel-resource-serializer.ts | 14 +++- 13 files changed, 101 insertions(+), 109 deletions(-) create mode 100644 packages/ui/src/serializers/yaml-camel-resource-serializer.test.ts diff --git a/packages/ui/src/hooks/entities.test.tsx b/packages/ui/src/hooks/entities.test.tsx index 249767606..b82ad2963 100644 --- a/packages/ui/src/hooks/entities.test.tsx +++ b/packages/ui/src/hooks/entities.test.tsx @@ -59,12 +59,14 @@ describe('useEntities', () => { expect(notifierSpy).toHaveBeenCalledWith('entities:updated', camelRouteYaml_1_1_updated); }); - it('should notifiy subscribers when the entities are updated', () => { + it('should notify subscribers when the entities are updated', () => { const notifierSpy = jest.spyOn(eventNotifier, 'next'); const { result } = renderHook(() => useEntities()); act(() => { + console.log('result.current.camelResource:', result.current.camelResource); result.current.camelResource.addNewEntity(); + console.log('result.current.camelResource:', result.current.camelResource); result.current.updateSourceCodeFromEntities(); }); @@ -162,69 +164,4 @@ describe('useEntities', () => { `, ); }); - - describe('comments', () => { - it(`should store code's comments`, () => { - const code = `# This is a comment - # An indented comment - -- route: - id: route-1234 - from: - id: from-1234 - uri: timer - parameters: - period: "1000" - timerName: template - # This comment won't be stored - steps: - - log: - id: log-1234 - message: \${body} -`; - - const { result } = renderHook(() => useEntities()); - - act(() => { - eventNotifier.next('code:updated', code); - }); - - expect(result.current.camelResource.getComments()).toEqual([ - '# This is a comment', - ' # An indented comment', - '', - ]); - }); - - it('should add comments to the source code', () => { - const notifierSpy = jest.spyOn(eventNotifier, 'next'); - const { result } = renderHook(() => useEntities()); - - act(() => { - result.current.camelResource.setComments(['# This is a comment', ' # An indented comment', '']); - result.current.camelResource.addNewEntity(); - result.current.updateSourceCodeFromEntities(); - }); - - expect(notifierSpy).toHaveBeenCalledWith( - 'entities:updated', - `# This is a comment - # An indented comment - -- route: - id: route-1234 - from: - id: from-1234 - uri: timer - parameters: - period: "1000" - timerName: template - steps: - - log: - id: log-1234 - message: \${body} -`, - ); - }); - }); }); diff --git a/packages/ui/src/hooks/entities.ts b/packages/ui/src/hooks/entities.ts index edc7a86b9..b0a7b03ae 100644 --- a/packages/ui/src/hooks/entities.ts +++ b/packages/ui/src/hooks/entities.ts @@ -6,17 +6,6 @@ import { BaseVisualCamelEntity } from '../models/visualization/base-visual-entit import { EventNotifier } from '../utils'; import { CamelResourceFactory } from '../models/camel/camel-resource-factory'; -/** - * Regular expression to match commented lines, regardless of indentation - * Given the following examples, the regular expression should match the comments: - * ``` - * # This is a comment - * # This is an indented comment - *# This is an indented comment - * ``` - * The regular expression should match the first three lines - */ - export interface EntitiesContextResult { entities: BaseCamelEntity[]; currentSchemaType: SourceSchemaType; diff --git a/packages/ui/src/models/camel/__snapshots__/camel-resource.test.ts.snap b/packages/ui/src/models/camel/__snapshots__/camel-resource.test.ts.snap index 27a2e2020..c764cbea2 100644 --- a/packages/ui/src/models/camel/__snapshots__/camel-resource.test.ts.snap +++ b/packages/ui/src/models/camel/__snapshots__/camel-resource.test.ts.snap @@ -1,5 +1,33 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`CamelResourceFactory.createCamelResource should create an empty KameletResource if no args is specified 1`] = ` +[ + { + "from": { + "id": "from-1234", + "parameters": { + "period": "{{period}}", + "timerName": "user", + }, + "steps": [ + { + "to": { + "parameters": { + "httpUri": "random-data-api.com/api/v2/users", + }, + "uri": "https", + }, + }, + { + "to": "kamelet:sink", + }, + ], + "uri": "timer", + }, + }, +] +`; + exports[`createCamelResource should create an empty KameletResource if no args is specified 1`] = ` [ { diff --git a/packages/ui/src/models/camel/camel-k-resource-factory.ts b/packages/ui/src/models/camel/camel-k-resource-factory.ts index 817292fb7..f5f538d72 100644 --- a/packages/ui/src/models/camel/camel-k-resource-factory.ts +++ b/packages/ui/src/models/camel/camel-k-resource-factory.ts @@ -13,7 +13,8 @@ import { export class CamelKResourceFactory { static getCamelKResource(json?: unknown, type?: SourceSchemaType): CamelResource | undefined { - const jsonRecord = json as Record; + const jsonRecord = json ? (json as Record) : {}; + if ((jsonRecord && typeof json === 'object' && 'kind' in jsonRecord) || type) { switch (jsonRecord['kind'] || type) { case SourceSchemaType.Integration: @@ -24,8 +25,6 @@ export class CamelKResourceFactory { return new KameletBindingResource(json as KameletBindingType); case SourceSchemaType.Pipe: return new PipeResource(json as PipeType); - default: - return undefined; } } return undefined; diff --git a/packages/ui/src/models/camel/camel-k-resource.ts b/packages/ui/src/models/camel/camel-k-resource.ts index 0a0c3225c..ce22e7e63 100644 --- a/packages/ui/src/models/camel/camel-k-resource.ts +++ b/packages/ui/src/models/camel/camel-k-resource.ts @@ -35,8 +35,6 @@ export abstract class CamelKResource implements CamelResource { parsedResource: unknown, private readonly serializer: CamelResourceSerializer = new YamlCamelResourceSerializer(), ) { - this.serializer = serializer; - if (parsedResource) { this.resource = parsedResource as CamelKType; } else { diff --git a/packages/ui/src/models/camel/camel-resource-factory.ts b/packages/ui/src/models/camel/camel-resource-factory.ts index c39d8d79c..5fd6d3494 100644 --- a/packages/ui/src/models/camel/camel-resource-factory.ts +++ b/packages/ui/src/models/camel/camel-resource-factory.ts @@ -1,6 +1,6 @@ import { SourceSchemaType } from './source-schema-type'; import { CamelResource } from './camel-resource'; -import { XmlCamelResourceSerializer, YamlCamelResourceSerializer } from '../../serializers'; +import { CamelResourceSerializer, XmlCamelResourceSerializer, YamlCamelResourceSerializer } from '../../serializers'; import { CamelRouteResource } from './camel-route-resource'; import { CamelKResourceFactory } from './camel-k-resource-factory'; @@ -14,14 +14,14 @@ export class CamelResourceFactory { * @param source */ static createCamelResource(source?: string, type?: SourceSchemaType): CamelResource { - if (XmlCamelResourceSerializer.isApplicable(source)) { - return new CamelRouteResource(source, new XmlCamelResourceSerializer()); - } + const serializer: CamelResourceSerializer = XmlCamelResourceSerializer.isApplicable(source) + ? new XmlCamelResourceSerializer() + : new YamlCamelResourceSerializer(); - const serializer = new YamlCamelResourceSerializer(); - const resource = CamelKResourceFactory.getCamelKResource(serializer.parse(source ?? ''), type); + const parsedCode = source ? serializer.parse(source) : source; + const resource = CamelKResourceFactory.getCamelKResource(parsedCode, type); if (resource) return resource; - return new CamelRouteResource(source, serializer); + return new CamelRouteResource(parsedCode, serializer); } } diff --git a/packages/ui/src/models/camel/camel-resource.test.ts b/packages/ui/src/models/camel/camel-resource.test.ts index f5d83a61f..a2a55b3fc 100644 --- a/packages/ui/src/models/camel/camel-resource.test.ts +++ b/packages/ui/src/models/camel/camel-resource.test.ts @@ -70,7 +70,7 @@ describe('CamelResourceFactory.createCamelResource', () => { }); it('should create a Kamelet', () => { - const resource = CamelResourceFactory.createCamelResource(kameletJson); + const resource = CamelResourceFactory.createCamelResource(JSON.stringify(kameletJson)); expect(resource.getType()).toEqual(SourceSchemaType.Kamelet); expect(resource.getVisualEntities().length).toEqual(1); }); diff --git a/packages/ui/src/models/camel/camel-route-resource.test.ts b/packages/ui/src/models/camel/camel-route-resource.test.ts index ebb35d1e5..3573d53ed 100644 --- a/packages/ui/src/models/camel/camel-route-resource.test.ts +++ b/packages/ui/src/models/camel/camel-route-resource.test.ts @@ -13,7 +13,7 @@ import { CamelResourceFactory } from './camel-resource-factory'; describe('CamelRouteResource', () => { it('should create CamelRouteResource', () => { - const resource = new CamelRouteResource(camelRouteYaml); + const resource = new CamelRouteResource(camelRouteJson); expect(resource.getType()).toEqual(SourceSchemaType.Route); expect(resource.getVisualEntities().length).toEqual(1); expect(resource.getEntities().length).toEqual(0); @@ -39,7 +39,7 @@ describe('CamelRouteResource', () => { [null, undefined], [[], undefined], ])('should return the appropriate entity for: %s', (json, expected) => { - const resource = new CamelRouteResource(JSON.stringify(json)); + const resource = new CamelRouteResource(json); const firstEntity = resource.getVisualEntities()[0] ?? resource.getEntities()[0]; if (typeof expected === 'function') { @@ -98,14 +98,14 @@ describe('CamelRouteResource', () => { }); it('should return visual entities', () => { - const resource = new CamelRouteResource(camelRouteYaml); + const resource = new CamelRouteResource(camelRouteJson); expect(resource.getVisualEntities()).toHaveLength(1); expect(resource.getVisualEntities()[0]).toBeInstanceOf(CamelRouteVisualEntity); expect(resource.getEntities()).toHaveLength(0); }); it('should return entities', () => { - const resource = new CamelRouteResource(JSON.stringify(beansJson)); + const resource = new CamelRouteResource(beansJson); expect(resource.getEntities()).toHaveLength(1); expect(resource.getEntities()[0]).toBeInstanceOf(BeansEntity); expect(resource.getVisualEntities()).toHaveLength(0); @@ -113,7 +113,7 @@ describe('CamelRouteResource', () => { describe('toJSON', () => { it('should return JSON', () => { - const resource = new CamelRouteResource(camelRouteYaml); + const resource = new CamelRouteResource(camelRouteJson); expect(resource.toJSON()).toMatchSnapshot(); }); @@ -141,7 +141,7 @@ describe('CamelRouteResource', () => { describe('removeEntity', () => { it('should not do anything if the ID is not provided', () => { - const resource = new CamelRouteResource(camelRouteYaml); + const resource = new CamelRouteResource(camelRouteJson); resource.removeEntity(); @@ -149,7 +149,7 @@ describe('CamelRouteResource', () => { }); it('should not do anything when providing a non existing ID', () => { - const resource = new CamelRouteResource(camelRouteYaml); + const resource = new CamelRouteResource(camelRouteJson); resource.removeEntity('non-existing-id'); @@ -157,7 +157,7 @@ describe('CamelRouteResource', () => { }); it('should allow to remove an entity', () => { - const resource = new CamelRouteResource(JSON.stringify([camelRouteJson, camelFromJson])); + const resource = new CamelRouteResource([camelRouteJson, camelFromJson]); const camelRouteEntity = resource.getVisualEntities()[0]; resource.removeEntity(camelRouteEntity.id); @@ -166,7 +166,7 @@ describe('CamelRouteResource', () => { }); it('should NOT create a new entity after deleting them all', () => { - const resource = new CamelRouteResource(camelRouteYaml); + const resource = new CamelRouteResource(camelRouteJson); const camelRouteEntity = resource.getVisualEntities()[0]; resource.removeEntity(camelRouteEntity.id); @@ -209,7 +209,7 @@ describe('CamelRouteResource', () => { [{ anotherUnknownContent: {} }], [{}], ])('should not throw error when calling: %s', (json) => { - const resource = new CamelRouteResource(JSON.stringify(json)); + const resource = new CamelRouteResource(json); const firstEntity = resource.getVisualEntities()[0] ?? resource.getEntities()[0]; expect(firstEntity.toJSON()).not.toBeUndefined(); }); diff --git a/packages/ui/src/models/camel/camel-route-resource.ts b/packages/ui/src/models/camel/camel-route-resource.ts index d3b28add2..8b847d212 100644 --- a/packages/ui/src/models/camel/camel-route-resource.ts +++ b/packages/ui/src/models/camel/camel-route-resource.ts @@ -50,12 +50,11 @@ export class CamelRouteResource implements CamelResource, BeansAwareResource { private resolvedEntities: BaseVisualCamelEntityDefinition | undefined; private serializer: CamelResourceSerializer; - constructor(code?: string, serializer?: CamelResourceSerializer) { + constructor(code?: unknown, serializer?: CamelResourceSerializer) { this.serializer = serializer ?? new YamlCamelResourceSerializer(); if (!code) return; - const parsedCode = this.serializer.parse(code); - const entities = Array.isArray(parsedCode) ? parsedCode : [parsedCode]; + const entities = Array.isArray(code) ? code : [code]; this.entities = entities.reduce((acc, rawItem) => { const entity = this.getEntity(rawItem); if (isDefined(entity) && typeof entity === 'object') { diff --git a/packages/ui/src/models/camel/kamelet-resource.test.ts b/packages/ui/src/models/camel/kamelet-resource.test.ts index cbdfd4102..591f16609 100644 --- a/packages/ui/src/models/camel/kamelet-resource.test.ts +++ b/packages/ui/src/models/camel/kamelet-resource.test.ts @@ -1,10 +1,10 @@ import { kameletJson } from '../../stubs/kamelet-route'; import { AddStepMode } from '../visualization/base-visual-entity'; import { CamelComponentFilterService } from '../visualization/flows/support/camel-component-filter.service'; -import { createCamelResource } from './camel-resource'; import { KameletResource } from './kamelet-resource'; import { SourceSchemaType } from './source-schema-type'; -import { cloneDeep } from 'lodash'; +import { CamelKResourceFactory } from './camel-k-resource-factory'; +import cloneDeep from 'lodash/cloneDeep'; describe('KameletResource', () => { it('should create a new KameletResource', () => { @@ -78,7 +78,7 @@ describe('KameletResource', () => { it('should delegate to the CamelComponentFilterService', () => { const filterSpy = jest.spyOn(CamelComponentFilterService, 'getKameletCompatibleComponents'); - const resource = createCamelResource(kameletJson); + const resource = CamelKResourceFactory.getCamelKResource(kameletJson)!; resource.getCompatibleComponents(AddStepMode.ReplaceStep, { path: 'from', label: 'timer' }); expect(filterSpy).toHaveBeenCalledWith(AddStepMode.ReplaceStep, { path: 'from', label: 'timer' }, undefined); diff --git a/packages/ui/src/models/camel/kamelet-resource.ts b/packages/ui/src/models/camel/kamelet-resource.ts index 19f4f8563..62299d808 100644 --- a/packages/ui/src/models/camel/kamelet-resource.ts +++ b/packages/ui/src/models/camel/kamelet-resource.ts @@ -62,7 +62,7 @@ export class KameletResource extends CamelKResource implements RouteTemplateBean * the CamelRouteVisualEntity. */ set(this.resource, 'metadata.name', this.flow.getId()); - set(this.resource, 'spec.template.from', this.flow.route.from); + set(this.resource, 'spec.template.from', this.flow.entityDef.template.from); set(this.resource, 'spec.template.beans', this.beans?.parent.beans); return this.resource as IKameletDefinition; } diff --git a/packages/ui/src/serializers/yaml-camel-resource-serializer.test.ts b/packages/ui/src/serializers/yaml-camel-resource-serializer.test.ts new file mode 100644 index 000000000..ea6518f01 --- /dev/null +++ b/packages/ui/src/serializers/yaml-camel-resource-serializer.test.ts @@ -0,0 +1,32 @@ +import { YamlCamelResourceSerializer } from './yaml-camel-resource-serializer'; +import { camelRouteJson, camelRouteYaml } from '../stubs'; +import { CamelRouteResource } from '../models/camel'; + +describe('YamlCamelResourceSerializer', () => { + let serializer: YamlCamelResourceSerializer; + + beforeEach(() => { + serializer = new YamlCamelResourceSerializer(); + }); + + it('parses YAML code into JSON object', () => { + const result = serializer.parse(camelRouteYaml); + expect(result).toEqual([camelRouteJson]); + }); + + it('returns empty array for empty or non-string input in parse', () => { + expect(serializer.parse('')).toEqual([]); + expect(serializer.parse(null as unknown as string)).toEqual([]); + expect(serializer.parse(123 as unknown as string)).toEqual([]); + }); + + it('includes comments in serialized YAML string', () => { + const entities = serializer.parse('# comment1\n' + camelRouteYaml); + console.log(serializer.comments); + expect(serializer.comments.includes('# comment1')).toBeTruthy(); + + serializer.comments.push('# Comment2'); + const result = serializer.serialize(new CamelRouteResource(entities)); + expect(result).toContain('# Comment2'); + }); +}); diff --git a/packages/ui/src/serializers/yaml-camel-resource-serializer.ts b/packages/ui/src/serializers/yaml-camel-resource-serializer.ts index a19092d2a..1d5af6472 100644 --- a/packages/ui/src/serializers/yaml-camel-resource-serializer.ts +++ b/packages/ui/src/serializers/yaml-camel-resource-serializer.ts @@ -3,10 +3,20 @@ import { parse, stringify } from 'yaml'; import { CamelResourceSerializer } from './camel-resource-serializer'; export class YamlCamelResourceSerializer implements CamelResourceSerializer { + /** + * Regular expression to match commented lines, regardless of indentation + * Given the following examples, the regular expression should match the comments: + * ``` + * # This is a comment + * # This is an indented comment + *# This is an indented comment + * ``` + * The regular expression should match the first three lines + */ COMMENTED_LINES_REGEXP = /^\s*#.*$/; comments: string[] = []; - static isApplicable(code: unknown): boolean { + static isApplicable(_code: unknown): boolean { //TODO // return !isXML(code); @@ -14,7 +24,7 @@ export class YamlCamelResourceSerializer implements CamelResourceSerializer { } parse(code: string): unknown { - if (!code || typeof code !== 'string') return {}; + if (!code || typeof code !== 'string') return []; this.comments = this.parseComments(code); const json = parse(code);