• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

karanshukla / navyfragen-app / 28693877194

04 Jul 2026 03:43AM UTC coverage: 96.417% (+0.05%) from 96.367%
28693877194

push

github

web-flow
Merge pull request #195 from karanshukla/claude/push-notifications-account-scope-lcc35y

Fix account auto-switch and device-wide push delivery

2147 of 2337 branches covered (91.87%)

Branch coverage included in aggregate %.

138 of 138 new or added lines in 7 files covered. (100.0%)

1 existing line in 1 file now uncovered.

8131 of 8323 relevant lines covered (97.69%)

6.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.0
/client/src/api/authService.ts
1
import { useMutation, useQuery, UseQueryResult } from "@tanstack/react-query";
2

3
import { apiClient, ApiError } from "./apiClient";
4
import { clearFriendsCache } from "./profileService";
5
import { queryClient } from "./queryClient";
6

7
/**
8
 * Represents a user profile on the client-side.
9
 * This interface is based on the app.bsky.actor.getProfile lexicon.
10
 * @see {@link https://docs.bsky.app/docs/api/app-bsky-actor-get-profile}
11
 */
12
export interface UserProfile {
13
  did?: string;
14
  handle?: string;
15
  displayName?: string;
16
  description?: string;
17
  avatar?: string;
18
  banner?: string;
19
}
20

21
/**
22
 * A remembered account in the multi-account switcher. Mirrors the server-side
23
 * `AccountEntry`. The list is populated server-side after each successful
24
 * OAuth login; the client only ever reads it (and POSTs a switch request).
25
 */
26
export interface AccountEntry {
27
  did: string;
28
  handle?: string;
29
  displayName?: string;
30
  avatar?: string;
31
}
32

33
export interface SessionResponse {
34
  isLoggedIn: boolean;
35
  profile: UserProfile | null;
36
  did: string | null;
37
  /** All accounts authenticated in this browser session (multi-account). */
38
  accounts?: AccountEntry[];
39
}
40

41
export interface LoginRequest {
42
  handle: string;
43
}
44

45
export interface LoginResponse {
46
  redirectUrl: string;
47
}
48

49
export interface SwitchAccountRequest {
50
  did: string;
51
}
52

53
export interface SwitchAccountResponse {
54
  success: boolean;
55
  did: string;
56
}
57

58
export interface E2ELoginRequest {
59
  identifier: string;
60
  password: string;
61
}
62

63
export interface E2ELoginResponse {
64
  success: boolean;
65
}
66

67
export const authKeys = {
8✔
68
  session: ["auth", "session"] as const,
69
};
70

71
export const authService = {
8✔
72
  getSession: (): Promise<SessionResponse> => {
73
    return apiClient.get<SessionResponse>("/session");
2✔
74
  },
75

76
  login: async (data: LoginRequest): Promise<LoginResponse> => {
77
    return apiClient.post<LoginResponse, LoginRequest>("/login", data);
3✔
78
  },
79

80
  logout: async (): Promise<{ message: string }> => {
81
    return apiClient.post<{ message: string }>("/logout");
2✔
82
  },
83

84
  switchAccount: async (data: SwitchAccountRequest): Promise<SwitchAccountResponse> => {
85
    return apiClient.post<SwitchAccountResponse, SwitchAccountRequest>("/accounts/switch", data);
×
86
  },
87

88
  e2eLogin: async (data: E2ELoginRequest): Promise<E2ELoginResponse> => {
89
    return apiClient.post<E2ELoginResponse, E2ELoginRequest>("/auth/e2e-login", data);
×
90
  },
91
};
92

93
// React Query hooks
94
export function useSession(): UseQueryResult<SessionResponse, ApiError> {
95
  return useQuery({
2✔
96
    queryKey: authKeys.session,
97
    queryFn: () => authService.getSession(),
1✔
98
  });
99
}
100

101
export function useLogin() {
102
  return useMutation({
3✔
103
    mutationFn: (data: LoginRequest) => authService.login(data),
1✔
104
  });
105
}
106

107
export function useLogout() {
108
  return useMutation({
29✔
109
    mutationFn: () => authService.logout(),
1✔
110
    onSuccess: () => {
111
      // Invalidate the session query to force a refetch
112
      queryClient.invalidateQueries({ queryKey: authKeys.session });
1✔
113
      window.location.href = "/";
1✔
114
    },
115
  });
116
}
117

118
export function useSwitchAccount() {
UNCOV
119
  return useMutation<SwitchAccountResponse, ApiError, SwitchAccountRequest>({
×
120
    mutationFn: (data: SwitchAccountRequest) => authService.switchAccount(data),
×
121
    onSuccess: (response) => {
122
      clearFriendsCache(response.did);
×
123
    },
124
  });
125
}
126

127
export function useE2ELogin() {
128
  return useMutation({
×
129
    mutationFn: (data: E2ELoginRequest) => authService.e2eLogin(data),
×
130
  });
131
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc