UNPKG

datajunction-ui

Version:

DataJunction Metrics Platform UI

297 lines (269 loc) 8.69 kB
import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { MemoryRouter, Route, Routes } from 'react-router-dom'; import DJClientContext from '../../../providers/djclient'; import { NamespacePage } from '../index'; import React from 'react'; import userEvent from '@testing-library/user-event'; const mockDjClient = { namespaces: jest.fn(), namespace: jest.fn(), listNodesForLanding: jest.fn(), addNamespace: jest.fn(), whoami: jest.fn(), users: jest.fn(), listTags: jest.fn(), }; describe('NamespacePage', () => { const original = window.location; const reloadFn = () => { window.location.reload(); }; beforeAll(() => { Object.defineProperty(window, 'location', { configurable: true, value: { reload: jest.fn() }, }); }); afterAll(() => { Object.defineProperty(window, 'location', { configurable: true, value: original, }); }); beforeEach(() => { fetch.resetMocks(); mockDjClient.whoami.mockResolvedValue({ username: 'dj' }); mockDjClient.users.mockResolvedValue([ { username: 'dj' }, { username: 'user1' }, ]); mockDjClient.listTags.mockResolvedValue([ { name: 'tag1' }, { name: 'tag2' }, ]); mockDjClient.namespaces.mockResolvedValue([ { namespace: 'common.one', num_nodes: 3, }, { namespace: 'common.one.a', num_nodes: 6, }, { namespace: 'common.one.b', num_nodes: 17, }, { namespace: 'common.one.c', num_nodes: 64, }, { namespace: 'default', num_nodes: 41, }, { namespace: 'default.fruits', num_nodes: 1, }, { namespace: 'default.fruits.citrus.lemons', num_nodes: 1, }, { namespace: 'default.vegetables', num_nodes: 2, }, ]); mockDjClient.namespace.mockResolvedValue([ { name: 'testNode', display_name: 'Test Node', type: 'transform', mode: 'active', updated_at: new Date(), tags: [{ name: 'tag1' }], edited_by: ['dj'], }, ]); mockDjClient.listNodesForLanding.mockResolvedValue({ data: { findNodesPaginated: { pageInfo: { hasNextPage: true, endCursor: 'eyJjcmVhdGVkX2F0IjogIjIwMjQtMDQtMTZUMjM6MjI6MjIuNDQxNjg2KzAwOjAwIiwgImlkIjogNjE0fQ==', hasPrevPage: true, startCursor: 'eyJjcmVhdGVkX2F0IjogIjIwMjQtMTAtMTZUMTY6MDM6MTcuMDgzMjY3KzAwOjAwIiwgImlkIjogMjQwOX0=', }, edges: [ { node: { name: 'default.test_node', type: 'DIMENSION', currentVersion: 'v4.0', tags: [], editedBy: ['dj'], current: { displayName: 'Test Node', status: 'VALID', updatedAt: '2024-10-18T15:15:33.532949+00:00', }, createdBy: { username: 'dj', }, }, }, ], }, }, }); }); afterEach(() => { jest.clearAllMocks(); }); it('displays namespaces and renders nodes', async () => { reloadFn(); const element = ( <DJClientContext.Provider value={{ DataJunctionAPI: mockDjClient }}> <NamespacePage /> </DJClientContext.Provider> ); render( <MemoryRouter initialEntries={['/namespaces/test.namespace']}> <Routes> <Route path="namespaces/:namespace" element={element} /> </Routes> </MemoryRouter>, ); await waitFor( () => { expect(mockDjClient.listNodesForLanding).toHaveBeenCalled(); expect(screen.getByText('Namespaces')).toBeInTheDocument(); // check that it displays namespaces expect(screen.getByText('common')).toBeInTheDocument(); expect(screen.getByText('one')).toBeInTheDocument(); expect(screen.getByText('fruits')).toBeInTheDocument(); expect(screen.getByText('vegetables')).toBeInTheDocument(); // check that it renders nodes expect(screen.getByText('Test Node')).toBeInTheDocument(); // check that it sorts nodes fireEvent.click(screen.getByText('name')); fireEvent.click(screen.getByText('name')); fireEvent.click(screen.getByText('display Name')); // paginate const previousButton = screen.getByText('← Previous'); expect(previousButton).toBeDefined(); fireEvent.click(previousButton); const nextButton = screen.getByText('Next →'); expect(nextButton).toBeDefined(); fireEvent.click(nextButton); // check that we can filter by node type const selectNodeType = screen.getAllByTestId('select-node-type')[0]; expect(selectNodeType).toBeDefined(); expect(selectNodeType).not.toBeNull(); fireEvent.keyDown(selectNodeType.firstChild, { key: 'ArrowDown' }); fireEvent.click(screen.getByText('Source')); // check that we can filter by tag const selectTag = screen.getAllByTestId('select-tag')[0]; expect(selectTag).toBeDefined(); expect(selectTag).not.toBeNull(); fireEvent.keyDown(selectTag.firstChild, { key: 'ArrowDown' }); // check that we can filter by user const selectUser = screen.getAllByTestId('select-user')[0]; expect(selectUser).toBeDefined(); expect(selectUser).not.toBeNull(); fireEvent.keyDown(selectUser.firstChild, { key: 'ArrowDown' }); // click to open and close tab fireEvent.click(screen.getByText('common')); fireEvent.click(screen.getByText('common')); }, { timeout: 3000 }, ); }, 60000); it('can add new namespace via add namespace popover', async () => { mockDjClient.addNamespace.mockReturnValue({ status: 201, json: {}, }); const element = ( <DJClientContext.Provider value={{ DataJunctionAPI: mockDjClient }}> <NamespacePage /> </DJClientContext.Provider> ); render( <MemoryRouter initialEntries={['/namespaces/test.namespace']}> <Routes> <Route path="namespaces/:namespace" element={element} /> </Routes> </MemoryRouter>, ); // Find the button to toggle the add namespace popover const addNamespaceToggle = screen.getByRole('button', { name: 'AddNamespaceTogglePopover', }); expect(addNamespaceToggle).toBeInTheDocument(); // Click the toggle and verify that the popover displays fireEvent.click(addNamespaceToggle); const addNamespacePopover = screen.getByRole('dialog', { name: 'AddNamespacePopover', }); expect(addNamespacePopover).toBeInTheDocument(); // Type in the new namespace await userEvent.type( screen.getByLabelText('Namespace'), 'some.random.namespace', ); // Save const saveNamespace = screen.getByRole('button', { name: 'SaveNamespace', }); await waitFor(() => { fireEvent.click(saveNamespace); }); expect(mockDjClient.addNamespace).toHaveBeenCalled(); expect(mockDjClient.addNamespace).toHaveBeenCalledWith( 'test.namespace.some.random.namespace', ); expect(screen.getByText('Saved')).toBeInTheDocument(); expect(window.location.reload).toHaveBeenCalled(); }); it('can fail to add namespace', async () => { mockDjClient.addNamespace.mockReturnValue({ status: 500, json: { message: 'you failed' }, }); const element = ( <DJClientContext.Provider value={{ DataJunctionAPI: mockDjClient }}> <NamespacePage /> </DJClientContext.Provider> ); render( <MemoryRouter initialEntries={['/namespaces/test.namespace']}> <Routes> <Route path="namespaces/:namespace" element={element} /> </Routes> </MemoryRouter>, ); // Open the add namespace popover const addNamespaceToggle = screen.getByRole('button', { name: 'AddNamespaceTogglePopover', }); fireEvent.click(addNamespaceToggle); // Type in the new namespace await userEvent.type( screen.getByLabelText('Namespace'), 'some.random.namespace', ); // Save const saveNamespace = screen.getByRole('button', { name: 'SaveNamespace', }); await waitFor(() => { fireEvent.click(saveNamespace); }); // Should display failure alert expect(screen.getByText('you failed')).toBeInTheDocument(); }); });