This is an automated email from the ASF dual-hosted git repository.

andytaylor pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/artemis-console.git


The following commit(s) were added to refs/heads/main by this push:
     new 0727103  ARTEMIS-5962 Fix delete address context menu item
0727103 is described below

commit 072710318d45f8c2363066044c1d73ba065198b1
Author: Domenico Francesco Bruscino <[email protected]>
AuthorDate: Mon Mar 23 11:11:06 2026 +0100

    ARTEMIS-5962 Fix delete address context menu item
---
 .../src/addresses/AddressesTable.test.tsx          | 273 +++++++++++++++++++++
 .../src/addresses/AddressesTable.tsx               |   2 +-
 2 files changed, 274 insertions(+), 1 deletion(-)

diff --git 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/addresses/AddressesTable.test.tsx
 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/addresses/AddressesTable.test.tsx
new file mode 100644
index 0000000..2ba16a1
--- /dev/null
+++ 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/addresses/AddressesTable.test.tsx
@@ -0,0 +1,273 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { render, screen, within } from '@testing-library/react'
+import { AddressesTable } from './AddressesTable'
+import { artemisService } from '../artemis-service'
+
+jest.mock('react-router-dom', () => ({
+  ...jest.requireActual('react-router-dom'),
+  useNavigate: () => jest.fn()
+}))
+
+jest.mock('@patternfly/react-core', () => ({
+  ...jest.requireActual('@patternfly/react-core'),
+  Modal: ({ children, 'aria-label': ariaLabel, ...props }: any) => (
+    <div aria-label={ariaLabel} data-testid={`modal-${ariaLabel}`} {...props}>
+      {children}
+    </div>
+  ),
+  Button: ({ children, ...props }: any) => <button 
{...props}>{children}</button>,
+  Icon: ({ children }: any) => <span>{children}</span>,
+  TextContent: ({ children }: any) => <div>{children}</div>,
+  Text: ({ children }: any) => <p>{children}</p>,
+  ModalVariant: {
+    medium: 'medium'
+  }
+}))
+
+jest.mock('../artemis-service', () => ({
+  artemisService: {
+    getAddresses: jest.fn(),
+    canCreateQueue: jest.fn(() => false),
+    canDeleteAddress: jest.fn(() => false),
+    canCreateAddress: jest.fn(() => false),
+    canSendMessageToAddress: jest.fn(() => false),
+    getBrokerObjectName: jest.fn(() => 
Promise.resolve('org.apache.activemq.artemis:broker=127.0.0.1')),
+    deleteAddress: jest.fn(() => Promise.resolve())
+  }
+}))
+jest.mock('../table/ArtemisTable', () => ({
+  ArtemisTable: () => <div data-testid="artemis-table">ArtemisTable</div>
+}))
+jest.mock('../queues/CreateQueue', () => ({
+  CreateQueue: () => <div>CreateQueue</div>
+}))
+const mockContextValue = {
+  tree: {},
+  selectedNode: undefined,
+  brokerNode: undefined,
+  setSelectedNode: jest.fn(),
+  findAndSelectNode: jest.fn()
+}
+
+jest.mock('../context', () => ({
+  ArtemisContext: {
+    Provider: ({ children }: any) => children
+  }
+}))
+
+// Mock React.useContext to return our mock context value
+jest.spyOn(require('react'), 'useContext').mockReturnValue(mockContextValue)
+jest.mock('./CreateAddress', () => ({
+  CreateAddress: () => <div>CreateAddress</div>
+}))
+jest.mock('../messages/SendMessage', () => ({
+  SendMessage: () => <div>SendMessage</div>
+}))
+jest.mock('../util/jmx', () => ({
+  createAddressObjectName: jest.fn((brokerObjectName: string, addressName: 
string) =>
+    `${brokerObjectName},component=addresses,address="${addressName}"`
+  )
+}))
+jest.mock('../artemis-preferences-service', () => ({
+  columnStorage: {
+    addresses: 'addresses-columns'
+  }
+}))
+jest.mock('@hawtio/react', () => ({
+  Attributes: () => <div>Attributes</div>,
+  Operations: () => <div>Operations</div>,
+  eventService: {
+    notify: jest.fn()
+  },
+  jolokiaService: {
+    errorMessage: jest.fn()
+  },
+  workspace: {
+    refreshTree: jest.fn()
+  },
+  Logger: {
+    get: jest.fn(() => ({
+      debug: jest.fn(),
+      info: jest.fn(),
+      warn: jest.fn(),
+      error: jest.fn()
+    })),
+    setLevel: jest.fn()
+  }
+}))
+
+type PermissionConfig = {
+  canCreateQueue?: boolean
+  canDeleteAddress?: boolean
+  canCreateAddress?: boolean
+  canSendMessageToAddress?: boolean
+}
+
+const setupPermissions = (config: PermissionConfig = {}) => {
+  const defaults = {
+    canCreateQueue: false,
+    canDeleteAddress: false,
+    canCreateAddress: false,
+    canSendMessageToAddress: false
+  }
+
+  const permissions = { ...defaults, ...config }
+
+  artemisService.canCreateQueue = jest.fn(() => permissions.canCreateQueue)
+  artemisService.canDeleteAddress = jest.fn(() => permissions.canDeleteAddress)
+  artemisService.canCreateAddress = jest.fn(() => permissions.canCreateAddress)
+  artemisService.canSendMessageToAddress = jest.fn(() => 
permissions.canSendMessageToAddress)
+}
+
+const renderComponent = () => {
+  const result = render(<AddressesTable search="" filter={undefined} />)
+  // Wait for modals to potentially render in portals
+  return result
+}
+
+describe('AddressesTable', () => {
+
+  beforeEach(() => {
+    jest.clearAllMocks()
+  })
+
+  describe('Delete Address Modal Conditional Rendering', () => {
+
+    test('should render delete modal in DOM when canDeleteAddress is true', () 
=> {
+      setupPermissions({ canDeleteAddress: true })
+      renderComponent()
+
+      // Check in both the main container and document body (for portals)
+      const deleteModal = 
document.querySelector('[aria-label="delete-address-modal"]')
+      expect(deleteModal).toBeInTheDocument()
+    })
+
+    test('should NOT render delete modal in DOM when canDeleteAddress is 
false', () => {
+      setupPermissions({ canDeleteAddress: false })
+      renderComponent()
+
+      const deleteModal = 
document.querySelector('[aria-label="delete-address-modal"]')
+      expect(deleteModal).not.toBeInTheDocument()
+    })
+
+    test('should NOT render delete modal when canDeleteAddress is false even 
if canCreateAddress is true', () => {
+      setupPermissions({
+        canDeleteAddress: false,
+        canCreateAddress: true
+      })
+      renderComponent()
+
+      const deleteModal = 
document.querySelector('[aria-label="delete-address-modal"]')
+      expect(deleteModal).not.toBeInTheDocument()
+    })
+
+    test('should render delete modal based on canDeleteAddress permission, not 
canCreateAddress', () => {
+      setupPermissions({
+        canDeleteAddress: true,
+        canCreateAddress: false
+      })
+      renderComponent()
+
+      const deleteModal = 
document.querySelector('[aria-label="delete-address-modal"]')
+      expect(deleteModal).toBeInTheDocument()
+    })
+
+    test('canDeleteAddress permission correctly controls modal rendering', () 
=> {
+      // First render with permission false
+      const { rerender } = render(<AddressesTable search="" filter={undefined} 
/>)
+      setupPermissions({ canDeleteAddress: false })
+      rerender(<AddressesTable search="" filter={undefined} />)
+
+      let deleteModal = 
document.querySelector('[aria-label="delete-address-modal"]')
+      expect(deleteModal).not.toBeInTheDocument()
+
+      // Re-render with permission true
+      setupPermissions({ canDeleteAddress: true })
+      rerender(<AddressesTable search="" filter={undefined} />)
+
+      deleteModal = 
document.querySelector('[aria-label="delete-address-modal"]')
+      expect(deleteModal).toBeInTheDocument()
+    })
+  })
+
+  describe('Service Permission Calls', () => {
+
+    test('should call canDeleteAddress service method', () => {
+      setupPermissions({ canDeleteAddress: true })
+      renderComponent()
+
+      expect(artemisService.canDeleteAddress).toHaveBeenCalled()
+    })
+
+    test('should call canCreateAddress service method', () => {
+      setupPermissions({ canCreateAddress: true })
+      renderComponent()
+
+      expect(artemisService.canCreateAddress).toHaveBeenCalled()
+    })
+
+    test('should call both canDeleteAddress and canCreateAddress 
independently', () => {
+      setupPermissions({
+        canDeleteAddress: true,
+        canCreateAddress: false
+      })
+      renderComponent()
+
+      expect(artemisService.canDeleteAddress).toHaveBeenCalled()
+      expect(artemisService.canCreateAddress).toHaveBeenCalled()
+    })
+  })
+
+  describe('Component Rendering', () => {
+
+    test('should render ArtemisTable component', () => {
+      setupPermissions()
+      renderComponent()
+
+      expect(screen.getByTestId('artemis-table')).toBeInTheDocument()
+    })
+
+    test('should render all modals when canDeleteAddress is true', () => {
+      setupPermissions({ canDeleteAddress: true })
+      renderComponent()
+
+      // All modals should be in the DOM (though not visible)
+      
expect(document.querySelector('[aria-label="create-queue-modal"]')).toBeInTheDocument()
+      
expect(document.querySelector('[aria-label="delete-address-modal"]')).toBeInTheDocument()
+      
expect(document.querySelector('[aria-label="attributes-modal"]')).toBeInTheDocument()
+      
expect(document.querySelector('[aria-label="operations-modal"]')).toBeInTheDocument()
+      
expect(document.querySelector('[aria-label="create=address-modal"]')).toBeInTheDocument()
+      
expect(document.querySelector('[aria-label="send-modal"]')).toBeInTheDocument()
+    })
+
+    test('should not render delete modal but render other modals when 
canDeleteAddress is false', () => {
+      setupPermissions({ canDeleteAddress: false })
+      renderComponent()
+
+      // Delete modal should NOT be in DOM
+      
expect(document.querySelector('[aria-label="delete-address-modal"]')).not.toBeInTheDocument()
+
+      // Other modals should still be in DOM
+      
expect(document.querySelector('[aria-label="create-queue-modal"]')).toBeInTheDocument()
+      
expect(document.querySelector('[aria-label="attributes-modal"]')).toBeInTheDocument()
+      
expect(document.querySelector('[aria-label="operations-modal"]')).toBeInTheDocument()
+      
expect(document.querySelector('[aria-label="create=address-modal"]')).toBeInTheDocument()
+      
expect(document.querySelector('[aria-label="send-modal"]')).toBeInTheDocument()
+    })
+  })
+})
diff --git 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/addresses/AddressesTable.tsx
 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/addresses/AddressesTable.tsx
index 726092b..0a4e551 100644
--- 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/addresses/AddressesTable.tsx
+++ 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/addresses/AddressesTable.tsx
@@ -203,7 +203,7 @@ export const AddressesTable: 
React.FunctionComponent<Navigate> = (navigate) => {
         ]}>
         <CreateQueue address={address}/>
       </Modal>
-      { canCreateAddress && <Modal
+      { canDeleteAddress && <Modal
         aria-label='delete-address-modal'
         variant={ModalVariant.medium}
         isOpen={showDeleteDialog}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to