Datasource Onboarding: add tracking (#60918)

* Datasource Onboarding: add tracking

* remove unused var

* set ds logo alt text to empty screenn and remove presentation role

* run i18n:extract

* Revert "run i18n:extract"

This reverts commit 5313ac9661.
This commit is contained in:
Giordano Ricci 2023-01-05 22:27:43 +00:00 committed by GitHub
parent dfed7e59a5
commit 122be161f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 13 deletions

View File

@ -0,0 +1,82 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import React from 'react';
import { DeepPartial } from 'react-hook-form';
import { Provider } from 'react-redux';
import { DataSourcePluginMeta } from '@grafana/data';
import * as runtime from '@grafana/runtime';
import { backendSrv } from 'app/core/services/backend_srv';
import { contextSrv } from 'app/core/services/context_srv';
import { configureStore } from 'app/store/configureStore';
import 'whatwg-fetch';
import { EmptyStateNoDatasource } from './EmptyStateNoDatasource';
let reportInteractionSpy: jest.SpyInstance;
const server = setupServer();
beforeEach(() => {
jest.spyOn(contextSrv, 'hasRole').mockReturnValue(true);
reportInteractionSpy = jest.spyOn(runtime, 'reportInteraction');
server.resetHandlers();
});
afterEach(() => {
jest.restoreAllMocks();
});
beforeAll(() => {
runtime.setBackendSrv(backendSrv);
server.listen({ onUnhandledRequest: 'bypass' });
});
afterAll(() => {
server.close();
});
describe('EmptyStateNoDatasource', () => {
it('correctly tracks user interactions', async () => {
server.use(
rest.get('/api/plugins', (_, res, ctx) => {
return res(
ctx.json<Array<DeepPartial<DataSourcePluginMeta>>>([
{ id: 'prometheus', name: 'Prometheus', info: { logos: { small: 'prometheus.png' } } },
{ id: 'mysql', name: 'MySQL', info: { logos: { small: 'mysql.png' } } },
{ id: 'elasticsearch', name: 'Elasticsearch', info: { logos: { small: 'elasticsearch.png' } } },
{ id: 'influxdb', name: 'InfluxDB', info: { logos: { small: 'influxdb.png' } } },
{ id: 'graphite', name: 'Graphite', info: { logos: { small: 'graphite.png' } } },
{ id: 'stackdriver', name: 'StackDriver', info: { logos: { small: 'stackdriver.png' } } },
{ id: 'cloudwatch', name: 'CloudWatch', info: { logos: { small: 'cloudwatch.png' } } },
{
id: 'grafana-azure-monitor-datasource',
name: 'Azure Monitor',
info: { logos: { small: 'grafana-azure-monitor-datasource.png' } },
},
])
);
})
);
render(
<Provider store={configureStore()}>
<EmptyStateNoDatasource title="A Title" CTAText="CTA" />
</Provider>
);
await waitFor(() => {
expect(screen.getByRole('heading', { name: 'A Title' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Prometheus' })).toBeInTheDocument();
});
fireEvent.click(screen.getByRole('button', { name: 'Prometheus' }));
expect(reportInteractionSpy).toHaveBeenLastCalledWith('dashboards_connectds_ds_clicked');
fireEvent.click(screen.getByRole('link', { name: 'View all' }));
expect(reportInteractionSpy).toHaveBeenCalledWith('dashboards_connectds_viewall_clicked');
fireEvent.click(screen.getByRole('button', { name: 'CTA' }));
expect(reportInteractionSpy).toHaveBeenLastCalledWith('dashboards_connectds_sampledata_clicked');
});
});

View File

@ -3,7 +3,7 @@ import React, { ComponentProps } from 'react';
import { useAsync } from 'react-use';
import { DataSourcePluginMeta, GrafanaTheme2, PageLayoutType } from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
import { getBackendSrv, reportInteraction } from '@grafana/runtime';
import { Icon, useStyles2 } from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
import { contextSrv } from 'app/core/core';
@ -68,23 +68,24 @@ export function EmptyStateNoDatasource({ onCTAClick, loading = false, title, CTA
<ul className={styles.datasources}>
{datasources.map((d) => (
<li key={d.id}>
<button onClick={() => onAddDatasource(d)}>
<img
src={d.info.logos.small}
alt={t('datasource-onboarding.logo', 'Logo for {{datasourceName}} data source', {
datasourceName: d.name,
})}
height="16"
width="16"
className={styles.logo}
/>
<button
onClick={() => {
reportInteraction('dashboards_connectds_ds_clicked');
onAddDatasource(d);
}}
>
<img src={d.info.logos.small} alt="" height="16" width="16" className={styles.logo} />
<span className={styles.datasourceName}>{d.name}</span>
<Icon name="arrow-right" size="lg" className={styles.arrowIcon} />
</button>
</li>
))}
<li>
<a href="/datasources/new" className={styles.viewAll}>
<a
href="/datasources/new"
className={styles.viewAll}
onClick={() => reportInteraction('dashboards_connectds_viewall_clicked')}
>
<span>{t('datasource-onboarding.viewAll', 'View all')}</span>
<Icon name="arrow-right" size="lg" />
</a>
@ -97,7 +98,13 @@ export function EmptyStateNoDatasource({ onCTAClick, loading = false, title, CTA
{t('datasource-onboarding.contact-admin', 'Please contact your administrator to configure data sources.')}
</h4>
)}
<button onClick={onCTAClick} className={styles.ctaButton}>
<button
onClick={() => {
reportInteraction('dashboards_connectds_sampledata_clicked');
onCTAClick?.();
}}
className={styles.ctaButton}
>
<span>{CTAText}</span>
<Icon name="arrow-right" size="lg" />
</button>