mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 06:20:11 +00:00
fix: await auth telemetry before auth flow navigation
This commit is contained in:
@@ -57,12 +57,26 @@ export class TelemetryRegistry implements TelemetryDispatcher {
|
||||
})
|
||||
}
|
||||
|
||||
private async dispatchAsync(
|
||||
action: (provider: TelemetryProvider) => void | Promise<void>
|
||||
): Promise<void> {
|
||||
await Promise.all(
|
||||
this.providers.map(async (provider) => {
|
||||
try {
|
||||
await action(provider)
|
||||
} catch (error) {
|
||||
console.error('[Telemetry] Provider dispatch failed', error)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
trackSignupOpened(): void {
|
||||
this.dispatch((provider) => provider.trackSignupOpened?.())
|
||||
}
|
||||
|
||||
trackAuth(metadata: AuthMetadata): void {
|
||||
this.dispatch((provider) => provider.trackAuth?.(metadata))
|
||||
async trackAuth(metadata: AuthMetadata): Promise<void> {
|
||||
await this.dispatchAsync((provider) => provider.trackAuth?.(metadata))
|
||||
}
|
||||
|
||||
trackUserLoggedIn(): void {
|
||||
|
||||
@@ -13,11 +13,6 @@ function lastDataLayerEntry(): Record<string, unknown> | undefined {
|
||||
return dl?.[dl.length - 1] as Record<string, unknown> | undefined
|
||||
}
|
||||
|
||||
async function flushAsyncWork() {
|
||||
await Promise.resolve()
|
||||
await Promise.resolve()
|
||||
}
|
||||
|
||||
function toUint8Array(data: BufferSource): Uint8Array {
|
||||
if (data instanceof ArrayBuffer) {
|
||||
return new Uint8Array(data)
|
||||
@@ -269,15 +264,13 @@ describe('GtmTelemetryProvider', () => {
|
||||
}
|
||||
})
|
||||
|
||||
provider.trackAuth({
|
||||
await provider.trackAuth({
|
||||
method: 'email',
|
||||
is_new_user: true,
|
||||
user_id: 'uid-123',
|
||||
email: ' Test@Example.com '
|
||||
})
|
||||
|
||||
await flushAsyncWork()
|
||||
|
||||
const dl = window.dataLayer as Record<string, unknown>[]
|
||||
const authEvent = dl.find((entry) => entry.event === 'sign_up')
|
||||
expect(authEvent).toMatchObject({
|
||||
@@ -297,14 +290,12 @@ describe('GtmTelemetryProvider', () => {
|
||||
it('omits user_data when email is absent', async () => {
|
||||
const provider = createInitializedProvider()
|
||||
|
||||
provider.trackAuth({
|
||||
await provider.trackAuth({
|
||||
method: 'google',
|
||||
is_new_user: false,
|
||||
user_id: 'uid-456'
|
||||
})
|
||||
|
||||
await flushAsyncWork()
|
||||
|
||||
expect(lastDataLayerEntry()).toMatchObject({
|
||||
event: 'login',
|
||||
method: 'google',
|
||||
@@ -317,15 +308,13 @@ describe('GtmTelemetryProvider', () => {
|
||||
const provider = createInitializedProvider()
|
||||
vi.stubGlobal('crypto', undefined)
|
||||
|
||||
provider.trackAuth({
|
||||
await provider.trackAuth({
|
||||
method: 'github',
|
||||
is_new_user: false,
|
||||
user_id: 'uid-789',
|
||||
email: 'user@example.com'
|
||||
})
|
||||
|
||||
await flushAsyncWork()
|
||||
|
||||
expect(lastDataLayerEntry()).toMatchObject({
|
||||
event: 'login',
|
||||
method: 'github',
|
||||
|
||||
@@ -135,12 +135,8 @@ export class GtmTelemetryProvider implements TelemetryProvider {
|
||||
})
|
||||
}
|
||||
|
||||
trackAuth(metadata: AuthMetadata): void {
|
||||
async trackAuth(metadata: AuthMetadata): Promise<void> {
|
||||
if (!this.initialized) return
|
||||
void this.pushAuthEvent(metadata)
|
||||
}
|
||||
|
||||
private async pushAuthEvent(metadata: AuthMetadata): Promise<void> {
|
||||
const basePayload = {
|
||||
method: metadata.method,
|
||||
...(metadata.user_id ? { user_id: metadata.user_id } : {})
|
||||
|
||||
@@ -351,7 +351,7 @@ export interface BeginCheckoutMetadata
|
||||
export interface TelemetryProvider {
|
||||
// Authentication flow events
|
||||
trackSignupOpened?(): void
|
||||
trackAuth?(metadata: AuthMetadata): void
|
||||
trackAuth?(metadata: AuthMetadata): void | Promise<void>
|
||||
trackUserLoggedIn?(): void
|
||||
|
||||
// Subscription flow events
|
||||
|
||||
@@ -295,6 +295,46 @@ describe('useAuthStore', () => {
|
||||
expect(store.loading).toBe(false)
|
||||
})
|
||||
|
||||
it('should wait for auth telemetry before resolving login', async () => {
|
||||
const mockUserCredential = { user: mockUser }
|
||||
vi.mocked(firebaseAuth.signInWithEmailAndPassword).mockResolvedValue(
|
||||
mockUserCredential as Partial<UserCredential> as UserCredential
|
||||
)
|
||||
|
||||
let resolveTrackAuth: (() => void) | undefined
|
||||
mockTrackAuth.mockImplementationOnce(
|
||||
() =>
|
||||
new Promise<void>((resolve) => {
|
||||
resolveTrackAuth = resolve
|
||||
})
|
||||
)
|
||||
|
||||
let resolved = false
|
||||
const loginPromise = store
|
||||
.login('test@example.com', 'password')
|
||||
.then((result) => {
|
||||
resolved = true
|
||||
return result
|
||||
})
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(mockTrackAuth).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
method: 'email',
|
||||
is_new_user: false,
|
||||
user_id: mockUser.uid,
|
||||
email: mockUser.email
|
||||
})
|
||||
)
|
||||
})
|
||||
expect(resolved).toBe(false)
|
||||
|
||||
resolveTrackAuth?.()
|
||||
|
||||
await expect(loginPromise).resolves.toEqual(mockUserCredential)
|
||||
expect(resolved).toBe(true)
|
||||
})
|
||||
|
||||
it('should handle login errors', async () => {
|
||||
const mockError = new Error('Invalid password')
|
||||
vi.mocked(firebaseAuth.signInWithEmailAndPassword).mockRejectedValue(
|
||||
|
||||
@@ -25,6 +25,7 @@ import { t } from '@/i18n'
|
||||
import { WORKSPACE_STORAGE_KEYS } from '@/platform/workspace/workspaceConstants'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import type { AuthMetadata } from '@/platform/telemetry/types'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { useApiKeyAuthStore } from '@/stores/apiKeyAuthStore'
|
||||
import type { AuthHeader } from '@/types/authTypes'
|
||||
@@ -350,6 +351,11 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const trackCloudAuth = async (metadata: AuthMetadata): Promise<void> => {
|
||||
if (!isCloud) return
|
||||
await useTelemetry()?.trackAuth(metadata)
|
||||
}
|
||||
|
||||
const login = async (
|
||||
email: string,
|
||||
password: string
|
||||
@@ -360,14 +366,12 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
{ createCustomer: true }
|
||||
)
|
||||
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'email',
|
||||
is_new_user: false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined
|
||||
})
|
||||
}
|
||||
await trackCloudAuth({
|
||||
method: 'email',
|
||||
is_new_user: false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -382,14 +386,12 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
{ createCustomer: true }
|
||||
)
|
||||
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'email',
|
||||
is_new_user: true,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined
|
||||
})
|
||||
}
|
||||
await trackCloudAuth({
|
||||
method: 'email',
|
||||
is_new_user: true,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -402,16 +404,13 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
{ createCustomer: true }
|
||||
)
|
||||
|
||||
if (isCloud) {
|
||||
const additionalUserInfo = getAdditionalUserInfo(result)
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'google',
|
||||
is_new_user:
|
||||
options?.isNewUser || additionalUserInfo?.isNewUser || false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined
|
||||
})
|
||||
}
|
||||
const additionalUserInfo = getAdditionalUserInfo(result)
|
||||
await trackCloudAuth({
|
||||
method: 'google',
|
||||
is_new_user: options?.isNewUser || additionalUserInfo?.isNewUser || false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -424,16 +423,13 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
{ createCustomer: true }
|
||||
)
|
||||
|
||||
if (isCloud) {
|
||||
const additionalUserInfo = getAdditionalUserInfo(result)
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'github',
|
||||
is_new_user:
|
||||
options?.isNewUser || additionalUserInfo?.isNewUser || false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined
|
||||
})
|
||||
}
|
||||
const additionalUserInfo = getAdditionalUserInfo(result)
|
||||
await trackCloudAuth({
|
||||
method: 'github',
|
||||
is_new_user: options?.isNewUser || additionalUserInfo?.isNewUser || false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user