diff --git a/hivemq-edge/src/frontend/src/modules/EdgeVisualisation/utils/topics-utils.spec.ts b/hivemq-edge/src/frontend/src/modules/EdgeVisualisation/utils/topics-utils.spec.ts index 02df613e3f..6281760c47 100644 --- a/hivemq-edge/src/frontend/src/modules/EdgeVisualisation/utils/topics-utils.spec.ts +++ b/hivemq-edge/src/frontend/src/modules/EdgeVisualisation/utils/topics-utils.spec.ts @@ -1,8 +1,23 @@ import { expect } from 'vitest' -import { getAdapterTopics, getBridgeTopics } from '@/modules/EdgeVisualisation/utils/topics-utils.ts' +import { GenericObjectType, RJSFSchema } from '@rjsf/utils' + import { mockBridge } from '@/api/hooks/useGetBridges/__handlers__' -import { TopicFilter } from '@/modules/EdgeVisualisation/types.ts' import { mockAdapter } from '@/api/hooks/useProtocolAdapters/__handlers__' +import { TopicFilter } from '@/modules/EdgeVisualisation/types.ts' + +import { MOCK_PROTOCOL_MODBUS, MOCK_ADAPTER_MODBUS } from '@/__test-utils__/adapters/modbus.ts' +import { MOCK_PROTOCOL_SIMULATION, MOCK_ADAPTER_SIMULATION } from '@/__test-utils__/adapters/simulation.ts' +import { MOCK_PROTOCOL_OPC_UA, MOCK_ADAPTER_OPC_UA } from '@/__test-utils__/adapters/opc-ua.ts' +import { MOCK_PROTOCOL_HTTP, MOCK_ADAPTER_HTTP } from '@/__test-utils__/adapters/http.ts' + +import { + discoverAdapterTopics, + flattenObject, + getAdapterTopics, + getBridgeTopics, + getTopicPaths, +} from './topics-utils.ts' +import { ProtocolAdapter } from '@/api/__generated__' describe('getBridgeTopics', () => { it('should extract topics from a Bridge', async () => { @@ -41,3 +56,96 @@ describe('getAdapterTopics', () => { expect(actual).toStrictEqual(expected) }) }) + +interface Suite { + protocol: NonNullable + formData?: GenericObjectType + expectedPath: string[] + expectedTopics: string[] +} + +const validationSuite: Suite[] = [ + { + protocol: MOCK_PROTOCOL_MODBUS, + formData: MOCK_ADAPTER_MODBUS, + expectedPath: ['subscriptions.*.destination'], + expectedTopics: ['a/valid/topic/modbus/1'], + }, + { + protocol: MOCK_PROTOCOL_SIMULATION, + formData: MOCK_ADAPTER_SIMULATION, + expectedPath: ['subscriptions.*.destination'], + expectedTopics: ['a/valid/topic/simulation/1'], + }, + { + protocol: MOCK_PROTOCOL_OPC_UA, + formData: MOCK_ADAPTER_OPC_UA, + expectedPath: ['subscriptions.*.mqtt-topic'], + expectedTopics: ['a/valid/topic/opc-ua-client/1', 'a/valid/topic/opc-ua-client/2'], + }, + { + protocol: MOCK_PROTOCOL_HTTP, + formData: MOCK_ADAPTER_HTTP, + expectedPath: ['destination'], + expectedTopics: ['a/valid/topic/http/1'], + }, + + { + protocol: { + ...MOCK_PROTOCOL_HTTP, + id: 'http-without-subscription', + configSchema: { + ...MOCK_PROTOCOL_HTTP.configSchema, + properties: { + ...MOCK_PROTOCOL_HTTP.configSchema?.properties, + destination: { + ...MOCK_PROTOCOL_HTTP.configSchema?.properties.destination, + format: 'something else', + }, + }, + }, + }, + expectedPath: [], + expectedTopics: [], + }, + { + protocol: {}, + expectedPath: [], + expectedTopics: [], + }, +] + +describe('flattenObject', () => { + it('should work', () => { + expect(flattenObject({})).toStrictEqual({}) + expect(flattenObject({ a: 1 })).toStrictEqual({ + a: 1, + }) + expect(flattenObject({ a: 1, b: { c: 1 } })).toStrictEqual({ + a: 1, + 'b.c': 1, + }) + expect(flattenObject({ a: 1, b: { c: 1, d: undefined, 'long-one': 1, 'with.dangerous-token': 1 } })).toStrictEqual({ + a: 1, + 'b.c': 1, + 'b.d': undefined, + 'b.long-one': 1, + 'b.with.dangerous-token': 1, + }) + }) +}) + +describe('discoverAdapterTopics', () => { + it.each(validationSuite)( + `should return $expectedTopics.length with $protocol.id`, + ({ protocol, formData, expectedPath, expectedTopics }) => { + const paths = getTopicPaths(protocol?.configSchema as RJSFSchema) + + expect(paths).toEqual(expectedPath) + + if (!formData) return + + expect(discoverAdapterTopics(protocol, formData?.config)).toEqual(expectedTopics) + } + ) +})