PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.4.19
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.4.19
1.4.19 1.4.18 1.4.17 1.4.16 1.4.15 1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.54 1.3.53 1.3.52 1.3.51 1.3.50 All 182 releases
disco / backend / views / components / Analytics / __tests__ / pages / CampaignsReports.test.jsx

CampaignsReports.test.jsx in Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO 1.4.19, at backend/views/components/Analytics/__tests__/pages/CampaignsReports.test.jsx

158 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import '@testing-library/jest-dom';
2 import { fireEvent, screen } from '@testing-library/react';
3 import userEvent from '@testing-library/user-event';
4 import CampaignsReports from '../../pages/CampaignsReports';
5 import { createMockCampaignsList, renderWithProviders } from '../setup/helpers';
6
7 jest.mock('../../features/campaigns/campaignsApi', () => ({
8 useGetCampaignsQuery: jest.fn(),
9 }));
10
11 const {
12 useGetCampaignsQuery,
13 } = require('../../features/campaigns/campaignsApi');
14
15 const mockData = createMockCampaignsList(3);
16
17 describe('CampaignsReports', () => {
18 afterEach(() => {
19 jest.clearAllMocks();
20 });
21
22 function setupLoaded(overrides = {}) {
23 useGetCampaignsQuery.mockReturnValue({
24 data: mockData,
25 isLoading: false,
26 isFetching: false,
27 ...overrides,
28 });
29 }
30
31 function setupLoading() {
32 useGetCampaignsQuery.mockReturnValue({
33 data: undefined,
34 isLoading: true,
35 isFetching: true,
36 });
37 }
38
39 describe('Rendering', () => {
40 it('renders page heading and subtitle', () => {
41 setupLoaded();
42 renderWithProviders(<CampaignsReports />);
43
44 expect(screen.getByText('Campaigns')).toBeInTheDocument();
45 expect(
46 screen.getByText('All discount campaigns')
47 ).toBeInTheDocument();
48 });
49
50 it('renders campaign names in the table', () => {
51 setupLoaded();
52 renderWithProviders(<CampaignsReports />);
53
54 expect(screen.getByText('Campaign 1')).toBeInTheDocument();
55 expect(screen.getByText('Campaign 2')).toBeInTheDocument();
56 expect(screen.getByText('Campaign 3')).toBeInTheDocument();
57 });
58
59 it('renders table column headers', () => {
60 setupLoaded();
61 renderWithProviders(<CampaignsReports />);
62
63 expect(screen.getByText('Name')).toBeInTheDocument();
64 expect(screen.getByText('Intent')).toBeInTheDocument();
65 expect(screen.getByText('Date Range')).toBeInTheDocument();
66 expect(screen.getByText(/Orders/)).toBeInTheDocument();
67 expect(screen.getByText(/Customers/)).toBeInTheDocument();
68 expect(screen.getByText(/Revenue/)).toBeInTheDocument();
69 expect(screen.getByText('Status')).toBeInTheDocument();
70 });
71
72 it('renders campaign links to detail page', () => {
73 setupLoaded();
74 renderWithProviders(<CampaignsReports />);
75
76 const link = screen.getByText('Campaign 1').closest('a');
77 expect(link).toHaveAttribute('href', '/campaigns-reports/1');
78 });
79 });
80
81 describe('Loading states', () => {
82 it('shows loading skeletons', () => {
83 setupLoading();
84 const { container } = renderWithProviders(<CampaignsReports />);
85
86 const pulseElements = container.querySelectorAll(
87 '.disco\\:animate-pulse'
88 );
89 expect(pulseElements.length).toBeGreaterThan(0);
90 expect(screen.queryByText('Campaign 1')).not.toBeInTheDocument();
91 });
92 });
93
94 describe('Empty states', () => {
95 it('shows empty state when no campaigns', () => {
96 useGetCampaignsQuery.mockReturnValue({
97 data: { data: [], collection: { count: 0 } },
98 isLoading: false,
99 isFetching: false,
100 });
101 renderWithProviders(<CampaignsReports />);
102
103 expect(
104 screen.getByText('Campaigns Not Found!')
105 ).toBeInTheDocument();
106 });
107 });
108
109 describe('User interactions', () => {
110 it('passes search value to hook', async () => {
111 setupLoaded();
112 const user = userEvent.setup();
113 renderWithProviders(<CampaignsReports />);
114
115 const searchInput = screen.getByPlaceholderText(
116 'Search campaigns...'
117 );
118 await user.type(searchInput, 'summer');
119
120 // The hook should be called with search parameter
121 const lastCall = useGetCampaignsQuery.mock.calls.at(-1)[0];
122 expect(lastCall.search).toBe('summer');
123 });
124
125 it('handles sort toggle by clicking column header', () => {
126 setupLoaded();
127 renderWithProviders(<CampaignsReports />);
128
129 // Click Revenue header (already sorted desc, should toggle to asc)
130 fireEvent.click(screen.getByText(/Revenue/));
131 const lastCall = useGetCampaignsQuery.mock.calls.at(-1)[0];
132 expect(lastCall.order).toBe('asc');
133 });
134
135 it('changes sort key when clicking different column', () => {
136 setupLoaded();
137 renderWithProviders(<CampaignsReports />);
138
139 fireEvent.click(screen.getByText(/Orders/));
140 const lastCall = useGetCampaignsQuery.mock.calls.at(-1)[0];
141 expect(lastCall.sort_by).toBe('orders');
142 expect(lastCall.order).toBe('desc');
143 });
144 });
145
146 describe('RTK Query integration', () => {
147 it('passes date range params to the query hook', () => {
148 setupLoaded();
149 renderWithProviders(<CampaignsReports />);
150
151 const firstCall = useGetCampaignsQuery.mock.calls[0][0];
152 expect(firstCall).toHaveProperty('date_from');
153 expect(firstCall).toHaveProperty('date_to');
154 expect(firstCall.limit).toBe(20);
155 });
156 });
157 });
158