From 4cf4b741922d680dede7a0f2ee968ce24e1fead6 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Fri, 18 Sep 2026 19:28:46 +0700 Subject: [PATCH 1/2] fix(hig): name menus from their labels and keep foreign key picker rows readable --- TablePro/Views/AIChat/AIChatPanelView.swift | 2 +- TablePro/Views/Export/ExportDialog.swift | 2 +- TablePro/Views/Results/ForeignKeyPickerView.swift | 1 + TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift | 2 +- TablePro/Views/UsersRoles/PrivilegeChecklistView.swift | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/TablePro/Views/AIChat/AIChatPanelView.swift b/TablePro/Views/AIChat/AIChatPanelView.swift index c3867971e..fef42a108 100644 --- a/TablePro/Views/AIChat/AIChatPanelView.swift +++ b/TablePro/Views/AIChat/AIChatPanelView.swift @@ -405,11 +405,11 @@ struct AIChatPanelView: View { .font(.caption) .foregroundStyle(.secondary) .frame(maxWidth: .infinity, alignment: .leading) + .accessibilityLabel(String(localized: "Choose AI provider and model")) } .menuStyle(.button) .buttonStyle(.borderless) .help(String(localized: "Choose AI provider and model")) - .accessibilityLabel(String(localized: "Choose AI provider and model")) } } diff --git a/TablePro/Views/Export/ExportDialog.swift b/TablePro/Views/Export/ExportDialog.swift index 939b117c9..0be6a48e4 100644 --- a/TablePro/Views/Export/ExportDialog.swift +++ b/TablePro/Views/Export/ExportDialog.swift @@ -323,12 +323,12 @@ struct ExportDialog: View { } } label: { Image(systemName: "bookmark") + .accessibilityLabel(String(localized: "Saved selections")) } .menuStyle(.button) .buttonStyle(.borderless) .fixedSize() .help(String(localized: "Saved selections")) - .accessibilityLabel(String(localized: "Saved selections")) .popover(isPresented: $isNamingProfile, arrowEdge: .bottom) { VStack(alignment: .leading, spacing: 10) { Text("Name this selection") diff --git a/TablePro/Views/Results/ForeignKeyPickerView.swift b/TablePro/Views/Results/ForeignKeyPickerView.swift index 6b67e94d3..b1b5def55 100644 --- a/TablePro/Views/Results/ForeignKeyPickerView.swift +++ b/TablePro/Views/Results/ForeignKeyPickerView.swift @@ -148,6 +148,7 @@ struct ForeignKeyPickerView: View { row(for: entry) .contentShape(Rectangle()) .onTapGesture { commit(entry) } + .accessibilityElement(children: .contain) .accessibilityAddTraits(.isButton) .accessibilityAction { commit(entry) } } diff --git a/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift b/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift index 989b06157..d4e299468 100644 --- a/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift +++ b/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift @@ -96,13 +96,13 @@ struct JSONRowInspectorView: View { .foregroundStyle(.secondary) .frame(width: 22, height: 20) .contentShape(Rectangle()) + .accessibilityLabel(String(localized: "JSON view options")) } .menuStyle(.button) .buttonStyle(.borderless) .menuIndicator(.hidden) .fixedSize() .help(String(localized: "JSON view options")) - .accessibilityLabel(String(localized: "JSON view options")) } // MARK: - Tree diff --git a/TablePro/Views/UsersRoles/PrivilegeChecklistView.swift b/TablePro/Views/UsersRoles/PrivilegeChecklistView.swift index 0bd5215c7..4d5fc01ce 100644 --- a/TablePro/Views/UsersRoles/PrivilegeChecklistView.swift +++ b/TablePro/Views/UsersRoles/PrivilegeChecklistView.swift @@ -66,6 +66,7 @@ struct PrivilegeChecklistView: View { Button(String(localized: "Revoke All")) { setAll(false) } } label: { Image(systemName: "ellipsis.circle") + .accessibilityLabel(String(localized: "Bulk actions")) } .menuStyle(.button) .buttonStyle(.borderless) @@ -73,7 +74,6 @@ struct PrivilegeChecklistView: View { .fixedSize() .disabled(viewModel.privilegeSections.isEmpty) .help(String(localized: "Bulk actions")) - .accessibilityLabel(String(localized: "Bulk actions")) } // MARK: - Content From f6b78844a549227262ddb7fc5f86db7402abbaf8 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Fri, 18 Sep 2026 19:28:49 +0700 Subject: [PATCH 2/2] test(editor): wait for the second batch's own results instead of the failed batch's banner --- TableProUITests/QueryRunUITests.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TableProUITests/QueryRunUITests.swift b/TableProUITests/QueryRunUITests.swift index ac811d3a8..dd17bb6b4 100644 --- a/TableProUITests/QueryRunUITests.swift +++ b/TableProUITests/QueryRunUITests.swift @@ -256,17 +256,17 @@ final class QueryRunUITests: UITestCase { typeQuery("COMMIT; SELECT * FROM run_all_kept_probe;", in: app) openRunMenu(in: app).menuItems["Run All Statements"].click() + /// The failed batch leaves its banner up and "Result 3 of 3" in the chooser until this one + /// lands, so only two results with no banner over them say the commit and the read both ran. let chooser = window.descendants(matching: .any) .matching(identifier: "result-set-menu") .firstMatch XCTAssertTrue( - waitForPredicate(timeout: 30) { chooser.title.contains("2") || banner.exists }, - "The commit and the read must both run: got \(chooser.title) \(bannerText(banner))" - ) - XCTAssertFalse( - banner.exists, + waitForPredicate(timeout: 30) { + !banner.exists && chooser.exists && chooser.title.contains("2") + }, "The transaction must still be open to commit, and its table must have survived the failure: " - + "got \(bannerText(banner))" + + "got \(chooser.exists ? chooser.title : "") \(bannerText(banner))" ) }