1<?php 2 3namespace dokuwiki\plugin\acknowledge\test; 4 5use DokuWikiTest; 6 7/** 8 * Tests for the acknowledgement statistics aggregation 9 * (helper_plugin_acknowledge::getStatistics). 10 * 11 * Verifies the per-namespace and wiki-wide completion counts, @group expansion, 12 * and the current-vs-outdated semantics. 13 * 14 * @group plugin_acknowledge 15 * @group plugins 16 */ 17class StatsTest extends DokuWikiTest 18{ 19 /** @var array */ 20 protected $pluginsEnabled = ['acknowledge', 'sqlite']; 21 22 /** @var \helper_plugin_acknowledge */ 23 protected $helper; 24 25 public static function setUpBeforeClass(): void 26 { 27 parent::setUpBeforeClass(); 28 /** @var \auth_plugin_authplain $auth */ 29 global $auth; 30 $auth->createUser('max', 'none', 'max', 'max@example.com', ['super']); 31 $auth->createUser('regular', 'none', 'regular', 'regular@example.com', ['user']); 32 } 33 34 public function setUp(): void 35 { 36 parent::setUp(); 37 $this->helper = plugin_load('helper', 'acknowledge'); 38 39 $db = $this->helper->getDB(); 40 41 // pages across two top-level namespaces (lastmod 1000), incl. a sub-namespace page 42 // that must roll up into its top-level namespace, plus a tracked page without assignees 43 $db->query( 44 "REPLACE INTO pages(page,lastmod) VALUES 45 ('stats1:a', 1000), 46 ('stats1:b', 1000), 47 ('stats1:sub:d', 1000), 48 ('stats2:c', 1000), 49 ('stats1:noassign', 1000)" 50 ); 51 52 // stats1:a -> required {regular, max(@super)}; regular current, max outdated 53 $this->helper->setPageAssignees('stats1:a', 'regular, @super'); 54 $this->helper->importAcknowledgement('stats1:a', 'regular', 2000); 55 $this->helper->importAcknowledgement('stats1:a', 'max', 500); 56 57 // stats1:b -> required {regular}; current -> fully acknowledged 58 $this->helper->setPageAssignees('stats1:b', 'regular'); 59 $this->helper->importAcknowledgement('stats1:b', 'regular', 2000); 60 61 // stats1:sub:d -> required {regular}; current -> fully acknowledged; rolls up into 'stats1' 62 $this->helper->setPageAssignees('stats1:sub:d', 'regular'); 63 $this->helper->importAcknowledgement('stats1:sub:d', 'regular', 2000); 64 65 // stats2:c -> required {max(@super)}; never acknowledged 66 $this->helper->setPageAssignees('stats2:c', '@super'); 67 } 68 69 /** 70 * Whole-wiki aggregation across both namespaces. 71 */ 72 public function testTotals() 73 { 74 $stats = $this->helper->getStatistics(); 75 76 self::assertEquals( 77 ['required' => 5, 'acked' => 3, 'pages' => 4], 78 $stats['total'] 79 ); 80 } 81 82 /** 83 * Root drill-down: pages are grouped by their top-level namespace, plus @group expansion, 84 * current-vs-outdated handling, and the haschildren flag for namespaces with deeper content. 85 */ 86 public function testNamespaceBreakdown() 87 { 88 $stats = $this->helper->getStatistics(); 89 $ns = $stats['namespaces']; 90 91 self::assertEquals( 92 ['required' => 4, 'acked' => 3, 'pages' => 3, 'haschildren' => true], 93 $ns['stats1'] 94 ); 95 96 self::assertEquals( 97 ['required' => 1, 'acked' => 0, 'pages' => 1, 'haschildren' => false], 98 $ns['stats2'] 99 ); 100 } 101 102 /** 103 * Pages without assignees are excluded from the statistics. 104 */ 105 public function testPageWithoutAssigneesExcluded() 106 { 107 $stats = $this->helper->getStatistics(); 108 109 // only stats1 and stats2 namespaces, noassign contributes nothing 110 self::assertEquals(['stats1', 'stats2'], array_keys($stats['namespaces'])); 111 self::assertSame(4, $stats['total']['pages']); 112 } 113 114 /** 115 * Drilling into a namespace groups pages by their immediate child namespace, while the 116 * total stays wiki-wide. 117 */ 118 public function testDrilldown() 119 { 120 $stats = $this->helper->getStatistics('stats1'); 121 122 // total is always the whole wiki, regardless of the drill-down namespace 123 self::assertEquals( 124 ['required' => 5, 'acked' => 3, 'pages' => 4], 125 $stats['total'] 126 ); 127 128 // within stats1: direct pages (a + b) group under 'stats1', the sub-namespace page 129 // groups under 'stats1:sub'; stats2 is out of scope 130 self::assertEquals(['stats1', 'stats1:sub'], array_keys($stats['namespaces'])); 131 132 // 'stats1' self group = direct pages a + b: required max+regular(a)+regular(b) = 3, 133 // acked regular(a)+regular(b) = 2; no pages deeper than stats1:* here -> haschildren false 134 self::assertEquals( 135 ['required' => 3, 'acked' => 2, 'pages' => 2, 'haschildren' => false], 136 $stats['namespaces']['stats1'] 137 ); 138 139 // 'stats1:sub' = page sub:d: required regular = 1, acked regular = 1 140 self::assertEquals( 141 ['required' => 1, 'acked' => 1, 'pages' => 1, 'haschildren' => false], 142 $stats['namespaces']['stats1:sub'] 143 ); 144 } 145} 146