Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @vitest-environment jsdom
*/
import { EditTableRowModal } from '@/features/instance/databases/modals/EditTableRowModal';
import { cleanup, render, screen } from '@testing-library/react';
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest';

// Monaco can't load in jsdom; stub the editor with a plain element that exposes the value it was
Expand Down Expand Up @@ -86,6 +86,20 @@ describe('EditTableRowModal', () => {
expect(screen.queryByRole('button', { name: /Delete Row/i })).toBeNull();
});

it('does not throw when Delete Row is clicked before the record has loaded', () => {
// The parent passes `data={searchByIdData?.data}`, which is undefined while the
// record fetch is in flight — but the Delete Row button renders regardless. Clicking
// it then used to do an unguarded `data[0]` and throw an unhandled
// "Cannot read properties of undefined (reading '0')" (RUM, browse table view).
const onDeleteRecord = vi.fn();
renderModal({ data: undefined, onDeleteRecord });

const deleteButton = screen.getByRole('button', { name: /Delete Row/i });
expect(() => fireEvent.click(deleteButton)).not.toThrow();
// Nothing to delete without a loaded record, so the delete is a no-op.
expect(onDeleteRecord).not.toHaveBeenCalled();
});

it('lets a normal row be edited and deleted', () => {
renderModal();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ export function EditTableRowModal({
/** Relationship/computed attribute names — read-only, so they are hidden from the editable JSON
* (saving a record that assigns one fails, even with null). */
syntheticAttributes?: string[];
data: { __createdtime__?: number; __updatedtime__?: number; [record: string]: unknown }[];
/** Undefined while the record fetch is in flight (the parent passes `searchByIdData?.data`), so
* every read must tolerate it — the editor renders a loading state and the write actions guard it. */
data?: { __createdtime__?: number; __updatedtime__?: number; [record: string]: unknown }[];
onSaveChanges: (data: Record<string, unknown>[]) => void;
onDeleteRecord: (data: unknown[]) => void;
isUpdateTableRecordsPending: boolean;
Expand Down Expand Up @@ -147,7 +149,7 @@ export function EditTableRowModal({
type="button"
autoFocus={false}
onClick={() => {
const primaryKeyValue = data[0]?.[primaryKey];
const primaryKeyValue = data?.[0]?.[primaryKey];
if (primaryKeyValue != null) {
onDeleteRecord([primaryKeyValue]);
}
Expand Down