@carlonicora/nextjs-jsonapi 1.96.0 → 1.97.1

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.
@@ -13,6 +13,7 @@ vi.mock("../../../hooks", async () => {
13
13
  useTableGenerator: vi.fn((_, params) => ({
14
14
  data: params.data.map((item: any, index: number) => ({
15
15
  ...item,
16
+ jsonApiData: item,
16
17
  _rowIndex: index,
17
18
  })),
18
19
  columns: [
@@ -332,9 +333,183 @@ describe("ContentListTable", () => {
332
333
 
333
334
  render(<ContentListTable data={dataRetriever} tableGeneratorType={mockModule as any} fields={["id", "title"]} />);
334
335
 
335
- // Should have navigation buttons in footer
336
336
  const buttons = screen.getAllByRole("button");
337
337
  expect(buttons.length).toBeGreaterThanOrEqual(2);
338
338
  });
339
339
  });
340
+
341
+ describe("grouping", () => {
342
+ it("should not group rows when groupBy is not provided", () => {
343
+ const dataRetriever = createMockDataRetriever({
344
+ data: [
345
+ { id: "1", title: "Article 1", category: "A" },
346
+ { id: "2", title: "Article 2", category: "B" },
347
+ { id: "3", title: "Article 3", category: "A" },
348
+ ],
349
+ });
350
+
351
+ render(<ContentListTable data={dataRetriever} tableGeneratorType={mockModule as any} fields={["id", "title"]} />);
352
+
353
+ expect(screen.getByText("Article 1")).toBeInTheDocument();
354
+ expect(screen.getByText("Article 2")).toBeInTheDocument();
355
+ expect(screen.getByText("Article 3")).toBeInTheDocument();
356
+ });
357
+
358
+ it("should group rows by attribute and show group headers", () => {
359
+ const dataRetriever = createMockDataRetriever({
360
+ data: [
361
+ { id: "1", title: "Article 1", category: "B" },
362
+ { id: "2", title: "Article 2", category: "A" },
363
+ { id: "3", title: "Article 3", category: "B" },
364
+ ],
365
+ });
366
+
367
+ render(
368
+ <ContentListTable
369
+ data={dataRetriever}
370
+ tableGeneratorType={mockModule as any}
371
+ fields={["id", "title"]}
372
+ groupBy="category"
373
+ />,
374
+ );
375
+
376
+ expect(screen.getByText("A")).toBeInTheDocument();
377
+ expect(screen.getByText("B")).toBeInTheDocument();
378
+ expect(screen.getByText("Article 1")).toBeInTheDocument();
379
+ expect(screen.getByText("Article 2")).toBeInTheDocument();
380
+ expect(screen.getByText("Article 3")).toBeInTheDocument();
381
+ });
382
+
383
+ it("should sort groups alphabetically", () => {
384
+ const dataRetriever = createMockDataRetriever({
385
+ data: [
386
+ { id: "1", title: "C Article", category: "C" },
387
+ { id: "2", title: "A Article", category: "A" },
388
+ { id: "3", title: "B Article", category: "B" },
389
+ ],
390
+ });
391
+
392
+ render(
393
+ <ContentListTable
394
+ data={dataRetriever}
395
+ tableGeneratorType={mockModule as any}
396
+ fields={["id", "title"]}
397
+ groupBy="category"
398
+ />,
399
+ );
400
+
401
+ const allCells = screen.getAllByRole("cell");
402
+ const texts = allCells.map((cell) => cell.textContent);
403
+ const groupIndices = ["A", "B", "C"].map((g) => texts.indexOf(g));
404
+ expect(groupIndices[0]).toBeLessThan(groupIndices[1]);
405
+ expect(groupIndices[1]).toBeLessThan(groupIndices[2]);
406
+ });
407
+
408
+ it("should group by relationship using the name property", () => {
409
+ const dataRetriever = createMockDataRetriever({
410
+ data: [
411
+ { id: "1", title: "Article 1", campaign: { id: "c1", name: "Campaign Alpha" } },
412
+ { id: "2", title: "Article 2", campaign: { id: "c2", name: "Campaign Beta" } },
413
+ { id: "3", title: "Article 3", campaign: { id: "c1", name: "Campaign Alpha" } },
414
+ ],
415
+ });
416
+
417
+ render(
418
+ <ContentListTable
419
+ data={dataRetriever}
420
+ tableGeneratorType={mockModule as any}
421
+ fields={["id", "title"]}
422
+ groupBy="campaign"
423
+ />,
424
+ );
425
+
426
+ expect(screen.getByText("Campaign Alpha")).toBeInTheDocument();
427
+ expect(screen.getByText("Campaign Beta")).toBeInTheDocument();
428
+ });
429
+
430
+ it("should handle null/undefined group values", () => {
431
+ const dataRetriever = createMockDataRetriever({
432
+ data: [
433
+ { id: "1", title: "Article 1", category: null },
434
+ { id: "2", title: "Article 2", category: "A" },
435
+ { id: "3", title: "Article 3", category: undefined },
436
+ ],
437
+ });
438
+
439
+ render(
440
+ <ContentListTable
441
+ data={dataRetriever}
442
+ tableGeneratorType={mockModule as any}
443
+ fields={["id", "title"]}
444
+ groupBy="category"
445
+ />,
446
+ );
447
+
448
+ expect(screen.getByText("A")).toBeInTheDocument();
449
+ const groupHeaders = screen
450
+ .getAllByRole("cell")
451
+ .filter((cell) => cell.textContent === "" && cell.classList.contains("bg-muted"));
452
+ expect(groupHeaders.length).toBeGreaterThanOrEqual(1);
453
+ });
454
+
455
+ it("should handle empty data with groupBy", () => {
456
+ const dataRetriever = createMockDataRetriever({ data: [] });
457
+
458
+ render(
459
+ <ContentListTable
460
+ data={dataRetriever}
461
+ tableGeneratorType={mockModule as any}
462
+ fields={["id", "title"]}
463
+ groupBy="category"
464
+ />,
465
+ );
466
+
467
+ expect(screen.getByText("No results.")).toBeInTheDocument();
468
+ });
469
+
470
+ it("should group by to-many relationship, duplicating rows across groups", () => {
471
+ const dataRetriever = createMockDataRetriever({
472
+ data: [
473
+ {
474
+ id: "1",
475
+ title: "Article 1",
476
+ tags: [
477
+ { id: "t1", name: "Alpha" },
478
+ { id: "t2", name: "Beta" },
479
+ ],
480
+ },
481
+ { id: "2", title: "Article 2", tags: [{ id: "t1", name: "Alpha" }] },
482
+ {
483
+ id: "3",
484
+ title: "Article 3",
485
+ tags: [
486
+ { id: "t2", name: "Beta" },
487
+ { id: "t3", name: "Gamma" },
488
+ ],
489
+ },
490
+ ],
491
+ });
492
+
493
+ render(
494
+ <ContentListTable
495
+ data={dataRetriever}
496
+ tableGeneratorType={mockModule as any}
497
+ fields={["id", "title"]}
498
+ groupBy="tags"
499
+ />,
500
+ );
501
+
502
+ expect(screen.getByText("Alpha")).toBeInTheDocument();
503
+ expect(screen.getByText("Beta")).toBeInTheDocument();
504
+ expect(screen.getByText("Gamma")).toBeInTheDocument();
505
+
506
+ const allText = screen.getAllByRole("cell").map((c) => c.textContent);
507
+ const article1Count = allText.filter((t) => t === "Article 1").length;
508
+ expect(article1Count).toBe(2);
509
+ const article2Count = allText.filter((t) => t === "Article 2").length;
510
+ expect(article2Count).toBe(1);
511
+ const article3Count = allText.filter((t) => t === "Article 3").length;
512
+ expect(article3Count).toBe(2);
513
+ });
514
+ });
340
515
  });