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

mozilla / fx-private-relay / 74d01625-9661-4180-904e-0bd85eb6c11f

29 May 2025 12:03PM CUT coverage: 85.583% (+0.2%) from 85.353%
74d01625-9661-4180-904e-0bd85eb6c11f

push

circleci

web-flow
Merge pull request #5573 from mozilla/MPP-4155-new-megabundle-banner

MPP-4155 New Megabundle Banner Landing Page

2490 of 3629 branches covered (68.61%)

Branch coverage included in aggregate %.

60 of 62 new or added lines in 8 files covered. (96.77%)

19 existing lines in 6 files now uncovered.

17598 of 19843 relevant lines covered (88.69%)

9.97 hits per line

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

60.38
/frontend/src/hooks/api/api.ts
1
import useSWR, { Fetcher, SWRConfig, SWRConfiguration, SWRResponse } from "swr";
44✔
2
import { getRuntimeConfig } from "../../config";
44✔
3
import { getCsrfToken } from "../../functions/cookies";
44✔
4

5
/**
6
 * Can be used to make API calls to the backend that work both in production and when running on the dev server.
7
 */
8
export const authenticatedFetch = async (
44✔
9
  path: string,
10
  init?: Parameters<typeof fetch>[1],
11
) => {
12
  let authToken;
13
  if (
28!
14
    process.env.NODE_ENV === "development" ||
56✔
15
    process.env.NEXT_PUBLIC_MOCK_API === "true"
16
  ) {
17
    // Note: If running on a separate (dev) server, logging in doesn't work.
18
    //       As a workaround, you can authenticate by opening http://127.0.0.1:8000/admin/authtoken/tokenproxy/,
19
    //       copying the token you need, then running:
20
    //           localStorage.setItem("authToken", "<your token>")
21
    //       in the browser console with the React UI open.
22
    authToken = localStorage.getItem("authToken");
×
23
  }
24
  const headers = new Headers(init?.headers ?? undefined);
28✔
25
  headers.set(
28✔
26
    "Content-Type",
27
    headers.get("Content-Type") ?? "application/json",
56✔
28
  );
29
  headers.set("Accept", headers.get("Accept") ?? "application/json");
28✔
30
  if (typeof authToken === "string") {
28!
31
    headers.set("Authorization", `Token ${authToken}`);
×
32
  }
33
  const csrfToken = getCsrfToken();
28✔
34
  if (typeof csrfToken === "string") {
28!
35
    headers.set("X-CSRFToken", csrfToken);
×
36
  }
37
  const options: Parameters<typeof fetch>[1] = {
28✔
38
    ...init,
39
    headers: headers,
40
    credentials: "include",
41
  };
42

43
  const url = `${getRuntimeConfig().backendOrigin}${path}`;
28✔
44
  const response = await fetch(url, options);
28✔
45
  return response;
×
46
};
47

48
export const apiFetch = async (
44✔
49
  route: string,
50
  init?: Parameters<typeof fetch>[1],
51
) => {
52
  const path = `/api/v1${route}`;
28✔
53
  return authenticatedFetch(path, init);
28✔
54
};
55

56
const fetcher: Fetcher = async (route: string, init?: RequestInit) => {
44✔
57
  const response = await apiFetch(route, init);
28✔
58
  if (!response.ok) {
×
59
    throw new FetchError(response);
×
60
  }
61
  const data: unknown = await response.json();
×
62
  return data;
×
63
};
64

65
/**
66
 * Make calls to our API using [SWR](https://swr.vercel.app). Generally wrapped in endpoint-specific hooks, e.g. {@link useProfiles}.
67
 */
68
export function useApiV1<Data = unknown>(
95✔
69
  route: string | null,
70
  swrOptions: Partial<SWRConfiguration> = {},
×
71
): SWRResponse<Data, FetchError> {
72
  const onErrorRetry: typeof SWRConfig.defaultValue.onErrorRetry = (
95✔
73
    error: unknown | FetchError,
74
    key,
75
    config,
76
    revalidate,
77
    revalidateOpts,
78
  ) => {
UNCOV
79
    if (error instanceof FetchError && error.response.ok === false) {
×
80
      // When the request got rejected by the back-end, do not retry:
81
      return;
×
82
    }
83
    // Otherwise, use SWR's default exponential back-off to retry:
UNCOV
84
    SWRConfig.defaultValue.onErrorRetry(
×
85
      error,
86
      key,
87
      config,
88
      revalidate,
89
      revalidateOpts,
90
    );
91
  };
92
  // TODO: Also use the sessionId cookie in the key,
93
  //       to ensure no data is cached from different users?
94
  //       (This is currently enforced by doing a full page refresh when logging out.)
95
  const result = useSWR(route, fetcher, {
95✔
96
    revalidateOnFocus: false,
97
    onErrorRetry: onErrorRetry,
98
    ...swrOptions,
99
  }) as SWRResponse<Data, FetchError>;
100
  return result;
95✔
101
}
102

103
export class FetchError extends Error {
28✔
104
  readonly response: Response;
105

106
  constructor(response: Response) {
107
    super();
×
108
    this.response = response;
×
109
  }
110
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc