TesterPayKit class

Main SDK class for TesterPayKit

Properties

aggregator → MetricsAggregator
Metrics aggregator
final
annotatedScreenshotService → AnnotatedScreenshotService
Annotated screenshot service (Phase 2)
final
anonymousAuthReady → Future<void>
Resolves once initial anonymous-tester-token acquisition has finished (success OR give-up). Always completes — never throws. Safe to await from a widget's initState before firing an authenticated GET, e.g. _updateRetestCount in TesterWrapper. Without this, the wrapper's initState calls raced the fire-and-forget token mint and 401-ed deterministically on every fresh launch (issue: web console retests → 401).
no setter
apiClient → ApiClient
API client
final
Breadcrumb tracker (Phase 1)
final
bugReportUploadService → BugReportUploadService
Bug report upload service (Phase 4)
final
config → TesterPayKitConfig
Current configuration
final
connectivityMonitor → ConnectivityMonitor
Triggers drain on connectivity change.
final
database → TesterPayKitDatabase
Database instance
final
deviceId → String
Device identifier (rotated every 30 days)
final
eventTracker → EventTracker
Event tracker
final
hashCode → int
The hash code for this object.
no setterinherited
isAuthenticated → bool
Whether the SDK currently holds a usable tester token.
no setter
isTokenReady → bool
Whether the anonymous tester token has been acquired. Host apps can use this to gate features that need auth, but it's OPTIONAL — the queue drains automatically once the token arrives.
no setter
A ready-made NavigatorObserver the host adds to its MaterialApp (navigatorObservers: [TesterPayKit.instance.navigatorObserver]) so route pushes are auto-counted as screen views — no per-screen trackScreenView instrumentation needed. See TpkNavigatorObserver for the why (under-counted navigation → under-paid testers).
no setter
networkCapture → NetworkCaptureService
Network capture service
final
onTokenReady → Future<void>
Resolves when the anonymous token is acquired (or all retries exhausted). Never throws — always completes.
no setter
outboxDao → OutboxDao
Outbox DAO — enqueue + query the outbox table.
final
outboxDepth → int
Number of pending items in the outbox. Backed by an in-memory count the OutboxDao refreshes after every outbox mutation.
no setter
outboxDrainer → OutboxDrainer
Background queue processor.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
serverDeviceId → String?
no setter
sessionManager → SessionManager
Session manager
final
submissionService → SubmissionService
Submission service
final
taskProgress → TaskProgressService
Tester checklist progress — drives the "X von Y erledigt" display and auto-completes tasks the tester demonstrably did (see TaskProgressService + the host-app TesterTaskRelevant annotations).
final

Methods

