fix(frontend-plugin-api): default api config error
Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/errors": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@backstage/version-bridge": "workspace:^",
|
||||
"@types/react": "^16.13.1 || ^17.0.0",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { ApiRef, ApiHolder, TypesToApiRefs } from './types';
|
||||
import { useVersionedContext } from '@backstage/version-bridge';
|
||||
import { NotImplementedError } from '@backstage/errors';
|
||||
|
||||
/**
|
||||
* React hook for retrieving {@link ApiHolder}, an API catalog.
|
||||
@@ -26,12 +27,12 @@ import { useVersionedContext } from '@backstage/version-bridge';
|
||||
export function useApiHolder(): ApiHolder {
|
||||
const versionedHolder = useVersionedContext<{ 1: ApiHolder }>('api-context');
|
||||
if (!versionedHolder) {
|
||||
throw new Error('API context is not available');
|
||||
throw new NotImplementedError('API context is not available');
|
||||
}
|
||||
|
||||
const apiHolder = versionedHolder.atVersion(1);
|
||||
if (!apiHolder) {
|
||||
throw new Error('ApiContext v1 not available');
|
||||
throw new NotImplementedError('ApiContext v1 not available');
|
||||
}
|
||||
return apiHolder;
|
||||
}
|
||||
@@ -47,7 +48,7 @@ export function useApi<T>(apiRef: ApiRef<T>): T {
|
||||
|
||||
const api = apiHolder.get(apiRef);
|
||||
if (!api) {
|
||||
throw new Error(`No implementation available for ${apiRef}`);
|
||||
throw new NotImplementedError(`No implementation available for ${apiRef}`);
|
||||
}
|
||||
return api;
|
||||
}
|
||||
@@ -73,7 +74,9 @@ export function withApis<T extends {}>(apis: TypesToApiRefs<T>) {
|
||||
|
||||
const api = apiHolder.get(ref);
|
||||
if (!api) {
|
||||
throw new Error(`No implementation available for ${ref}`);
|
||||
throw new NotImplementedError(
|
||||
`No implementation available for ${ref}`,
|
||||
);
|
||||
}
|
||||
impls[key] = api;
|
||||
}
|
||||
|
||||
@@ -211,8 +211,8 @@ describe('RouteTracker', () => {
|
||||
action: 'navigate',
|
||||
attributes: {},
|
||||
context: {
|
||||
extensionId: 'App',
|
||||
pluginId: 'root',
|
||||
extensionId: 'app',
|
||||
pluginId: 'app',
|
||||
},
|
||||
subject: '/not-routable-extension',
|
||||
value: undefined,
|
||||
@@ -221,8 +221,8 @@ describe('RouteTracker', () => {
|
||||
action: 'click',
|
||||
attributes: undefined,
|
||||
context: {
|
||||
extensionId: 'App',
|
||||
pluginId: 'root',
|
||||
extensionId: 'app',
|
||||
pluginId: 'app',
|
||||
},
|
||||
subject: 'test',
|
||||
value: undefined,
|
||||
|
||||
@@ -35,8 +35,8 @@ describe('AnalyticsContext', () => {
|
||||
it('returns default values', () => {
|
||||
const { result } = renderHook(() => useAnalyticsContext());
|
||||
expect(result.current).toEqual({
|
||||
extensionId: 'App',
|
||||
pluginId: 'root',
|
||||
extensionId: 'app',
|
||||
pluginId: 'app',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -49,8 +49,8 @@ describe('AnalyticsContext', () => {
|
||||
</AnalyticsContext>,
|
||||
);
|
||||
|
||||
expect(result.getByTestId('extension-id')).toHaveTextContent('App');
|
||||
expect(result.getByTestId('plugin-id')).toHaveTextContent('root');
|
||||
expect(result.getByTestId('extension-id')).toHaveTextContent('app');
|
||||
expect(result.getByTestId('plugin-id')).toHaveTextContent('app');
|
||||
});
|
||||
|
||||
it('uses provided analytics context', () => {
|
||||
@@ -60,7 +60,7 @@ describe('AnalyticsContext', () => {
|
||||
</AnalyticsContext>,
|
||||
);
|
||||
|
||||
expect(result.getByTestId('extension-id')).toHaveTextContent('App');
|
||||
expect(result.getByTestId('extension-id')).toHaveTextContent('app');
|
||||
expect(result.getByTestId('plugin-id')).toHaveTextContent('custom');
|
||||
});
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ export const useAnalyticsContext = (): AnalyticsContextValue => {
|
||||
if (theContext === undefined) {
|
||||
return {
|
||||
pluginId: 'app',
|
||||
extensionId: 'App',
|
||||
extensionId: 'app',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -53,8 +53,8 @@ describe('useAnalytics', () => {
|
||||
some: 'value',
|
||||
},
|
||||
context: {
|
||||
extensionId: 'App',
|
||||
pluginId: 'root',
|
||||
extensionId: 'app',
|
||||
pluginId: 'app',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,8 +23,11 @@ import { Tracker } from './Tracker';
|
||||
function useAnalyticsApi(): AnalyticsApi {
|
||||
try {
|
||||
return useApi(analyticsApiRef);
|
||||
} catch {
|
||||
return { captureEvent: () => {} };
|
||||
} catch (error) {
|
||||
if (error.name === 'NotImplementedError') {
|
||||
return { captureEvent: () => {} };
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-4
@@ -493,8 +493,8 @@ describe('GoogleAnalytics4', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Backward compatibility', () => {
|
||||
it('fallback category for legacy context extension property', () => {
|
||||
describe('api backward compatibility', () => {
|
||||
it('continue working with legacy App category', () => {
|
||||
const api = GoogleAnalytics4.fromConfig(basicValidConfig);
|
||||
|
||||
expect(api.captureEvent).toBeDefined();
|
||||
@@ -512,6 +512,24 @@ describe('GoogleAnalytics4', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('use lowercase app as the new default category', () => {
|
||||
const api = GoogleAnalytics4.fromConfig(basicValidConfig);
|
||||
|
||||
expect(api.captureEvent).toBeDefined();
|
||||
|
||||
api.captureEvent({
|
||||
action: 'navigate',
|
||||
subject: '/',
|
||||
context: { ...context, extensionId: '', extension: '' },
|
||||
});
|
||||
|
||||
expect(fnEvent).toHaveBeenCalledWith('page_view', {
|
||||
action: 'page_view',
|
||||
label: '/',
|
||||
category: 'app',
|
||||
});
|
||||
});
|
||||
|
||||
it('prioritize new context extension id over old extension property', () => {
|
||||
const api = GoogleAnalytics4.fromConfig(basicValidConfig);
|
||||
|
||||
@@ -520,13 +538,13 @@ describe('GoogleAnalytics4', () => {
|
||||
api.captureEvent({
|
||||
action: 'navigate',
|
||||
subject: '/',
|
||||
context: { ...context, extensionId: 'App', extension: '' },
|
||||
context: { ...context, extensionId: 'app', extension: '' },
|
||||
});
|
||||
|
||||
expect(fnEvent).toHaveBeenCalledWith('page_view', {
|
||||
action: 'page_view',
|
||||
label: '/',
|
||||
category: 'App',
|
||||
category: 'app',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+3
-2
@@ -171,9 +171,10 @@ export class GoogleAnalytics4 implements AnalyticsApi, NewAnalyticsApi {
|
||||
}
|
||||
|
||||
const extensionId = context.extensionId || context.extension;
|
||||
const category = extensionId ? String(extensionId) : 'App';
|
||||
const category = extensionId ? String(extensionId) : 'app';
|
||||
|
||||
if (action === 'navigate' && category === 'App') {
|
||||
// The legacy default extension was 'App' and the new one is 'app'
|
||||
if (action === 'navigate' && category.toLocaleLowerCase() === 'app') {
|
||||
this.capture.event(
|
||||
{
|
||||
category,
|
||||
|
||||
@@ -3896,6 +3896,7 @@ __metadata:
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/config": "workspace:^"
|
||||
"@backstage/core-app-api": "workspace:^"
|
||||
"@backstage/errors": "workspace:^"
|
||||
"@backstage/test-utils": "workspace:^"
|
||||
"@backstage/types": "workspace:^"
|
||||
"@backstage/version-bridge": "workspace:^"
|
||||
|
||||
Reference in New Issue
Block a user