@@ -2166,7 +2166,7 @@ test.describe("MIDI Studio V2", () => {
21662166 await expect ( page . locator ( "#songSheetStyleInput" ) ) . toHaveValue ( "public-domain-reel" ) ;
21672167 await expect ( page . locator ( "#songDetails [data-song-detail-field='tags']" ) ) . toHaveCount ( 0 ) ;
21682168 await expect ( page . locator ( "#songDetails [data-song-detail-field='usage']" ) ) . toHaveCount ( 0 ) ;
2169- await expect ( page . locator ( "#songDetails [data-song-detail-field='notes']" ) ) . toHaveValue ( "Traditional Camptown Races style public-domain test arrangement with lead, bass, chords/pad, and drums." ) ;
2169+ await expect ( page . locator ( "#songDetailNotes [data-song-detail-field='notes']" ) ) . toHaveValue ( "Traditional Camptown Races style public-domain test arrangement with lead, bass, chords/pad, and drums." ) ;
21702170 await expect ( page . locator ( "#songSectionsLoopDetails [data-song-detail-field='sections']" ) ) . toHaveCount ( 0 ) ;
21712171 await expect ( page . locator ( "#songSheetSectionsInput" ) ) . toHaveValue ( / i n t r o : G C G D / ) ;
21722172 await expect ( page . locator ( "#songSheetLoopSectionsInput" ) ) . toHaveValue ( "loop" ) ;
@@ -2189,7 +2189,7 @@ test.describe("MIDI Studio V2", () => {
21892189 await page . locator ( "#songSheetTempoInput" ) . fill ( "156" ) ;
21902190 await page . locator ( "#songSheetKeyInput" ) . selectOption ( "C major" ) ;
21912191 await page . locator ( "#songSheetStyleInput" ) . selectOption ( "chip" ) ;
2192- await page . locator ( "#songDetails [data-song-detail-field='notes']" ) . fill ( "Edited notes from Song Setup." ) ;
2192+ await page . locator ( "#songDetailNotes [data-song-detail-field='notes']" ) . fill ( "Edited notes from Song Setup." ) ;
21932193 await page . locator ( "#songSectionsLoopDetails [data-song-detail-field='loopEnabled']" ) . setChecked ( false ) ;
21942194 expect ( await page . evaluate ( ( ) => {
21952195 const song = window . __midiStudioV2App . selectedSong ( ) ;
@@ -2358,7 +2358,7 @@ test.describe("MIDI Studio V2", () => {
23582358 songTempo : "#songSheetTempoInput" ,
23592359 songKey : "#songSheetKeyInput" ,
23602360 songStyle : "#songSheetStyleInput" ,
2361- songNotes : "#songDetails [data-song-detail-field='notes']"
2361+ songNotes : "#songDetailNotes [data-song-detail-field='notes']"
23622362 } ;
23632363 const ownership = await page . evaluate ( ( selectors ) => Object . fromEntries ( Object . entries ( selectors ) . map ( ( [ name , selector ] ) => {
23642364 const elements = Array . from ( document . querySelectorAll ( selector ) ) ;
@@ -2949,6 +2949,108 @@ test.describe("MIDI Studio V2", () => {
29492949 }
29502950 } ) ;
29512951
2952+ test ( "keeps PR063 notes layout and Octave Timeline quick instruments scoped to the left column" , async ( { page } ) => {
2953+ const server = await openMidiStudioForImport ( page ) ;
2954+ try {
2955+ await page . locator ( "#toolImportManifestInput" ) . setInputFiles ( uatManifestPath ) ;
2956+ await selectMidiStudioTab ( page , "song-setup" ) ;
2957+
2958+ const notesLayout = await page . locator ( "#songDetailsContent" ) . evaluate ( ( container ) => {
2959+ const editor = container . querySelector ( ".midi-studio-v2__song-detail-editor" ) ;
2960+ const core = container . querySelector ( ".midi-studio-v2__song-detail-core-fields" ) ;
2961+ const notesList = container . querySelector ( "#songDetailNotes" ) ;
2962+ const notesRow = notesList ?. querySelector ( ".midi-studio-v2__editable-detail" ) ;
2963+ const notesField = notesList ?. querySelector ( "[data-song-detail-field='notes']" ) ;
2964+ const detailRows = Array . from ( container . querySelectorAll ( "#songDetails .midi-studio-v2__editable-detail, .midi-studio-v2__song-detail-core-fields .tool-starter__field, #songDetailNotes .midi-studio-v2__editable-detail" ) ) ;
2965+ const editorRect = editor . getBoundingClientRect ( ) ;
2966+ const coreRect = core . getBoundingClientRect ( ) ;
2967+ const notesRect = notesRow . getBoundingClientRect ( ) ;
2968+ const notesFieldRect = notesField . getBoundingClientRect ( ) ;
2969+ const laterRows = detailRows . filter ( ( row ) => row . getBoundingClientRect ( ) . top > notesRect . top + 1 ) ;
2970+ const sameRowPeers = detailRows . filter ( ( row ) => {
2971+ const rect = row . getBoundingClientRect ( ) ;
2972+ return row !== notesRow && Math . abs ( rect . top - notesRect . top ) <= 2 ;
2973+ } ) ;
2974+ return {
2975+ editorWidth : editorRect . width ,
2976+ laterRows : laterRows . length ,
2977+ notesAfterCore : notesRect . top >= coreRect . bottom - 2 ,
2978+ notesFieldWidth : notesFieldRect . width ,
2979+ notesListWidth : notesList . getBoundingClientRect ( ) . width ,
2980+ notesRowWidth : notesRect . width ,
2981+ sameRowPeers : sameRowPeers . length
2982+ } ;
2983+ } ) ;
2984+ expect ( notesLayout . laterRows ) . toBe ( 0 ) ;
2985+ expect ( notesLayout . notesAfterCore ) . toBe ( true ) ;
2986+ expect ( notesLayout . sameRowPeers ) . toBe ( 0 ) ;
2987+ expect ( notesLayout . notesListWidth ) . toBeGreaterThanOrEqual ( notesLayout . editorWidth - 2 ) ;
2988+ expect ( notesLayout . notesRowWidth ) . toBeGreaterThanOrEqual ( notesLayout . editorWidth - 4 ) ;
2989+ expect ( notesLayout . notesFieldWidth ) . toBeGreaterThan ( notesLayout . editorWidth * 0.85 ) ;
2990+
2991+ await expect ( page . locator ( "#songDetailsContent #songSheetTempoInput" ) ) . toBeVisible ( ) ;
2992+ await expect ( page . locator ( "#songDetailsContent #songSheetKeyInput" ) ) . toBeVisible ( ) ;
2993+ await expect ( page . locator ( "#songDetailsContent #songSheetStyleInput" ) ) . toBeVisible ( ) ;
2994+ expect ( await page . locator ( "#songSheetTempoInput" ) . evaluate ( ( input ) => input . readOnly || input . disabled ) ) . toBe ( false ) ;
2995+ expect ( await page . locator ( "#songSheetKeyInput" ) . evaluate ( ( select ) => select . disabled ) ) . toBe ( false ) ;
2996+ expect ( await page . locator ( "#songSheetStyleInput" ) . evaluate ( ( select ) => select . disabled ) ) . toBe ( false ) ;
2997+ await page . locator ( "#songSheetTempoInput" ) . fill ( "151" ) ;
2998+ await page . locator ( "#songSheetKeyInput" ) . selectOption ( "C major" ) ;
2999+ await page . locator ( "#songSheetStyleInput" ) . selectOption ( "chip" ) ;
3000+ expect ( await page . evaluate ( ( ) => {
3001+ const arrangement = window . __midiStudioV2App . selectedSong ( ) . studioArrangement ;
3002+ return {
3003+ key : arrangement . key ,
3004+ style : arrangement . style ,
3005+ tempo : arrangement . tempo
3006+ } ;
3007+ } ) ) . toEqual ( { key : "C major" , style : "chip" , tempo : "151" } ) ;
3008+
3009+ await expect ( page . locator ( "#songSheetContent #songSheetTempoInput, #songSheetContent #songSheetKeyInput, #songSheetContent #songSheetStyleInput" ) ) . toHaveCount ( 0 ) ;
3010+ await expect ( page . locator ( "#songSheetSectionsInput" ) ) . toBeVisible ( ) ;
3011+ await expect ( page . locator ( "#songSheetLoopSectionsInput" ) ) . toBeVisible ( ) ;
3012+ await expect ( page . locator ( "#songSheetSummary [data-song-sheet-summary-field='bars'] [data-song-sheet-computed='true']" ) ) . toHaveCount ( 1 ) ;
3013+ await expect ( page . locator ( "#songSheetSummary [data-song-sheet-summary-field='warnings'] [data-song-sheet-diagnostics='true']" ) ) . toHaveCount ( 1 ) ;
3014+
3015+ await selectMidiStudioTab ( page , "studio" ) ;
3016+ await waitForCanvasRender ( page ) ;
3017+ const quickAccordion = page . locator ( '.tool-starter__panel--left [aria-controls="timelineInstrumentQuickContent"]' ) ;
3018+ await expect ( quickAccordion ) . toBeVisible ( ) ;
3019+ await expect ( quickAccordion ) . toContainText ( "Instruments" ) ;
3020+ await expect ( page . locator ( '.tool-starter__panel--left #timelineInstrumentQuickContent' ) ) . toBeVisible ( ) ;
3021+ await expect ( page . locator ( ".tool-starter__panel--center #timelineInstrumentQuickList" ) ) . toHaveCount ( 0 ) ;
3022+ await expect ( timelineQuickInstrumentRow ( page , "lead" ) ) . toBeVisible ( ) ;
3023+ await expect ( timelineQuickInstrumentRow ( page , "lead" ) . locator ( "[data-timeline-quick-mute='lead']" ) ) . toBeVisible ( ) ;
3024+ await expect ( timelineQuickInstrumentRow ( page , "lead" ) . locator ( "[data-timeline-quick-solo='lead']" ) ) . toBeVisible ( ) ;
3025+ await expect ( timelineQuickInstrumentRow ( page , "lead" ) . locator ( "[data-toggle-instrument-visibility='lead']" ) ) . toBeVisible ( ) ;
3026+ await expect ( page . locator ( "#timelineInstrumentQuickList select, #timelineInstrumentQuickList input:not([type='checkbox']), #timelineInstrumentQuickList [data-lane-instrument-type-select], #timelineInstrumentQuickList [data-lane-instrument-select]" ) ) . toHaveCount ( 0 ) ;
3027+
3028+ await timelineQuickInstrumentRow ( page , "bass" ) . click ( ) ;
3029+ expect ( await page . evaluate ( ( ) => window . __midiStudioV2App . instrumentGrid . selectedInstrumentId ) ) . toBe ( "bass" ) ;
3030+ await selectMidiStudioTab ( page , "instruments" ) ;
3031+ await expect ( instrumentRow ( page , "bass" ) ) . toHaveClass ( / i s - s e l e c t e d / ) ;
3032+ await expect ( instrumentTypeSelect ( page , "bass" ) ) . toBeVisible ( ) ;
3033+ await expect ( instrumentSelect ( page , "bass" ) ) . toBeVisible ( ) ;
3034+ expect ( await instrumentTypeSelect ( page , "bass" ) . evaluate ( ( select ) => select . closest ( "[data-midi-studio-tab-panel]" ) ?. dataset . midiStudioTabPanel ) ) . toBe ( "instruments" ) ;
3035+ expect ( await instrumentSelect ( page , "bass" ) . evaluate ( ( select ) => select . closest ( "[data-midi-studio-tab-panel]" ) ?. dataset . midiStudioTabPanel ) ) . toBe ( "instruments" ) ;
3036+
3037+ await selectInstrumentRow ( page , "lead" ) ;
3038+ expect ( await page . evaluate ( ( ) => window . __midiStudioV2App . instrumentGrid . selectedInstrumentId ) ) . toBe ( "lead" ) ;
3039+ await selectMidiStudioTab ( page , "studio" ) ;
3040+ await expect ( timelineQuickInstrumentRow ( page , "lead" ) ) . toHaveClass ( / i s - s e l e c t e d / ) ;
3041+
3042+ await page . locator ( "#playButton" ) . click ( ) ;
3043+ await expect ( page . locator ( "#playButton" ) ) . toBeDisabled ( ) ;
3044+ await expect ( page . locator ( "#stopButton" ) ) . toBeEnabled ( ) ;
3045+ await page . locator ( "#stopButton" ) . click ( ) ;
3046+ await expect ( page . locator ( "#stopButton" ) ) . toBeDisabled ( ) ;
3047+ await expect ( page . locator ( "#playButton" ) ) . toBeEnabled ( ) ;
3048+ } finally {
3049+ await workspaceV2CoverageReporter . stop ( page ) ;
3050+ await server . close ( ) ;
3051+ }
3052+ } ) ;
3053+
29523054 test ( "derives primary song, instrument, grid, playback, and diagnostics views from the canonical selected song" , async ( { page } ) => {
29533055 const server = await openMidiStudioForImport ( page ) ;
29543056 try {
0 commit comments