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

kiva / ui / 19147367510

06 Nov 2025 07:26PM UTC coverage: 91.443% (+41.5%) from 49.902%
19147367510

push

github

emuvente
test: refactor category-row-arrows-visible-mixin test with runner method

3722 of 3979 branches covered (93.54%)

Branch coverage included in aggregate %.

18923 of 20785 relevant lines covered (91.04%)

78.6 hits per line

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

0.0
/src/client-entry.js
1
/* global UI_TAG */
×
2
/* eslint-disable no-underscore-dangle, vue/require-name-property */
×
3
import '#src/assets/scss/tailwind/tailwind.css';
×
4
import '#src/assets/scss/app.scss';
×
5

6
// Facilitate using sprite icon SVGs in KvIcon
×
7
// eslint-disable-next-line import/no-unresolved
×
8
import 'virtual:svg-store';
×
9

10
const config = window.__KV_CONFIG__ || {};
×
11

12
async function getCookieStore() {
×
13
        const { default: CookieStore } = await import('#src/util/cookieStore');
×
14
        return new CookieStore();
×
15
}
×
16

17
async function getKvAuth0(cookieStore) {
×
18
        const { default: KvAuth0, MockKvAuth0 } = await import('#src/util/KvAuth0');
×
19
        if (config.auth0.enable) {
×
20
                return new KvAuth0({
×
21
                        audience: config.auth0.apiAudience,
×
22
                        checkFakeAuth: config.auth0.checkFakeAuth,
×
23
                        clientID: config.auth0.browserClientID,
×
24
                        cookieStore,
×
25
                        domain: config.auth0.domain,
×
26
                        mfaAudience: config.auth0.mfaAudience,
×
27
                        redirectUri: config.auth0.browserCallbackUri,
×
28
                        scope: config.auth0.scope,
×
29
                });
×
30
        }
×
31
        return MockKvAuth0;
×
32
}
×
33

34
async function getDevice() {
×
35
        const { userAgent } = window.navigator;
×
36
        if (!userAgent) {
×
37
                return null;
×
38
        }
×
39
        const { default: Bowser } = await import('bowser');
×
40
        return Bowser.getParser(userAgent).parse().parsedResult;
×
41
}
×
42

43
async function getLocale() {
×
44
        const { getUserLocale } = await import('get-user-locale');
×
45
        return getUserLocale();
×
46
}
×
47

48
async function getFetch() {
×
49
        const { fetch } = await import('whatwg-fetch');
×
50
        return fetch;
×
51
}
×
52

53
async function getRouter() {
×
54
        const { default: createRouter } = await import('#src/router');
×
55
        return createRouter({ isServer: false });
×
56
}
×
57

58
async function getUserId(apolloClient) {
×
59
        const { default: userIdQuery } = await import('#src/graphql/query/userId.graphql');
×
60
        const result = await apolloClient.query({ query: userIdQuery });
×
61
        return result?.data?.my?.userAccount?.id ?? null;
×
62
}
×
63

64
async function hydrateApolloCache(apolloClient) {
×
65
        // Gather the state from the server.
×
66
        const states = [
×
67
                window.__APOLLO_STATE__,
×
68
                window.__APOLLO_STATE_ESI__,
×
69
        ].filter(x => !!x);
×
70
        // If no state is available, skip hydration.
×
71
        // This can happen if the server didn't render any data.
×
72
        if (states.length === 0) {
×
73
                return;
×
74
        }
×
75
        // Apply the merged state to the Apollo cache.
×
76
        const { applyStateToCache, mergeStateObjects } = await import('#src/util/apolloCacheUtils');
×
77
        applyStateToCache(apolloClient, mergeStateObjects(...states));
×
78
}
×
79

80
async function setupApolloCachePersistence(cache) {
×
81
        const { persistCache, SessionStorageWrapper } = await import('apollo3-cache-persist');
×
82
        await persistCache({
×
83
                cache,
×
84
                storage: new SessionStorageWrapper(window.sessionStorage),
×
85
        });
×
86
}
×
87

