Skip to content

Commit 62fb35e

Browse files
authored
Merge pull request #400
feat(20611): Add uniqueness validation to topic filter * feat(20611): add custom validation to the topic filter * feat(20611): fix error messages * fix(20611): simplify default payload for topic and client filters * test(20611): fix test * test(20611): fix test * test(20611): add test * fix(20611): fix translations
1 parent 8e3e6d0 commit 62fb35e

File tree

6 files changed

+59
-25
lines changed

6 files changed

+59
-25
lines changed

hivemq-edge/src/frontend/src/extensions/datahub/designer/client_filter/ClientFilterPanel.spec.cy.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
/// <reference types="cypress" />
22

33
import { Button } from '@chakra-ui/react'
4+
import { Node } from 'reactflow'
45

56
import { MockStoreWrapper } from '@datahub/__test-utils__/MockStoreWrapper.tsx'
6-
import { DataHubNodeType } from '@datahub/types.ts'
7-
import { getNodePayload } from '@datahub/utils/node.utils.ts'
7+
import { ClientFilterData, DataHubNodeType } from '@datahub/types.ts'
88

99
import { ClientFilterPanel } from './ClientFilterPanel.tsx'
1010

11+
const MOCK_CLIENT_FILTER: Node<ClientFilterData> = {
12+
id: '3',
13+
type: DataHubNodeType.CLIENT_FILTER,
14+
position: { x: 0, y: 0 },
15+
data: { clients: ['client10', 'client20', 'client30'] },
16+
}
17+
1118
const wrapper: React.JSXElementConstructor<{ children: React.ReactNode }> = ({ children }) => (
1219
<MockStoreWrapper
1320
config={{
1421
initialState: {
15-
nodes: [
16-
{
17-
id: '3',
18-
type: DataHubNodeType.CLIENT_FILTER,
19-
position: { x: 0, y: 0 },
20-
data: getNodePayload(DataHubNodeType.CLIENT_FILTER),
21-
},
22-
],
22+
nodes: [MOCK_CLIENT_FILTER],
2323
},
2424
}}
2525
>

hivemq-edge/src/frontend/src/extensions/datahub/designer/topic_filter/TopicFilterPanel.spec.cy.tsx

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
/// <reference types="cypress" />
22

33
import { Button } from '@chakra-ui/react'
4+
import { Node } from 'reactflow'
45

56
import { MockStoreWrapper } from '@datahub/__test-utils__/MockStoreWrapper.tsx'
6-
import { DataHubNodeType } from '@datahub/types.ts'
7-
import { getNodePayload } from '@datahub/utils/node.utils.ts'
7+
import { DataHubNodeType, TopicFilterData } from '@datahub/types.ts'
88
import { TopicFilterPanel } from './TopicFilterPanel.tsx'
9+
import { mockDataPolicy } from '@datahub/api/hooks/DataHubDataPoliciesService/__handlers__'
10+
11+
const MOCK_TOPIC_FILTER: Node<TopicFilterData> = {
12+
id: '3',
13+
type: DataHubNodeType.CLIENT_FILTER,
14+
position: { x: 0, y: 0 },
15+
data: { topics: ['root/test1', 'root/test2', 'root/test1', 'root/topic/ref/1'] },
16+
}
917

1018
const wrapper: React.JSXElementConstructor<{ children: React.ReactNode }> = ({ children }) => (
1119
<MockStoreWrapper
1220
config={{
1321
initialState: {
14-
nodes: [
15-
{
16-
id: '3',
17-
type: DataHubNodeType.TOPIC_FILTER,
18-
position: { x: 0, y: 0 },
19-
data: getNodePayload(DataHubNodeType.TOPIC_FILTER),
20-
},
21-
],
22+
nodes: [MOCK_TOPIC_FILTER],
2223
},
2324
}}
2425
>
@@ -33,6 +34,7 @@ describe('TopicFilterPanel', () => {
3334
beforeEach(() => {
3435
cy.viewport(800, 800)
3536
cy.intercept('/api/v1/management/protocol-adapters/adapters', { statusCode: 404 })
37+
cy.intercept('/api/v1/data-hub/data-validation/policies', { statusCode: 404 })
3638
})
3739

3840
it('should render the fields for a Validator', () => {
@@ -47,6 +49,22 @@ describe('TopicFilterPanel', () => {
4749
cy.get('label#root_topics_1-label + input').should('have.value', 'root/test2')
4850
})
4951

52+
it('should validate properly the topic filters', () => {
53+
cy.intercept('/api/v1/data-hub/data-validation/policies', {
54+
items: [mockDataPolicy],
55+
}).as('getPolicies')
56+
cy.mountWithProviders(<TopicFilterPanel selectedNode="3" />, { wrapper })
57+
cy.get('label#root_topics_0-label').should('have.attr', 'data-invalid')
58+
cy.get('label#root_topics_1-label').should('not.have.attr', 'data-invalid')
59+
cy.get('label#root_topics_2-label').should('have.attr', 'data-invalid')
60+
cy.get('label#root_topics_3-label').should('not.have.attr', 'data-invalid')
61+
62+
cy.wait('@getPolicies')
63+
64+
cy.get('button[type=submit]').click()
65+
cy.get('label#root_topics_3-label').should('have.attr', 'data-invalid')
66+
})
67+
5068
it('should be accessible', () => {
5169
cy.injectAxe()
5270
cy.mountWithProviders(<TopicFilterPanel selectedNode="3" />, { wrapper })

hivemq-edge/src/frontend/src/extensions/datahub/designer/topic_filter/TopicFilterPanel.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@ import { datahubRJSFWidgets } from '@datahub/designer/datahubRJSFWidgets.tsx'
1010
import useDataHubDraftStore from '@datahub/hooks/useDataHubDraftStore.ts'
1111
import { validateDuplicates } from '@datahub/utils/rjsf.utils.ts'
1212
import { ReactFlowSchemaForm } from '@datahub/components/forms/'
13+
import { useGetAllDataPolicies } from '@datahub/api/hooks/DataHubDataPoliciesService/useGetAllDataPolicies.tsx'
1314

1415
export const TopicFilterPanel: FC<PanelProps> = ({ selectedNode, onFormSubmit }) => {
1516
const { t } = useTranslation('datahub')
17+
const { isLoading, data } = useGetAllDataPolicies()
1618
const { nodes } = useDataHubDraftStore()
1719

20+
const listFilters = useMemo(() => {
21+
if (isLoading || !data) return undefined
22+
return data.items?.map((e) => e.matching.topicFilter)
23+
}, [data, isLoading])
24+
1825
const formData = useMemo(() => {
1926
const adapterNode = nodes.find((e) => e.id === selectedNode) as Node<TopicFilterData> | undefined
2027
return adapterNode ? adapterNode.data : null
@@ -27,11 +34,16 @@ export const TopicFilterPanel: FC<PanelProps> = ({ selectedNode, onFormSubmit })
2734
if (hasDuplicate) {
2835
for (const [key, value] of duplicates) {
2936
for (const index of value) {
30-
errors['topics']?.[index]?.addError(t(`the topic ${key} is already defined`))
37+
errors['topics']?.[index]?.addError(t('error.validation.topicFilter.duplicate', { filter: key }))
3138
}
3239
}
3340
}
3441

42+
for (const [index, value] of (formData?.['topics'] || []).entries()) {
43+
if (listFilters?.includes(value))
44+
errors['topics']?.[index]?.addError(t('error.validation.topicFilter.alreadyMatching', { filter: value }))
45+
}
46+
3547
return errors
3648
}
3749

hivemq-edge/src/frontend/src/extensions/datahub/locales/en/datahub.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@
247247
"protobuf": {
248248
"template": "// CANNOT DECODE THE PROTOBUF SOURCE - {{ source }}",
249249
"encoding": "The encoding of the PROTOBUF code into a Base64 descriptor cannot be validated."
250+
},
251+
"topicFilter": {
252+
"duplicate": "The topic filter {{ filter }} is already defined",
253+
"alreadyMatching": "A policy is already matching the topic filter {{ filter }}"
250254
}
251255
},
252256
"loading": {

hivemq-edge/src/frontend/src/extensions/datahub/utils/node.utils.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ describe('getNodePayload', () => {
2525
{
2626
type: DataHubNodeType.TOPIC_FILTER,
2727
expected: {
28-
topics: ['root/test1', 'root/test2'],
28+
topics: ['topic/example/1'],
2929
},
3030
},
3131
{
3232
type: DataHubNodeType.CLIENT_FILTER,
3333
expected: {
34-
clients: ['client10', 'client20', 'client30'],
34+
clients: ['client/example/1'],
3535
},
3636
},
3737
{

hivemq-edge/src/frontend/src/extensions/datahub/utils/node.utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ export const getNodeId = (stub = 'node') => `${stub}_${uuidv4()}`
2727
export const getNodePayload = (type: string): DataHubNodeData => {
2828
if (type === DataHubNodeType.TOPIC_FILTER) {
2929
return {
30-
topics: ['root/test1', 'root/test2'],
30+
topics: ['topic/example/1'],
3131
} as TopicFilterData
3232
}
3333
if (type === DataHubNodeType.CLIENT_FILTER) {
3434
return {
35-
clients: ['client10', 'client20', 'client30'],
35+
clients: ['client/example/1'],
3636
} as ClientFilterData
3737
}
3838

0 commit comments

Comments
 (0)