From d80d3d6eca1b003dc26dc76b5997056557e720d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Fri, 30 Oct 2026 00:16:00 +0700 Subject: [PATCH] fix(analytics): record the first successful editor query again (#3886) (cherry picked from commit c43fab2b32cdd7b938cc033fa0bb43b7f26edb8a) --- .../MainContentCoordinator+History.swift | 3 ++ .../Views/Main/FirstQueryAnalyticsTests.swift | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 apple/TableProTests/Views/Main/FirstQueryAnalyticsTests.swift diff --git a/apple/TablePro/Views/Main/Extensions/MainContentCoordinator+History.swift b/apple/TablePro/Views/Main/Extensions/MainContentCoordinator+History.swift index 5415915038..8caead141f 100644 --- a/apple/TablePro/Views/Main/Extensions/MainContentCoordinator+History.swift +++ b/apple/TablePro/Views/Main/Extensions/MainContentCoordinator+History.swift @@ -10,6 +10,9 @@ extension MainContentCoordinator { if #available(macOS 14.0, *) { FeatureTipSignals.editorQueryRan() } + if request.wasSuccessful { + MacAnalyticsProvider.shared.markFirstQueryExecuted() + } } let recorder = services.queryHistoryManager return Task(priority: .utility) { diff --git a/apple/TableProTests/Views/Main/FirstQueryAnalyticsTests.swift b/apple/TableProTests/Views/Main/FirstQueryAnalyticsTests.swift new file mode 100644 index 0000000000..05ae4ddff7 --- /dev/null +++ b/apple/TableProTests/Views/Main/FirstQueryAnalyticsTests.swift @@ -0,0 +1,41 @@ +import Foundation +import Testing + +@testable import TablePro + +/// The heartbeat's first-query timestamp lost its only caller when `DatabaseManager.execute(query:)` +/// was removed, so it stayed nil on every Mac. Recording an editor run's history is where it is set now. +@MainActor +struct FirstQueryAnalyticsTests { + private func request(_ source: QueryHistorySource, succeeded: Bool, connectionId: UUID) -> QueryHistoryRecordRequest { + QueryHistoryRecordRequest( + query: "SELECT 1", + connectionId: connectionId, + databaseName: "db", + databaseType: .postgresql, + source: source, + executionTime: 0.01, + rowCount: 1, + wasSuccessful: succeeded, + errorMessage: succeeded ? nil : "syntax error" + ) + } + + // The mark is written before recordHistory returns its task, so every assertion runs before the + // first suspension and no other suite can touch the shared defaults in between. + @Test("Only a successful editor query records the first-query timestamp") + func successfulEditorQueryMarksFirstQuery() async { + AppStorageEnvironment.shared.defaults.removeObject(forKey: MacAnalyticsProvider.Keys.firstQueryExecutedAt) + let fixture = CoordinatorFixture() + let connectionId = fixture.connection.id + + let failed = fixture.coordinator.recordHistory(request(.editor, succeeded: false, connectionId: connectionId)) + let browsed = fixture.coordinator.recordHistory(request(.tableBrowse, succeeded: true, connectionId: connectionId)) + #expect(MacAnalyticsProvider.shared.firstQueryExecutedAt == nil) + + let ran = fixture.coordinator.recordHistory(request(.editor, succeeded: true, connectionId: connectionId)) + #expect(MacAnalyticsProvider.shared.firstQueryExecutedAt != nil) + + _ = await (failed.value, browsed.value, ran.value) + } +}