broken changes

This commit is contained in:
Mark Gregory
2026-11-05 13:42:20 +00:00
parent d5b24bff29
commit d565e40215
7 changed files with 808 additions and 258 deletions
+79 -8
View File
@@ -1733,14 +1733,28 @@ extension KJamsCloneTests {
if let rep = host.bitmapImageRepForCachingDisplay(in:host.bounds) { host.cacheDisplay(in:host.bounds,to:rep);try XCTUnwrap(rep.representation(using:.png,properties:[:])).write(to:URL(fileURLWithPath:"/private/tmp/kjmix-dj-native.png")) }
XCTAssertEqual(model.dj.a.player.currentSongID,id);XCTAssertEqual(model.dj.b.player.currentSongID,id)
XCTAssertFalse(model.dj.a.player.playing);XCTAssertNil(model.player.currentSongID)
let settings = NSHostingView(rootView:StudioSettingsDialog(model:model).preferredColorScheme(.dark))
settings.frame = NSRect(x:0,y:0,width:760,height:680)
let settingsWindow = NSWindow(contentRect:settings.frame,styleMask:[.borderless],backing:.buffered,defer:false)
settingsWindow.appearance = NSAppearance(named:.darkAqua);settingsWindow.contentView = settings
settingsWindow.setFrameOrigin(NSPoint(x:-10000,y:-10000));settingsWindow.orderFront(nil)
defer { settingsWindow.orderOut(nil);settingsWindow.contentView = nil }
try await Task.sleep(nanoseconds:200_000_000);settings.layoutSubtreeIfNeeded()
if let rep = settings.bitmapImageRepForCachingDisplay(in:settings.bounds) { settings.cacheDisplay(in:settings.bounds,to:rep);try XCTUnwrap(rep.representation(using:.png,properties:[:])).write(to:URL(fileURLWithPath:"/private/tmp/kjmix-settings-native.png")) }
func capturePreferences(_ scope: String,_ category: String,_ path: String) async throws {
let settings = NSHostingView(rootView:StudioSettingsDialog(model:model,scope:scope,category:category).preferredColorScheme(.dark))
settings.frame = NSRect(x:0,y:0,width:850,height:700)
let settingsWindow = NSWindow(contentRect:settings.frame,styleMask:[.borderless],backing:.buffered,defer:false)
settingsWindow.appearance = NSAppearance(named:.darkAqua);settingsWindow.contentView = settings
settingsWindow.setFrameOrigin(NSPoint(x:-10000,y:-10000));settingsWindow.orderFront(nil)
defer { settingsWindow.orderOut(nil);settingsWindow.contentView = nil }
try await Task.sleep(nanoseconds:150_000_000);settings.layoutSubtreeIfNeeded()
if let rep = settings.bitmapImageRepForCachingDisplay(in:settings.bounds) { settings.cacheDisplay(in:settings.bounds,to:rep);try XCTUnwrap(rep.representation(using:.png,properties:[:])).write(to:URL(fileURLWithPath:path)) }
}
try await capturePreferences("Karaoke","General","/private/tmp/kjmix-settings-native.png")
try await capturePreferences("DJ","General","/private/tmp/kjmix-dj-settings-general.png")
try await capturePreferences("DJ","Sound","/private/tmp/kjmix-dj-settings-sound.png")
try await capturePreferences("DJ","Appearance","/private/tmp/kjmix-dj-settings-appearance.png")
let console = NSHostingView(rootView:DJContinuousConsole(system:model.dj,loadA:{},loadB:{}).frame(width:1320,height:390).foregroundStyle(.white).preferredColorScheme(.dark))
console.frame = NSRect(x:0,y:0,width:1320,height:390)
let consoleWindow = NSWindow(contentRect:console.frame,styleMask:[.borderless],backing:.buffered,defer:false)
consoleWindow.appearance = NSAppearance(named:.darkAqua);consoleWindow.contentView = console;consoleWindow.setFrameOrigin(NSPoint(x:-10000,y:-10000));consoleWindow.orderFront(nil)
defer { consoleWindow.orderOut(nil);consoleWindow.contentView = nil }
try await Task.sleep(nanoseconds:150_000_000);console.layoutSubtreeIfNeeded()
if let rep = console.bitmapImageRepForCachingDisplay(in:console.bounds) { console.cacheDisplay(in:console.bounds,to:rep);try XCTUnwrap(rep.representation(using:.png,properties:[:])).write(to:URL(fileURLWithPath:"/private/tmp/kjmix-dj-console.png")) }
}
}
@@ -1852,3 +1866,60 @@ extension KJamsCloneTests {
XCTAssertFalse(player.playing);XCTAssertNil(player.currentSongID)
}
}
extension KJamsCloneTests {
@MainActor func testNativeDJFaderOrientationAndControlActionUpdateBinding() async throws {
var value = 0.5
let host = NSHostingView(rootView:DJHardwareFader(value:Binding(get:{value},set:{value = $0}),label:"Tempo test",vertical:true).frame(width:52,height:94))
host.frame = NSRect(x:0,y:0,width:52,height:94)
let window = NSWindow(contentRect:host.frame,styleMask:[.borderless],backing:.buffered,defer:false)
window.contentView = host;window.setFrameOrigin(NSPoint(x:-10000,y:-10000));window.orderFront(nil)
defer { window.orderOut(nil);window.contentView = nil }
try await Task.sleep(nanoseconds:150_000_000);host.layoutSubtreeIfNeeded()
func find(_ view: NSView) -> NSSlider? { if let slider = view as? NSSlider { return slider };return view.subviews.compactMap{find($0)}.first }
let slider = try XCTUnwrap(find(host))
XCTAssertTrue(slider.isVertical);XCTAssertEqual(slider.doubleValue,0.5,accuracy:0.001)
slider.doubleValue = 0.25
XCTAssertTrue(slider.sendAction(slider.action,to:slider.target));XCTAssertEqual(value,0.25,accuracy:0.001)
slider.doubleValue = 1
XCTAssertTrue(slider.sendAction(slider.action,to:slider.target));XCTAssertEqual(value,1,accuracy:0.001)
}
}
extension KJamsCloneTests {
func testDJPreferencesTempoDirectionRangesAndMixCurves() {
var prefs = DJPreferences()
XCTAssertEqual(prefs.tempo(at:0.5),1,accuracy:0.0001)
XCTAssertEqual(prefs.tempo(at:1),0.84,accuracy:0.0001)
XCTAssertEqual(prefs.position(for:1.16),0,accuracy:0.0001)
prefs.invertTempo = false;prefs.tempoRange = 8
XCTAssertEqual(prefs.tempo(at:0),0.92,accuracy:0.0001)
XCTAssertEqual(prefs.tempo(at:1),1.08,accuracy:0.0001)
XCTAssertEqual(prefs.position(for:prefs.tempo(at:0.25)),0.25,accuracy:0.0001)
let linear = DJMix.weights(0.5,curve:"Linear")
XCTAssertEqual(linear.0,0.5);XCTAssertEqual(linear.1,0.5)
prefs.tempoRange = .nan;prefs.libraryFont = .infinity;prefs.crossfaderCurve = "invalid"
XCTAssertEqual(prefs.sanitized.tempoRange,16);XCTAssertEqual(prefs.sanitized.libraryFont,11);XCTAssertEqual(prefs.sanitized.crossfaderCurve,"Equal power")
}
@MainActor func testDJSettingsPersistenceLoadProtectionEQAndHotCueAutoplay() throws {
let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
defer { try? FileManager.default.removeItem(at:root) }
let fixture = try XCTUnwrap(Bundle(for:Self.self).resourceURL?.appendingPathComponent("Fixtures/Demo.mp3"))
let first = Song(id:1,title:"First",audio:fixture.path,cdg:nil,rating:0,plays:0)
let second = Song(id:2,title:"Second",audio:fixture.path,cdg:nil,rating:0,plays:0)
let system = DJSystem(storageURL:root);system.master = 0
defer { system.a.player.stop();system.b.player.stop() }
system.load(first,into:"A");system.a.player.toggle()
system.load(second,into:"A");XCTAssertNotNil(system.error);XCTAssertEqual(system.a.song?.id,1)
system.a.player.stopDeck();system.error = nil
system.settings.autoPlayOnLoad = true;system.settings.resetEQOnLoad = true
system.settings.tempoRange = 8;system.settings.crossfaderCurve = "Linear";system.settings.headroomDB = 6
system.a.player.lowGain = 6;system.load(second,into:"A")
XCTAssertNil(system.error);XCTAssertEqual(system.a.song?.id,2);XCTAssertTrue(system.a.player.playing);XCTAssertEqual(system.a.player.lowGain,0)
system.a.player.stopDeck();system.settings.autoPlayOnLoad = false;system.settings.autoPlayHotCue = true
system.hotCue(0,deck:system.a);XCTAssertFalse(system.a.player.playing)
system.hotCue(0,deck:system.a);XCTAssertTrue(system.a.player.playing)
let restored = DJSystem(storageURL:root)
XCTAssertEqual(restored.settings,system.settings)
}
}