| |
| |
| |
| |
| |
| |
|
|
| import { flushPromises, mount } from '@vue/test-utils'; |
|
|
| |
| |
| |
| |
| jest.mock('CoreHome', () => ({ |
| Tooltips: {}, |
| Sparkline: { template: '<img class="sparkline-stub" />' }, |
| |
| |
| |
| MatomoUrl: { |
| parse: () => ({}), |
| }, |
| NumberFormatter: { |
| formatNumber: (value: number) => String(value), |
| }, |
| }), { virtual: true }); |
|
|
| |
| const SparklinesGrid = require('./SparklinesGrid.vue').default; |
|
|
| describe('CoreVisualizations/SparklinesGrid', () => { |
| let initializeSparklinesSpy: jest.Mock; |
|
|
| beforeEach(() => { |
| |
| |
| initializeSparklinesSpy = jest.fn(); |
| window.initializeSparklines = initializeSparklinesSpy; |
| }); |
|
|
| function entry(description: string, order = 1) { |
| return { |
| url: '?module=API&action=get', |
| metrics: { '': [{ value: '1', description }] }, |
| order, |
| title: null, |
| group: '0', |
| seriesIndices: null, |
| graphParams: null, |
| }; |
| } |
|
|
| function placeholder(order: number) { |
| |
| return { |
| url: '', |
| metrics: {}, |
| order, |
| title: null, |
| group: `placeholder${order}`, |
| seriesIndices: null, |
| graphParams: null, |
| }; |
| } |
|
|
| function createWrapper(props: Record<string, unknown> = {}) { |
| |
| return mount(SparklinesGrid as any, { |
| props: { |
| sparklines: { 0: [entry('Visits')], 1: [entry('Actions'), entry('Bounce rate')] }, |
| ...props, |
| }, |
| }); |
| } |
|
|
| it('flattens grouped sparklines into one card per entry', () => { |
| const wrapper = createWrapper(); |
|
|
| expect(wrapper.findAllComponents({ name: 'SparklineCard' }).length).toBe(3); |
| }); |
|
|
| it('drops layout placeholders so they do not render as empty cards', () => { |
| |
| |
| const wrapper = createWrapper({ |
| sparklines: { |
| 0: [entry('Visits', 1)], |
| 1: [placeholder(10)], |
| 2: [entry('Actions', 20)], |
| }, |
| }); |
|
|
| const titles = wrapper.findAll('.metricValue__title').map((node) => node.text()); |
| expect(wrapper.findAllComponents({ name: 'SparklineCard' }).length).toBe(2); |
| expect(titles).toEqual(['Visits', 'Actions']); |
| }); |
|
|
| it('forwards allMetricsDocumentation to each card, surfacing it as the title tooltip', () => { |
| const wrapper = createWrapper({ |
| sparklines: { 0: [{ ...entry('Visits'), metrics: { '': [{ value: '1', description: 'Visits', column: 'nb_visits' }] } }] }, |
| allMetricsDocumentation: { nb_visits: 'The number of visits.' }, |
| }); |
|
|
| const card = wrapper.findComponent({ name: 'SparklineCard' }); |
| expect(card.props('allMetricsDocumentation')).toEqual({ nb_visits: 'The number of visits.' }); |
| expect(wrapper.find('.metricValue__title').attributes('title')).toBe('The number of visits.'); |
| }); |
|
|
| it('uses the responsive grid columns (s6 m6 l4 xl3) on reporting pages', () => { |
| const wrapper = createWrapper(); |
| const col = wrapper.find('.row.sparklinesGrid > div'); |
|
|
| expect(col.classes()).toEqual(expect.arrayContaining(['col', 's6', 'm6', 'l4', 'xl3'])); |
| }); |
|
|
| it('orders cards by backend `order`, not by numeric group-key iteration order', () => { |
| |
| |
| |
| |
| const wrapper = createWrapper({ |
| sparklines: { |
| 1: [entry('First', 1)], |
| 0: [entry('Third', 30)], |
| 2: [entry('Second', 20)], |
| }, |
| }); |
|
|
| const titles = wrapper.findAll('.metricValue__title').map((node) => node.text()); |
| expect(titles).toEqual(['First', 'Second', 'Third']); |
| }); |
|
|
| it('collapses to two columns in widget mode', () => { |
| const wrapper = createWrapper({ isWidget: true }); |
| const col = wrapper.find('.row.sparklinesGrid > div'); |
|
|
| expect(col.classes()).toContain('s6'); |
| expect(col.classes()).not.toContain('xl3'); |
| }); |
|
|
| it('re-runs the sparkline click-to-evolution wiring after mount', async () => { |
| createWrapper(); |
| await flushPromises(); |
|
|
| expect(initializeSparklinesSpy).toHaveBeenCalledTimes(1); |
| }); |
| }); |
|
|