import {mountWithTheme} from 'sentry-test/enzyme';
import {Client} from 'sentry/api';
import SentryApplicationDashboard from 'sentry/views/settings/organizationDeveloperSettings/sentryApplicationDashboard';
describe('Sentry Application Dashboard', function () {
const NUM_INSTALLS = 5;
const NUM_UNINSTALLS = 2;
let org;
let orgId;
let sentryApp;
let request;
let wrapper;
beforeEach(() => {
Client.clearMockResponses();
org = TestStubs.Organization();
orgId = org.slug;
});
describe('Viewing the Sentry App Dashboard for a published integration', () => {
beforeEach(() => {
sentryApp = TestStubs.SentryApp({
status: 'published',
schema: {
elements: [
{type: 'stacktrace-link', uri: '/test'},
{
type: 'issue-link',
create: {uri: '/test', required_fields: []},
link: {uri: '/test', required_fields: []},
},
],
},
});
request = TestStubs.SentryAppWebhookRequest();
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/stats/`,
body: {
totalInstalls: NUM_INSTALLS,
totalUninstalls: NUM_UNINSTALLS,
installStats: [[1569783600, NUM_INSTALLS]],
uninstallStats: [[1569783600, NUM_UNINSTALLS]],
},
});
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/requests/`,
body: [request],
});
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/interaction/`,
body: {
componentInteractions: {
'stacktrace-link': [[1569783600, 1]],
'issue-link': [[1569783600, 1]],
},
views: [[1569783600, 1]],
},
});
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/`,
body: sentryApp,
});
wrapper = mountWithTheme(
);
});
it('shows the total install/uninstall stats', () => {
const installsStat = wrapper
.find('StatsSection')
.filterWhere(h => h.text().includes('Total installs'))
.find('p');
const uninstallsStat = wrapper
.find('StatsSection')
.filterWhere(h => h.text().includes('Total uninstalls'))
.find('p');
expect(installsStat.text()).toEqual(`${NUM_INSTALLS}`);
expect(uninstallsStat.text()).toEqual(`${NUM_UNINSTALLS}`);
});
it('shows the installation stats in a graph', () => {
const chart = wrapper.find('BarChart');
const chartSeries = chart.props().series;
expect(chart.exists()).toBeTruthy();
expect(chartSeries).toHaveLength(2);
expect(chartSeries).toContainEqual({
data: [{name: 1569783600 * 1000, value: NUM_INSTALLS}],
seriesName: 'installed',
});
expect(chartSeries).toContainEqual({
data: [{name: 1569783600 * 1000, value: NUM_UNINSTALLS}],
seriesName: 'uninstalled',
});
});
it('shows the request log', () => {
const requestLog = wrapper.find('PanelBody');
const requestLogText = requestLog.find('PanelItem').text();
// The mock response has 1 request
expect(requestLog.find('PanelItem')).toHaveLength(1);
// Make sure that all the info is displayed
expect(requestLogText).toEqual(
expect.stringContaining('https://example.com/webhook')
);
expect(requestLogText).toEqual(expect.stringContaining('400'));
expect(requestLogText).toEqual(expect.stringContaining('issue.assigned'));
expect(requestLogText).toEqual(expect.stringContaining('Test Org'));
});
it('shows an empty message if there are no requests', () => {
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/requests/`,
body: [],
});
wrapper = mountWithTheme(
);
expect(wrapper.find('PanelBody').exists('PanelItem')).toBeFalsy();
expect(wrapper.find('EmptyMessage').text()).toEqual(
expect.stringContaining('No requests found in the last 30 days.')
);
});
it('shows the integration views in a line chart', () => {
const chart = wrapper
.find('Panel')
.filterWhere(h => h.text().includes('Integration Views'))
.find('LineChart');
const chartData = chart.props().series[0].data;
expect(chart.exists()).toBeTruthy();
expect(chartData).toHaveLength(1);
expect(chartData).toContainEqual({name: 1569783600 * 1000, value: 1});
});
it('shows the component interactions in a line chart', () => {
const chart = wrapper
.find('Panel')
.filterWhere(h => h.text().includes('Component Interactions'))
.find('LineChart');
const chartSeries = chart.props().series;
expect(chart.exists()).toBeTruthy();
expect(chartSeries).toHaveLength(2);
expect(chartSeries).toContainEqual({
data: [{name: 1569783600 * 1000, value: 1}],
seriesName: 'stacktrace-link',
});
expect(chartSeries).toContainEqual({
data: [{name: 1569783600 * 1000, value: 1}],
seriesName: 'issue-link',
});
});
});
describe('Viewing the Sentry App Dashboard for an internal integration', () => {
beforeEach(() => {
sentryApp = TestStubs.SentryApp({
status: 'internal',
schema: {
elements: [{type: 'stacktrace-link', uri: '/test'}],
},
});
request = TestStubs.SentryAppWebhookRequest();
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/stats/`,
body: {
totalInstalls: 1,
totalUninstalls: 0,
installStats: [[1569783600, 1]],
uninstallStats: [[1569783600, 0]],
},
});
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/requests/`,
body: [request],
});
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/interaction/`,
body: {
componentInteractions: {
'stacktrace-link': [[1569783600, 1]],
},
views: [[1569783600, 1]],
},
});
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/`,
body: sentryApp,
});
wrapper = mountWithTheme(
);
});
it('does not show the installation stats or graph', () => {
expect(wrapper.exists('StatsSection')).toBeFalsy();
expect(wrapper.exists('BarChart')).toBeFalsy();
});
it('shows the request log', () => {
const requestLog = wrapper.find('PanelBody');
const requestLogText = requestLog.find('PanelItem').text();
// The mock response has 1 request
expect(requestLog.find('PanelItem')).toHaveLength(1);
// Make sure that all the info is displayed
expect(requestLogText).toEqual(
expect.stringContaining('https://example.com/webhook')
);
expect(requestLogText).toEqual(expect.stringContaining('400'));
expect(requestLogText).toEqual(expect.stringContaining('issue.assigned'));
});
it('shows an empty message if there are no requests', () => {
Client.addMockResponse({
url: `/sentry-apps/${sentryApp.slug}/requests/`,
body: [],
});
wrapper = mountWithTheme(
);
expect(wrapper.find('PanelBody').exists('PanelItem')).toBeFalsy();
expect(wrapper.find('EmptyMessage').text()).toEqual(
expect.stringContaining('No requests found in the last 30 days.')
);
});
it('does not show the integration views', () => {
const chart = wrapper.findWhere(h => h.text().includes('Integration Views'));
expect(chart.exists()).toBeFalsy();
});
it('shows the component interactions in a line chart', () => {
const chart = wrapper
.find('Panel')
.filterWhere(h => h.text().includes('Component Interactions'))
.find('LineChart');
const chartSeries = chart.props().series;
expect(chart.exists()).toBeTruthy();
expect(chartSeries).toHaveLength(1);
expect(chartSeries).toContainEqual({
data: [{name: 1569783600 * 1000, value: 1}],
seriesName: 'stacktrace-link',
});
});
});
});