@memberjunction/ng-pagination 5.43.0 → 5.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-pagination",
3
- "version": "5.43.0",
3
+ "version": "5.45.0",
4
4
  "description": "MemberJunction: Reusable pagination component for server-side paged data with first/prev/next/last navigation",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=index.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
@@ -1,7 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- describe('@memberjunction/ng-pagination', () => {
3
- it('should have a passing test', () => {
4
- expect(true).toBe(true);
5
- });
6
- });
7
- //# sourceMappingURL=index.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, it, expect } from 'vitest';\n\ndescribe('@memberjunction/ng-pagination', () => {\n it('should have a passing test', () => {\n expect(true).toBe(true);\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=pagination.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pagination.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pagination.test.ts"],"names":[],"mappings":""}
@@ -1,258 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- /**
3
- * We test PaginationComponent as a plain TypeScript class.
4
- * Angular decorators are no-ops at test time; we only exercise the pure logic.
5
- */
6
- // Minimal stub so the @Component / @Input / @Output decorators don't explode at import time.
7
- vi.mock('@angular/core', () => ({
8
- Component: () => () => { },
9
- Input: () => () => { },
10
- Output: () => () => { },
11
- EventEmitter: class {
12
- listeners = [];
13
- emit(value) {
14
- for (const fn of this.listeners)
15
- fn(value);
16
- }
17
- subscribe(fn) {
18
- this.listeners.push(fn);
19
- return { unsubscribe: () => { this.listeners = this.listeners.filter(l => l !== fn); } };
20
- }
21
- },
22
- }));
23
- vi.mock('@angular/common', () => ({ CommonModule: {} }));
24
- import { PaginationComponent } from '../lib/pagination.component';
25
- function createComponent(overrides = {}) {
26
- const c = new PaginationComponent();
27
- if (overrides.TotalRowCount !== undefined)
28
- c.TotalRowCount = overrides.TotalRowCount;
29
- if (overrides.PageNumber !== undefined)
30
- c.PageNumber = overrides.PageNumber;
31
- if (overrides.PageSize !== undefined)
32
- c.PageSize = overrides.PageSize;
33
- if (overrides.IsLoading !== undefined)
34
- c.IsLoading = overrides.IsLoading;
35
- return c;
36
- }
37
- describe('PaginationComponent', () => {
38
- // ------------------------------------------------------------------ TotalPages
39
- describe('TotalPages', () => {
40
- it('returns 0 when TotalRowCount is 0', () => {
41
- const c = createComponent({ TotalRowCount: 0, PageSize: 10 });
42
- expect(c.TotalPages).toBe(0);
43
- });
44
- it('returns 0 when TotalRowCount is negative', () => {
45
- const c = createComponent({ TotalRowCount: -5, PageSize: 10 });
46
- expect(c.TotalPages).toBe(0);
47
- });
48
- it('returns 0 when PageSize is 0', () => {
49
- const c = createComponent({ TotalRowCount: 50, PageSize: 0 });
50
- expect(c.TotalPages).toBe(0);
51
- });
52
- it('returns 0 when PageSize is negative', () => {
53
- const c = createComponent({ TotalRowCount: 50, PageSize: -1 });
54
- expect(c.TotalPages).toBe(0);
55
- });
56
- it('returns 1 when rows fit exactly in one page', () => {
57
- const c = createComponent({ TotalRowCount: 10, PageSize: 10 });
58
- expect(c.TotalPages).toBe(1);
59
- });
60
- it('rounds up for partial last page', () => {
61
- const c = createComponent({ TotalRowCount: 11, PageSize: 10 });
62
- expect(c.TotalPages).toBe(2);
63
- });
64
- it('handles large datasets', () => {
65
- const c = createComponent({ TotalRowCount: 1_000_000, PageSize: 100 });
66
- expect(c.TotalPages).toBe(10_000);
67
- });
68
- it('handles PageSize=1', () => {
69
- const c = createComponent({ TotalRowCount: 5, PageSize: 1 });
70
- expect(c.TotalPages).toBe(5);
71
- });
72
- it('handles single row with default PageSize', () => {
73
- const c = createComponent({ TotalRowCount: 1 });
74
- expect(c.TotalPages).toBe(1);
75
- });
76
- });
77
- // ---------------------------------------------------------- DisplayFrom / DisplayTo
78
- describe('DisplayFrom', () => {
79
- it('returns 0 when TotalRowCount is 0', () => {
80
- const c = createComponent({ TotalRowCount: 0 });
81
- expect(c.DisplayFrom).toBe(0);
82
- });
83
- it('returns 1 on the first page', () => {
84
- const c = createComponent({ TotalRowCount: 50, PageNumber: 1, PageSize: 10 });
85
- expect(c.DisplayFrom).toBe(1);
86
- });
87
- it('returns correct start for second page', () => {
88
- const c = createComponent({ TotalRowCount: 50, PageNumber: 2, PageSize: 10 });
89
- expect(c.DisplayFrom).toBe(11);
90
- });
91
- it('returns correct start for last page', () => {
92
- const c = createComponent({ TotalRowCount: 25, PageNumber: 3, PageSize: 10 });
93
- expect(c.DisplayFrom).toBe(21);
94
- });
95
- });
96
- describe('DisplayTo', () => {
97
- it('returns 0 when TotalRowCount is 0', () => {
98
- const c = createComponent({ TotalRowCount: 0, PageSize: 10 });
99
- expect(c.DisplayTo).toBe(0);
100
- });
101
- it('caps at TotalRowCount on last partial page', () => {
102
- const c = createComponent({ TotalRowCount: 25, PageNumber: 3, PageSize: 10 });
103
- expect(c.DisplayTo).toBe(25);
104
- });
105
- it('equals PageSize * PageNumber on a full page', () => {
106
- const c = createComponent({ TotalRowCount: 50, PageNumber: 2, PageSize: 10 });
107
- expect(c.DisplayTo).toBe(20);
108
- });
109
- it('equals TotalRowCount on single-page dataset', () => {
110
- const c = createComponent({ TotalRowCount: 7, PageNumber: 1, PageSize: 10 });
111
- expect(c.DisplayTo).toBe(7);
112
- });
113
- });
114
- // -------------------------------------------------------- CanGoBack / CanGoForward
115
- describe('CanGoBack', () => {
116
- it('returns false on first page', () => {
117
- const c = createComponent({ TotalRowCount: 50, PageNumber: 1 });
118
- expect(c.CanGoBack).toBe(false);
119
- });
120
- it('returns true on page > 1', () => {
121
- const c = createComponent({ TotalRowCount: 50, PageNumber: 2, PageSize: 10 });
122
- expect(c.CanGoBack).toBe(true);
123
- });
124
- it('returns false when IsLoading even on page > 1', () => {
125
- const c = createComponent({ TotalRowCount: 50, PageNumber: 2, PageSize: 10, IsLoading: true });
126
- expect(c.CanGoBack).toBe(false);
127
- });
128
- });
129
- describe('CanGoForward', () => {
130
- it('returns false on last page', () => {
131
- const c = createComponent({ TotalRowCount: 20, PageNumber: 2, PageSize: 10 });
132
- expect(c.CanGoForward).toBe(false);
133
- });
134
- it('returns true when not on last page', () => {
135
- const c = createComponent({ TotalRowCount: 30, PageNumber: 2, PageSize: 10 });
136
- expect(c.CanGoForward).toBe(true);
137
- });
138
- it('returns false when IsLoading even if not on last page', () => {
139
- const c = createComponent({ TotalRowCount: 30, PageNumber: 1, PageSize: 10, IsLoading: true });
140
- expect(c.CanGoForward).toBe(false);
141
- });
142
- it('returns false when TotalRowCount is 0', () => {
143
- const c = createComponent({ TotalRowCount: 0, PageNumber: 1, PageSize: 10 });
144
- expect(c.CanGoForward).toBe(false);
145
- });
146
- it('returns false on single-page dataset', () => {
147
- const c = createComponent({ TotalRowCount: 5, PageNumber: 1, PageSize: 10 });
148
- expect(c.CanGoForward).toBe(false);
149
- });
150
- });
151
- // ----------------------------------------------------------------- Navigation
152
- describe('Navigation methods', () => {
153
- let comp;
154
- let emitted;
155
- beforeEach(() => {
156
- comp = createComponent({ TotalRowCount: 50, PageNumber: 3, PageSize: 10 });
157
- emitted = [];
158
- comp.PageChange.subscribe((e) => emitted.push(e));
159
- });
160
- describe('GoToFirst', () => {
161
- it('emits page 1 when CanGoBack is true', () => {
162
- comp.GoToFirst();
163
- expect(emitted).toHaveLength(1);
164
- expect(emitted[0]).toEqual({ PageNumber: 1, PageSize: 10, StartRow: 0 });
165
- });
166
- it('does nothing on page 1', () => {
167
- comp.PageNumber = 1;
168
- comp.GoToFirst();
169
- expect(emitted).toHaveLength(0);
170
- });
171
- });
172
- describe('GoToPrevious', () => {
173
- it('emits previous page', () => {
174
- comp.GoToPrevious();
175
- expect(emitted).toHaveLength(1);
176
- expect(emitted[0]).toEqual({ PageNumber: 2, PageSize: 10, StartRow: 10 });
177
- });
178
- it('does nothing on page 1', () => {
179
- comp.PageNumber = 1;
180
- comp.GoToPrevious();
181
- expect(emitted).toHaveLength(0);
182
- });
183
- });
184
- describe('GoToNext', () => {
185
- it('emits next page', () => {
186
- comp.GoToNext();
187
- expect(emitted).toHaveLength(1);
188
- expect(emitted[0]).toEqual({ PageNumber: 4, PageSize: 10, StartRow: 30 });
189
- });
190
- it('does nothing on last page', () => {
191
- comp.PageNumber = 5; // last page of 50/10
192
- comp.GoToNext();
193
- expect(emitted).toHaveLength(0);
194
- });
195
- });
196
- describe('GoToLast', () => {
197
- it('emits last page', () => {
198
- comp.GoToLast();
199
- expect(emitted).toHaveLength(1);
200
- expect(emitted[0]).toEqual({ PageNumber: 5, PageSize: 10, StartRow: 40 });
201
- });
202
- it('does nothing when already on last page', () => {
203
- comp.PageNumber = 5;
204
- comp.GoToLast();
205
- expect(emitted).toHaveLength(0);
206
- });
207
- });
208
- });
209
- // ------------------------------------------------------------ PageChangeEvent shape
210
- describe('PageChangeEvent', () => {
211
- it('StartRow is always (PageNumber - 1) * PageSize', () => {
212
- const comp = createComponent({ TotalRowCount: 500, PageNumber: 1, PageSize: 25 });
213
- const events = [];
214
- comp.PageChange.subscribe((e) => events.push(e));
215
- comp.GoToNext(); // page 2
216
- expect(events[0].StartRow).toBe(25);
217
- comp.PageNumber = 10;
218
- comp.GoToNext(); // page 11
219
- expect(events[1].StartRow).toBe(250);
220
- });
221
- it('carries the current PageSize', () => {
222
- const comp = createComponent({ TotalRowCount: 100, PageNumber: 1, PageSize: 42 });
223
- const events = [];
224
- comp.PageChange.subscribe((e) => events.push(e));
225
- comp.GoToNext();
226
- expect(events[0].PageSize).toBe(42);
227
- });
228
- });
229
- // ----------------------------------------------------------------- Edge cases
230
- describe('Edge cases', () => {
231
- it('does not emit when IsLoading blocks all navigation', () => {
232
- const comp = createComponent({ TotalRowCount: 100, PageNumber: 3, PageSize: 10, IsLoading: true });
233
- const events = [];
234
- comp.PageChange.subscribe((e) => events.push(e));
235
- comp.GoToFirst();
236
- comp.GoToPrevious();
237
- comp.GoToNext();
238
- comp.GoToLast();
239
- expect(events).toHaveLength(0);
240
- });
241
- it('handles PageSize=1 navigation correctly', () => {
242
- const comp = createComponent({ TotalRowCount: 3, PageNumber: 2, PageSize: 1 });
243
- expect(comp.TotalPages).toBe(3);
244
- expect(comp.DisplayFrom).toBe(2);
245
- expect(comp.DisplayTo).toBe(2);
246
- expect(comp.CanGoBack).toBe(true);
247
- expect(comp.CanGoForward).toBe(true);
248
- });
249
- it('works with very large PageSize', () => {
250
- const comp = createComponent({ TotalRowCount: 5, PageNumber: 1, PageSize: 10000 });
251
- expect(comp.TotalPages).toBe(1);
252
- expect(comp.DisplayFrom).toBe(1);
253
- expect(comp.DisplayTo).toBe(5);
254
- expect(comp.CanGoForward).toBe(false);
255
- });
256
- });
257
- });
258
- //# sourceMappingURL=pagination.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pagination.test.js","sourceRoot":"","sources":["../../src/__tests__/pagination.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect, vi, beforeEach } from 'vitest';\n\n/**\n * We test PaginationComponent as a plain TypeScript class.\n * Angular decorators are no-ops at test time; we only exercise the pure logic.\n */\n\n// Minimal stub so the @Component / @Input / @Output decorators don't explode at import time.\nvi.mock('@angular/core', () => ({\n Component: () => () => {},\n Input: () => () => {},\n Output: () => () => {},\n EventEmitter: class<T = unknown> {\n private listeners: ((value: T) => void)[] = [];\n emit(value: T): void {\n for (const fn of this.listeners) fn(value);\n }\n subscribe(fn: (value: T) => void): { unsubscribe: () => void } {\n this.listeners.push(fn);\n return { unsubscribe: () => { this.listeners = this.listeners.filter(l => l !== fn); } };\n }\n },\n}));\nvi.mock('@angular/common', () => ({ CommonModule: {} }));\n\nimport { PaginationComponent, PageChangeEvent } from '../lib/pagination.component';\n\nfunction createComponent(overrides: Partial<Pick<PaginationComponent, 'TotalRowCount' | 'PageNumber' | 'PageSize' | 'IsLoading'>> = {}): PaginationComponent {\n const c = new PaginationComponent();\n if (overrides.TotalRowCount !== undefined) c.TotalRowCount = overrides.TotalRowCount;\n if (overrides.PageNumber !== undefined) c.PageNumber = overrides.PageNumber;\n if (overrides.PageSize !== undefined) c.PageSize = overrides.PageSize;\n if (overrides.IsLoading !== undefined) c.IsLoading = overrides.IsLoading;\n return c;\n}\n\ndescribe('PaginationComponent', () => {\n // ------------------------------------------------------------------ TotalPages\n describe('TotalPages', () => {\n it('returns 0 when TotalRowCount is 0', () => {\n const c = createComponent({ TotalRowCount: 0, PageSize: 10 });\n expect(c.TotalPages).toBe(0);\n });\n\n it('returns 0 when TotalRowCount is negative', () => {\n const c = createComponent({ TotalRowCount: -5, PageSize: 10 });\n expect(c.TotalPages).toBe(0);\n });\n\n it('returns 0 when PageSize is 0', () => {\n const c = createComponent({ TotalRowCount: 50, PageSize: 0 });\n expect(c.TotalPages).toBe(0);\n });\n\n it('returns 0 when PageSize is negative', () => {\n const c = createComponent({ TotalRowCount: 50, PageSize: -1 });\n expect(c.TotalPages).toBe(0);\n });\n\n it('returns 1 when rows fit exactly in one page', () => {\n const c = createComponent({ TotalRowCount: 10, PageSize: 10 });\n expect(c.TotalPages).toBe(1);\n });\n\n it('rounds up for partial last page', () => {\n const c = createComponent({ TotalRowCount: 11, PageSize: 10 });\n expect(c.TotalPages).toBe(2);\n });\n\n it('handles large datasets', () => {\n const c = createComponent({ TotalRowCount: 1_000_000, PageSize: 100 });\n expect(c.TotalPages).toBe(10_000);\n });\n\n it('handles PageSize=1', () => {\n const c = createComponent({ TotalRowCount: 5, PageSize: 1 });\n expect(c.TotalPages).toBe(5);\n });\n\n it('handles single row with default PageSize', () => {\n const c = createComponent({ TotalRowCount: 1 });\n expect(c.TotalPages).toBe(1);\n });\n });\n\n // ---------------------------------------------------------- DisplayFrom / DisplayTo\n describe('DisplayFrom', () => {\n it('returns 0 when TotalRowCount is 0', () => {\n const c = createComponent({ TotalRowCount: 0 });\n expect(c.DisplayFrom).toBe(0);\n });\n\n it('returns 1 on the first page', () => {\n const c = createComponent({ TotalRowCount: 50, PageNumber: 1, PageSize: 10 });\n expect(c.DisplayFrom).toBe(1);\n });\n\n it('returns correct start for second page', () => {\n const c = createComponent({ TotalRowCount: 50, PageNumber: 2, PageSize: 10 });\n expect(c.DisplayFrom).toBe(11);\n });\n\n it('returns correct start for last page', () => {\n const c = createComponent({ TotalRowCount: 25, PageNumber: 3, PageSize: 10 });\n expect(c.DisplayFrom).toBe(21);\n });\n });\n\n describe('DisplayTo', () => {\n it('returns 0 when TotalRowCount is 0', () => {\n const c = createComponent({ TotalRowCount: 0, PageSize: 10 });\n expect(c.DisplayTo).toBe(0);\n });\n\n it('caps at TotalRowCount on last partial page', () => {\n const c = createComponent({ TotalRowCount: 25, PageNumber: 3, PageSize: 10 });\n expect(c.DisplayTo).toBe(25);\n });\n\n it('equals PageSize * PageNumber on a full page', () => {\n const c = createComponent({ TotalRowCount: 50, PageNumber: 2, PageSize: 10 });\n expect(c.DisplayTo).toBe(20);\n });\n\n it('equals TotalRowCount on single-page dataset', () => {\n const c = createComponent({ TotalRowCount: 7, PageNumber: 1, PageSize: 10 });\n expect(c.DisplayTo).toBe(7);\n });\n });\n\n // -------------------------------------------------------- CanGoBack / CanGoForward\n describe('CanGoBack', () => {\n it('returns false on first page', () => {\n const c = createComponent({ TotalRowCount: 50, PageNumber: 1 });\n expect(c.CanGoBack).toBe(false);\n });\n\n it('returns true on page > 1', () => {\n const c = createComponent({ TotalRowCount: 50, PageNumber: 2, PageSize: 10 });\n expect(c.CanGoBack).toBe(true);\n });\n\n it('returns false when IsLoading even on page > 1', () => {\n const c = createComponent({ TotalRowCount: 50, PageNumber: 2, PageSize: 10, IsLoading: true });\n expect(c.CanGoBack).toBe(false);\n });\n });\n\n describe('CanGoForward', () => {\n it('returns false on last page', () => {\n const c = createComponent({ TotalRowCount: 20, PageNumber: 2, PageSize: 10 });\n expect(c.CanGoForward).toBe(false);\n });\n\n it('returns true when not on last page', () => {\n const c = createComponent({ TotalRowCount: 30, PageNumber: 2, PageSize: 10 });\n expect(c.CanGoForward).toBe(true);\n });\n\n it('returns false when IsLoading even if not on last page', () => {\n const c = createComponent({ TotalRowCount: 30, PageNumber: 1, PageSize: 10, IsLoading: true });\n expect(c.CanGoForward).toBe(false);\n });\n\n it('returns false when TotalRowCount is 0', () => {\n const c = createComponent({ TotalRowCount: 0, PageNumber: 1, PageSize: 10 });\n expect(c.CanGoForward).toBe(false);\n });\n\n it('returns false on single-page dataset', () => {\n const c = createComponent({ TotalRowCount: 5, PageNumber: 1, PageSize: 10 });\n expect(c.CanGoForward).toBe(false);\n });\n });\n\n // ----------------------------------------------------------------- Navigation\n describe('Navigation methods', () => {\n let comp: PaginationComponent;\n let emitted: PageChangeEvent[];\n\n beforeEach(() => {\n comp = createComponent({ TotalRowCount: 50, PageNumber: 3, PageSize: 10 });\n emitted = [];\n comp.PageChange.subscribe((e: PageChangeEvent) => emitted.push(e));\n });\n\n describe('GoToFirst', () => {\n it('emits page 1 when CanGoBack is true', () => {\n comp.GoToFirst();\n expect(emitted).toHaveLength(1);\n expect(emitted[0]).toEqual({ PageNumber: 1, PageSize: 10, StartRow: 0 });\n });\n\n it('does nothing on page 1', () => {\n comp.PageNumber = 1;\n comp.GoToFirst();\n expect(emitted).toHaveLength(0);\n });\n });\n\n describe('GoToPrevious', () => {\n it('emits previous page', () => {\n comp.GoToPrevious();\n expect(emitted).toHaveLength(1);\n expect(emitted[0]).toEqual({ PageNumber: 2, PageSize: 10, StartRow: 10 });\n });\n\n it('does nothing on page 1', () => {\n comp.PageNumber = 1;\n comp.GoToPrevious();\n expect(emitted).toHaveLength(0);\n });\n });\n\n describe('GoToNext', () => {\n it('emits next page', () => {\n comp.GoToNext();\n expect(emitted).toHaveLength(1);\n expect(emitted[0]).toEqual({ PageNumber: 4, PageSize: 10, StartRow: 30 });\n });\n\n it('does nothing on last page', () => {\n comp.PageNumber = 5; // last page of 50/10\n comp.GoToNext();\n expect(emitted).toHaveLength(0);\n });\n });\n\n describe('GoToLast', () => {\n it('emits last page', () => {\n comp.GoToLast();\n expect(emitted).toHaveLength(1);\n expect(emitted[0]).toEqual({ PageNumber: 5, PageSize: 10, StartRow: 40 });\n });\n\n it('does nothing when already on last page', () => {\n comp.PageNumber = 5;\n comp.GoToLast();\n expect(emitted).toHaveLength(0);\n });\n });\n });\n\n // ------------------------------------------------------------ PageChangeEvent shape\n describe('PageChangeEvent', () => {\n it('StartRow is always (PageNumber - 1) * PageSize', () => {\n const comp = createComponent({ TotalRowCount: 500, PageNumber: 1, PageSize: 25 });\n const events: PageChangeEvent[] = [];\n comp.PageChange.subscribe((e: PageChangeEvent) => events.push(e));\n\n comp.GoToNext(); // page 2\n expect(events[0].StartRow).toBe(25);\n\n comp.PageNumber = 10;\n comp.GoToNext(); // page 11\n expect(events[1].StartRow).toBe(250);\n });\n\n it('carries the current PageSize', () => {\n const comp = createComponent({ TotalRowCount: 100, PageNumber: 1, PageSize: 42 });\n const events: PageChangeEvent[] = [];\n comp.PageChange.subscribe((e: PageChangeEvent) => events.push(e));\n\n comp.GoToNext();\n expect(events[0].PageSize).toBe(42);\n });\n });\n\n // ----------------------------------------------------------------- Edge cases\n describe('Edge cases', () => {\n it('does not emit when IsLoading blocks all navigation', () => {\n const comp = createComponent({ TotalRowCount: 100, PageNumber: 3, PageSize: 10, IsLoading: true });\n const events: PageChangeEvent[] = [];\n comp.PageChange.subscribe((e: PageChangeEvent) => events.push(e));\n\n comp.GoToFirst();\n comp.GoToPrevious();\n comp.GoToNext();\n comp.GoToLast();\n expect(events).toHaveLength(0);\n });\n\n it('handles PageSize=1 navigation correctly', () => {\n const comp = createComponent({ TotalRowCount: 3, PageNumber: 2, PageSize: 1 });\n expect(comp.TotalPages).toBe(3);\n expect(comp.DisplayFrom).toBe(2);\n expect(comp.DisplayTo).toBe(2);\n expect(comp.CanGoBack).toBe(true);\n expect(comp.CanGoForward).toBe(true);\n });\n\n it('works with very large PageSize', () => {\n const comp = createComponent({ TotalRowCount: 5, PageNumber: 1, PageSize: 10000 });\n expect(comp.TotalPages).toBe(1);\n expect(comp.DisplayFrom).toBe(1);\n expect(comp.DisplayTo).toBe(5);\n expect(comp.CanGoForward).toBe(false);\n });\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=pagination.component.dom.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pagination.component.dom.test.d.ts","sourceRoot":"","sources":["../../src/lib/pagination.component.dom.test.ts"],"names":[],"mappings":""}
@@ -1,92 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest';
2
- import { TestBed } from '@angular/core/testing';
3
- import { PaginationComponent } from './pagination.component';
4
- /**
5
- * DOM-level spec for `<mj-pagination>`. The component's whole reason to exist is
6
- * template gating + click wiring:
7
- * - it renders nothing unless there is more than one page,
8
- * - first/prev are disabled on page 1, next/last on the last page,
9
- * - clicking a nav button emits a `PageChange` with the right StartRow.
10
- *
11
- * None of that is observable from the class alone — these assertions drive the
12
- * rendered buttons and read the emitted `@Output`.
13
- */
14
- describe('PaginationComponent (DOM)', () => {
15
- function render(setup) {
16
- const fixture = TestBed.createComponent(PaginationComponent);
17
- setup(fixture.componentInstance);
18
- fixture.detectChanges();
19
- return { fixture, host: fixture.nativeElement };
20
- }
21
- function buttonByTitle(host, title) {
22
- const btn = host.querySelector(`button[title="${title}"]`);
23
- if (!btn)
24
- throw new Error(`No pager button with title="${title}"`);
25
- return btn;
26
- }
27
- it('renders nothing when there is a single page of data', () => {
28
- const { host } = render((c) => {
29
- c.TotalRowCount = 50;
30
- c.PageSize = 100;
31
- c.PageNumber = 1;
32
- });
33
- expect(host.querySelector('.pagination')).toBeNull();
34
- });
35
- it('renders the pager and a "from-to of total" summary across multiple pages', () => {
36
- const { host } = render((c) => {
37
- c.TotalRowCount = 250;
38
- c.PageSize = 100;
39
- c.PageNumber = 2;
40
- });
41
- expect(host.querySelector('.pagination')).not.toBeNull();
42
- // DisplayFrom = 101, DisplayTo = 200, total 250 (formatted with the number pipe).
43
- expect(host.querySelector('.pager-summary')?.textContent?.replace(/\s+/g, ' ').trim()).toBe('101-200 of 250');
44
- expect(host.querySelector('.pager-page-info')?.textContent?.replace(/\s+/g, ' ').trim()).toBe('Page 2 of 3');
45
- });
46
- it('disables first/prev on the first page and enables next/last', () => {
47
- const { host } = render((c) => {
48
- c.TotalRowCount = 250;
49
- c.PageSize = 100;
50
- c.PageNumber = 1;
51
- });
52
- expect(buttonByTitle(host, 'First page').disabled).toBe(true);
53
- expect(buttonByTitle(host, 'Previous page').disabled).toBe(true);
54
- expect(buttonByTitle(host, 'Next page').disabled).toBe(false);
55
- expect(buttonByTitle(host, 'Last page').disabled).toBe(false);
56
- });
57
- it('emits PageChange with the correct StartRow when Next is clicked', () => {
58
- const events = [];
59
- const { fixture, host } = render((c) => {
60
- c.TotalRowCount = 250;
61
- c.PageSize = 100;
62
- c.PageNumber = 1;
63
- });
64
- fixture.componentInstance.PageChange.subscribe((e) => events.push(e));
65
- buttonByTitle(host, 'Next page').click();
66
- expect(events).toEqual([{ PageNumber: 2, PageSize: 100, StartRow: 100 }]);
67
- });
68
- it('does not emit when a disabled button is clicked', () => {
69
- const spy = vi.fn();
70
- const { fixture, host } = render((c) => {
71
- c.TotalRowCount = 250;
72
- c.PageSize = 100;
73
- c.PageNumber = 1;
74
- });
75
- fixture.componentInstance.PageChange.subscribe(spy);
76
- // Previous is disabled on page 1; clicking the disabled button must be a no-op.
77
- buttonByTitle(host, 'Previous page').click();
78
- expect(spy).not.toHaveBeenCalled();
79
- });
80
- it('shows the loading spinner and disables navigation while IsLoading', () => {
81
- const { host } = render((c) => {
82
- c.TotalRowCount = 250;
83
- c.PageSize = 100;
84
- c.PageNumber = 2;
85
- c.IsLoading = true;
86
- });
87
- expect(host.querySelector('.pager-loading')).not.toBeNull();
88
- expect(buttonByTitle(host, 'Next page').disabled).toBe(true);
89
- expect(buttonByTitle(host, 'Previous page').disabled).toBe(true);
90
- });
91
- });
92
- //# sourceMappingURL=pagination.component.dom.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pagination.component.dom.test.js","sourceRoot":"","sources":["../../src/lib/pagination.component.dom.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect, vi } from 'vitest';\nimport { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { PaginationComponent, PageChangeEvent } from './pagination.component';\n\n/**\n * DOM-level spec for `<mj-pagination>`. The component's whole reason to exist is\n * template gating + click wiring:\n * - it renders nothing unless there is more than one page,\n * - first/prev are disabled on page 1, next/last on the last page,\n * - clicking a nav button emits a `PageChange` with the right StartRow.\n *\n * None of that is observable from the class alone — these assertions drive the\n * rendered buttons and read the emitted `@Output`.\n */\ndescribe('PaginationComponent (DOM)', () => {\n function render(\n setup: (c: PaginationComponent) => void,\n ): { fixture: ComponentFixture<PaginationComponent>; host: HTMLElement } {\n const fixture = TestBed.createComponent(PaginationComponent);\n setup(fixture.componentInstance);\n fixture.detectChanges();\n return { fixture, host: fixture.nativeElement as HTMLElement };\n }\n\n function buttonByTitle(host: HTMLElement, title: string): HTMLButtonElement {\n const btn = host.querySelector(`button[title=\"${title}\"]`) as HTMLButtonElement | null;\n if (!btn) throw new Error(`No pager button with title=\"${title}\"`);\n return btn;\n }\n\n it('renders nothing when there is a single page of data', () => {\n const { host } = render((c) => {\n c.TotalRowCount = 50;\n c.PageSize = 100;\n c.PageNumber = 1;\n });\n expect(host.querySelector('.pagination')).toBeNull();\n });\n\n it('renders the pager and a \"from-to of total\" summary across multiple pages', () => {\n const { host } = render((c) => {\n c.TotalRowCount = 250;\n c.PageSize = 100;\n c.PageNumber = 2;\n });\n expect(host.querySelector('.pagination')).not.toBeNull();\n // DisplayFrom = 101, DisplayTo = 200, total 250 (formatted with the number pipe).\n expect(host.querySelector('.pager-summary')?.textContent?.replace(/\\s+/g, ' ').trim()).toBe(\n '101-200 of 250',\n );\n expect(host.querySelector('.pager-page-info')?.textContent?.replace(/\\s+/g, ' ').trim()).toBe(\n 'Page 2 of 3',\n );\n });\n\n it('disables first/prev on the first page and enables next/last', () => {\n const { host } = render((c) => {\n c.TotalRowCount = 250;\n c.PageSize = 100;\n c.PageNumber = 1;\n });\n expect(buttonByTitle(host, 'First page').disabled).toBe(true);\n expect(buttonByTitle(host, 'Previous page').disabled).toBe(true);\n expect(buttonByTitle(host, 'Next page').disabled).toBe(false);\n expect(buttonByTitle(host, 'Last page').disabled).toBe(false);\n });\n\n it('emits PageChange with the correct StartRow when Next is clicked', () => {\n const events: PageChangeEvent[] = [];\n const { fixture, host } = render((c) => {\n c.TotalRowCount = 250;\n c.PageSize = 100;\n c.PageNumber = 1;\n });\n fixture.componentInstance.PageChange.subscribe((e) => events.push(e));\n\n buttonByTitle(host, 'Next page').click();\n\n expect(events).toEqual([{ PageNumber: 2, PageSize: 100, StartRow: 100 }]);\n });\n\n it('does not emit when a disabled button is clicked', () => {\n const spy = vi.fn();\n const { fixture, host } = render((c) => {\n c.TotalRowCount = 250;\n c.PageSize = 100;\n c.PageNumber = 1;\n });\n fixture.componentInstance.PageChange.subscribe(spy);\n\n // Previous is disabled on page 1; clicking the disabled button must be a no-op.\n buttonByTitle(host, 'Previous page').click();\n\n expect(spy).not.toHaveBeenCalled();\n });\n\n it('shows the loading spinner and disables navigation while IsLoading', () => {\n const { host } = render((c) => {\n c.TotalRowCount = 250;\n c.PageSize = 100;\n c.PageNumber = 2;\n c.IsLoading = true;\n });\n expect(host.querySelector('.pager-loading')).not.toBeNull();\n expect(buttonByTitle(host, 'Next page').disabled).toBe(true);\n expect(buttonByTitle(host, 'Previous page').disabled).toBe(true);\n });\n});\n"]}