checkForUnreportedCrashes(BuildContext context) → Future<void>
Check for unreported crashes (call this in your app's main widget)
completeTask(String taskId) → Future<void>
Complete a task
createSubmission() → Future<SubmissionResult>
Create a weekly submission. Now delegates to the non-blocking createSubmissionAsync — the submission is enqueued to the outbox and uploaded in background.
createSubmissionAsync() → Future<String>
Create a weekly submission without blocking. The submission is enqueued to the outbox and uploaded in background. Returns a local UUID. Use getSubmissionStatus to track progress.
dispose() → Future<void>
Dispose resources
flushAndEndSession({String endReason = 'lifecycle_flush'}) → Future<void>
Drain in-memory breadcrumbs + local events to the server, then end the active session. Safe to call when no session is active (no-op) and idempotent within a single session.
flushCachedCrashes() → Future<int>
Drain the local Drift crash_contexts table to the server as minimal bug-reports. Each unreported crash becomes one bug-report with title="Auto-reported crash: <error>", description=stackTrace, severity="medium", category="crash". Marks each row as reported only after a successful POST so a network hiccup doesn't lose data.
getAppMetadata() → Future<AppMetadata>
Get app metadata.
getDeviceMetadata() → Future<DeviceMetadata>
Get device metadata
getSubmissions({SubmissionStatus? status, int limit = 10}) → Future<List<WeeklySummary>>
Get submissions
getSubmissionStatus(String localId) → Future<OutboxItemStatus?>
Get the status of a previously submitted item. Returns null if the local UUID is unknown.
loginAnonymous({required String code, String? projectId}) → Future<bool>
Runtime anonymous login — parity with the TS SDK's loginAnonymous(projectId, testerCode). Trades a {projectId, code} pair for a tester JWT, persists the code for auto-login next launch, and kicks off the same post-auth setup (device register + session sync + durability sweep) the build-time config.testerId path runs. Lets a host show an in-app invite-code screen instead of baking the code into the build.
logoutTester() → Future<void>
Clear the tester token + persisted code ("log out" / switch tester). The next launch (or a wrapper re-check) prompts for a code again.
maybeRecordAnnotationTap(Offset globalPosition) → void
Translate a raw global tap position into a task interaction: if the tap landed on a widget the host annotated with TesterTaskRelevant, feed it to the interaction tracker (which auto-completes the task when its trigger condition is met). Fed by the wrapper's global tap listener. Best-effort + guarded — never interferes with the tap.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
onAppDetached() → Future<void>
Called when app is detached from engine — last chance to flush + END the session before the engine tears down (real termination).
onAppInactive() → void
Called when app becomes inactive (e.g., incoming call). We do NOT end the session here — inactive is too noisy on iOS (every notification banner fires this) and would shred otherwise-healthy sessions into 5-second slivers.
onAppPaused() → Future<void>
Called when the app goes to the BACKGROUND. We PAUSE the session, we do NOT end it: freeze the foreground (paid-time) clock so background time isn't paid, and flush the at-risk in-memory breadcrumbs. The session spans background↔foreground cycles and is only ended by onAppDetached (real termination), an explicit "End Session", or the launch-time reconcile of a killed session. (Was: flushAndEndSession — which wrongly closed the session on every backgrounding, so coming back started a brand-new one.)
onAppResumed() → Future<void>
Called when the app RESUMES to the foreground.
runDurabilitySweep() → Future<void>
One durability pass for the payout pipeline. The data only earns money once it reaches the server, so this makes that resilient to hard-kills, network hiccups, and the host never calling createSubmission by hand. Safe to call anytime — every step is idempotent + best-effort:
savedTesterCode() → Future<String?>
The invite code previously entered at runtime (persisted), or null. The wrapper reads this on startup to auto-restore a login before deciding whether to prompt for a code.
setTesterMode({required bool enabled}) → Future<void>
Set tester mode enabled/disabled
showOnboardingIfNeeded(BuildContext context, {String? productName}) → Future<void>
Show the TesterPayKit onboarding the first time after SDK init. Hosts should call this once their own onboarding is done and the app is mounted with a Navigator available (typically in the shell's initState post-frame callback).
showWelcomeSheetIfNeeded(BuildContext context, {required WelcomeBrief brief, required String productName, VoidCallback? onLater}) → Future<void>
Show TesterWelcomeSheet once per app version. The host passes in a TesterBrief (release notes + concrete tasks); the sheet renders, the tester taps "Test starten" — we persist testerpaykit_welcome_shown_<version> so the same version doesn't re-prompt on the next launch.
submitBugReport({required String description, Map<String, dynamic>? metadata}) → String
Submit a bug report. Returns a local UUID immediately. The report is enqueued to the outbox and uploaded in background. Use getSubmissionStatus to track progress.
submitFeedback({required String content, int? rating}) → Future<void>
Submit feedback
syncSubmissions() → Future<void>
Sync pending submissions with server
toString() → String
A string representation of this object.
inherited
trackCrash(String error, StackTrace stackTrace) → Future<void>
Track a crash
trackError(String error, {StackTrace? stackTrace}) → Future<void>
Track an error
trackScreenView(String screenName) → Future<void>
Track a screen view
trackTap({String? screenName}) → Future<void>
Track a tap event

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Properties

instance → TesterPayKit
Get the singleton instance
no setter
isInitialized → bool
Check if SDK is initialized
no setter

Static Methods

initialize({required TesterPayKitConfig config, TesterPayKitDatabase? databaseOverride}) → Future<TesterPayKit>
Initialize the SDK. Returns in <50ms. Token acquisition happens in background via TokenAcquirer. Safe to call multiple times; returns singleton.