({
+ ...jest.requireActual('react-router-dom'),
+ useRouteMatch: () => ({ url: history.location.pathname }),
+ useHistory: () => history,
+}));
+
+const mockDashboardUrl = 'http://localhost:3000';
+jest.spyOn(defaultServices.api, 'grafanaDashboardUrl').mockReturnValue(of(mockDashboardUrl));
+
+const mockTarget = { connectUrl: 'service:jmx:rmi://someUrl', alias: 'fooTarget' };
+jest.spyOn(defaultServices.target, 'target').mockReturnValue(of(mockTarget));
+
+const mockController = new ChartController(
+ defaultServices.api,
+ defaultServices.target,
+ defaultServices.notificationChannel,
+ defaultServices.settings
+);
+const mockChartContext = {
+ controller: mockController,
+};
+
+describe('
', () => {
+ beforeEach(() => (history = createMemoryHistory({ initialEntries: ['/'] })));
+ afterEach(cleanup);
+
+ it('renders correctly', async () => {
+ jest.spyOn(mockController, 'attach').mockReturnValue(of(ControllerState.READY));
+
+ let tree;
+ await act(async () => {
+ tree = renderer.create(
+
+
+
+
+
+
+
+
+
+ );
+ });
+ expect(tree.toJSON()).toMatchSnapshot('with-content');
+ });
+
+ it('renders loading state correctly', async () => {
+ jest.spyOn(mockController, 'attach').mockReturnValue(of(ControllerState.UNKNOWN));
+
+ let tree;
+ await act(async () => {
+ tree = renderer.create(
+
+
+
+
+
+
+
+
+
+ );
+ });
+ expect(tree.toJSON()).toMatchSnapshot('loading-view');
+ });
+
+ it('renders empty state correctly', async () => {
+ jest.spyOn(mockController, 'attach').mockReturnValue(of(ControllerState.NO_DATA));
+
+ let tree;
+ await act(async () => {
+ tree = renderer.create(
+
+
+
+
+
+
+
+
+
+ );
+ });
+ expect(tree.toJSON()).toMatchSnapshot('empty-state');
+ });
+
+ it('renders empty state with information and action button', async () => {
+ jest.spyOn(mockController, 'attach').mockReturnValue(of(ControllerState.NO_DATA));
+
+ renderChartCard(
+
+ );
+
+ expect(screen.getByText('CPU Load')).toBeInTheDocument();
+ expect(screen.getByText('No source recording')).toBeInTheDocument();
+ expect(
+ screen.getByText((s) => s.includes('Metrics cards display data taken from running flight recordings'))
+ ).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: /create/i })).toBeInTheDocument();
+ });
+
+ it('navigates to recording creation with prefilled state when empty state button clicked', async () => {
+ jest.spyOn(mockController, 'attach').mockReturnValue(of(ControllerState.NO_DATA));
+
+ const { user } = renderChartCard(
+
+ );
+
+ expect(history.location.pathname).toBe('/');
+ await user.click(screen.getByRole('button', { name: /create/i }));
+ expect(history.location.pathname).toBe('/recordings/create');
+ expect(history.location.state).toEqual({
+ duration: -1,
+ labels: [
+ {
+ key: 'origin',
+ value: 'dashboard_metrics',
+ },
+ ],
+ maxAge: 120,
+ maxSize: 100 * 1024 * 1024,
+ name: 'dashboard_metrics',
+ restartExisting: true,
+ templateName: 'Continuous',
+ templateType: 'TARGET',
+ });
+ });
+
+ it.each([
+ ['CPU Load', 120, 5],
+ ['Heap Usage', 90, 10],
+ ['Network Utilization', 60, 15],
+ ['File I/O', 30, 20],
+ ])('renders iframe', async (chartKind: string, duration: number, period: number) => {
+ jest.spyOn(mockController, 'attach').mockReturnValue(of(ControllerState.READY));
+
+ const { container } = renderChartCard(
+
+ );
+
+ const iframe = container.querySelector('iframe');
+ expect(iframe).toBeTruthy();
+ const u = new URL(iframe?.src || '');
+ expect(u.host).toBe('localhost:3000');
+ expect(u.protocol).toBe('http:');
+ const params = new URLSearchParams();
+ params.set('theme', 'light');
+ params.set('panelId', String(kindToId(chartKind)));
+ params.set('to', 'now');
+ params.set('from', `now-${duration}s`);
+ params.set('refresh', `${period}s`);
+ expect(u.searchParams.toString()).toEqual(params.toString());
+ });
+});
+
+const renderChartCard = (
+ ui: React.ReactElement,
+ {
+ services = defaultServices,
+ notifications = NotificationsInstance,
+ chartContext = mockChartContext,
+ preloadState = {},
+ store = setupStore(preloadState),
+ user = userEvent.setup(),
+ ...renderOptions
+ } = {}
+) => {
+ return renderWithProvidersAndRedux(
+ ui,
+ [
+ {
+ kind: ChartContext.Provider,
+ instance: chartContext,
+ },
+ {
+ kind: NotificationsContext.Provider,
+ instance: notifications,
+ },
+ {
+ kind: ServiceContext.Provider,
+ instance: services,
+ },
+ ],
+ {
+ store,
+ user,
+ ...renderOptions,
+ }
+ );
+};
diff --git a/src/test/Dashboard/Charts/__snapshots__/ChartCard.test.tsx.snap b/src/test/Dashboard/Charts/__snapshots__/ChartCard.test.tsx.snap
new file mode 100644
index 000000000..956a37c10
--- /dev/null
+++ b/src/test/Dashboard/Charts/__snapshots__/ChartCard.test.tsx.snap
@@ -0,0 +1,348 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`
renders correctly: with-content 1`] = `
+
+`;
+
+exports[`
renders empty state correctly: empty-state 1`] = `
+
+
+
+
+
+
+
+
+
+
+ No source recording
+
+
+ Metrics cards display data taken from running flight recordings with the label
+
+
+ origin=dashboard_metrics
+
+
+ . No such recordings are currently available.
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`
renders loading state correctly: loading-view 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/test/Settings/Settings.test.tsx b/src/test/Settings/Settings.test.tsx
index 3bfc24f27..94cb432c5 100644
--- a/src/test/Settings/Settings.test.tsx
+++ b/src/test/Settings/Settings.test.tsx
@@ -70,6 +70,15 @@ jest.mock('@app/Settings/AutomatedAnalysisConfig', () => ({
} as UserSetting,
}));
+jest.mock('@app/Settings/ChartCardsConfig', () => ({
+ ChartCardsConfig: {
+ titleKey: 'SETTINGS.CHARTS_CONFIG.TITLE',
+ descConstruct: 'SETTINGS.CHARTS_CONFIG.DESCRIPTION',
+ category: 'SETTINGS.CATEGORIES.DASHBOARD',
+ content: () =>
Chart Cards Config Component,
+ } as UserSetting,
+}));
+
jest.mock('@app/Settings/CredentialsStorage', () => ({
CredentialsStorage: {
titleKey: 'SETTINGS.CREDENTIALS_STORAGE.TITLE',
diff --git a/src/test/Settings/__snapshots__/Settings.test.tsx.snap b/src/test/Settings/__snapshots__/Settings.test.tsx.snap
index 437b9e6d7..554622e5c 100644
--- a/src/test/Settings/__snapshots__/Settings.test.tsx.snap
+++ b/src/test/Settings/__snapshots__/Settings.test.tsx.snap
@@ -517,6 +517,57 @@ exports[`
renders correctly 1`] = `
+