88
async function setupAuthErrorHandling(kvAuth0, apolloClient) {
×
89
        const { default: showTipMessage } = await import('#src/graphql/mutation/tipMessage/showTipMessage.graphql');
×
90
        // Show a tip message when there is an unhandled auth0 error
×
91
        kvAuth0.onError(({ eventId, user }) => {
×
92
                let message = 'We\'re sorry, something went wrong.';
×
93
                if (user) {
×
94
                        message = `${message} Please log out and try again.`;
×
95
                } else {
×
96
                        message = `${message} Please clear your cookies and try again.`;
×
97
                }
×
98
                if (eventId) {
×
99
                        message = `${message} (event id: ${eventId})`;
×
100
                }
×
101
                apolloClient.mutate({
×
102
                        mutation: showTipMessage,
×
103
                        variables: {
×
104
                                message,
×
105
                                type: 'error',
×
106
                                persist: true,
×
107
                        },
×
108
                });
×
109
        });
×
110
}
×
111

112
async function setupTouchDetection(apolloClient) {
×
113
        const { default: usingTouchMutation } = await import('#src/graphql/mutation/updateUsingTouch.graphql');
×
114
        // Setup adding touch info to the state
×
115
        window.addEventListener('touchstart', function onFirstTouch() {
×
116
                apolloClient.mutate({
×
117
                        mutation: usingTouchMutation,
×
118
                        variables: { usingTouch: true }
×
119
                });
×
120
                window.removeEventListener('touchstart', onFirstTouch);
×
121
        });
×
122
}
×
123

124
async function setupAnalytics(app, apolloClient) {
×
125
        const userId = await getUserId(apolloClient);
×
126
        await app.config.globalProperties.$setKvAnalyticsData(userId);
×
127
        app.config.globalProperties.$fireServerPageView();
×
128
        app.config.globalProperties.$fireQueuedEvents();
×
129
        const { default: collectWebVitals } = await import('#src/util/webVitals');
×
130
        collectWebVitals(app.config.globalProperties.$kvTrackEvent);
×
131
}
×
132

133
async function setupSentry(app, router) {
×
134
        const Sentry = await import('@sentry/vue');
×
135
        Sentry.init({
×
136
                app,
×
137
                dsn: config.sentryURI,
×
138
                integrations: [
×
139
                        Sentry.browserTracingIntegration({
×
140
                                router,
×
141
                        }),
×
142
                        Sentry.vueIntegration({
×
143
                                tracingOptions: {
×
144
                                        trackComponents: true,
×
145
                                },
×
146
                        }),
×
147
                ],
×
148
                release: UI_TAG,
×
149
                // Set tracesSampleRate to 1.0 to capture 100%
×
150
                // of transactions for performance monitoring.
×
151
                // We recommend adjusting this value in production
×
152
                tracesSampleRate: config?.sentryTraceSampleRate,
×
153
                tracePropagationTargets: [config.host],
×
154
                beforeSend(event) {
×
155
                        // make sentry colleted event easy to compare to
×
156
                        const eventAsString = JSON.stringify(event);
×
157
                        // match specific 3rd party events for exclusion
×
158
                        // Skip sending failed to fetch error caused by unhandled promise rejection in google ads
×
159
                        // Sentry Event Link: https://kiva.sentry.io/issues/4413252219/events/726c65f507684f43b748e913d4793518/
×
160
                        // This url is unreachable: https://pagead2.googlesyndication.com/pagead/buyside_topics/set/
×
161
                        if (eventAsString.indexOf('Failed to fetch') !== -1
×
162
                                && eventAsString.indexOf('pagead') !== -1) {
×
163
                                return false;
×
164
                        }
×
165
                        // Skip Load failed caused by failed fetch calls in 3rd party libraries
×
166
                        // NOTE: we do see failed loads for our own async modules, this doesn't filter those out
×
167
                        // Sentry Event Link: https://kiva.sentry.io/issues/3808313433/events/427b92cf47ed4aaeb321caf20783eba0/
×
168
                        if ((eventAsString.indexOf('Load failed') !== -1
×
169
                                || eventAsString.indexOf('Failed to fetch') !== -1
×
170
                                || eventAsString.indexOf('TypeError') !== -1)
×
171
                                && (
×
172
                                        (eventAsString.indexOf('ct.pinterest') !== -1)
×
173
                                        || (eventAsString.indexOf('rum.management') !== -1)
×
174
                                )
×
175
                        ) {
×
176
                                return false;
×
177
                        }
×
178
                        // Skip sending errors from CefSharp
×
179
                        // https://forum.sentry.io/t/unhandledrejection-non-error-promise-rejection-captured-with-value/14062/20
×
180
                        if (eventAsString.indexOf('Object Not Found Matching Id') !== -1) {
×
181
                                return false;
×
182
                        }
×
183
                        // return event otherwise
×
184
                        return event;
×
185
                },
×
186
        });
×
187
}
×
188

