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->assertSelections([100, 400, 200, 300], 'getall', $this->cacheKey
);
96 $this->assertEquals([1], array_unique(array_values($all)));
98 $this->assertSelections([], 'get', $this->cacheKey
);
101 public function testFetch() {
102 $this->testFillArray();
104 $cids = $this->prevNext
->fetch($this->cacheKey
, 0, 2);
105 $this->assertEquals([100, 400], $cids);
107 $cids = $this->prevNext
->fetch($this->cacheKey
, 0, 4);
108 $this->assertEquals([100, 400, 200, 300], $cids);
110 $cids = $this->prevNext
->fetch($this->cacheKey
, 2, 2);
111 $this->assertEquals([200, 300], $cids);
114 public function getFillFunctions() {
122 * Select and unselect one item.
124 * @dataProvider getFillFunctions
126 public function testMarkSelection_1($fillFunction) {
127 call_user_func([$this, $fillFunction]);
129 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
130 list ($id1, $id2) = array_keys($all);
131 $this->prevNext
->markSelection($this->cacheKey
, 'select', $id1);
133 $this->assertSelections([$id1]);
135 $this->prevNext
->markSelection($this->cacheKey
, 'unselect', $id1);
136 $this->assertSelections([]);
140 * Select and unselect two items.
142 * @dataProvider getFillFunctions
144 public function testMarkSelection_2($fillFunction) {
145 call_user_func([$this, $fillFunction]);
147 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
148 list ($id1, $id2, $id3) = array_keys($all);
150 $this->prevNext
->markSelection($this->cacheKey
, 'select', [$id1, $id3]);
151 $this->assertSelections([$id1, $id3]);
153 $this->prevNext
->markSelection($this->cacheKey
, 'unselect', $id1);
154 $this->assertSelections([$id3]);
156 $this->prevNext
->markSelection($this->cacheKey
, 'select', $id2);
157 $this->assertSelections([$id2, $id3]);
159 $this->prevNext
->markSelection($this->cacheKey
, 'unselect');
160 $this->assertSelections([]);
164 * Check the neighbors of the first item.
166 * @dataProvider getFillFunctions
168 public function testGetPosition_first($fillFunction) {
169 call_user_func([$this, $fillFunction]);
171 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
172 list ($id1, $id2, $id3) = array_keys($all);
174 $pos = $this->prevNext
->getPositions($this->cacheKey
, $id1);
176 $this->assertTrue((bool) $pos['foundEntry']);
178 $this->assertEquals($id2, $pos['next']['id1']);
179 $this->assertTrue(!empty($pos['next']['data']));
181 $this->assertTrue(!isset($pos['prev']));
185 * Check the neighbors of a middle item.
187 * @dataProvider getFillFunctions
189 public function testGetPosition_middle($fillFunction) {
190 call_user_func([$this, $fillFunction]);
192 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
193 list ($id1, $id2, $id3) = array_keys($all);
195 $pos = $this->prevNext
->getPositions($this->cacheKey
, $id2);
196 $this->assertTrue((bool) $pos['foundEntry']);
198 $this->assertEquals($id3, $pos['next']['id1']);
199 $this->assertTrue(!empty($pos['next']['data']));
201 $this->assertEquals($id1, $pos['prev']['id1']);
202 $this->assertTrue(!empty($pos['prev']['data']));
206 * Check the neighbors of the last item.
208 * @dataProvider getFillFunctions
210 public function testGetPosition_last($fillFunction) {
211 call_user_func([$this, $fillFunction]);
213 $all = $this->prevNext
->getSelection($this->cacheKey
, 'getall')[$this->cacheKey
];
214 list ($idLast, $idPrev) = array_reverse(array_keys($all));
216 $pos = $this->prevNext
->getPositions($this->cacheKey
, $idLast);
217 $this->assertTrue((bool) $pos['foundEntry']);
219 $this->assertTrue(!isset($pos['next']));
221 $this->assertEquals($idPrev, $pos['prev']['id1']);
222 $this->assertTrue(!empty($pos['prev']['data']));
226 * Check the neighbors of the last item.
228 * @dataProvider getFillFunctions
230 public function testGetPosition_invalid($fillFunction) {
231 call_user_func([$this, $fillFunction]);
233 $pos = $this->prevNext
->getPositions($this->cacheKey
, 99999999);
234 $this->assertFalse((bool) $pos['foundEntry']);
235 $this->assertTrue(!isset($pos['next']));
236 $this->assertTrue(!isset($pos['prev']));
239 public function testDeleteByCacheKey() {
240 // Add background data
241 $this->prevNext
->fillWithArray($this->cacheKeyB
, [
242 ['entity_id1' => 100, 'data' => 'Alice'],
243 ['entity_id1' => 150, 'data' => 'Dave'],
245 $this->prevNext
->markSelection($this->cacheKeyB
, 'select', 100);
246 $this->assertSelections([100], 'get', $this->cacheKeyB
);
247 $this->assertSelections([100, 150], 'getall', $this->cacheKeyB
);
249 // Add some data that we're actually working with.
250 $this->testFillArray();
252 $all = $this->assertSelections([100, 400, 200, 300], 'getall', $this->cacheKey
);
254 list ($id1, $id2, $id3) = array_keys($all);
255 $this->prevNext
->markSelection($this->cacheKey
, 'select', [$id1, $id3]);
256 $this->assertSelections([$id1, $id3], 'get', $this->cacheKey
);
258 $this->prevNext
->deleteItem(NULL, $this->cacheKey
);
259 $this->assertSelections([], 'getall', $this->cacheKey
);
260 $this->assertSelections([], 'get', $this->cacheKey
);
262 // Ensure background data was untouched.
263 $this->assertSelections([100], 'get', $this->cacheKeyB
);
264 $this->assertSelections([100, 150], 'getall', $this->cacheKeyB
);
267 public function testDeleteByEntityId() {
269 $this->prevNext
->fillWithArray($this->cacheKey
, [
270 ['entity_id1' => 100, 'data' => 'Alice'],
271 ['entity_id1' => 150, 'data' => 'Dave'],
273 $this->prevNext
->markSelection($this->cacheKey
, 'select', 100);
274 $this->assertSelections([100], 'get', $this->cacheKey
);
275 $this->assertSelections([100, 150], 'getall', $this->cacheKey
);
277 $this->prevNext
->fillWithArray($this->cacheKeyB
, [
278 ['entity_id1' => 100, 'data' => 'Alice'],
279 ['entity_id1' => 400, 'data' => 'Bob'],
281 $this->prevNext
->markSelection($this->cacheKeyB
, 'select', [100, 400]);
282 $this->assertSelections([100, 400], 'get', $this->cacheKeyB
);
283 $this->assertSelections([100, 400], 'getall', $this->cacheKeyB
);
286 $this->prevNext
->deleteItem(100);
287 $this->assertSelections([], 'get', $this->cacheKey
);
288 $this->assertSelections([150], 'getall', $this->cacheKey
);
289 $this->assertSelections([400], 'get', $this->cacheKeyB
);
290 $this->assertSelections([400], 'getall', $this->cacheKeyB
);
293 public function testDeleteAll() {
295 $this->prevNext
->fillWithArray($this->cacheKey
, [
296 ['entity_id1' => 100, 'data' => 'Alice'],
297 ['entity_id1' => 150, 'data' => 'Dave'],
299 $this->prevNext
->markSelection($this->cacheKey
, 'select', 100);
300 $this->assertSelections([100], 'get', $this->cacheKey
);
301 $this->assertSelections([100, 150], 'getall', $this->cacheKey
);
303 $this->prevNext
->fillWithArray($this->cacheKeyB
, [
304 ['entity_id1' => 100, 'data' => 'Alice'],
305 ['entity_id1' => 400, 'data' => 'Bob'],
307 $this->prevNext
->markSelection($this->cacheKeyB
, 'select', [100, 400]);
308 $this->assertSelections([100, 400], 'get', $this->cacheKeyB
);
309 $this->assertSelections([100, 400], 'getall', $this->cacheKeyB
);
312 $this->prevNext
->deleteItem(NULL, NULL);
313 $this->assertSelections([], 'get', $this->cacheKey
);
314 $this->assertSelections([], 'getall', $this->cacheKey
);
315 $this->assertSelections([], 'get', $this->cacheKeyB
);
316 $this->assertSelections([], 'getall', $this->cacheKeyB
);
320 * Assert that the current cacheKey has a list of selected contact IDs.
323 * Contact IDs that should be selected.
324 * @param string $action
325 * @param string|NULL $cacheKey
327 * Contact IDs that were returned by getSelection($cacheKey, $action)
329 protected function assertSelections($ids, $action = 'get', $cacheKey = NULL) {
330 if ($cacheKey === NULL) {
331 $cacheKey = $this->cacheKey
;
333 $selected = $this->prevNext
->getSelection($cacheKey, $action)[$cacheKey];
334 $this->assertEquals($ids, array_keys($selected), 'selected cache not correct for ' . $cacheKey
335 . ' defined keys are ' . $this->cacheKey
. 'and ' . $this->cacheKeyB
336 . ' result from getall is ' . print_r($this->prevNext
->getSelection($cacheKey, 'getall'), 1)
337 . ' and the prevNext cache is ' . print_r($this->prevNext
, TRUE)
340 $this->assertCount(count($ids), $selected);