CRM-20972 Attempt to handle new type of Execption thrown in php7.1 when function...
[civicrm-core.git] / tests / phpunit / api / v3 / SyntaxConformanceTest.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
81621fee 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
15a4309a 6 | Copyright CiviCRM LLC (c) 2004-2017 |
6a488035
TO
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035 27
6a488035 28/**
e5dd95b2 29 * Test that the core actions for APIv3 entities comply with standard syntax+behavior.
6a488035 30 *
e5dd95b2
TO
31 * By default, this tests all API entities. To only test specific entities, call phpunit with
32 * environment variable SYNTAX_CONFORMANCE_ENTITIES, e.g.
33 *
34 * env SYNTAX_CONFORMANCE_ENTITIES="Contact Event" ./scripts/phpunit api_v3_SyntaxConformanceTest
35 *
36 * @package CiviCRM_APIv3
37 * @subpackage API_Core
acb109b7 38 * @group headless
6a488035 39 */
8086a0bf 40class api_v3_SyntaxConformanceTest extends CiviUnitTestCase {
18eee50e 41 protected $_apiversion = 3;
6a488035 42
4a97890c
TO
43 /**
44 * @var array e.g. $this->deletes['CRM_Contact_DAO_Contact'][] = $contactID;
45 */
46 protected $deletableTestObjects;
47
be2e0c6a
TO
48 /**
49 * This test case doesn't require DB reset.
50 */
6a488035 51 public $DBResetRequired = FALSE;
6ead217b 52
8efea814
EM
53 protected $_entity;
54
be2e0c6a
TO
55 /**
56 * Map custom group entities to civicrm components.
57 */
82e1689e 58 static $componentMap = array(
82e1689e
N
59 'Contribution' => 'CiviContribute',
60 'Membership' => 'CiviMember',
61 'Participant' => 'CiviEvent',
82e1689e
N
62 'Event' => 'CiviEvent',
63 'Case' => 'CiviCase',
82e1689e
N
64 'Pledge' => 'CiviPledge',
65 'Grant' => 'CiviGrant',
bf38705f 66 'Campaign' => 'CiviCampaign',
67 'Survey' => 'CiviCampaign',
82e1689e
N
68 );
69
63e9c3fd
EM
70 /**
71 * Set up function.
72 *
73 * There are two types of missing APIs:
74 * Those that are to be implemented
75 * (in some future version when someone steps in -hint hint-). List the entities in toBeImplemented[ {$action} ]
76 * Those that don't exist
77 * and that will never exist (eg an obsoleted Entity
78 * 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)
79 */
00be9182 80 public function setUp() {
6a488035 81 parent::setUp();
6ead217b 82 $this->enableCiviCampaign();
92915c55 83 $this->toBeImplemented['get'] = array(
1c7f266f 84 'CxnApp', // CxnApp.get exists but relies on remote data outside our control; QA w/UtilsTest::testBasicArrayGet
92915c55
TO
85 'Profile',
86 'CustomValue',
87 'Constant',
88 'CustomSearch',
89 'Extension',
90 'ReportTemplate',
91 'System',
db7de9c1 92 'Setting',
27ed0b9a 93 'Payment',
93afbc3a 94 'Logging',
92915c55
TO
95 );
96 $this->toBeImplemented['create'] = array(
1c7f266f
TO
97 'Cxn',
98 'CxnApp',
0d57e900 99 'JobLog',
92915c55
TO
100 'SurveyRespondant',
101 'OptionGroup',
102 'MailingRecipients',
103 'UFMatch',
92915c55
TO
104 'CustomSearch',
105 'Extension',
106 'ReportTemplate',
db7de9c1 107 'System',
225d474b 108 'User',
27ed0b9a 109 'Payment',
9422657e 110 'Order',
31fc4809 111 'SavedSearch', //work fine in local
93afbc3a 112 'Logging',
92915c55
TO
113 );
114 $this->toBeImplemented['delete'] = array(
1c7f266f
TO
115 'Cxn',
116 'CxnApp',
0d57e900 117 'JobLog',
92915c55
TO
118 'MembershipPayment',
119 'OptionGroup',
120 'SurveyRespondant',
121 'UFJoin',
122 'UFMatch',
123 'Extension',
db7de9c1 124 'System',
27ed0b9a 125 'Payment',
9422657e 126 'Order',
92915c55 127 );
567b2076
EM
128 $this->onlyIDNonZeroCount['get'] = array(
129 'ActivityType',
130 'Entity',
131 'Domain',
132 'Setting',
225d474b 133 'User',
567b2076 134 );
6a488035 135 $this->deprecatedAPI = array('Location', 'ActivityType', 'SurveyRespondant');
4a97890c 136 $this->deletableTestObjects = array();
6a488035
TO
137 }
138
00be9182 139 public function tearDown() {
4a97890c
TO
140 foreach ($this->deletableTestObjects as $entityName => $entities) {
141 foreach ($entities as $entityID) {
142 CRM_Core_DAO::deleteTestObjects($entityName, array('id' => $entityID));
143 }
144 }
145 }
6a488035 146
4cbe18b8 147 /**
db7de9c1
EM
148 * Generate list of all entities.
149 *
150 * @param array $skip
151 * Entities to skip.
4cbe18b8
EM
152 *
153 * @return array
154 */
db7de9c1 155 public static function entities($skip = array()) {
e5dd95b2
TO
156 // The order of operations in here is screwy. In the case where SYNTAX_CONFORMANCE_ENTITIES is
157 // defined, we should be able to parse+return it immediately. However, some weird dependency
158 // crept into the system where civicrm_api('Entity','get') must be called as part of entities()
159 // (even if its return value is ignored).
dcf56200 160
e5dd95b2 161 $tmp = civicrm_api('Entity', 'Get', array('version' => 3));
dcf56200 162 if (getenv('SYNTAX_CONFORMANCE_ENTITIES')) {
e5dd95b2 163 $tmp = array(
21dfd5f5 164 'values' => explode(' ', getenv('SYNTAX_CONFORMANCE_ENTITIES')),
e5dd95b2 165 );
dcf56200
TO
166 }
167
6a488035
TO
168 if (!is_array($skip)) {
169 $skip = array();
170 }
171 $tmp = array_diff($tmp['values'], $skip);
172 $entities = array();
173 foreach ($tmp as $e) {
174 $entities[] = array($e);
175 }
176 return $entities;
177 }
178
4cbe18b8 179 /**
db7de9c1
EM
180 * Get list of entities for get test.
181 *
4cbe18b8
EM
182 * @return array
183 */
6a488035
TO
184 public static function entities_get() {
185 // all the entities, beside the ones flagged
97715495 186 return static::entities(static::toBeSkipped_get(TRUE));
6a488035
TO
187 }
188
4cbe18b8 189 /**
567b2076
EM
190 * Get entities for create tests.
191 *
4cbe18b8
EM
192 * @return array
193 */
6a488035 194 public static function entities_create() {
97715495 195 return static::entities(static::toBeSkipped_create(TRUE));
6a488035
TO
196 }
197
4cbe18b8
EM
198 /**
199 * @return array
200 */
6a488035 201 public static function entities_updatesingle() {
97715495 202 return static::entities(static::toBeSkipped_updatesingle(TRUE));
6a488035
TO
203 }
204
4cbe18b8
EM
205 /**
206 * @return array
207 */
b9af4758
E
208 public static function entities_getlimit() {
209 return static::entities(static::toBeSkipped_getlimit());
210 }
211
ced9bfed
EM
212 /**
213 * Generate list of entities that can be retrieved using SQL operator syntax.
214 *
215 * @return array
216 */
dcf5b21f
EM
217 public static function entities_getSqlOperators() {
218 return static::entities(static::toBeSkipped_getSqlOperators());
219 }
92915c55 220
4cbe18b8
EM
221 /**
222 * @return array
223 */
6a488035 224 public static function entities_delete() {
97715495 225 return static::entities(static::toBeSkipped_delete(TRUE));
6a488035
TO
226 }
227
32dafeec
EM
228 /**
229 * @return array
230 */
231 public static function entities_getfields() {
232 return static::entities(static::toBeSkipped_getfields(TRUE));
233 }
92915c55 234
4cbe18b8
EM
235 /**
236 * @return array
237 */
2fc5f1e7
EM
238 public static function custom_data_entities_get() {
239 return static::custom_data_entities();
240 }
241
4cbe18b8
EM
242 /**
243 * @return array
244 */
2fc5f1e7 245 public static function custom_data_entities() {
82e1689e 246 $entities = CRM_Core_BAO_CustomQuery::$extendsMap;
84fb7424 247 $enabledComponents = Civi::settings()->get('enable_components');
82e1689e 248 $customDataEntities = array();
2fc5f1e7 249 $invalidEntities = array('Individual', 'Organization', 'Household');
2f6264b4 250 $entitiesToFix = array('Case', 'Relationship');
481a74f4 251 foreach ($entities as $entityName => $entity) {
22e263ad 252 if (!in_array($entityName, $invalidEntities)
92915c55
TO
253 && !in_array($entityName, $entitiesToFix)
254 ) {
22e263ad 255 if (!empty(self::$componentMap[$entityName]) && empty($enabledComponents[self::$componentMap[$entityName]])) {
6c6e6187
TO
256 CRM_Core_BAO_ConfigSetting::enableComponent(self::$componentMap[$entityName]);
257 }
258 $customDataEntities[] = array($entityName);
82e1689e
N
259 }
260 }
2fc5f1e7
EM
261 return $customDataEntities;
262 }
263
4cbe18b8 264 /**
567b2076
EM
265 * Get entities to be skipped on get tests.
266 *
4cbe18b8
EM
267 * @param bool $sequential
268 *
269 * @return array
270 */
6a488035 271 public static function toBeSkipped_get($sequential = FALSE) {
92915c55
TO
272 $entitiesWithoutGet = array(
273 'MailingEventSubscribe',
274 'MailingEventConfirm',
275 'MailingEventResubscribe',
276 'MailingEventUnsubscribe',
567b2076 277 'Location',
92915c55 278 );
6a488035
TO
279 if ($sequential === TRUE) {
280 return $entitiesWithoutGet;
281 }
282 $entities = array();
283 foreach ($entitiesWithoutGet as $e) {
284 $entities[] = array($e);
285 }
286 return $entities;
287 }
b7d29345 288
b14ce773 289 /**
fd786d03
EM
290 * Get entities to be skipped for get call.
291 *
b14ce773 292 * Mailing Contact Just doesn't support id. We have always insisted on finding a way to
4a2db77c 293 * support id in API but in this case the underlying tables are crying out for a restructure
225d474b
EM
294 * & it just doesn't make sense.
295 *
296 * User doesn't support get By ID because the user id is actually the CMS user ID & is not part of
297 * CiviCRM - so can only be tested through UserTest - not SyntaxConformanceTest.
b7d29345 298 *
8ab09481 299 * Entity doesn't support get By ID because it simply gives the result of string Entites in CiviCRM
300 *
4a2db77c 301 * @param bool $sequential
b7d29345 302 *
a6c01b45
CW
303 * @return array
304 * Entities that cannot be retrieved by ID
b14ce773 305 */
306 public static function toBeSkipped_getByID($sequential = FALSE) {
8ab09481 307 return array('MailingContact', 'User', 'Attachment', 'Entity');
b14ce773 308 }
6a488035 309
4cbe18b8
EM
310 /**
311 * @param bool $sequential
312 *
313 * @return array
314 */
6a488035 315 public static function toBeSkipped_create($sequential = FALSE) {
21eb0c57 316 $entitiesWithoutCreate = array('Constant', 'Entity', 'Location', 'Profile', 'MailingRecipients');
6a488035
TO
317 if ($sequential === TRUE) {
318 return $entitiesWithoutCreate;
319 }
320 $entities = array();
321 foreach ($entitiesWithoutCreate as $e) {
322 $entities[] = array($e);
323 }
324 return $entities;
325 }
326
4cbe18b8
EM
327 /**
328 * @param bool $sequential
329 *
330 * @return array
331 */
6a488035 332 public static function toBeSkipped_delete($sequential = FALSE) {
92915c55
TO
333 $entitiesWithout = array(
334 'MailingContact',
335 'MailingEventConfirm',
336 'MailingEventResubscribe',
337 'MailingEventSubscribe',
338 'MailingEventUnsubscribe',
339 'MailingRecipients',
340 'Constant',
341 'Entity',
342 'Location',
343 'Domain',
344 'Profile',
345 'CustomValue',
92c99a4a 346 'Setting',
225d474b 347 'User',
93afbc3a 348 'Logging',
92915c55 349 );
6a488035
TO
350 if ($sequential === TRUE) {
351 return $entitiesWithout;
352 }
353 $entities = array();
354 foreach ($entitiesWithout as $e) {
355 $entities[] = array($e);
356 }
357 return $entities;
358 }
b7d29345 359
32dafeec
EM
360 /**
361 * @param bool $sequential
362 *
363 * @return array
364 * @todo add metadata for ALL these entities
365 */
366 public static function toBeSkipped_getfields($sequential = FALSE) {
17eeaef9 367 $entitiesWithMetadataNotYetFixed = array('ReportTemplate', 'CustomSearch');
32dafeec 368 if ($sequential === TRUE) {
6c6e6187 369 return $entitiesWithMetadataNotYetFixed;
32dafeec
EM
370 }
371 $entities = array();
372 foreach ($entitiesWithMetadataNotYetFixed as $e) {
373 $entities[] = array($e);
374 }
375 return $entities;
376 }
92915c55 377
6c6e6187 378 /**
eceb18cc 379 * Generate list of entities to test for get by id functions.
6c6e6187 380 * @param bool $sequential
a6c01b45
CW
381 * @return array
382 * Entities to be skipped
6c6e6187 383 */
b07a3bf9 384 public static function toBeSkipped_automock($sequential = FALSE) {
92915c55
TO
385 $entitiesWithoutGet = array(
386 'MailingContact',
387 'EntityTag',
388 'Participant',
389 'ParticipantPayment',
390 'Setting',
391 'SurveyRespondant',
392 'MailingRecipients',
393 'CustomSearch',
394 'Extension',
395 'ReportTemplate',
af9b09df 396 'System',
93afbc3a 397 'Logging',
92915c55 398 );
b07a3bf9
TO
399 if ($sequential === TRUE) {
400 return $entitiesWithoutGet;
401 }
402 $entities = array();
403 foreach ($entitiesWithoutGet as $e) {
404 $entities[] = array($e);
405 }
406 return $entities;
407 }
408
b7d29345 409 /**
6c6e6187 410 * At this stage exclude the ones that don't pass & add them as we can troubleshoot them
1e1fdcf6
EM
411 * @param bool $sequential
412 * @return array
6c6e6187 413 */
6a488035
TO
414 public static function toBeSkipped_updatesingle($sequential = FALSE) {
415 $entitiesWithout = array(
92915c55
TO
416 'Attachment',
417 // pseudo-entity; testUpdateSingleValueAlter doesn't introspect properly on it. Multiple magic fields
6a488035
TO
418 'Mailing',
419 'MailingGroup',
420 'MailingJob',
421 'Address',
422 'MailingEventUnsubscribe',
423 'MailingEventSubscribe',
424 'Constant',
425 'Entity',
426 'Location',
427 'Domain',
428 'Profile',
429 'CustomValue',
430 'SurveyRespondant',
6a488035
TO
431 'UFMatch',
432 'UFJoin',
433 'UFField',
434 'OptionValue',
435 'Relationship',
436 'RelationshipType',
6a488035
TO
437 'Note',
438 'OptionGroup',
439 'Membership',
6a488035
TO
440 'Group',
441 'GroupOrganization',
442 'GroupNesting',
6a488035
TO
443 'File',
444 'EntityTag',
445 'CustomField',
446 'CustomGroup',
447 'Contribution',
6a488035
TO
448 'ActivityType',
449 'MailingEventConfirm',
450 'Case',
1816ac4c 451 'CaseContact',
6a488035
TO
452 'Contact',
453 'ContactType',
454 'MailingEventResubscribe',
455 'UFGroup',
456 'Activity',
6a488035
TO
457 'Event',
458 'GroupContact',
459 'MembershipPayment',
460 'Participant',
461 'ParticipantPayment',
462 'LineItem',
6a488035
TO
463 'PledgePayment',
464 'ContributionPage',
465 'Phone',
faacb3e4 466 'PaymentProcessor',
6a488035 467 'Setting',
b14ce773 468 'MailingContact',
af9b09df 469 'SystemLog',
92915c55 470 //skip this because it doesn't make sense to update logs,
93afbc3a 471 'Logging',
6a488035
TO
472 );
473 if ($sequential === TRUE) {
474 return $entitiesWithout;
475 }
476 $entities = array();
477 foreach ($entitiesWithout as $e) {
478 $entities[] = array(
479 $e,
480 );
481 }
482 return array('pledge');
483 return $entities;
484 }
485
b7d29345 486 /**
b9af4758 487 * At this stage exclude the ones that don't pass & add them as we can troubleshoot them
b7d29345 488 */
b9af4758
E
489 public static function toBeSkipped_getlimit() {
490 $entitiesWithout = array(
92915c55
TO
491 'Case',
492 //case api has non-std mandatory fields one of (case_id, contact_id, activity_id, contact_id)
493 'EntityTag',
494 // non-standard api - has inappropriate mandatory fields & doesn't implement limit
495 'Event',
496 // failed 'check that a 5 limit returns 5' - probably is_template field is wrong or something, or could be limit doesn't work right
497 'Extension',
498 // can't handle creating 25
499 'Note',
500 // fails on 5 limit - probably a set up problem
501 'Setting',
502 //a bit of a pseudoapi - keys by domain
b9af4758
E
503 );
504 return $entitiesWithout;
505 }
506
dcf5b21f
EM
507 /**
508 * At this stage exclude the ones that don't pass & add them as we can troubleshoot them
509 */
510 public static function toBeSkipped_getSqlOperators() {
511 $entitiesWithout = array(
6c6e6187 512 'Case', //case api has non-std mandatory fields one of (case_id, contact_id, activity_id, contact_id)
0ae1863a 513 'Contact', // on the todo list!
dcf5b21f
EM
514 'EntityTag', // non-standard api - has inappropriate mandatory fields & doesn't implement limit
515 'Extension', // can't handle creating 25
516 'Note', // note has a default get that isn't implemented in createTestObject -meaning you don't 'get' them
dcf5b21f
EM
517 'Setting', //a bit of a pseudoapi - keys by domain
518 );
519 return $entitiesWithout;
520 }
521
0f583c8f
EM
522 /**
523 * @param $entity
524 * @param $key
525 *
526 * @return array
527 */
9b873358 528 public function getKnownUnworkablesUpdateSingle($entity, $key) {
6a488035
TO
529 // can't update values are values for which updates don't result in the value being changed
530 $knownFailures = array(
03fe1a00
TO
531 'ActionSchedule' => array(
532 'cant_update' => array(
533 'group_id',
534 ),
535 ),
0f583c8f
EM
536 'ActivityContact' => array(
537 'cant_update' => array(
92915c55
TO
538 'activity_id',
539 //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
0f583c8f
EM
540 ),
541 ),
6a488035
TO
542 'Address' => array(
543 'cant_update' => array(
544 'state_province_id', //issues with country id - need to ensure same country
6c6e6187 545 'master_id', //creates relationship
6a488035 546 ),
21dfd5f5 547 'cant_return' => array(),
6a488035 548 ),
6ead217b
E
549 'Batch' => array(
550 'cant_update' => array(
551 'entity_table', // believe this field is defined in error
552 ),
553 'cant_return' => array(
554 'entity_table',
21dfd5f5 555 ),
6ead217b 556 ),
1753bd71
TO
557 'CaseType' => array(
558 'cant_update' => array(
559 'definition',
21dfd5f5 560 ),
1753bd71 561 ),
95520636
TO
562 'MembershipBlock' => array(
563 'cant_update' => array(
564 // The fake/auto-generated values leave us unable to properly cleanup fake data
565 'entity_type',
566 'entity_id',
21dfd5f5 567 ),
95520636 568 ),
7d543448 569 'ContributionSoft' => array(
570 'cant_update' => array(
571 // can't be changed through api
572 'pcp_id',
573 ),
574 ),
7629d5a6 575 'Email' => array(
576 'cant_update' => array(
577 // This is being legitimately manipulated to always have a valid primary - skip.
578 'is_primary',
579 ),
580 ),
3523b615 581 'Navigation' => array(
582 'cant_update' => array(
583 // Weight is deliberately altered when this is changed - skip.
584 'parent_id',
585 ),
586 ),
9859f345 587 'LocationType' => array(
588 'cant_update' => array(
589 // I'm on the fence about whether the test should skip or the behaviour is wrong.
590 // display_name is set to match name if display_name is not provided. It would be more 'normal'
591 // to only calculate a default IF id is not set - but perhaps the current behaviour is kind
592 // of what someone updating the name expects..
593 'name',
594 ),
595 ),
6a488035
TO
596 'Pledge' => array(
597 'cant_update' => array(
598 'pledge_original_installment_amount',
599 'installments',
600 'original_installment_amount',
601 'next_pay_date',
af9b09df 602 'amount', // can't be changed through API,
6a488035
TO
603 ),
604 'break_return' => array(// if these are passed in they are retrieved from the wrong table
605 'honor_contact_id',
606 'cancel_date',
607 'contribution_page_id',
608 'financial_account_id',
609 'financial_type_id',
21dfd5f5 610 'currency',
6a488035
TO
611 ),
612 'cant_return' => array(// can't be retrieved from api
613 'honor_type_id', //due to uniquename missing
614 'end_date',
615 'modified_date',
616 'acknowledge_date',
617 'start_date',
618 'frequency_day',
619 'currency',
620 'max_reminders',
621 'initial_reminder_day',
622 'additional_reminder_day',
623 'frequency_unit',
624 'pledge_contribution_page_id',
625 'pledge_status_id',
626 'pledge_campaign_id',
b06d9acd 627 'pledge_financial_type_id',
21dfd5f5 628 ),
6a488035
TO
629 ),
630 'PaymentProcessorType' => array(
631 'cant_update' => array(
632 'billing_mode',
633 ),
6c6e6187
TO
634 'break_return' => array(),
635 'cant_return' => array(),
6a488035 636 ),
db232378
EM
637 'PriceFieldValue' => array(
638 'cant_update' => array(
639 'weight', //won't update as there is no 1 in the same price set
640 ),
641 ),
e6e7e540 642 'ReportInstance' => array(
643 // View mode is part of the navigation which is not retrieved by the api.
644 'cant_return' => array('view_mode'),
645 ),
5ba7b9fd
JV
646 'SavedSearch' => array(
647 // I think the fields below are generated based on form_values.
648 'cant_update' => array(
649 'search_custom_id',
650 'where_clause',
651 'select_tables',
652 'where_tables',
dafc75f8
JV
653 ),
654 ),
d47a6f4a
J
655 'StatusPreference' => array(
656 'break_return' => array(
657 'ignore_severity',
658 ),
659 ),
6a488035 660 );
9b873358 661 if (empty($knownFailures[$entity]) || empty($knownFailures[$entity][$key])) {
6a488035
TO
662 return array();
663 }
664 return $knownFailures[$entity][$key];
665 }
666
be2e0c6a 667 /* ----- testing the _get ----- */
6a488035
TO
668
669 /**
670 * @dataProvider toBeSkipped_get
be2e0c6a 671 * Entities that don't need a get action
1e1fdcf6 672 * @param $Entity
6a488035
TO
673 */
674 public function testNotImplemented_get($Entity) {
675 $result = civicrm_api($Entity, 'Get', array('version' => 3));
ba4a1892 676 $this->assertEquals(1, $result['is_error']);
311873a0 677 // $this->assertContains("API ($Entity, Get) does not exist", $result['error_message']);
6c6e6187 678 $this->assertRegExp('/API (.*) does not exist/', $result['error_message']);
6a488035
TO
679 }
680
681 /**
682 * @dataProvider entities
1e1fdcf6 683 * @param $Entity
6a488035
TO
684 */
685 public function testWithoutParam_get($Entity) {
686 // should get php complaining that a param is missing
2a4cb975
SL
687 try {
688 $result = civicrm_api($Entity, 'Get');
689 $this->fail('Expected an exception. No exception was thrown.');
690 }
691 catch (ArgumentCountError $e) {
692 /* ok */
693 }
694 catch (PHPUnit_Framework_Error $e) {
695 /* ok */
696 }
6a488035
TO
697 }
698
699 /**
700 * @dataProvider entities
1e1fdcf6 701 * @param $Entity
6a488035
TO
702 */
703 public function testGetFields($Entity) {
bd6658bd 704 if (in_array($Entity, $this->deprecatedAPI) || $Entity == 'Entity' || $Entity == 'CustomValue') {
6a488035
TO
705 return;
706 }
707
708 $result = civicrm_api($Entity, 'getfields', array('version' => 3));
709 $this->assertTrue(is_array($result['values']), "$Entity ::get fields doesn't return values array in line " . __LINE__);
710 foreach ($result['values'] as $key => $value) {
711 $this->assertTrue(is_array($value), $Entity . "::" . $key . " is not an array in line " . __LINE__);
712 }
713 }
714
715 /**
716 * @dataProvider entities_get
1e1fdcf6 717 * @param $Entity
6a488035
TO
718 */
719 public function testEmptyParam_get($Entity) {
720
721 if (in_array($Entity, $this->toBeImplemented['get'])) {
722 // $this->markTestIncomplete("civicrm_api3_{$Entity}_get to be implemented");
723 return;
724 }
725 $result = civicrm_api($Entity, 'Get', array());
ba4a1892 726 $this->assertEquals(1, $result['is_error']);
34e21ce8 727 $this->assertContains("Unknown api version", $result['error_message']);
6a488035 728 }
92915c55 729
6a488035
TO
730 /**
731 * @dataProvider entities_get
1e1fdcf6 732 * @param $Entity
6a488035
TO
733 */
734 public function testEmptyParam_getString($Entity) {
735
736 if (in_array($Entity, $this->toBeImplemented['get'])) {
737 // $this->markTestIncomplete("civicrm_api3_{$Entity}_get to be implemented");
738 return;
739 }
d0e1eff2 740 $result = $this->callAPIFailure($Entity, 'Get', 'string');
6a488035
TO
741 $this->assertEquals(2000, $result['error_code']);
742 $this->assertEquals('Input variable `params` is not an array', $result['error_message']);
743 }
92915c55 744
6a488035
TO
745 /**
746 * @dataProvider entities_get
747 * @Xdepends testEmptyParam_get // no need to test the simple if the empty doesn't work/is skipped. doesn't seem to work
1e1fdcf6 748 * @param $Entity
6a488035
TO
749 */
750 public function testSimple_get($Entity) {
751 // $this->markTestSkipped("test gives core error on test server (but not on our locals). Skip until we can get server to pass");
6a488035
TO
752 if (in_array($Entity, $this->toBeImplemented['get'])) {
753 return;
754 }
755 $result = civicrm_api($Entity, 'Get', array('version' => 3));
756 // @TODO: list the get that have mandatory params
757 if ($result['is_error']) {
758 $this->assertContains("Mandatory key(s) missing from params array", $result['error_message']);
759 // either id or contact_id or entity_id is one of the field missing
760 $this->assertContains("id", $result['error_message']);
761 }
762 else {
763 $this->assertEquals(3, $result['version']);
764 $this->assertArrayHasKey('count', $result);
765 $this->assertArrayHasKey('values', $result);
766 }
767 }
768
2fc5f1e7
EM
769 /**
770 * @dataProvider custom_data_entities_get
1e1fdcf6 771 * @param $entityName
2fc5f1e7
EM
772 */
773 public function testCustomDataGet($entityName) {
774 $this->createLoggedInUser();// so subsidiary activities are created
1391d5ec 775 // We are not passing 'check_permissions' so the the more limited permissions *should* be
776 // ignored but per CRM-17700 there is a history of custom data applying permissions when it shouldn't.
777 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'view my contact');
2fc5f1e7
EM
778 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, $entityName . 'Test.php');
779 $customFieldName = 'custom_' . $ids['custom_field_id'];
780 $objects = $this->getMockableBAOObjects($entityName, 1);
781 $params = array('id' => $objects[0]->id, 'custom_' . $ids['custom_field_id'] => "custom string");
782 $result = $this->callAPISuccess($entityName, 'create', $params);
783
784 $getParams = array('id' => $result['id'], 'return' => array($customFieldName));
785 $check = $this->callAPISuccess($entityName, 'get', $getParams);
786 $this->assertEquals("custom string", $check['values'][$check['id']][$customFieldName]);
787
788 $this->customFieldDelete($ids['custom_field_id']);
789 $this->customGroupDelete($ids['custom_group_id']);
790 $this->callAPISuccess($entityName, 'delete', array('id' => $result['id']));
b2c4e136 791 $this->quickCleanup(array('civicrm_uf_match'));
2fc5f1e7
EM
792 }
793
6a488035
TO
794 /**
795 * @dataProvider entities_get
1e1fdcf6 796 * @param $Entity
6a488035
TO
797 */
798 public function testAcceptsOnlyID_get($Entity) {
799 // big random number. fun fact: if you multiply it by pi^e, the result is another random number, but bigger ;)
800 $nonExistantID = 30867307034;
b14ce773 801 if (in_array($Entity, $this->toBeImplemented['get'])
92915c55 802 || in_array($Entity, $this->toBeSkipped_getByID())
b14ce773 803 ) {
6a488035
TO
804 return;
805 }
806
807 // FIXME
808 // the below function returns different values and hence an early return
809 // we'll fix this once beta1 is released
810 // return;
811
c679daca 812 $result = civicrm_api($Entity, 'Get', array('version' => 3, 'id' => $nonExistantID));
6a488035
TO
813
814 if ($result['is_error']) {
815 // just to get a clearer message in the log
816 $this->assertEquals("only id should be enough", $result['error_message']);
817 }
818 if (!in_array($Entity, $this->onlyIDNonZeroCount['get'])) {
819 $this->assertEquals(0, $result['count']);
820 }
821 }
822
823 /**
eceb18cc 824 * Create two entities and make sure we can fetch them individually by ID.
4a97890c
TO
825 *
826 * @dataProvider entities_get
827 *
828 * limitations include the problem with avoiding loops when creating test objects -
829 * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
830 * Currency - only seems to support US
1e1fdcf6 831 * @param $entityName
4a97890c
TO
832 */
833 public function testByID_get($entityName) {
b07a3bf9 834 if (in_array($entityName, self::toBeSkipped_automock(TRUE))) {
4a97890c
TO
835 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
836 return;
837 }
838
18eee50e 839 $baos = $this->getMockableBAOObjects($entityName);
840 list($baoObj1, $baoObj2) = $baos;
4a97890c
TO
841
842 // fetch first by ID
6ead217b 843 $result = $this->callAPISuccess($entityName, 'get', array(
4a97890c
TO
844 'id' => $baoObj1->id,
845 ));
6ead217b 846
4a97890c
TO
847 $this->assertTrue(!empty($result['values'][$baoObj1->id]), 'Should find first object by id');
848 $this->assertEquals($baoObj1->id, $result['values'][$baoObj1->id]['id'], 'Should find id on first object');
849 $this->assertEquals(1, count($result['values']));
850
851 // fetch second by ID
6ead217b 852 $result = $this->callAPISuccess($entityName, 'get', array(
4a97890c
TO
853 'id' => $baoObj2->id,
854 ));
4a97890c
TO
855 $this->assertTrue(!empty($result['values'][$baoObj2->id]), 'Should find second object by id');
856 $this->assertEquals($baoObj2->id, $result['values'][$baoObj2->id]['id'], 'Should find id on second object');
857 $this->assertEquals(1, count($result['values']));
858 }
859
b9af4758
E
860 /**
861 * Ensure that the "get" operation accepts limiting the #result records.
862 *
863 * TODO Consider making a separate entity list ("entities_getlimit")
864 * For the moment, the "entities_updatesingle" list should give a good
865 * sense for which entities support createTestObject
866 *
867 * @dataProvider entities_getlimit
8efea814 868 *
c490a46a 869 * @param string $entityName
b9af4758 870 */
00be9182 871 public function testLimit($entityName) {
b9af4758
E
872 $cases = array(); // each case is array(0 => $inputtedApiOptions, 1 => $expectedResultCount)
873 $cases[] = array(
874 array('options' => array('limit' => NULL)),
ebddc2d9
EM
875 30,
876 'check that a NULL limit returns unlimited',
b9af4758
E
877 );
878 $cases[] = array(
879 array('options' => array('limit' => FALSE)),
ebddc2d9
EM
880 30,
881 'check that a FALSE limit returns unlimited',
b9af4758
E
882 );
883 $cases[] = array(
884 array('options' => array('limit' => 0)),
ebddc2d9
EM
885 30,
886 'check that a 0 limit returns unlimited',
b9af4758
E
887 );
888 $cases[] = array(
889 array('options' => array('limit' => 5)),
890 5,
891 'check that a 5 limit returns 5',
892 );
893 $cases[] = array(
894 array(),
895 25,
896 'check that no limit returns 25',
897 );
898
6252a38c 899 $baoString = _civicrm_api3_get_BAO($entityName);
b9af4758
E
900 if (empty($baoString)) {
901 $this->markTestIncomplete("Entity [$entityName] cannot be mocked - no known DAO");
902 return;
903 }
904
905 // make 30 test items -- 30 > 25 (the default limit)
4038f8ec 906 $ids = array();
b9af4758 907 for ($i = 0; $i < 30; $i++) {
8d5544c5 908 $baoObj = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
4038f8ec 909 $ids[] = $baoObj->id;
37eb13b2 910 $baoObj->free();
b9af4758
E
911 }
912
913 // each case is array(0 => $inputtedApiOptions, 1 => $expectedResultCount)
914 foreach ($cases as $case) {
ebddc2d9 915 $this->checkLimitAgainstExpected($entityName, $case[0], $case[1], $case[2]);
a85a667f
EM
916
917 //non preferred / legacy syntax
22e263ad 918 if (isset($case[0]['options']['limit'])) {
ebddc2d9
EM
919 $this->checkLimitAgainstExpected($entityName, array('rowCount' => $case[0]['options']['limit']), $case[1], $case[2]);
920 $this->checkLimitAgainstExpected($entityName, array('option_limit' => $case[0]['options']['limit']), $case[1], $case[2]);
921 $this->checkLimitAgainstExpected($entityName, array('option.limit' => $case[0]['options']['limit']), $case[1], $case[2]);
a85a667f 922 }
b9af4758 923 }
4038f8ec
TO
924 foreach ($ids as $id) {
925 CRM_Core_DAO::deleteTestObjects($baoString, array('id' => $id));
926 }
8d5544c5 927 $baoObj->free();
b9af4758
E
928 }
929
dcf5b21f
EM
930 /**
931 * Ensure that the "get" operation accepts limiting the #result records.
932 *
933 * @dataProvider entities_getSqlOperators
934 *
c490a46a 935 * @param string $entityName
dcf5b21f 936 */
00be9182 937 public function testSqlOperators($entityName) {
8ab09481 938 $toBeIgnored = array_merge($this->toBeImplemented['get'],
939 $this->deprecatedAPI,
940 $this->toBeSkipped_get(TRUE),
941 $this->toBeSkipped_getByID()
942 );
943 if (in_array($entityName, $toBeIgnored)) {
dcf5b21f
EM
944 return;
945 }
8ab09481 946
947 $baoString = _civicrm_api3_get_BAO($entityName);
948
dcf5b21f
EM
949 $entities = $this->callAPISuccess($entityName, 'get', array('options' => array('limit' => 0), 'return' => 'id'));
950 $entities = array_keys($entities['values']);
951 $totalEntities = count($entities);
952 if ($totalEntities < 3) {
953 $ids = array();
954 for ($i = 0; $i < 3 - $totalEntities; $i++) {
955 $baoObj = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
956 $ids[] = $baoObj->id;
37eb13b2 957 $baoObj->free();
dcf5b21f
EM
958 }
959 $totalEntities = 3;
960 }
961 $entities = $this->callAPISuccess($entityName, 'get', array('options' => array('limit' => 0)));
962 $entities = array_keys($entities['values']);
963 $this->assertGreaterThan(2, $totalEntities);
964 $this->callAPISuccess($entityName, 'getsingle', array('id' => array('IN' => array($entities[0]))));
965 $this->callAPISuccessGetCount($entityName, array('id' => array('NOT IN' => array($entities[0]))), $totalEntities - 1);
966 $this->callAPISuccessGetCount($entityName, array('id' => array('>' => $entities[0])), $totalEntities - 1);
967 }
968
ebddc2d9 969 /**
eceb18cc 970 * Check that get fetches an appropriate number of results.
ebddc2d9 971 *
e16033b4
TO
972 * @param string $entityName
973 * Name of entity to test.
dcf5b21f 974 * @param array $params
e16033b4 975 * @param int $limit
dcf5b21f 976 * @param string $message
ebddc2d9 977 */
00be9182 978 public function checkLimitAgainstExpected($entityName, $params, $limit, $message) {
ebddc2d9 979 $result = $this->callAPISuccess($entityName, 'get', $params);
22e263ad 980 if ($limit == 30) {
ebddc2d9
EM
981 $this->assertGreaterThanOrEqual($limit, $result['count'], $message);
982 $this->assertGreaterThanOrEqual($limit, $result['count'], $message);
983 }
984 else {
985 $this->assertEquals($limit, $result['count'], $message);
986 $this->assertEquals($limit, count($result['values']), $message);
987 }
988 }
92915c55 989
afb0ff51
TO
990 /**
991 * Create two entities and make sure we can fetch them individually by ID (e.g. using "contact_id=>2"
992 * or "group_id=>4")
993 *
994 * @dataProvider entities_get
995 *
996 * limitations include the problem with avoiding loops when creating test objects -
997 * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
998 * Currency - only seems to support US
1e1fdcf6
EM
999 * @param $entityName
1000 * @throws \PHPUnit_Framework_IncompleteTestError
afb0ff51
TO
1001 */
1002 public function testByIDAlias_get($entityName) {
c4de8b59 1003 if (in_array($entityName, self::toBeSkipped_automock(TRUE))) {
afb0ff51
TO
1004 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
1005 return;
1006 }
1007
6252a38c 1008 $baoString = _civicrm_api3_get_BAO($entityName);
afb0ff51
TO
1009 if (empty($baoString)) {
1010 $this->markTestIncomplete("Entity [$entityName] cannot be mocked - no known DAO");
1011 return;
1012 }
1013
c4de8b59
TO
1014 $idFieldName = _civicrm_api_get_entity_name_from_camel($entityName) . '_id';
1015
afb0ff51
TO
1016 // create entities
1017 $baoObj1 = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
a1a2a83d 1018 $this->assertTrue(is_int($baoObj1->id), 'check first id');
afb0ff51
TO
1019 $this->deletableTestObjects[$baoString][] = $baoObj1->id;
1020 $baoObj2 = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
a1a2a83d 1021 $this->assertTrue(is_int($baoObj2->id), 'check second id');
afb0ff51
TO
1022 $this->deletableTestObjects[$baoString][] = $baoObj2->id;
1023
1024 // fetch first by ID
1025 $result = civicrm_api($entityName, 'get', array(
1026 'version' => 3,
c4de8b59 1027 $idFieldName => $baoObj1->id,
afb0ff51
TO
1028 ));
1029 $this->assertAPISuccess($result);
1030 $this->assertTrue(!empty($result['values'][$baoObj1->id]), 'Should find first object by id');
1031 $this->assertEquals($baoObj1->id, $result['values'][$baoObj1->id]['id'], 'Should find id on first object');
1032 $this->assertEquals(1, count($result['values']));
1033
1034 // fetch second by ID
1035 $result = civicrm_api($entityName, 'get', array(
1036 'version' => 3,
c4de8b59 1037 $idFieldName => $baoObj2->id,
afb0ff51
TO
1038 ));
1039 $this->assertAPISuccess($result);
1040 $this->assertTrue(!empty($result['values'][$baoObj2->id]), 'Should find second object by id');
1041 $this->assertEquals($baoObj2->id, $result['values'][$baoObj2->id]['id'], 'Should find id on second object');
1042 $this->assertEquals(1, count($result['values']));
1043 }
1044
1045 /**
6a488035 1046 * @dataProvider entities_get
1e1fdcf6 1047 * @param $Entity
6a488035
TO
1048 */
1049 public function testNonExistantID_get($Entity) {
1050 // cf testAcceptsOnlyID_get
1051 $nonExistantID = 30867307034;
1052 if (in_array($Entity, $this->toBeImplemented['get'])) {
1053 return;
1054 }
1055
1056 $result = civicrm_api($Entity, 'Get', array('version' => 3, 'id' => $nonExistantID));
1057
1058 // redundant with testAcceptsOnlyID_get
1059 if ($result['is_error']) {
1060 return;
1061 }
1062
6a488035
TO
1063 $this->assertArrayHasKey('version', $result);
1064 $this->assertEquals(3, $result['version']);
1065 if (!in_array($Entity, $this->onlyIDNonZeroCount['get'])) {
1066 $this->assertEquals(0, $result['count']);
1067 }
1068 }
1069
a1a2a83d 1070 /* ---- testing the _create ---- */
6a488035
TO
1071
1072 /**
1073 * @dataProvider toBeSkipped_create
6c6e6187 1074 entities that don't need a create action
1e1fdcf6 1075 * @param $Entity
6a488035
TO
1076 */
1077 public function testNotImplemented_create($Entity) {
1078 $result = civicrm_api($Entity, 'Create', array('version' => 3));
ba4a1892 1079 $this->assertEquals(1, $result['is_error']);
311873a0 1080 $this->assertContains(strtolower("API ($Entity, Create) does not exist"), strtolower($result['error_message']));
6a488035
TO
1081 }
1082
1083 /**
1084 * @dataProvider entities
01ee5d42 1085 * @expectedException CiviCRM_API3_Exception
1e1fdcf6 1086 * @param $Entity
6a488035
TO
1087 */
1088 public function testWithoutParam_create($Entity) {
df197a56 1089 if ($Entity === 'Setting') {
1090 $this->markTestSkipped('It seems OK for setting to skip here as it silently sips invalid params');
6a488035 1091 }
91387828
TO
1092 elseif ($Entity === 'Mailing') {
1093 $this->markTestSkipped('It seems OK for "Mailing" to skip here because you can create empty drafts');
1094 }
df197a56 1095 // should create php complaining that a param is missing
1096 civicrm_api3($Entity, 'Create');
6a488035
TO
1097 }
1098
1217e5e6
SL
1099 /**
1100 * @dataProvider entities_create
1101 *
1102 * Check that create doesn't work with an invalid
1103 * @param $Entity
1104 * @throws \PHPUnit_Framework_IncompleteTestError
1105 */
1106 public function testInvalidSort_get($Entity) {
1107 $invalidEntitys = array('ActivityType', 'Setting', 'System');
1108 if (in_array($Entity, $invalidEntitys)) {
7da14720 1109 $this->markTestSkipped('It seems OK for ' . $Entity . ' to skip here as it silently sips invalid params');
1217e5e6
SL
1110 }
1111 $result = $this->callAPIFailure($Entity, 'get', array('options' => array('sort' => 'sleep(1)')));
1112 }
1113
8ff43f60
SL
1114 /**
1115 * @dataProvider entities_create
1116 *
1117 * Check that create doesn't work with an invalid
1118 * @param $Entity
1119 * @throws \PHPUnit_Framework_IncompleteTestError
1120 */
1121 public function testValidSortSingleArrayById_get($Entity) {
1122 $invalidEntitys = array('ActivityType', 'Setting', 'System');
74ec0ddb
SL
1123 $tests = array(
1124 'id' => '_id',
1125 'id desc' => '_id desc',
1126 'id DESC' => '_id DESC',
1127 'id ASC' => '_id ASC',
1128 'id asc' => '_id asc');
1129 foreach ($tests as $test => $expected) {
1130 if (in_array($Entity, $invalidEntitys)) {
1131 $this->markTestSkipped('It seems OK for ' . $Entity . ' to skip here as it silently ignores passed in params');
1132 }
1133 $params = array('sort' => array($test));
1134 $result = _civicrm_api3_get_options_from_params($params, FALSE, $Entity, 'get');
1135 $lowercase_entity = _civicrm_api_get_entity_name_from_camel($Entity);
1136 $this->assertEquals($lowercase_entity . $expected, $result['sort']);
8ff43f60 1137 }
8ff43f60
SL
1138 }
1139
18eee50e 1140 /**
1141 * @dataProvider entities_create
1142 *
1143 * Check that create doesn't work with an invalid
1e1fdcf6
EM
1144 * @param $Entity
1145 * @throws \PHPUnit_Framework_IncompleteTestError
18eee50e 1146 */
1147 public function testInvalidID_create($Entity) {
1148 // turn test off for noew
6ead217b 1149 $this->markTestIncomplete("Entity [ $Entity ] cannot be mocked - no known DAO");
18eee50e 1150 return;
1151 if (in_array($Entity, $this->toBeImplemented['create'])) {
1152 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
1153 return;
1154 }
1155 $result = $this->callAPIFailure($Entity, 'Create', array('id' => 999));
1156 }
1157
6a488035
TO
1158 /**
1159 * @dataProvider entities
1160 */
1161 public function testCreateWrongTypeParamTag_create() {
1162 $result = civicrm_api("Tag", 'Create', 'this is not a string');
ba4a1892 1163 $this->assertEquals(1, $result['is_error']);
6a488035
TO
1164 $this->assertEquals("Input variable `params` is not an array", $result['error_message']);
1165 }
1166
1167 /**
1168 * @dataProvider entities_updatesingle
1169 *
1170 * limitations include the problem with avoiding loops when creating test objects -
1171 * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
1172 * Currency - only seems to support US
1e1fdcf6 1173 * @param $entityName
6a488035
TO
1174 */
1175 public function testCreateSingleValueAlter($entityName) {
1176 if (in_array($entityName, $this->toBeImplemented['create'])) {
1177 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
1178 return;
1179 }
1180
6252a38c 1181 $baoString = _civicrm_api3_get_BAO($entityName);
6a488035
TO
1182 $this->assertNotEmpty($baoString, $entityName);
1183 $this->assertNotEmpty($entityName, $entityName);
905fd0e9 1184 $fieldsGet = $fields = $this->callAPISuccess($entityName, 'getfields', array('action' => 'get', 'options' => array('get_options' => 'all')));
9b873358 1185 if ($entityName != 'Pledge') {
905fd0e9 1186 $fields = $this->callAPISuccess($entityName, 'getfields', array('action' => 'create', 'options' => array('get_options' => 'all')));
6a488035
TO
1187 }
1188 $fields = $fields['values'];
39bc176e 1189 $return = array_keys($fieldsGet['values']);
6a488035 1190 $valuesNotToReturn = $this->getKnownUnworkablesUpdateSingle($entityName, 'break_return');
6c6e6187 1191 // these can't be requested as return values
1fd111c8 1192 $entityValuesThatDoNotWork = array_merge(
92915c55
TO
1193 $this->getKnownUnworkablesUpdateSingle($entityName, 'cant_update'),
1194 $this->getKnownUnworkablesUpdateSingle($entityName, 'cant_return'),
1195 $valuesNotToReturn
1196 );
6a488035 1197
6c6e6187 1198 $return = array_diff($return, $valuesNotToReturn);
6a488035
TO
1199 $baoObj = new CRM_Core_DAO();
1200 $baoObj->createTestObject($baoString, array('currency' => 'USD'), 2, 0);
39bc176e
EM
1201
1202 $getEntities = $this->callAPISuccess($entityName, 'get', array(
6ead217b
E
1203 'sequential' => 1,
1204 'return' => $return,
1205 'options' => array(
1206 'sort' => 'id DESC',
1207 'limit' => 2,
1208 ),
1209 ));
a8699624 1210
6a488035 1211 // lets use first rather than assume only one exists
39bc176e
EM
1212 $entity = $getEntities['values'][0];
1213 $entity2 = $getEntities['values'][1];
1214 $this->deletableTestObjects[$baoString][] = $entity['id'];
1215 $this->deletableTestObjects[$baoString][] = $entity2['id'];
6a488035 1216 foreach ($fields as $field => $specs) {
a8699624 1217 $resetFKTo = NULL;
6a488035 1218 $fieldName = $field;
6a488035 1219 if ($field == 'currency' || $field == 'id' || $field == strtolower($entityName) . '_id'
92915c55
TO
1220 || in_array($field, $entityValuesThatDoNotWork)
1221 ) {
6a488035
TO
1222 //@todo id & entity_id are correct but we should fix currency & frequency_day
1223 continue;
1224 }
0ce6d639 1225 $this->assertArrayHasKey('type', $specs, "the _spec function for $entityName field $field does not specify the type");
6a488035
TO
1226 switch ($specs['type']) {
1227 case CRM_Utils_Type::T_DATE:
6a488035
TO
1228 $entity[$fieldName] = '2012-05-20';
1229 break;
6c6e6187 1230
b6afca8f 1231 case CRM_Utils_Type::T_TIMESTAMP:
6a488035
TO
1232 case 12:
1233 $entity[$fieldName] = '2012-05-20 03:05:20';
1234 break;
1235
1236 case CRM_Utils_Type::T_STRING:
1237 case CRM_Utils_Type::T_BLOB:
1238 case CRM_Utils_Type::T_MEDIUMBLOB:
1239 case CRM_Utils_Type::T_TEXT:
1240 case CRM_Utils_Type::T_LONGTEXT:
1241 case CRM_Utils_Type::T_EMAIL:
833478f1
JV
1242 if ($fieldName == 'form_values' && $entityName == 'SavedSearch') {
1243 // This is a hack for the SavedSearch API.
1244 // It expects form_values to be an array.
f1d23743
JV
1245 // If you want to fix this, you should definitely read this forum
1246 // post.
1247 // http://forum.civicrm.org/index.php/topic,33990.0.html
1248 // See also my question on the CiviCRM Stack Exchange:
1249 // https://civicrm.stackexchange.com/questions/3437
e29aa052 1250 $entity[$fieldName] = array('sort_name' => "SortName2");
f1d23743
JV
1251 }
1252 else {
1253 $entity[$fieldName] = substr('New String', 0, CRM_Utils_Array::Value('maxlength', $specs, 100));
7629d5a6 1254 if ($fieldName == 'email') {
1255 $entity[$fieldName] = strtolower($entity[$fieldName]);
1256 }
638c59ed
KJ
1257 // typecast with array to satisfy changes made in CRM-13160
1258 if ($entityName == 'MembershipType' && in_array($fieldName, array(
1259 'relationship_type_id',
1260 'relationship_direction',
1261 ))
1262 ) {
1263 $entity[$fieldName] = (array) $entity[$fieldName];
1264 }
f1d23743 1265 }
6a488035
TO
1266 break;
1267
1268 case CRM_Utils_Type::T_INT:
1269 // probably created with a 1
a8699624
EM
1270 if ($fieldName == 'weight') {
1271 $entity[$fieldName] = 2;
1272 }
1273 elseif (!empty($specs['FKClassName'])) {
9b873358 1274 if ($specs['FKClassName'] == $baoString) {
6a488035
TO
1275 $entity[$fieldName] = (string) $entity2['id'];
1276 }
92e4c2a5 1277 else {
a8699624 1278 if (!empty($entity[$fieldName])) {
1deccd7e 1279 $resetFKTo = array($fieldName => $entity[$fieldName]);
a8699624 1280 }
1deccd7e 1281 $entity[$fieldName] = (string) empty($entity2[$field]) ? '' : $entity2[$field];
6c6e6187 1282 //todo - there isn't always something set here - & our checking on unset values is limited
6a488035
TO
1283 if (empty($entity[$field])) {
1284 unset($entity[$field]);
1285 }
1286 }
1287 }
a8699624
EM
1288 else {
1289 $entity[$fieldName] = '6';
1290 }
6a488035
TO
1291 break;
1292
6a488035
TO
1293 case CRM_Utils_Type::T_BOOLEAN:
1294 // probably created with a 1
1295 $entity[$fieldName] = '0';
1296 break;
1297
1298 case CRM_Utils_Type::T_FLOAT:
1299 case CRM_Utils_Type::T_MONEY:
edd31a24 1300 $entity[$field] = '22.75';
6a488035
TO
1301 break;
1302
1303 case CRM_Utils_Type::T_URL:
1304 $entity[$field] = 'warm.beer.com';
1305 }
905fd0e9
CW
1306 if (empty($specs['FKClassName']) && (!empty($specs['pseudoconstant']) || !empty($specs['options']))) {
1307 $options = CRM_Utils_Array::value('options', $specs, array());
1308 if (!$options) {
edd31a24 1309 //eg. pdf_format id doesn't ship with any
22e263ad 1310 if (isset($specs['pseudoconstant']['optionGroupName'])) {
92915c55 1311 $optionValue = $this->callAPISuccess('option_value', 'create', array(
905fd0e9 1312 'option_group_id' => $specs['pseudoconstant']['optionGroupName'],
af9b09df 1313 'label' => 'new option value',
905fd0e9 1314 'sequential' => 1,
92915c55 1315 ));
905fd0e9 1316 $optionValue = $optionValue['values'];
34e9aa63
CW
1317 $keyColumn = CRM_Utils_Array::value('keyColumn', $specs['pseudoconstant'], 'value');
1318 $options[$optionValue[0][$keyColumn]] = 'new option value';
edd31a24 1319 }
3d3ef918 1320 }
905fd0e9
CW
1321 $entity[$field] = array_rand($options);
1322 }
1323 if (!empty($specs['FKClassName']) && !empty($specs['pseudoconstant'])) {
1324 // in the weird situation where a field has both an fk and pseudoconstant defined,
1325 // e.g. campaign_id field, need to flush caches.
1326 // FIXME: Why doesn't creating a campaign clear caches?
1327 civicrm_api3($entityName, 'getfields', array('cache_clear' => 1));
6a488035
TO
1328 }
1329 $updateParams = array(
6a488035 1330 'id' => $entity['id'],
6ead217b 1331 $field => isset($entity[$field]) ? $entity[$field] : NULL,
6a488035 1332 );
22e263ad 1333 if (isset($updateParams['financial_type_id']) && in_array($entityName, array('Grant'))) {
deb562a8
EM
1334 //api has special handling on these 2 fields for backward compatibility reasons
1335 $entity['contribution_type_id'] = $updateParams['financial_type_id'];
1336 }
258c92c6
SL
1337 if (isset($updateParams['next_sched_contribution_date']) && in_array($entityName, array('ContributionRecur'))) {
1338 //api has special handling on these 2 fields for backward compatibility reasons
1339 $entity['next_sched_contribution'] = $updateParams['next_sched_contribution_date'];
1340 }
6a488035 1341
f27f2724 1342 $update = $this->callAPISuccess($entityName, 'create', $updateParams);
6a488035
TO
1343 $checkParams = array(
1344 'id' => $entity['id'],
6a488035
TO
1345 'sequential' => 1,
1346 'return' => $return,
1347 'options' => array(
1348 'sort' => 'id DESC',
1349 'limit' => 2,
1350 ),
1351 );
1352
f27f2724 1353 $checkEntity = $this->callAPISuccess($entityName, 'getsingle', $checkParams);
0298287b 1354
92915c55
TO
1355 $this->assertAPIArrayComparison($entity, $checkEntity, array(), "checking if $fieldName was correctly updated\n" . print_r(array(
1356 'update-params' => $updateParams,
1357 'update-result' => $update,
1358 'getsingle-params' => $checkParams,
1359 'getsingle-result' => $checkEntity,
af9b09df 1360 'expected entity' => $entity,
92915c55 1361 ), TRUE));
a8699624
EM
1362 if ($resetFKTo) {
1363 //reset the foreign key fields because otherwise our cleanup routine fails & some other unexpected stuff can kick in
1364 $entity = array_merge($entity, $resetFKTo);
1365 $updateParams = array_merge($updateParams, $resetFKTo);
1366 $this->callAPISuccess($entityName, 'create', $updateParams);
22e263ad 1367 if (isset($updateParams['financial_type_id']) && in_array($entityName, array('Grant'))) {
a8699624
EM
1368 //api has special handling on these 2 fields for backward compatibility reasons
1369 $entity['contribution_type_id'] = $updateParams['financial_type_id'];
1370 }
258c92c6
SL
1371 if (isset($updateParams['next_sched_contribution_date']) && in_array($entityName, array('ContributionRecur'))) {
1372 //api has special handling on these 2 fields for backward compatibility reasons
1373 $entity['next_sched_contribution'] = $updateParams['next_sched_contribution_date'];
1374 }
a8699624 1375 }
6a488035 1376 }
6a488035
TO
1377 $baoObj->free();
1378 }
1379
be2e0c6a 1380 /* ---- testing the _getFields ---- */
6a488035 1381
be2e0c6a 1382 /* ---- testing the _delete ---- */
6a488035
TO
1383
1384 /**
1385 * @dataProvider toBeSkipped_delete
6c6e6187 1386 entities that don't need a delete action
1e1fdcf6 1387 * @param $Entity
6a488035
TO
1388 */
1389 public function testNotImplemented_delete($Entity) {
1390 $nonExistantID = 151416349;
1391 $result = civicrm_api($Entity, 'Delete', array('version' => 3, 'id' => $nonExistantID));
ba4a1892 1392 $this->assertEquals(1, $result['is_error']);
311873a0 1393 $this->assertContains(strtolower("API ($Entity, Delete) does not exist"), strtolower($result['error_message']));
6a488035
TO
1394 }
1395
1396 /**
1397 * @dataProvider entities
1e1fdcf6 1398 * @param $Entity
6a488035
TO
1399 */
1400 public function testWithoutParam_delete($Entity) {
1401 // should delete php complaining that a param is missing
2a4cb975
SL
1402 try {
1403 $result = civicrm_api($Entity, 'Delete');
1404 $this->fail('Expected an exception. No exception was thrown.');
1405 }
1406 catch (ArgumentCountError $e) {
1407 /* ok */
1408 }
1409 catch (PHPUnit_Framework_Error $e) {
1410 /* ok */
1411 }
6a488035
TO
1412 }
1413
1414 /**
1415 * @dataProvider entities_delete
1e1fdcf6 1416 * @param $Entity
6a488035
TO
1417 */
1418 public function testEmptyParam_delete($Entity) {
1419 if (in_array($Entity, $this->toBeImplemented['delete'])) {
1420 // $this->markTestIncomplete("civicrm_api3_{$Entity}_delete to be implemented");
1421 return;
1422 }
1423 $result = civicrm_api($Entity, 'Delete', array());
ba4a1892 1424 $this->assertEquals(1, $result['is_error']);
34e21ce8 1425 $this->assertContains("Unknown api version", $result['error_message']);
6a488035 1426 }
92915c55 1427
18eee50e 1428 /**
1429 * @dataProvider entities_delete
1e1fdcf6
EM
1430 * @param $Entity
1431 * @throws \PHPUnit_Framework_IncompleteTestError
18eee50e 1432 */
1433 public function testInvalidID_delete($Entity) {
18eee50e 1434 $result = $this->callAPIFailure($Entity, 'Delete', array('id' => 999));
1435 }
92915c55 1436
6a488035
TO
1437 /**
1438 * @dataProvider entities
1439 */
1440 public function testDeleteWrongTypeParamTag_delete() {
1441 $result = civicrm_api("Tag", 'Delete', 'this is not a string');
ba4a1892 1442 $this->assertEquals(1, $result['is_error']);
6a488035
TO
1443 $this->assertEquals("Input variable `params` is not an array", $result['error_message']);
1444 }
1445
18eee50e 1446 /**
1447 * Create two entities and make sure delete action only deletes one!
1448 *
1449 * @dataProvider entities_delete
1450 *
1451 * limitations include the problem with avoiding loops when creating test objects -
1452 * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
1453 * Currency - only seems to support US
1e1fdcf6
EM
1454 * @param $entityName
1455 * @throws \PHPUnit_Framework_IncompleteTestError
18eee50e 1456 */
1457 public function testByID_delete($entityName) {
1458 // turn test off for noew
1459 $this->markTestIncomplete("Entity [$entityName] cannot be mocked - no known DAO");
1460 return;
1461
1462 if (in_array($entityName, self::toBeSkipped_automock(TRUE))) {
1463 // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
1464 return;
1465 }
1466 $startCount = $this->callAPISuccess($entityName, 'getcount', array());
1467 $createcount = 2;
1468 $baos = $this->getMockableBAOObjects($entityName, $createcount);
1469 list($baoObj1, $baoObj2) = $baos;
1470
1471 // make sure exactly 2 exist
1472 $result = $this->callAPISuccess($entityName, 'getcount', array(),
1473 $createcount + $startCount
1474 );
1475
1476 $this->callAPISuccess($entityName, 'delete', array('id' => $baoObj2->id));
1477 //make sure 1 less exists now
1478 $result = $this->callAPISuccess($entityName, 'getcount', array(),
6c6e6187 1479 ($createcount + $startCount) - 1
18eee50e 1480 );
1481
1482 //make sure id #1 exists
1483 $result = $this->callAPISuccess($entityName, 'getcount', array('id' => $baoObj1->id),
1484 1
1485 );
1486 //make sure id #2 desn't exist
1487 $result = $this->callAPISuccess($entityName, 'getcount', array('id' => $baoObj2->id),
1488 0
1489 );
1490 }
1491
32dafeec
EM
1492 /**
1493 * Create two entities and make sure delete action only deletes one!
1494 *
1495 * @dataProvider entities_getfields
1e1fdcf6 1496 * @param $entity
32dafeec
EM
1497 */
1498 public function testGetfieldsHasTitle($entity) {
1499 $entities = $this->getEntitiesSupportingCustomFields();
1500 if (in_array($entity, $entities)) {
1501 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, $entity . 'Test.php');
1502 }
6c6e6187 1503 $actions = $this->callAPISuccess($entity, 'getactions', array());
4c41ecb2 1504 foreach ($actions['values'] as $action) {
92915c55 1505 if (substr($action, -7) == '_create' || substr($action, -4) == '_get' || substr($action, -7) == '_delete') {
7385c761
EM
1506 //getactions can't distinguish between contribution_page.create & contribution_page.create
1507 continue;
1508 }
4c41ecb2
EM
1509 $fields = $this->callAPISuccess($entity, 'getfields', array('action' => $action));
1510 if (!empty($ids) && in_array($action, array('create', 'get'))) {
7385c761 1511 $this->assertArrayHasKey('custom_' . $ids['custom_field_id'], $fields['values']);
4c41ecb2 1512 }
32dafeec 1513
4c41ecb2
EM
1514 foreach ($fields['values'] as $fieldName => $fieldSpec) {
1515 $this->assertArrayHasKey('title', $fieldSpec, "no title for $entity - $fieldName on action $action");
1516 $this->assertNotEmpty($fieldSpec['title'], "empty title for $entity - $fieldName");
1517 }
32dafeec 1518 }
32dafeec
EM
1519 if (!empty($ids)) {
1520 $this->customFieldDelete($ids['custom_field_id']);
1521 $this->customGroupDelete($ids['custom_group_id']);
1522 }
1523 }
1524
1525 /**
1526 * @return array
1527 */
1528 public function getEntitiesSupportingCustomFields() {
1529 $entities = self::custom_data_entities_get();
1530 $returnEntities = array();
1531 foreach ($entities as $entityArray) {
1532 $returnEntities[] = $entityArray[0];
1533 }
1534 return $returnEntities;
1535 }
92915c55 1536
8efea814 1537 /**
100fef9d 1538 * @param string $entityName
8efea814
EM
1539 * @param int $count
1540 *
8efea814
EM
1541 * @return array
1542 */
1543 private function getMockableBAOObjects($entityName, $count = 2) {
6252a38c 1544 $baoString = _civicrm_api3_get_BAO($entityName);
18eee50e 1545 if (empty($baoString)) {
1546 $this->markTestIncomplete("Entity [$entityName] cannot be mocked - no known DAO");
fcb93467 1547 return array();
18eee50e 1548 }
1549 $baos = array();
6ead217b 1550 $i = 0;
22e263ad 1551 while ($i < $count) {
6c6e6187 1552 // create entities
18eee50e 1553 $baoObj = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
a1a2a83d 1554 $this->assertTrue(is_int($baoObj->id), 'check first id');
18eee50e 1555 $this->deletableTestObjects[$baoString][] = $baoObj->id;
1556 $baos[] = $baoObj;
2241036a 1557 $i++;
18eee50e 1558 }
1559 return $baos;
1560 }
1561
6a488035 1562 /**
fe482240 1563 * Verify that HTML metacharacters provided as inputs appear consistently.
6a488035
TO
1564 * as outputs.
1565 *
1566 * At time of writing, the encoding scheme requires (for example) that an
1567 * event title be partially-HTML-escaped before writing to DB. To provide
1568 * consistency, the API must perform extra encoding and decoding on some
1569 * fields.
1570 *
1571 * In this example, the event 'title' is subject to encoding, but the
1572 * event 'description' is not.
1573 */
1574 public function testEncodeDecodeConsistency() {
1575 // Create example
1576 $createResult = civicrm_api('Event', 'Create', array(
1577 'version' => 3,
1578 'title' => 'CiviCRM <> TheRest',
1579 'description' => 'TheRest <> CiviCRM',
1580 'event_type_id' => 1,
1581 'is_public' => 1,
1582 'start_date' => 20081021,
1583 ));
1584 $this->assertAPISuccess($createResult);
1585 $eventId = $createResult['id'];
1586 $this->assertEquals('CiviCRM <> TheRest', $createResult['values'][$eventId]['title']);
1587 $this->assertEquals('TheRest <> CiviCRM', $createResult['values'][$eventId]['description']);
1588
1589 // Verify "get" handles decoding in result value
1590 $getByIdResult = civicrm_api('Event', 'Get', array(
1591 'version' => 3,
1592 'id' => $eventId,
1593 ));
1594 $this->assertAPISuccess($getByIdResult);
1595 $this->assertEquals('CiviCRM <> TheRest', $getByIdResult['values'][$eventId]['title']);
1596 $this->assertEquals('TheRest <> CiviCRM', $getByIdResult['values'][$eventId]['description']);
1597
1598 // Verify "get" handles encoding in search value
1599 $getByTitleResult = civicrm_api('Event', 'Get', array(
1600 'version' => 3,
1601 'title' => 'CiviCRM <> TheRest',
1602 ));
1603 $this->assertAPISuccess($getByTitleResult);
1604 $this->assertEquals('CiviCRM <> TheRest', $getByTitleResult['values'][$eventId]['title']);
1605 $this->assertEquals('TheRest <> CiviCRM', $getByTitleResult['values'][$eventId]['description']);
1606
1607 // Verify that "getSingle" handles decoding
6ead217b 1608 $getSingleResult = $this->callAPISuccess('Event', 'GetSingle', array(
6a488035
TO
1609 'id' => $eventId,
1610 ));
1611
6a488035
TO
1612 $this->assertEquals('CiviCRM <> TheRest', $getSingleResult['title']);
1613 $this->assertEquals('TheRest <> CiviCRM', $getSingleResult['description']);
1614
1615 // Verify that chaining handles decoding
6ead217b 1616 $chainResult = $this->callAPISuccess('Event', 'Get', array(
6a488035 1617 'id' => $eventId,
6c6e6187 1618 'api.event.get' => array(),
6a488035
TO
1619 ));
1620 $this->assertEquals('CiviCRM <> TheRest', $chainResult['values'][$eventId]['title']);
1621 $this->assertEquals('TheRest <> CiviCRM', $chainResult['values'][$eventId]['description']);
1622 $this->assertEquals('CiviCRM <> TheRest', $chainResult['values'][$eventId]['api.event.get']['values'][0]['title']);
1623 $this->assertEquals('TheRest <> CiviCRM', $chainResult['values'][$eventId]['api.event.get']['values'][0]['description']);
1624
1625 // Verify that "setvalue" handles encoding for updates
1626 $setValueTitleResult = civicrm_api('Event', 'setvalue', array(
1627 'version' => 3,
1628 'id' => $eventId,
1629 'field' => 'title',
1630 'value' => 'setValueTitle: CiviCRM <> TheRest',
1631 ));
1632 $this->assertAPISuccess($setValueTitleResult);
1633 $this->assertEquals('setValueTitle: CiviCRM <> TheRest', $setValueTitleResult['values']['title']);
1634 $setValueDescriptionResult = civicrm_api('Event', 'setvalue', array(
1635 'version' => 3,
1636 'id' => $eventId,
1637 'field' => 'description',
1638 'value' => 'setValueDescription: TheRest <> CiviCRM',
1639 ));
bc2bc079 1640 //$this->assertTrue((bool)$setValueDescriptionResult['is_error']); // not supported by setValue
1641 $this->assertEquals('setValueDescription: TheRest <> CiviCRM', $setValueDescriptionResult['values']['description']);
6c6e6187 1642 }
6a488035
TO
1643
1644 /**
1645 * Verify that write operations (create/update) use partial HTML-encoding
1646 *
1647 * In this example, the event 'title' is subject to encoding, but the
1648 * event 'description' is not.
1649 */
1650 public function testEncodeWrite() {
1651 // Create example
1652 $createResult = civicrm_api('Event', 'Create', array(
1653 'version' => 3,
1654 'title' => 'createNew: CiviCRM <> TheRest',
1655 'description' => 'createNew: TheRest <> CiviCRM',
1656 'event_type_id' => 1,
1657 'is_public' => 1,
1658 'start_date' => 20081021,
1659 ));
1660 $this->assertAPISuccess($createResult);
1661 $eventId = $createResult['id'];
1662 $this->assertDBQuery('createNew: CiviCRM &lt;&gt; TheRest', 'SELECT title FROM civicrm_event WHERE id = %1', array(
21dfd5f5 1663 1 => array($eventId, 'Integer'),
6a488035
TO
1664 ));
1665 $this->assertDBQuery('createNew: TheRest <> CiviCRM', 'SELECT description FROM civicrm_event WHERE id = %1', array(
21dfd5f5 1666 1 => array($eventId, 'Integer'),
6a488035
TO
1667 ));
1668
1669 // Verify that "create" handles encoding for updates
1670 $createWithIdResult = civicrm_api('Event', 'Create', array(
1671 'version' => 3,
1672 'id' => $eventId,
1673 'title' => 'createWithId: CiviCRM <> TheRest',
1674 'description' => 'createWithId: TheRest <> CiviCRM',
1675 ));
1676 $this->assertAPISuccess($createWithIdResult);
1677 $this->assertDBQuery('createWithId: CiviCRM &lt;&gt; TheRest', 'SELECT title FROM civicrm_event WHERE id = %1', array(
21dfd5f5 1678 1 => array($eventId, 'Integer'),
6a488035
TO
1679 ));
1680 $this->assertDBQuery('createWithId: TheRest <> CiviCRM', 'SELECT description FROM civicrm_event WHERE id = %1', array(
21dfd5f5 1681 1 => array($eventId, 'Integer'),
6a488035
TO
1682 ));
1683
1684 // Verify that "setvalue" handles encoding for updates
1685 $setValueTitleResult = civicrm_api('Event', 'setvalue', array(
1686 'version' => 3,
1687 'id' => $eventId,
1688 'field' => 'title',
1689 'value' => 'setValueTitle: CiviCRM <> TheRest',
1690 ));
1691 $this->assertAPISuccess($setValueTitleResult);
1692 $this->assertDBQuery('setValueTitle: CiviCRM &lt;&gt; TheRest', 'SELECT title FROM civicrm_event WHERE id = %1', array(
21dfd5f5 1693 1 => array($eventId, 'Integer'),
6a488035
TO
1694 ));
1695 $setValueDescriptionResult = civicrm_api('Event', 'setvalue', array(
1696 'version' => 3,
1697 'id' => $eventId,
1698 'field' => 'description',
1699 'value' => 'setValueDescription: TheRest <> CiviCRM',
1700 ));
bc2bc079 1701 //$this->assertTrue((bool)$setValueDescriptionResult['is_error']); // not supported by setValue
1702 $this->assertAPISuccess($setValueDescriptionResult);
1703 $this->assertDBQuery('setValueDescription: TheRest <> CiviCRM', 'SELECT description FROM civicrm_event WHERE id = %1', array(
21dfd5f5 1704 1 => array($eventId, 'Integer'),
bc2bc079 1705 ));
6a488035 1706 }
96025800 1707
6a488035 1708}