feat: added split notes function

This commit is contained in:
Xiaohan-Tian
2026-05-18 19:00:21 -07:00
parent d10965066f
commit 4cf474be7e
9 changed files with 645 additions and 6 deletions
+34 -3
View File
@@ -1,5 +1,5 @@
import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import Toolbar from './Toolbar';
@@ -52,13 +52,13 @@ const storeState = {
setShowPianoRoll: vi.fn(),
activeRegionId: null,
setActiveRegionId: vi.fn(),
selectedRegionIds: [],
selectedRegionIds: [] as string[],
selectedTrackId: null,
playheadPosition: 0,
refreshProjectState: vi.fn(),
requestMainContentScroll: vi.fn(),
requestPianoRollScroll: vi.fn(),
tracks: [],
tracks: [] as unknown[],
};
type StoreState = typeof storeState;
@@ -108,6 +108,14 @@ vi.mock('../core/state/KGMainContentState', () => ({ KGMainContentState: {} }));
vi.mock('../util/regionDeleteUtil', () => ({ regionDeleteManager: { deleteSelectedRegions: vi.fn(() => false) } }));
vi.mock('../core/commands/region/SplitRegionCommand', () => ({ SplitRegionCommand: class {} }));
vi.mock('../core/commands/region/MergeMidiRegionsCommand', () => ({ MergeMidiRegionsCommand: class {} }));
const regionEditUtilMocks = vi.hoisted(() => ({
splitSelectedRegionAtPlayheadMock: vi.fn(),
mergeSelectedMidiRegionsMock: vi.fn(),
}));
vi.mock('../util/regionEditUtil', () => ({
splitSelectedRegionAtPlayhead: regionEditUtilMocks.splitSelectedRegionAtPlayheadMock,
mergeSelectedMidiRegions: regionEditUtilMocks.mergeSelectedMidiRegionsMock,
}));
vi.mock('../util/copyPasteUtil', () => ({
handleCopyOperation: vi.fn(() => false),
handlePasteOperation: vi.fn(() => false),
@@ -135,6 +143,8 @@ vi.mock('../util/dialogUtil', () => ({
describe('Toolbar settings side-panel behavior', () => {
beforeEach(() => {
regionEditUtilMocks.splitSelectedRegionAtPlayheadMock.mockReset();
regionEditUtilMocks.mergeSelectedMidiRegionsMock.mockReset();
storeState.toggleChatBox.mockClear();
storeState.toggleKGOnePanel.mockClear();
storeState.toggleEventListPanel.mockClear();
@@ -162,4 +172,25 @@ describe('Toolbar settings side-panel behavior', () => {
expect(storeState.activateSidePanel).toHaveBeenCalledWith('eventList');
expect(storeState.toggleEventListPanel).not.toHaveBeenCalled();
});
it('routes the split toolbar button through the shared split helper', async () => {
storeState.selectedRegionIds = ['region-1'];
storeState.playheadPosition = 12;
regionEditUtilMocks.splitSelectedRegionAtPlayheadMock.mockResolvedValue('Split 1 note at beat 12.00');
render(<Toolbar />);
fireEvent.click(screen.getByTitle('Split Region at Playhead'));
await waitFor(() => {
expect(regionEditUtilMocks.splitSelectedRegionAtPlayheadMock).toHaveBeenCalledWith({
selectedRegionIds: ['region-1'],
playheadPosition: 12,
refreshProjectState: storeState.refreshProjectState,
});
});
await waitFor(() => {
expect(storeState.setStatus).toHaveBeenCalledWith('Split 1 note at beat 12.00');
});
});
});
+1
View File
@@ -16,6 +16,7 @@ import {
} from 'react-icons/fa';
import { KGProject, type KeySignature } from '../core/KGProject';
import { KGMidiInput } from '../core/midi-input/KGMidiInput';
import { KGMidiRegion } from '../core/region/KGMidiRegion';
import { KGAudioTrack } from '../core/track/KGAudioTrack';
import { plainToInstance } from 'class-transformer';
import { FaPencil, FaCopy, FaPaste, FaTrash, FaWandMagicSparkles, FaListUl } from 'react-icons/fa6';