8 * Check that the active prev-next service behaves as expected.
13 class PrevNextTest
extends \CiviEndToEndTestCase
{
26 * @var \CRM_Core_PrevNextCache_Interface
30 protected function setUp() {
32 $this->prevNext
= \Civi
::service('prevnext');
33 $this->cacheKey
= 'PrevNextTest_' . \CRM_Utils_String
::createRandom(16, \CRM_Utils_String
::ALPHANUMERIC
);
34 $this->cacheKeyB
= 'PrevNextTestb_' . \CRM_Utils_String
::createRandom(16, \CRM_Utils_String
::ALPHANUMERIC
);
36 \CRM_Core_DAO
::singleValueQuery('SELECT count(*) FROM civicrm_contact') > 25,
37 'The contact table must have at least 25 records.'
41 protected function tearDown() {
42 \Civi
::service('prevnext')->deleteItem(NULL, $this->cacheKey
);
43 \Civi
::service('prevnext')->deleteItem(NULL, $this->cacheKeyB
);
46 public function testFillSql() {
51 $query = new \
CRM_Contact_BAO_Query([['sort_name', 'IS NOT NULL', 1, 0, 0]], NULL, NULL, FALSE, FALSE, 1, FALSE, TRUE, FALSE, NULL, 'AND');
52 $sql = $query->searchQuery($start, $prefillLimit, $sort, FALSE, $query->_includeContactIds
,
54 $selectSQL = "SELECT DISTINCT %1, contact_a.id, contact_a.sort_name";
55 $sql = str_replace(array("SELECT contact_a.id as contact_id", "SELECT contact_a.id as id"), $selectSQL, $sql);
58 $this->prevNext
->fillWithSql($this->cacheKey
, $sql, [1 => [$this->cacheKey
, 'String']]),
59 "fillWithSql should return TRUE on success"
62 $this->assertEquals(25, $this->prevNext
->getCount($this->cacheKey
));
63 $this->assertEquals(0, $this->prevNext
->getCount('not-a-key-' . $this->cacheKey
));
65 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
66 $this->assertCount($prefillLimit, $all);
67 $this->assertCount($prefillLimit, array_unique(array_keys($all)));
68 $this->assertEquals([1], array_unique(array_values($all)));
70 $this->assertSelections([]);
73 public function testFillArray() {
75 ['entity_id1' => 100, 'data' => 'Alice'],
76 ['entity_id1' => 400, 'data' => 'Bob'],
77 ['entity_id1' => 200, 'data' => 'Carol'],
80 ['entity_id1' => 300, 'data' => 'Dave'],
84 $this->prevNext
->fillWithArray($this->cacheKey
, $rowSetA),
85 "fillWithArray should return TRUE on success"
88 $this->prevNext
->fillWithArray($this->cacheKey
, $rowSetB),
89 "fillWithArray should return TRUE on success"
92 $this->assertEquals(4, $this->prevNext
->getCount($this->cacheKey
));
93 $this->assertEquals(0, $this->prevNext
->getCount('not-a-key-' . $this->cacheKey
));
95 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
96 $this->assertEquals([100, 400, 200, 300], array_keys($all));
97 $this->assertEquals([1], array_unique(array_values($all)));
99 $this->assertSelections([]);
102 public function testFetch() {
103 $this->testFillArray();
105 $cids = $this->prevNext
->fetch($this->cacheKey
, 0, 2);
106 $this->assertEquals([100, 400], $cids);
108 $cids = $this->prevNext
->fetch($this->cacheKey
, 0, 4);
109 $this->assertEquals([100, 400, 200, 300], $cids);
111 $cids = $this->prevNext
->fetch($this->cacheKey
, 2, 2);
112 $this->assertEquals([200, 300], $cids);
115 public function getFillFunctions() {
123 * Select and unselect one item.
125 * @dataProvider getFillFunctions
127 public function testMarkSelection_1($fillFunction) {
128 call_user_func([$this, $fillFunction]);
130 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
131 list ($id1, $id2) = array_keys($all);
132 $this->prevNext
->markSelection($this->cacheKey
, 'select', $id1);
134 $this->assertSelections([$id1]);
136 $this->prevNext
->markSelection($this->cacheKey
, 'unselect', $id1);
137 $this->assertSelections([]);
141 * Select and unselect two items.
143 * @dataProvider getFillFunctions
145 public function testMarkSelection_2($fillFunction) {
146 call_user_func([$this, $fillFunction]);
148 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
149 list ($id1, $id2, $id3) = array_keys($all);
151 $this->prevNext
->markSelection($this->cacheKey
, 'select', [$id1, $id3]);
152 $this->assertSelections([$id1, $id3]);
154 $this->prevNext
->markSelection($this->cacheKey
, 'unselect', $id1);
155 $this->assertSelections([$id3]);
157 $this->prevNext
->markSelection($this->cacheKey
, 'select', $id2);
158 $this->assertSelections([$id2, $id3]);
160 $this->prevNext
->markSelection($this->cacheKey
, 'unselect');
161 $this->assertSelections([]);
165 * Check the neighbors of the first item.
167 * @dataProvider getFillFunctions
169 public function testGetPosition_first($fillFunction) {
170 call_user_func([$this, $fillFunction]);
172 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
173 list ($id1, $id2, $id3) = array_keys($all);
175 $pos = $this->prevNext
->getPositions($this->cacheKey
, $id1);
177 $this->assertTrue((bool) $pos['foundEntry']);
179 $this->assertEquals($id2, $pos['next']['id1']);
180 $this->assertTrue(!empty($pos['next']['data']));
182 $this->assertTrue(!isset($pos['prev']));
186 * Check the neighbors of a middle item.
188 * @dataProvider getFillFunctions
190 public function testGetPosition_middle($fillFunction) {
191 call_user_func([$this, $fillFunction]);
193 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
194 list ($id1, $id2, $id3) = array_keys($all);
196 $pos = $this->prevNext
->getPositions($this->cacheKey
, $id2);
197 $this->assertTrue((bool) $pos['foundEntry']);
199 $this->assertEquals($id3, $pos['next']['id1']);
200 $this->assertTrue(!empty($pos['next']['data']));
202 $this->assertEquals($id1, $pos['prev']['id1']);
203 $this->assertTrue(!empty($pos['prev']['data']));
207 * Check the neighbors of the last item.
209 * @dataProvider getFillFunctions
211 public function testGetPosition_last($fillFunction) {
212 call_user_func([$this, $fillFunction]);
214 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
215 list ($idLast, $idPrev) = array_reverse(array_keys($all));
217 $pos = $this->prevNext
->getPositions($this->cacheKey
, $idLast);
218 $this->assertTrue((bool) $pos['foundEntry']);
220 $this->assertTrue(!isset($pos['next']));
222 $this->assertEquals($idPrev, $pos['prev']['id1']);
223 $this->assertTrue(!empty($pos['prev']['data']));
227 * Check the neighbors of the last item.
229 * @dataProvider getFillFunctions
231 public function testGetPosition_invalid($fillFunction) {
232 call_user_func([$this, $fillFunction]);
234 $pos = $this->prevNext
->getPositions($this->cacheKey
, 99999999);
235 $this->assertFalse((bool) $pos['foundEntry']);
236 $this->assertTrue(!isset($pos['next']));
237 $this->assertTrue(!isset($pos['prev']));
240 public function testDeleteByCacheKey() {
241 // Add background data
242 $this->prevNext
->fillWithArray($this->cacheKeyB
, [
243 ['entity_id1' => 100, 'data' => 'Alice'],
244 ['entity_id1' => 150, 'data' => 'Dave'],
246 $this->prevNext
->markSelection($this->cacheKeyB
, 'select', 100);
247 $this->assertSelections([100], 'get', $this->cacheKeyB
);
248 $this->assertSelections([100, 150], 'getall', $this->cacheKeyB
);
250 // Add some data that we're actually working with.
251 $this->testFillArray();
253 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
254 $this->assertEquals([100, 400, 200, 300], array_keys($all));
256 list ($id1, $id2, $id3) = array_keys($all);
257 $this->prevNext
->markSelection($this->cacheKey
, 'select', [$id1, $id3]);
258 $this->assertSelections([$id1, $id3]);
260 $this->prevNext
->deleteItem(NULL, $this->cacheKey
);
261 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
262 $this->assertEquals([], array_keys($all));
263 $this->assertSelections([]);
265 // Ensure background data was untouched.
266 $this->assertSelections([100], 'get', $this->cacheKeyB
);
267 $this->assertSelections([100, 150], 'getall', $this->cacheKeyB
);
270 public function testDeleteByEntityId() {
272 $this->prevNext
->fillWithArray($this->cacheKey
, [
273 ['entity_id1' => 100, 'data' => 'Alice'],
274 ['entity_id1' => 150, 'data' => 'Dave'],
276 $this->prevNext
->markSelection($this->cacheKey
, 'select', 100);
277 $this->assertSelections([100], 'get', $this->cacheKey
);
278 $this->assertSelections([100, 150], 'getall', $this->cacheKey
);
280 $this->prevNext
->fillWithArray($this->cacheKeyB
, [
281 ['entity_id1' => 100, 'data' => 'Alice'],
282 ['entity_id1' => 400, 'data' => 'Bob'],
284 $this->prevNext
->markSelection($this->cacheKeyB
, 'select', [100, 400]);
285 $this->assertSelections([100, 400], 'get', $this->cacheKeyB
);
286 $this->assertSelections([100, 400], 'getall', $this->cacheKeyB
);
289 $this->prevNext
->deleteItem(100);
290 $this->assertSelections([], 'get', $this->cacheKey
);
291 $this->assertSelections([150], 'getall', $this->cacheKey
);
292 $this->assertSelections([400], 'get', $this->cacheKeyB
);
293 $this->assertSelections([400], 'getall', $this->cacheKeyB
);
296 public function testDeleteAll() {
298 $this->prevNext
->fillWithArray($this->cacheKey
, [
299 ['entity_id1' => 100, 'data' => 'Alice'],
300 ['entity_id1' => 150, 'data' => 'Dave'],
302 $this->prevNext
->markSelection($this->cacheKey
, 'select', 100);
303 $this->assertSelections([100], 'get', $this->cacheKey
);
304 $this->assertSelections([100, 150], 'getall', $this->cacheKey
);
306 $this->prevNext
->fillWithArray($this->cacheKeyB
, [
307 ['entity_id1' => 100, 'data' => 'Alice'],
308 ['entity_id1' => 400, 'data' => 'Bob'],
310 $this->prevNext
->markSelection($this->cacheKeyB
, 'select', [100, 400]);
311 $this->assertSelections([100, 400], 'get', $this->cacheKeyB
);
312 $this->assertSelections([100, 400], 'getall', $this->cacheKeyB
);
315 $this->prevNext
->deleteItem(NULL, NULL);
316 $this->assertSelections([], 'get', $this->cacheKey
);
317 $this->assertSelections([], 'getall', $this->cacheKey
);
318 $this->assertSelections([], 'get', $this->cacheKeyB
);
319 $this->assertSelections([], 'getall', $this->cacheKeyB
);
323 * Assert that the current cacheKey has a list of selected contact IDs.
326 * Contact IDs that should be selected.
327 * @param string $action
328 * @param string|NULL $cacheKey
330 protected function assertSelections($ids, $action = 'get', $cacheKey = NULL) {
331 if ($cacheKey === NULL) {
332 $cacheKey = $this->cacheKey
;
334 $selected = $this->prevNext
->getSelection($cacheKey, $action)[$cacheKey];
335 $this->assertEquals($ids, array_keys($selected), 'selected cache not correct for ' . $cacheKey . 'defined keys are ' . $this->cacheKey
. 'and ' . $this->cacheKeyB
);
336 $this->assertCount(count($ids), $selected);