feat: create tests, more integration testing, fix ID tests, use UUID (almost) everywhere

ref: N25B-412
This commit is contained in:
Björn Otgaar
2026-01-04 18:29:19 +01:00
parent c5f44536b7
commit 149b82cb66
11 changed files with 332 additions and 146 deletions

View File

@@ -1,30 +1,17 @@
// PlanEditorDialog.test.tsx
import { describe, it, beforeEach, jest } from '@jest/globals';
import { screen } from '@testing-library/react';
import { screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { renderWithProviders } from '../../../../test-utils/test-utils.tsx';
import PlanEditorDialog from '../../../../../src/pages/VisProgPage/visualProgrammingUI/components/PlanEditor';
import type { Plan } from '../../../../../src/pages/VisProgPage/visualProgrammingUI/components/Plan';
import '@testing-library/jest-dom';
// Mock crypto.randomUUID for consistent IDs in tests
const mockUUID = 'test-uuid-123';
Object.defineProperty(globalThis, 'crypto', {
value: {
randomUUID: () => mockUUID,
},
writable: true,
});
// Mock structuredClone
(globalThis as any).structuredClone = jest.fn((val) => JSON.parse(JSON.stringify(val)));
// Mock HTMLDialogElement methods
const mockDialogMethods = {
showModal: jest.fn(),
close: jest.fn(),
};
// UUID Regex for checking ID's
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
describe('PlanEditorDialog', () => {
let user: ReturnType<typeof userEvent.setup>;
@@ -33,9 +20,6 @@ describe('PlanEditorDialog', () => {
beforeEach(() => {
user = userEvent.setup();
jest.clearAllMocks();
// Mock dialog element methods
HTMLDialogElement.prototype.showModal = mockDialogMethods.showModal;
HTMLDialogElement.prototype.close = mockDialogMethods.close;
});
const defaultPlan: Plan = {
@@ -90,7 +74,6 @@ describe('PlanEditorDialog', () => {
await user.click(screen.getByRole('button', { name: 'Create Plan' }));
expect(mockDialogMethods.showModal).toHaveBeenCalled();
// One for button, one for dialog.
expect(screen.getAllByText('Create Plan').length).toEqual(2);
@@ -101,7 +84,6 @@ describe('PlanEditorDialog', () => {
await user.click(screen.getByRole('button', { name: 'Edit Plan' }));
expect(mockDialogMethods.showModal).toHaveBeenCalled();
// One for button, one for dialog
expect(screen.getAllByText('Edit Plan').length).toEqual(2);
});
@@ -121,7 +103,7 @@ describe('PlanEditorDialog', () => {
await user.click(screen.getByRole('button', { name: 'Create Plan' }));
await user.click(screen.getByText('Cancel'));
expect(mockDialogMethods.close).toHaveBeenCalled();
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
});
@@ -198,7 +180,7 @@ describe('PlanEditorDialog', () => {
it('should add a gesture action to the plan', async () => {
renderDialog({ plan: defaultPlan });
await user.click(screen.getByRole('button', { name: 'Edit Plan' }));
await user.click(screen.getByRole('button', { name: /edit plan/i }));
const actionTypeSelect = screen.getByLabelText(/Action Type/i);
const addButton = screen.getByText('Add Step');
@@ -207,14 +189,14 @@ describe('PlanEditorDialog', () => {
await user.selectOptions(actionTypeSelect, 'gesture');
// Find the input field after type change
const gestureInput = screen.getByPlaceholderText(/Gesture name|text/i);
await user.type(gestureInput, 'Wave hand');
const select = screen.getByTestId("tagSelectorTestID")
const options = within(select).getAllByRole('option')
await user.selectOptions(select, options[1])
await user.click(addButton);
// Check if step was added
expect(screen.getByText('gesture:')).toBeInTheDocument();
expect(screen.getByText('Wave hand')).toBeInTheDocument();
});
it('should add an LLM action to the plan', async () => {
@@ -329,17 +311,17 @@ describe('PlanEditorDialog', () => {
await user.click(screen.getByText('Create'));
expect(mockOnSave).toHaveBeenCalledWith({
id: mockUUID,
id: expect.stringMatching(uuidRegex),
name: 'My New Plan',
steps: [
{
id: mockUUID,
id: expect.stringMatching(uuidRegex),
text: 'First step',
type: 'speech',
},
],
});
expect(mockDialogMethods.close).toHaveBeenCalled();
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
it('should call onSave with updated plan when editing', async () => {
@@ -366,13 +348,13 @@ describe('PlanEditorDialog', () => {
name: 'Updated Plan Name',
steps: [
{
id: mockUUID,
id: expect.stringMatching(uuidRegex),
text: 'New speech action',
type: 'speech',
},
],
});
expect(mockDialogMethods.close).toHaveBeenCalled();
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
it('should call onSave with undefined when reset button is clicked', async () => {
@@ -382,7 +364,7 @@ describe('PlanEditorDialog', () => {
await user.click(screen.getByText('Reset'));
expect(mockOnSave).toHaveBeenCalledWith(undefined);
expect(mockDialogMethods.close).toHaveBeenCalled();
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
it('should disable save button when no draft plan exists', async () => {
@@ -438,7 +420,7 @@ describe('PlanEditorDialog', () => {
// Check gesture placeholder
await user.selectOptions(actionTypeSelect, 'gesture');
const gestureInput = screen.getByPlaceholderText(/Gesture|text/i);
const gestureInput = screen.getByTestId("valueEditorTestID")
expect(gestureInput).toBeInTheDocument();
// Check LLM placeholder