189
function setupClientRouting({
×
190
        apolloClient,
×
191
        app,
×
192
        cookieStore,
×
193
        device,
×
194
        kvAuth0,
×
195
        renderConfig,
×
196
        router,
×
197
}) {
×
198
        // Add router hook for handling asyncData.
×
199
        // Doing it after initial route is resolved so that we don't double-fetch
×
200
        // the data that we already have. Using router.beforeResolve() so that all
×
201
        // async components are resolved.
×
202
        router.beforeResolve(async (to, from, next) => {
×
203
                const [{ authenticationGuard }, { preFetchAll }] = await Promise.all([
×
204
                        import('#src/util/authenticationGuard'),
×
205
                        import('#src/util/apolloPreFetch'),
×
206
                ]);
×
207

208
                const { matched } = to;
×
209
                const prevMatched = from.matched;
×
210
                const activated = matched.filter((c, i) => prevMatched[i] !== c);
×
211

212
                try {
×
213
                        await authenticationGuard({ route: to, apolloClient, kvAuth0 });
×
214
                        // Pre-fetch graphql queries from activated components
×
215
                        await preFetchAll(activated, apolloClient, {
×
216
                                cookieStore,
×
217
                                device,
×
218
                                kvAuth0,
×
219
                                renderConfig,
×
220
                                route: to,
×
221
                        });
×
222
                        next();
×
223
                } catch (error) {
×
224
                        // pass error through next to ensure redirect to login
×
225
                        next(error);
×
226
                }
×
227
        });
×
228

229
        router.beforeEach((to, from, next) => {
×
230
                app.config.globalProperties.$Progress.start(6500);
×
231
                next();
×
232
        });
×
233

234
        router.afterEach((to, from) => {
×
235
                // finish loading
×
236
                app.config.globalProperties.$Progress.finish();
×
237

238
                if (to?.query?.noAnalytics?.toLowerCase() !== 'true') {
×
239
                        // fire pageview
×
240
                        app.config.globalProperties.$fireAsyncPageView(to, from);
×
241
                }
×
242
        });
×
243

244
        router.onError(() => app.config.globalProperties.$Progress.fail());
×
245
}
×
246

247
async function initApp() {
×
248
        const [{ default: createApp }, cookieStore, device, locale, fetch, router] = await Promise.all([
×
249
                import('#src/main'),
×
250
                getCookieStore(),
×
251
                getDevice(),
×
252
                getLocale(),
×
253
                getFetch(),
×
254
                getRouter(),
×
255
        ]);
×
256
        const kvAuth0 = await getKvAuth0(cookieStore);
×
257

258
        // Create the App instance
×
259
        const {
×
260
                app,
×
261
                apolloClient,
×
262
                renderConfig,
×
263
        } = await createApp({
×
264
                appConfig: config,
×
265
                apollo: {
×
266
                        uri: config.graphqlUri,
×
267
                        types: config.graphqlPossibleTypes,
×
268
                },
×
269
                // Since we're in the browser and not the CDN, just check if the user is logged in
×
270
                cdnNotedLoggedIn: kvAuth0.isNotedLoggedIn(),
×
271
                cookieStore,
×
272
                device,
×
273
                kvAuth0,
×
274
                locale,
×
275
                fetch,
×
276
                router,
×
277
        });
×
278

279
        // Apply persisted state from session storage to Client Store
×
280
        if (config.apolloPersistCache) {
×
281
                await setupApolloCachePersistence(apolloClient.cache);
×
282
        }
×
283
        // Apply Server state to Client Store
×
284
        await hydrateApolloCache(apolloClient);
×
285

286
        setupAuthErrorHandling(kvAuth0, apolloClient);
×
287
        setupTouchDetection(apolloClient);
×
288

289
        if (config.enableSentry) {
×
290
                setupSentry(app, router);
×
291
        }
×
292

293
        if (config.enableAnalytics) {
×
294
                setupAnalytics(app, apolloClient);
×
295
        }
×
296

297
        setupClientRouting({
×
298
                apolloClient,
×
299
                app,
×
300
                cookieStore,
×
301
                device,
×
302
                kvAuth0,
×
303
                renderConfig,
×
304
                router,
×
305
        });
×
306

307
        // Mount app in DOM
×
308
        app.mount('#app');
×
309
}
×
310

311
// Start application once browser is idle
×
312
if ('requestIdleCallback' in window) {
×
313
        requestIdleCallback(initApp, { timeout: 2000 });
×
314
} else {
×
315
        setTimeout(initApp, 500);
×
316
}
×
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