Merge pull request #3179 from webpartners/master
[civicrm-core.git] / tests / phpunit / api / v3 / SyntaxConformanceTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 require_once 'CiviTest/CiviUnitTestCase.php';
29
30
31 /**
32 * Test APIv3 civicrm_sytanc conformance* functions
33 *
34 * @package CiviCRM_APIv3
35 * @subpackage API_Core
36 */
37
38 class api_v3_SyntaxConformanceTest extends CiviUnitTestCase {
39 protected $_apiversion = 3;
40
41 /**
42 * @var array e.g. $this->deletes['CRM_Contact_DAO_Contact'][] = $contactID;
43 */
44 protected $deletableTestObjects;
45
46 /** This test case doesn't require DB reset */
47 public $DBResetRequired = FALSE;
48
49 protected $_entity;
50
51 /** Map custom group entities to civicrm components */
52 static $componentMap = array(
53 'Contact' => NULL,
54 'Individual' => NULL,
55 'Household' => NULL,
56 'Organization' => NULL,
57 'Contribution' => 'CiviContribute',
58 'Membership' => 'CiviMember',
59 'Participant' => 'CiviEvent',
60 'Group' => NULL,
61 'Relationship' => NULL,
62 'Event' => 'CiviEvent',
63 'Case' => 'CiviCase',
64 'Activity' => NULL,
65 'Pledge' => 'CiviPledge',
66 'Grant' => 'CiviGrant',
67 'Address' => NULL,
68 );
69
70 /* they are two types of missing APIs:
71 - Those that are to be implemented
72 (in some future version when someone steps in -hint hint-). List the entities in toBeImplemented[ {$action} ]
73 Those that don't exist
74 and that will never exist (eg an obsoleted Entity
75 they need to be returned by the function toBeSkipped_{$action} (because it has to be a static method and therefore couldn't access a this->toBeSkipped)
76 */
77 function setUp() {
78 parent::setUp();
79 $this->enableCiviCampaign();
80 $this->toBeImplemented['get'] = array('Profile', 'CustomValue', 'Constant', 'CustomSearch', 'Extension', 'ReportTemplate', 'System', 'Setting');
81 $this->toBeImplemented['create'] = array('SurveyRespondant', 'OptionGroup', 'MailingRecipients', 'UFMatch', 'LocationType', 'CustomSearch', 'Extension', 'ReportTemplate', 'System');
82 $this->toBeImplemented['delete'] = array('MembershipPayment', 'OptionGroup', 'SurveyRespondant', 'UFJoin', 'UFMatch', 'Extension', 'LocationType', 'System');
83 $this->onlyIDNonZeroCount['get'] = array('ActivityType', 'Entity', 'Domain','Setting');
84 $this->deprecatedAPI = array('Location', 'ActivityType', 'SurveyRespondant');
85 $this->deletableTestObjects = array();
86 }
87
88 function tearDown() {
89 foreach ($this->deletableTestObjects as $entityName => $entities) {
90 foreach ($entities as $entityID) {
91 CRM_Core_DAO::deleteTestObjects($entityName, array('id' => $entityID));
92 }
93 }
94 }
95
96 /**
97 * @param null $skip
98 *
99 * @return array
100 */
101 public static function entities($skip = NULL) {
102 // To only test specific entities, call phpunit with SYNTAX_CONFORMANCE_ENTITIES="TheEntityName"
103 // or uncomment this line:
104 //return array(array ('Tag'), array ('Activity') );
105
106 if (getenv('SYNTAX_CONFORMANCE_ENTITIES')) {
107 $result = array();
108 foreach (explode(' ', getenv('SYNTAX_CONFORMANCE_ENTITIES')) as $entity) {
109 $result[] = array($entity);
110 }
111 return $result;
112 }
113
114 $tmp = civicrm_api('Entity', 'Get', array('version' => 3));
115 if (!is_array($skip)) {
116 $skip = array();
117 }
118 $tmp = array_diff($tmp['values'], $skip);
119 $entities = array();
120 foreach ($tmp as $e) {
121 $entities[] = array($e);
122 }
123 return $entities;
124 }
125
126 /**
127 * @return array
128 */
129 public static function entities_get() {
130 // all the entities, beside the ones flagged
131 return static::entities(static::toBeSkipped_get(TRUE));
132 }
133
134 /**
135 * @return array
136 */
137 public static function entities_create() {
138 return static::entities(static::toBeSkipped_create(TRUE));
139 }
140
141 /**
142 * @return array
143 */
144 public static function entities_updatesingle() {
145 return static::entities(static::toBeSkipped_updatesingle(TRUE));
146 }
147
148 /**
149 * @return array
150 */
151 public static function entities_getlimit() {
152 return static::entities(static::toBeSkipped_getlimit());
153 }
154
155 /**
156 * @return array
157 */
158 public static function entities_delete() {
159 return static::entities(static::toBeSkipped_delete(TRUE));
160 }
161
162 /**
163 * @return array
164 */
165 public static function custom_data_entities_get() {
166 return static::custom_data_entities();
167 }
168
169 /**
170 * @return array
171 */
172 public static function custom_data_entities() {
173 $enableComponents = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'enable_components', NULL, array());
174 $entities = CRM_Core_BAO_CustomQuery::$extendsMap;
175 $components = self::$componentMap;
176 $customDataEntities = array();
177 $invalidEntities = array('Individual', 'Organization', 'Household');
178 $entitiesToFix = array('Case', 'Relationship');
179 foreach ($entities as $entityName => $entity ) {
180 if(!in_array($entityName, $invalidEntities)
181 && !in_array($entityName, $entitiesToFix)
182 && (!empty($components[$entityName]) && in_array($components[$entityName], $enableComponents) || $components[$entityName] == NULL)) {
183 $customDataEntities[] = array($entityName );
184 }
185 }
186 return $customDataEntities;
187 }
188
189 /**
190 * @param bool $sequential
191 *
192 * @return array
193 */
194 public static function toBeSkipped_get($sequential = FALSE) {
195 $entitiesWithoutGet = array('MailingEventSubscribe', 'MailingEventConfirm', 'MailingEventResubscribe', 'MailingEventUnsubscribe', 'MailingGroup', 'Location');
196 if ($sequential === TRUE) {
197 return $entitiesWithoutGet;
198 }
199 $entities = array();
200 foreach ($entitiesWithoutGet as $e) {
201 $entities[] = array($e);
202 }
203 return $entities;
204 }
205
206 /**
207 * Mailing Contact Just doesn't support id. We have always insisted on finding a way to
208 * support id in API but in this case the underlying tables are crying out for a restructue
209 * & it just doesn't make sense
210 *
211 * @param bool|\unknown_type $sequential
212 *
213 * @return multitype:string |multitype:multitype:string
214 */
215 public static function toBeSkipped_getByID($sequential = FALSE) {
216 return array('MailingContact');
217 }
218
219 /**
220 * @param bool $sequential
221 *
222 * @return array
223 */
224 public static function toBeSkipped_create($sequential = FALSE) {
225 $entitiesWithoutCreate = array('MailingGroup', 'Constant', 'Entity', 'Location', 'Profile', 'MailingRecipients');
226 if ($sequential === TRUE) {
227 return $entitiesWithoutCreate;
228 }
229 $entities = array();
230 foreach ($entitiesWithoutCreate as $e) {
231 $entities[] = array($e);
232 }
233 return $entities;
234 }
235
236 /**
237 * @param bool $sequential
238 *
239 * @return array
240 */
241 public static function toBeSkipped_delete($sequential = FALSE) {
242 $entitiesWithout = array('MailingContact', 'MailingEventConfirm', 'MailingEventResubscribe', 'MailingEventSubscribe', 'MailingEventUnsubscribe', 'MailingGroup', 'MailingRecipients', 'Constant', 'Entity', 'Location', 'Domain', 'Profile', 'CustomValue', 'Setting');
243 if ($sequential === TRUE) {
244 return $entitiesWithout;
245 }
246 $entities = array();
247 foreach ($entitiesWithout as $e) {
248 $entities[] = array($e);
249 }
250 return $entities;
251 }
252
253 /**
254 * Generate list of entities to test for get by id functions
255 * @param boolean $sequential
256 * @return multitype:string |multitype:multitype:string
257 */
258 public static function toBeSkipped_automock($sequential = FALSE) {
259 $entitiesWithoutGet = array('MailingContact', 'EntityTag', 'Participant', 'ParticipantPayment', 'Setting', 'SurveyRespondant', 'MailingRecipients', 'CustomSearch', 'Extension', 'ReportTemplate', 'System');
260 if ($sequential === TRUE) {
261 return $entitiesWithoutGet;
262 }
263 $entities = array();
264 foreach ($entitiesWithoutGet as $e) {
265 $entities[] = array($e);
266 }
267 return $entities;
268 }
269
270
271 /**
272 * At this stage exclude the ones that don't pass & add them as we can troubleshoot them
273 */
274 public static function toBeSkipped_updatesingle($sequential = FALSE) {
275 $entitiesWithout = array(
276 'Mailing',
277 'MailingGroup',
278 'MailingJob',
279 'Address',
280 'MailingEventUnsubscribe',
281 'MailingEventSubscribe',
282 'Constant',
283 'Entity',
284 'Location',
285 'Domain',
286 'Profile',
287 'CustomValue',
288 'SurveyRespondant',
289 'Tag',
290 'UFMatch',
291 'UFJoin',
292 'UFField',
293 'OptionValue',
294 'Relationship',
295 'RelationshipType',
296 'ParticipantStatusType',
297 'Note',
298 'OptionGroup',
299 'Membership',
300 'MembershipType',
301 'MembershipStatus',
302 'Group',
303 'GroupOrganization',
304 'GroupNesting',
305 'Job',
306 'File',
307 'EntityTag',
308 'CustomField',
309 'CustomGroup',
310 'Contribution',
311 'ContributionRecur',
312 'ActivityType',
313 'MailingEventConfirm',
314 'Case',
315 'Contact',
316 'ContactType',
317 'MailingEventResubscribe',
318 'UFGroup',
319 'Activity',
320 'Email',
321 'Event',
322 'GroupContact',
323 'MembershipPayment',
324 'Participant',
325 'ParticipantPayment',
326 'LineItem',
327 'PriceSet',
328 'PriceField',
329 'PriceFieldValue',
330 'PledgePayment',
331 'ContributionPage',
332 'Phone',
333 'PaymentProcessor',
334 'MailSettings',
335 'Setting',
336 'MailingContact',
337 'SystemLog' //skip this because it doesn't make sense to update logs
338 );
339 if ($sequential === TRUE) {
340 return $entitiesWithout;
341 }
342 $entities = array();
343 foreach ($entitiesWithout as $e) {
344 $entities[] = array(
345 $e,
346 );
347 }
348 return array('pledge');
349 return $entities;
350 }
351
352 /**
353 * At this stage exclude the ones that don't pass & add them as we can troubleshoot them
354 */
355 public static function toBeSkipped_getlimit() {
356 $entitiesWithout = array(
357 'Case',//case api has non-std mandatory fields one of (case_id, contact_id, activity_id, contact_id)
358 'EntityTag', // non-standard api - has inappropriate mandatory fields & doesn't implement limit
359 'Event', // failed 'check that a 5 limit returns 5' - probably is_template field is wrong or something, or could be limit doesn't work right
360 'Extension', // can't handle creating 25
361 'MailingGroup', // no get call on MailingGroup
362 'Note', // fails on 5 limit - probably a set up problem
363 'Setting', //a bit of a pseudoapi - keys by domain
364 );
365 return $entitiesWithout;
366 }
367
368 /**
369 * @param $entity
370 * @param $key
371 *
372 * @return array
373 */
374 public function getKnownUnworkablesUpdateSingle($entity, $key){
375 // can't update values are values for which updates don't result in the value being changed
376 $knownFailures = array(
377 'ActionSchedule' => array(
378 'cant_update' => array(
379 'group_id',
380 ),
381 ),
382 'ActivityContact' => array(
383 'cant_update' => array(
384 'activity_id', //we have an FK on activity_id + contact_id + record id so if we don't leave this one distinct we get an FK constraint error
385 ),
386 ),
387 'Address' => array(
388 'cant_update' => array(
389 'state_province_id', //issues with country id - need to ensure same country
390 'master_id',//creates relationship
391 ),
392 'cant_return' => array(
393 )
394 ),
395 'Batch' => array(
396 'cant_update' => array(
397 'entity_table', // believe this field is defined in error
398 ),
399 'cant_return' => array(
400 'entity_table',
401 )
402 ),
403 'Pledge' => array(
404 'cant_update' => array(
405 'pledge_original_installment_amount',
406 'installments',
407 'original_installment_amount',
408 'next_pay_date',
409 'amount' // can't be changed through API
410 ),
411 'break_return' => array(// if these are passed in they are retrieved from the wrong table
412 'honor_contact_id',
413 'cancel_date',
414 'contribution_page_id',
415 'financial_account_id',
416 'financial_type_id',
417 'currency'
418 ),
419 'cant_return' => array(// can't be retrieved from api
420 'honor_type_id', //due to uniquename missing
421 'end_date',
422 'modified_date',
423 'acknowledge_date',
424 'start_date',
425 'frequency_day',
426 'currency',
427 'max_reminders',
428 'initial_reminder_day',
429 'additional_reminder_day',
430 'frequency_unit',
431 'pledge_contribution_page_id',
432 'pledge_status_id',
433 'pledge_campaign_id',
434 'pledge_financial_type_id',
435 )
436 ),
437 'PaymentProcessorType' => array(
438 'cant_update' => array(
439 'billing_mode',
440 ),
441 'break_return' => array(
442 ),
443 'cant_return' => array(
444 ),
445 ),
446 );
447 if(empty($knownFailures[$entity]) || empty($knownFailures[$entity][$key])){
448 return array();
449 }
450 return $knownFailures[$entity][$key];
451 }
452
453 /** testing the _get **/
454
455 /**
456 * @dataProvider toBeSkipped_get
457 entities that don't need a get action
458 */
459 public function testNotImplemented_get($Entity) {
460 $result = civicrm_api($Entity, 'Get', array('version' => 3));
461 $this->assertEquals(1, $result['is_error'], 'In line ' . __LINE__);
462 // $this->assertContains("API ($Entity, Get) does not exist", $result['error_message']);
463 $this->assertRegExp('/API (.*) does not exist/', $result['error_message']);
464 }
465
466 /**
467 * @dataProvider entities
468 * @expectedException PHPUnit_Framework_Error
469 */
470 public function testWithoutParam_get($Entity) {
471 // should get php complaining that a param is missing
472 $result = civicrm_api($Entity, 'Get');
473 }
474
475 /**
476 * @dataProvider entities
477 */
478 public function testGetFields($Entity) {
479 if (in_array($Entity, $this->deprecatedAPI) || $Entity == 'Entity' || $Entity == 'CustomValue' || $Entity == 'MailingGroup') {
480 return;
481 }
482
483 $result = civicrm_api($Entity, 'getfields', array('version' => 3));
484 $this->assertTrue(is_array($result['values']), "$Entity ::get fields doesn't return values array in line " . __LINE__);
485 foreach ($result['values'] as $key => $value) {
486 $this->assertTrue(is_array($value), $Entity . "::" . $key . " is not an array in line " . __LINE__);
487 }
488 }
489
490 /**
491 * @dataProvider entities_get
492 */
493 public function testEmptyParam_get($Entity) {
494
495 if (in_array($Entity, $this->toBeImplemented['get'])) {
496 // $this->markTestIncomplete("civicrm_api3_{$Entity}_get to be implemented");
497 return;
498 }
499 $result = civicrm_api($Entity, 'Get', array());
500 $this->assertEquals(1, $result['is_error'], 'In line ' . __LINE__);
501 $this->assertContains("Mandatory key(s) missing from params array", $result['error_message']);
502 }
503 /**
504 * @dataProvider entities_get
505 */
506 public function testEmptyParam_getString($Entity) {
507
508 if (in_array($Entity, $this->toBeImplemented['get'])) {
509 // $this->markTestIncomplete("civicrm_api3_{$Entity}_get to be implemented");
510 return;
511 }
512 $result = $this->callAPIFailure($Entity, 'Get', 'string');
513 $this->assertEquals(2000, $result['error_code']);
514 $this->assertEquals('Input variable `params` is not an array', $result['error_message']);
515 }
516 /**
517 * @dataProvider entities_get
518 * @Xdepends testEmptyParam_get // no need to test the simple if the empty doesn't work/is skipped. doesn't seem to work
519 */
520 public function testSimple_get($Entity) {
521 // $this->markTestSkipped("test gives core error on test server (but not on our locals). Skip until we can get server to pass");
522 if (in_array($Entity, $this->toBeImplemented['get'])) {
523 return;
524 }
525 $result = civicrm_api($Entity, 'Get', array('version' => 3));
526 // @TODO: list the get that have mandatory params
527 if ($result['is_error']) {
528 $this->assertContains("Mandatory key(s) missing from params array", $result['error_message']);
529 // either id or contact_id or entity_id is one of the field missing
530 $this->assertContains("id", $result['error_message']);
531 }
532 else {
533 $this->assertEquals(3, $result['version']);
534 $this->assertArrayHasKey('count', $result);
535 $this->assertArrayHasKey('values', $result);
536 }
537 }
538
539 /**
540 * @dataProvider custom_data_entities_get
541 */
542 public function testCustomDataGet($entityName) {
543 $this->createLoggedInUser();// so subsidiary activities are created
544 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, $entityName . 'Test.php');
545 $customFieldName = 'custom_' . $ids['custom_field_id'];
546 $objects = $this->getMockableBAOObjects($entityName, 1);
547 $params = array('id' => $objects[0]->id, 'custom_' . $ids['custom_field_id'] => "custom string");
548 $result = $this->callAPISuccess($entityName, 'create', $params);
549
550 $getParams = array('id' => $result['id'], 'return' => array($customFieldName));
551 $check = $this->callAPISuccess($entityName, 'get', $getParams);
552 $this->assertEquals("custom string", $check['values'][$check['id']][$customFieldName]);
553
554 $this->customFieldDelete($ids['custom_field_id']);
555 $this->customGroupDelete($ids['custom_group_id']);
556 $this->callAPISuccess($entityName, 'delete', array('id' => $result['id']));
557 }
558
559 /**
560 * @dataProvider entities_get
561 */
562 public function testAcceptsOnlyID_get($Entity) {
563 // big random number. fun fact: if you multiply it by pi^e, the result is another random number, but bigger ;)
564 $nonExistantID = 30867307034;
565 if (in_array($Entity, $this->toBeImplemented['get'])
566 || in_array($Entity, $this->toBeSkipped_getByID())
567 ) {
568 return;
569 }
570
571 // FIXME
572 // the below function returns different values and hence an early return
573 // we'll fix this once beta1 is released
574 // return;
575
576 $result = civicrm_api($Entity, 'Get', array('version' => 3, 'id' => $nonExistantID));
577
578 if ($result['is_error']) {
579 // just to get a clearer message in the log
580 $this->assertEquals("only id should be enough", $result['error_message']);
581 }
582 if (!in_array($Entity, $this->onlyIDNonZeroCount['get'])) {
583 $this->assertEquals(0, $result['count']);
584 }
585 }
586
587 /**
588 * Create two entities and make sure we can fetch them individually by ID
589 *
590 * @dataProvider entities_get
591 *
592 * limitations include the problem with avoiding loops when creating test objects -
593 * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
594 * Currency - only seems to support US
595 */
596 public function testByID_get($entityName) {
597 if (in_array($entityName, self::toBeSkipped_automock(TRUE))) {
598 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
599 return;
600 }
601
602 $baos = $this->getMockableBAOObjects($entityName);
603 list($baoObj1, $baoObj2) = $baos;
604
605 // fetch first by ID
606 $result = $this->callAPISuccess($entityName, 'get', array(
607 'id' => $baoObj1->id,
608 ));
609
610 $this->assertTrue(!empty($result['values'][$baoObj1->id]), 'Should find first object by id');
611 $this->assertEquals($baoObj1->id, $result['values'][$baoObj1->id]['id'], 'Should find id on first object');
612 $this->assertEquals(1, count($result['values']));
613
614 // fetch second by ID
615 $result = $this->callAPISuccess($entityName, 'get', array(
616 'id' => $baoObj2->id,
617 ));
618 $this->assertTrue(!empty($result['values'][$baoObj2->id]), 'Should find second object by id');
619 $this->assertEquals($baoObj2->id, $result['values'][$baoObj2->id]['id'], 'Should find id on second object');
620 $this->assertEquals(1, count($result['values']));
621 }
622
623 /**
624 * Ensure that the "get" operation accepts limiting the #result records.
625 *
626 * TODO Consider making a separate entity list ("entities_getlimit")
627 * For the moment, the "entities_updatesingle" list should give a good
628 * sense for which entities support createTestObject
629 *
630 * @dataProvider entities_getlimit
631 *
632 * @param $entityName
633 *
634 * @internal param string $entity
635 */
636 function testLimit($entityName) {
637 $cases = array(); // each case is array(0 => $inputtedApiOptions, 1 => $expectedResultCount)
638 $cases[] = array(
639 array('options' => array('limit' => NULL)),
640 30,
641 'check that a NULL limit returns unlimited',
642 );
643 $cases[] = array(
644 array('options' => array('limit' => FALSE)),
645 30,
646 'check that a FALSE limit returns unlimited',
647 );
648 $cases[] = array(
649 array('options' => array('limit' => 0)),
650 30,
651 'check that a 0 limit returns unlimited',
652 );
653 $cases[] = array(
654 array('options' => array('limit' => 5)),
655 5,
656 'check that a 5 limit returns 5',
657 );
658 $cases[] = array(
659 array(),
660 25,
661 'check that no limit returns 25',
662 );
663
664 $baoString = _civicrm_api3_get_DAO($entityName);
665 if (empty($baoString)) {
666 $this->markTestIncomplete("Entity [$entityName] cannot be mocked - no known DAO");
667 return;
668 }
669
670 // make 30 test items -- 30 > 25 (the default limit)
671 $ids = array();
672 for ($i = 0; $i < 30; $i++) {
673 $baoObj = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
674 $ids[] = $baoObj->id;
675 }
676
677 // each case is array(0 => $inputtedApiOptions, 1 => $expectedResultCount)
678 foreach ($cases as $case) {
679 $this->checkLimitAgainstExpected($entityName, $case[0], $case[1], $case[2]);
680
681 //non preferred / legacy syntax
682 if(isset($case[0]['options']['limit'])) {
683 $this->checkLimitAgainstExpected($entityName, array('rowCount' => $case[0]['options']['limit']), $case[1], $case[2]);
684 $this->checkLimitAgainstExpected($entityName, array('option_limit' => $case[0]['options']['limit']), $case[1], $case[2]);
685 $this->checkLimitAgainstExpected($entityName, array('option.limit' => $case[0]['options']['limit']), $case[1], $case[2]);
686 }
687 }
688 foreach ($ids as $id) {
689 CRM_Core_DAO::deleteTestObjects($baoString, array('id' => $id));
690 }
691 $baoObj->free();
692 }
693
694 /**
695 * Check that get fetches an appropriate number of results
696 *
697 * @param string $entityName Name of entity to test
698 * @param unknown $params
699 * @param unknown $limit
700 * @param unknown $message
701 */
702 function checkLimitAgainstExpected($entityName, $params, $limit, $message) {
703 $result = $this->callAPISuccess($entityName, 'get', $params);
704 if($limit == 30) {
705 $this->assertGreaterThanOrEqual($limit, $result['count'], $message);
706 $this->assertGreaterThanOrEqual($limit, $result['count'], $message);
707 }
708 else {
709 $this->assertEquals($limit, $result['count'], $message);
710 $this->assertEquals($limit, count($result['values']), $message);
711 }
712 }
713 /**
714 * Create two entities and make sure we can fetch them individually by ID (e.g. using "contact_id=>2"
715 * or "group_id=>4")
716 *
717 * @dataProvider entities_get
718 *
719 * limitations include the problem with avoiding loops when creating test objects -
720 * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
721 * Currency - only seems to support US
722 */
723 public function testByIDAlias_get($entityName) {
724 if (in_array($entityName, self::toBeSkipped_automock(TRUE))) {
725 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
726 return;
727 }
728
729 $baoString = _civicrm_api3_get_DAO($entityName);
730 if (empty($baoString)) {
731 $this->markTestIncomplete("Entity [$entityName] cannot be mocked - no known DAO");
732 return;
733 }
734
735 $idFieldName = _civicrm_api_get_entity_name_from_camel($entityName) . '_id';
736
737 // create entities
738 $baoObj1 = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
739 $this->assertTrue(is_integer($baoObj1->id), 'check first id');
740 $this->deletableTestObjects[$baoString][] = $baoObj1->id;
741 $baoObj2 = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
742 $this->assertTrue(is_integer($baoObj2->id), 'check second id');
743 $this->deletableTestObjects[$baoString][] = $baoObj2->id;
744
745 // fetch first by ID
746 $result = civicrm_api($entityName, 'get', array(
747 'version' => 3,
748 $idFieldName => $baoObj1->id,
749 ));
750 $this->assertAPISuccess($result);
751 $this->assertTrue(!empty($result['values'][$baoObj1->id]), 'Should find first object by id');
752 $this->assertEquals($baoObj1->id, $result['values'][$baoObj1->id]['id'], 'Should find id on first object');
753 $this->assertEquals(1, count($result['values']));
754
755 // fetch second by ID
756 $result = civicrm_api($entityName, 'get', array(
757 'version' => 3,
758 $idFieldName => $baoObj2->id,
759 ));
760 $this->assertAPISuccess($result);
761 $this->assertTrue(!empty($result['values'][$baoObj2->id]), 'Should find second object by id');
762 $this->assertEquals($baoObj2->id, $result['values'][$baoObj2->id]['id'], 'Should find id on second object');
763 $this->assertEquals(1, count($result['values']));
764 }
765
766 /**
767 * @dataProvider entities_get
768 */
769 public function testNonExistantID_get($Entity) {
770 // cf testAcceptsOnlyID_get
771 $nonExistantID = 30867307034;
772 if (in_array($Entity, $this->toBeImplemented['get'])) {
773 return;
774 }
775
776 $result = civicrm_api($Entity, 'Get', array('version' => 3, 'id' => $nonExistantID));
777
778 // redundant with testAcceptsOnlyID_get
779 if ($result['is_error']) {
780 return;
781 }
782
783
784 $this->assertArrayHasKey('version', $result);
785 $this->assertEquals(3, $result['version']);
786 if (!in_array($Entity, $this->onlyIDNonZeroCount['get'])) {
787 $this->assertEquals(0, $result['count']);
788 }
789 }
790
791 /** testing the _create **/
792
793 /**
794 * @dataProvider toBeSkipped_create
795 entities that don't need a create action
796 */
797 public function testNotImplemented_create($Entity) {
798 $result = civicrm_api($Entity, 'Create', array('version' => 3));
799 $this->assertEquals(1, $result['is_error'], 'In line ' . __LINE__);
800 $this->assertContains(strtolower("API ($Entity, Create) does not exist"), strtolower($result['error_message']));
801 }
802
803 /**
804 * @dataProvider entities
805 * @expectedException PHPUnit_Framework_Error
806 */
807 public function testWithoutParam_create($Entity) {
808 // should create php complaining that a param is missing
809 $result = civicrm_api($Entity, 'Create');
810 }
811
812 /**
813 * @dataProvider entities_create
814 */
815 public function testEmptyParam_create($Entity) {
816 $this->markTestIncomplete("fixing this test to test the api functions fails on numberous tests
817 which will either create a completely blank entity (batch, participant status) or
818 have a damn good crack at it (e.g mailing job). Marking this as incomplete beats false success");
819 //
820 return;
821 if (in_array($Entity, $this->toBeImplemented['create'])) {
822 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
823 return;
824 }
825 $result = $this->callAPIFailure($Entity, 'Create', array());
826 $this->assertContains("Mandatory key(s) missing from params array", $result['error_message']);
827 }
828
829 /**
830 * @dataProvider entities_create
831 *
832 * Check that create doesn't work with an invalid
833 */
834 public function testInvalidID_create($Entity) {
835 // turn test off for noew
836 $this->markTestIncomplete("Entity [ $Entity ] cannot be mocked - no known DAO");
837 return;
838 if (in_array($Entity, $this->toBeImplemented['create'])) {
839 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
840 return;
841 }
842 $result = $this->callAPIFailure($Entity, 'Create', array('id' => 999));
843 }
844
845 /**
846 * @dataProvider entities
847 */
848 public function testCreateWrongTypeParamTag_create() {
849 $result = civicrm_api("Tag", 'Create', 'this is not a string');
850 $this->assertEquals(1, $result['is_error'], 'In line ' . __LINE__);
851 $this->assertEquals("Input variable `params` is not an array", $result['error_message']);
852 }
853
854 /**
855 * @dataProvider entities_updatesingle
856 *
857 * limitations include the problem with avoiding loops when creating test objects -
858 * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
859 * Currency - only seems to support US
860 */
861 public function testCreateSingleValueAlter($entityName) {
862 if (in_array($entityName, $this->toBeImplemented['create'])) {
863 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
864 return;
865 }
866
867 $baoString = _civicrm_api3_get_DAO($entityName);
868 $this->assertNotEmpty($baoString, $entityName);
869 $this->assertNotEmpty($entityName, $entityName);
870 $fieldsGet = $fields = $this->callAPISuccess($entityName, 'getfields', array('action' => 'get'));
871 if($entityName != 'Pledge'){
872 $fields = $this->callAPISuccess($entityName, 'getfields', array('action' => 'create'));
873 }
874 $fields = $fields['values'];
875 $return = array_keys($fieldsGet['values']);
876 $valuesNotToReturn = $this->getKnownUnworkablesUpdateSingle($entityName, 'break_return');
877 // these can't be requested as return values
878 $entityValuesThatDoNotWork = array_merge(
879 $this->getKnownUnworkablesUpdateSingle($entityName, 'cant_update'),
880 $this->getKnownUnworkablesUpdateSingle($entityName, 'cant_return'),
881 $valuesNotToReturn
882 );
883
884 $return = array_diff($return,$valuesNotToReturn);
885 $baoObj = new CRM_Core_DAO();
886 $baoObj->createTestObject($baoString, array('currency' => 'USD'), 2, 0);
887
888 $getEntities = $this->callAPISuccess($entityName, 'get', array(
889 'sequential' => 1,
890 'return' => $return,
891 'options' => array(
892 'sort' => 'id DESC',
893 'limit' => 2,
894 ),
895 ));
896 // lets use first rather than assume only one exists
897 $entity = $getEntities['values'][0];
898 $entity2 = $getEntities['values'][1];
899 $this->deletableTestObjects[$baoString][] = $entity['id'];
900 $this->deletableTestObjects[$baoString][] = $entity2['id'];
901 foreach ($fields as $field => $specs) {
902 $fieldName = $field;
903 if (!empty($specs['uniquename'])) {
904 $fieldName = $specs['uniquename'];
905 }
906 if ($field == 'currency' || $field == 'id' || $field == strtolower($entityName) . '_id'
907 || in_array($field,$entityValuesThatDoNotWork)) {
908 //@todo id & entity_id are correct but we should fix currency & frequency_day
909 continue;
910 }
911 $this->assertArrayHasKey('type', $specs, "the _spec function for $entityName field $field does not specify the type");
912 switch ($specs['type']) {
913 case CRM_Utils_Type::T_DATE:
914 case CRM_Utils_Type::T_TIMESTAMP:
915 $entity[$fieldName] = '2012-05-20';
916 break;
917 //case CRM_Utils_Type::T_DATETIME:
918
919 case 12:
920 $entity[$fieldName] = '2012-05-20 03:05:20';
921 break;
922
923 case CRM_Utils_Type::T_STRING:
924 case CRM_Utils_Type::T_BLOB:
925 case CRM_Utils_Type::T_MEDIUMBLOB:
926 case CRM_Utils_Type::T_TEXT:
927 case CRM_Utils_Type::T_LONGTEXT:
928 case CRM_Utils_Type::T_EMAIL:
929 $entity[$fieldName] = substr('New String',0, CRM_Utils_Array::Value('maxlength',$specs,100));
930 break;
931
932 case CRM_Utils_Type::T_INT:
933 // probably created with a 1
934 $entity[$fieldName] = '6';
935 if (!empty($specs['FKClassName'])) {
936 if($specs['FKClassName'] == $baoString){
937 $entity[$fieldName] = (string) $entity2['id'];
938 }
939 else{
940 $uniqueName = CRM_Utils_Array::value('uniqueName', $specs);
941 $entity[$fieldName] = (string) empty($entity2[$field]) ? CRM_Utils_Array::value($uniqueName, $entity2) : $entity2[$field];
942 //todo - there isn't always something set here - & our checking on unset values is limited
943 if (empty($entity[$field])) {
944 unset($entity[$field]);
945 }
946 }
947 }
948 break;
949
950 case CRM_Utils_Type::T_BOOLEAN:
951 // probably created with a 1
952 $entity[$fieldName] = '0';
953 break;
954
955 case CRM_Utils_Type::T_FLOAT:
956 case CRM_Utils_Type::T_MONEY:
957 $entity[$field] = '22.75';
958 break;
959
960 case CRM_Utils_Type::T_URL:
961 $entity[$field] = 'warm.beer.com';
962 }
963 if (!empty($specs['pseudoconstant'])) {
964 $options = $this->callAPISuccess($entityName, 'getoptions', array('context' => 'create', 'field' => $field));
965 if (empty($options['values'])) {
966 //eg. pdf_format id doesn't ship with any
967 if(isset($specs['pseudoconstant']['optionGroupName'])) {
968 $optionGroupID = $this->callAPISuccess('option_group', 'getvalue', array('name' => 'pdf_format', 'return' => 'id'));
969 $optionValue = $this->callAPISuccess('option_value', 'create', array('option_group_id' => $optionGroupID, 'label' => 'new option value'));
970 $options['values'][] = $optionValue['id'];
971 }
972 }
973 $entity[$field] = array_rand($options['values']);
974 }
975 $updateParams = array(
976 'id' => $entity['id'],
977 $field => isset($entity[$field]) ? $entity[$field] : NULL,
978 );
979 if(isset($updateParams['financial_type_id']) && $entityName != 'Product') {
980 //api has special handling on these 2 fields for backward compatibility reasons
981 $entity['contribution_type_id'] = $updateParams['financial_type_id'];
982 }
983
984 $update = $this->callAPISuccess($entityName, 'create', $updateParams);
985 $checkParams = array(
986 'id' => $entity['id'],
987 'sequential' => 1,
988 'return' => $return,
989 'options' => array(
990 'sort' => 'id DESC',
991 'limit' => 2,
992 ),
993 );
994
995 $checkEntity = $this->callAPISuccess($entityName, 'getsingle', $checkParams);
996 $this->assertAPIArrayComparison($entity, $checkEntity, array(), "checking if $fieldName was correctly updated\n" . print_r(array('update-params' => $updateParams, 'update-result' => $update, 'getsingle-params' => $checkParams, 'getsingle-result' => $checkEntity, 'expected entity' => $entity), TRUE));
997 }
998 $baoObj->free();
999 }
1000
1001 /** testing the _getFields **/
1002
1003 /** testing the _delete **/
1004
1005 /**
1006 * @dataProvider toBeSkipped_delete
1007 entities that don't need a delete action
1008 */
1009 public function testNotImplemented_delete($Entity) {
1010 $nonExistantID = 151416349;
1011 $result = civicrm_api($Entity, 'Delete', array('version' => 3, 'id' => $nonExistantID));
1012 $this->assertEquals(1, $result['is_error'], 'In line ' . __LINE__);
1013 $this->assertContains(strtolower("API ($Entity, Delete) does not exist"), strtolower($result['error_message']));
1014 }
1015
1016 /**
1017 * @dataProvider entities
1018 * @expectedException PHPUnit_Framework_Error
1019 */
1020 public function testWithoutParam_delete($Entity) {
1021 // should delete php complaining that a param is missing
1022 $result = civicrm_api($Entity, 'Delete');
1023 }
1024
1025 /**
1026 * @dataProvider entities_delete
1027 */
1028 public function testEmptyParam_delete($Entity) {
1029 if (in_array($Entity, $this->toBeImplemented['delete'])) {
1030 // $this->markTestIncomplete("civicrm_api3_{$Entity}_delete to be implemented");
1031 return;
1032 }
1033 $result = civicrm_api($Entity, 'Delete', array());
1034 $this->assertEquals(1, $result['is_error'], 'In line ' . __LINE__);
1035 $this->assertContains("Mandatory key(s) missing from params array", $result['error_message']);
1036 }
1037 /**
1038 * @dataProvider entities_delete
1039 */
1040 public function testInvalidID_delete($Entity) {
1041 // turn test off for now
1042 $this->markTestIncomplete("Entity [ $Entity ] cannot be mocked - no known DAO");
1043 return;
1044 if (in_array($Entity, $this->toBeImplemented['delete'])) {
1045 // $this->markTestIncomplete("civicrm_api3_{$Entity}_delete to be implemented");
1046 return;
1047 }
1048 $result = $this->callAPIFailure($Entity, 'Delete', array('id' => 999));
1049 }
1050 /**
1051 * @dataProvider entities
1052 */
1053 public function testDeleteWrongTypeParamTag_delete() {
1054 $result = civicrm_api("Tag", 'Delete', 'this is not a string');
1055 $this->assertEquals(1, $result['is_error'], 'In line ' . __LINE__);
1056 $this->assertEquals("Input variable `params` is not an array", $result['error_message']);
1057 }
1058
1059 /**
1060 * Create two entities and make sure delete action only deletes one!
1061 *
1062 * @dataProvider entities_delete
1063 *
1064 * limitations include the problem with avoiding loops when creating test objects -
1065 * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
1066 * Currency - only seems to support US
1067 */
1068 public function testByID_delete($entityName) {
1069 // turn test off for noew
1070 $this->markTestIncomplete("Entity [$entityName] cannot be mocked - no known DAO");
1071 return;
1072
1073 if (in_array($entityName, self::toBeSkipped_automock(TRUE))) {
1074 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
1075 return;
1076 }
1077 $startCount = $this->callAPISuccess($entityName, 'getcount', array());
1078 $createcount = 2;
1079 $baos = $this->getMockableBAOObjects($entityName, $createcount);
1080 list($baoObj1, $baoObj2) = $baos;
1081
1082 // make sure exactly 2 exist
1083 $result = $this->callAPISuccess($entityName, 'getcount', array(),
1084 $createcount + $startCount
1085 );
1086
1087 $this->callAPISuccess($entityName, 'delete', array('id' => $baoObj2->id));
1088 //make sure 1 less exists now
1089 $result = $this->callAPISuccess($entityName, 'getcount', array(),
1090 ($createcount + $startCount) -1
1091 );
1092
1093 //make sure id #1 exists
1094 $result = $this->callAPISuccess($entityName, 'getcount', array('id' => $baoObj1->id),
1095 1
1096 );
1097 //make sure id #2 desn't exist
1098 $result = $this->callAPISuccess($entityName, 'getcount', array('id' => $baoObj2->id),
1099 0
1100 );
1101 }
1102
1103 /**
1104 * @param $entityName
1105 * @param int $count
1106 *
1107 * @internal param $entityName
1108 *
1109 * @return array
1110 */
1111 private function getMockableBAOObjects($entityName, $count = 2) {
1112 $baoString = _civicrm_api3_get_DAO($entityName);
1113 if (empty($baoString)) {
1114 $this->markTestIncomplete("Entity [$entityName] cannot be mocked - no known DAO");
1115 return;
1116 }
1117 $baos = array();
1118 $i = 0;
1119 while($i < $count) {
1120 // create entities
1121 $baoObj = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
1122 $this->assertTrue(is_integer($baoObj->id), 'check first id');
1123 $this->deletableTestObjects[$baoString][] = $baoObj->id;
1124 $baos[] = $baoObj;
1125 $i ++;
1126 }
1127 return $baos;
1128 }
1129
1130
1131 /**
1132 * Verify that HTML metacharacters provided as inputs appear consistently
1133 * as outputs.
1134 *
1135 * At time of writing, the encoding scheme requires (for example) that an
1136 * event title be partially-HTML-escaped before writing to DB. To provide
1137 * consistency, the API must perform extra encoding and decoding on some
1138 * fields.
1139 *
1140 * In this example, the event 'title' is subject to encoding, but the
1141 * event 'description' is not.
1142 */
1143 public function testEncodeDecodeConsistency() {
1144 // Create example
1145 $createResult = civicrm_api('Event', 'Create', array(
1146 'version' => 3,
1147 'title' => 'CiviCRM <> TheRest',
1148 'description' => 'TheRest <> CiviCRM',
1149 'event_type_id' => 1,
1150 'is_public' => 1,
1151 'start_date' => 20081021,
1152 ));
1153 $this->assertAPISuccess($createResult);
1154 $eventId = $createResult['id'];
1155 $this->assertEquals('CiviCRM <> TheRest', $createResult['values'][$eventId]['title']);
1156 $this->assertEquals('TheRest <> CiviCRM', $createResult['values'][$eventId]['description']);
1157
1158 // Verify "get" handles decoding in result value
1159 $getByIdResult = civicrm_api('Event', 'Get', array(
1160 'version' => 3,
1161 'id' => $eventId,
1162 ));
1163 $this->assertAPISuccess($getByIdResult);
1164 $this->assertEquals('CiviCRM <> TheRest', $getByIdResult['values'][$eventId]['title']);
1165 $this->assertEquals('TheRest <> CiviCRM', $getByIdResult['values'][$eventId]['description']);
1166
1167 // Verify "get" handles encoding in search value
1168 $getByTitleResult = civicrm_api('Event', 'Get', array(
1169 'version' => 3,
1170 'title' => 'CiviCRM <> TheRest',
1171 ));
1172 $this->assertAPISuccess($getByTitleResult);
1173 $this->assertEquals('CiviCRM <> TheRest', $getByTitleResult['values'][$eventId]['title']);
1174 $this->assertEquals('TheRest <> CiviCRM', $getByTitleResult['values'][$eventId]['description']);
1175
1176 // Verify that "getSingle" handles decoding
1177 $getSingleResult = $this->callAPISuccess('Event', 'GetSingle', array(
1178 'id' => $eventId,
1179 ));
1180
1181 $this->assertEquals('CiviCRM <> TheRest', $getSingleResult['title']);
1182 $this->assertEquals('TheRest <> CiviCRM', $getSingleResult['description']);
1183
1184 // Verify that chaining handles decoding
1185 $chainResult = $this->callAPISuccess('Event', 'Get', array(
1186 'id' => $eventId,
1187 'api.event.get' => array(
1188 ),
1189 ));
1190 $this->assertEquals('CiviCRM <> TheRest', $chainResult['values'][$eventId]['title']);
1191 $this->assertEquals('TheRest <> CiviCRM', $chainResult['values'][$eventId]['description']);
1192 $this->assertEquals('CiviCRM <> TheRest', $chainResult['values'][$eventId]['api.event.get']['values'][0]['title']);
1193 $this->assertEquals('TheRest <> CiviCRM', $chainResult['values'][$eventId]['api.event.get']['values'][0]['description']);
1194
1195 // Verify that "setvalue" handles encoding for updates
1196 $setValueTitleResult = civicrm_api('Event', 'setvalue', array(
1197 'version' => 3,
1198 'id' => $eventId,
1199 'field' => 'title',
1200 'value' => 'setValueTitle: CiviCRM <> TheRest',
1201 ));
1202 $this->assertAPISuccess($setValueTitleResult);
1203 $this->assertEquals('setValueTitle: CiviCRM <> TheRest', $setValueTitleResult['values']['title']);
1204 $setValueDescriptionResult = civicrm_api('Event', 'setvalue', array(
1205 'version' => 3,
1206 'id' => $eventId,
1207 'field' => 'description',
1208 'value' => 'setValueDescription: TheRest <> CiviCRM',
1209 ));
1210 //$this->assertTrue((bool)$setValueDescriptionResult['is_error']); // not supported by setValue
1211 $this->assertEquals('setValueDescription: TheRest <> CiviCRM', $setValueDescriptionResult['values']['description']);
1212 }
1213
1214 /**
1215 * Verify that write operations (create/update) use partial HTML-encoding
1216 *
1217 * In this example, the event 'title' is subject to encoding, but the
1218 * event 'description' is not.
1219 */
1220 public function testEncodeWrite() {
1221 // Create example
1222 $createResult = civicrm_api('Event', 'Create', array(
1223 'version' => 3,
1224 'title' => 'createNew: CiviCRM <> TheRest',
1225 'description' => 'createNew: TheRest <> CiviCRM',
1226 'event_type_id' => 1,
1227 'is_public' => 1,
1228 'start_date' => 20081021,
1229 ));
1230 $this->assertAPISuccess($createResult);
1231 $eventId = $createResult['id'];
1232 $this->assertDBQuery('createNew: CiviCRM &lt;&gt; TheRest', 'SELECT title FROM civicrm_event WHERE id = %1', array(
1233 1 => array($eventId, 'Integer')
1234 ));
1235 $this->assertDBQuery('createNew: TheRest <> CiviCRM', 'SELECT description FROM civicrm_event WHERE id = %1', array(
1236 1 => array($eventId, 'Integer')
1237 ));
1238
1239 // Verify that "create" handles encoding for updates
1240 $createWithIdResult = civicrm_api('Event', 'Create', array(
1241 'version' => 3,
1242 'id' => $eventId,
1243 'title' => 'createWithId: CiviCRM <> TheRest',
1244 'description' => 'createWithId: TheRest <> CiviCRM',
1245 ));
1246 $this->assertAPISuccess($createWithIdResult);
1247 $this->assertDBQuery('createWithId: CiviCRM &lt;&gt; TheRest', 'SELECT title FROM civicrm_event WHERE id = %1', array(
1248 1 => array($eventId, 'Integer')
1249 ));
1250 $this->assertDBQuery('createWithId: TheRest <> CiviCRM', 'SELECT description FROM civicrm_event WHERE id = %1', array(
1251 1 => array($eventId, 'Integer')
1252 ));
1253
1254 // Verify that "setvalue" handles encoding for updates
1255 $setValueTitleResult = civicrm_api('Event', 'setvalue', array(
1256 'version' => 3,
1257 'id' => $eventId,
1258 'field' => 'title',
1259 'value' => 'setValueTitle: CiviCRM <> TheRest',
1260 ));
1261 $this->assertAPISuccess($setValueTitleResult);
1262 $this->assertDBQuery('setValueTitle: CiviCRM &lt;&gt; TheRest', 'SELECT title FROM civicrm_event WHERE id = %1', array(
1263 1 => array($eventId, 'Integer')
1264 ));
1265 $setValueDescriptionResult = civicrm_api('Event', 'setvalue', array(
1266 'version' => 3,
1267 'id' => $eventId,
1268 'field' => 'description',
1269 'value' => 'setValueDescription: TheRest <> CiviCRM',
1270 ));
1271 //$this->assertTrue((bool)$setValueDescriptionResult['is_error']); // not supported by setValue
1272 $this->assertAPISuccess($setValueDescriptionResult);
1273 $this->assertDBQuery('setValueDescription: TheRest <> CiviCRM', 'SELECT description FROM civicrm_event WHERE id = %1', array(
1274 1 => array($eventId, 'Integer')
1275 ));
1276 }
1277
1278 }