]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/service/RESTAPI3Test.php
Release 6.5.6
[Github/sugarcrm.git] / tests / service / RESTAPI3Test.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
5  * 
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  * 
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
16  * details.
17  * 
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  * 
23  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25  * 
26  * The interactive user interfaces in modified source and object code versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  * 
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the "Powered by
32  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33  * technical reasons, the Appropriate Legal Notices must display the words
34  * "Powered by SugarCRM".
35  ********************************************************************************/
36
37
38 require_once('service/v3/SugarWebServiceUtilv3.php');
39 require_once('tests/service/APIv3Helper.php');
40
41
42 class RESTAPI3Test extends Sugar_PHPUnit_Framework_TestCase
43 {
44     protected $_user;
45
46     protected $_lastRawResponse;
47
48     private static $helperObject;
49
50     private $_unified_search_modules_content;
51
52     public function setUp()
53     {
54         global $beanList, $beanFiles;
55         include('include/modules.php');
56
57         //Reload langauge strings
58         $GLOBALS['app_strings'] = return_application_language($GLOBALS['current_language']);
59         $GLOBALS['app_list_strings'] = return_app_list_strings_language($GLOBALS['current_language']);
60         $GLOBALS['mod_strings'] = return_module_language($GLOBALS['current_language'], 'Accounts');
61         //Create an anonymous user for login purposes/
62         $this->_user = SugarTestUserUtilities::createAnonymousUser();
63         $GLOBALS['current_user'] = $this->_user;
64
65         self::$helperObject = new APIv3Helper();
66
67         if(file_exists(sugar_cached('modules/unified_search_modules.php')))
68         {
69             $this->unified_search_modules_content = file_get_contents(sugar_cached('modules/unified_search_modules.php'));
70             unlink(sugar_cached('modules/unified_search_modules.php'));
71         }
72
73         require_once('modules/Home/UnifiedSearchAdvanced.php');
74         $unifiedSearchAdvanced = new UnifiedSearchAdvanced();
75         $_REQUEST['enabled_modules'] = 'Accounts,Contacts,Opportunities';
76         $unifiedSearchAdvanced->saveGlobalSearchSettings();
77
78         $GLOBALS['db']->query("DELETE FROM accounts WHERE name like 'UNIT TEST%' ");
79         $GLOBALS['db']->query("DELETE FROM opportunities WHERE name like 'UNIT TEST%' ");
80         $GLOBALS['db']->query("DELETE FROM contacts WHERE first_name like 'UNIT TEST%' ");
81         $GLOBALS['db']->query("DELETE FROM calls WHERE name like 'UNIT TEST%' ");
82         $GLOBALS['db']->query("DELETE FROM tasks WHERE name like 'UNIT TEST%' ");
83         $GLOBALS['db']->query("DELETE FROM meetings WHERE name like 'UNIT TEST%' ");
84         $GLOBALS['db']->commit();
85         //$this->useOutputBuffering = false;
86     }
87
88     public function tearDown()
89         {
90             if(isset($GLOBALS['listViewDefs'])) unset($GLOBALS['listViewDefs']);
91             if(isset($GLOBALS['viewdefs'])) unset($GLOBALS['viewdefs']);
92             unset($GLOBALS['app_list_strings']);
93             unset($GLOBALS['app_strings']);
94             unset($GLOBALS['mod_strings']);
95
96         if(!empty($this->unified_search_modules_content))
97         {
98             file_put_contents(sugar_cached('modules/unified_search_modules.php'), $this->unified_search_modules_content);
99         }
100
101         $GLOBALS['db']->query("DELETE FROM accounts WHERE name like 'UNIT TEST%' ");
102         $GLOBALS['db']->query("DELETE FROM opportunities WHERE name like 'UNIT TEST%' ");
103         $GLOBALS['db']->query("DELETE FROM contacts WHERE first_name like 'UNIT TEST%' ");
104         $GLOBALS['db']->query("DELETE FROM calls WHERE name like 'UNIT TEST%' ");
105         $GLOBALS['db']->query("DELETE FROM tasks WHERE name like 'UNIT TEST%' ");
106         $GLOBALS['db']->query("DELETE FROM meetings WHERE name like 'UNIT TEST%' ");
107         SugarTestUserUtilities::removeAllCreatedAnonymousUsers();
108         unset($GLOBALS['reload_vardefs']);
109         }
110
111     protected function _makeRESTCall($method,$parameters)
112     {
113         // specify the REST web service to interact with
114         $url = $GLOBALS['sugar_config']['site_url'].'/service/v3/rest.php';
115         // Open a curl session for making the call
116         $curl = curl_init($url);
117         // set URL and other appropriate options
118         curl_setopt($curl, CURLOPT_URL, $url);
119         curl_setopt($curl, CURLOPT_POST, 1);
120         curl_setopt($curl, CURLOPT_HEADER, 0);
121         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
122         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
123         curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0);
124         curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 );
125         // build the request URL
126         $json = json_encode($parameters);
127         $postArgs = "method=$method&input_type=JSON&response_type=JSON&rest_data=$json";
128         curl_setopt($curl, CURLOPT_POSTFIELDS, $postArgs);
129         // Make the REST call, returning the result
130         $response = curl_exec($curl);
131         // Close the connection
132         curl_close($curl);
133
134         $this->_lastRawResponse = $response;
135
136         // Convert the result from JSON format to a PHP array
137         return json_decode($response,true);
138     }
139
140     protected function _returnLastRawResponse()
141     {
142         return "Error in web services call. Response was: {$this->_lastRawResponse}";
143     }
144
145     protected function _login()
146     {
147         $GLOBALS['db']->commit(); // Making sure we commit any changes before logging in
148
149         return $this->_makeRESTCall('login',
150             array(
151                 'user_auth' =>
152                     array(
153                         'user_name' => $this->_user->user_name,
154                         'password' => $this->_user->user_hash,
155                         'version' => '.01',
156                         ),
157                 'application_name' => 'SugarTestRunner',
158                 'name_value_list' => array(),
159                 )
160             );
161     }
162
163     public function testSearchByModule()
164     {
165         $seedData = self::$helperObject->populateSeedDataForSearchTest($this->_user->id);
166
167         $searchModules = array('Accounts','Contacts','Opportunities');
168         $searchString = "UNIT TEST";
169         $offSet = 0;
170         $maxResults = 10;
171
172         $result = $this->_login(); // Logging in just before the REST call as this will also commit any pending DB changes
173         $session = $result['id'];
174         $results = $this->_makeRESTCall('search_by_module',
175                         array(
176                             'session' => $session,
177                             'search'  => $searchString,
178                             'modules' => $searchModules,
179                             'offset'  => $offSet,
180                             'max'     => $maxResults,
181                             'user'    => $this->_user->id)
182                         );
183
184         $this->assertTrue( self::$helperObject->findBeanIdFromEntryList($results['entry_list'],$seedData[0]['id'],'Accounts') );
185         $this->assertFalse( self::$helperObject->findBeanIdFromEntryList($results['entry_list'],$seedData[1]['id'],'Accounts') );
186         $this->assertTrue( self::$helperObject->findBeanIdFromEntryList($results['entry_list'],$seedData[2]['id'],'Contacts') );
187         $this->assertTrue( self::$helperObject->findBeanIdFromEntryList($results['entry_list'],$seedData[3]['id'],'Opportunities') );
188         $this->assertFalse( self::$helperObject->findBeanIdFromEntryList($results['entry_list'],$seedData[4]['id'],'Opportunities') );
189     }
190
191     public function testSearchByModuleWithReturnFields()
192     {
193         $seedData = self::$helperObject->populateSeedDataForSearchTest($this->_user->id);
194
195         $returnFields = array('name','id','deleted');
196         $searchModules = array('Accounts','Contacts','Opportunities');
197         $searchString = "UNIT TEST";
198         $offSet = 0;
199         $maxResults = 10;
200
201         $result = $this->_login(); // Logging in just before the REST call as this will also commit any pending DB changes
202         $session = $result['id'];
203         $results = $this->_makeRESTCall('search_by_module',
204                         array(
205                             'session' => $session,
206                             'search'  => $searchString,
207                             'modules' => $searchModules,
208                             'offset'  => $offSet,
209                             'max'     => $maxResults,
210                             'user'    => $this->_user->id,
211                             'selectFields' => $returnFields)
212                         );
213
214
215         $this->assertEquals($seedData[0]['fieldValue'], self::$helperObject->findFieldByNameFromEntryList($results['entry_list'],$seedData[0]['id'],'Accounts', $seedData[0]['fieldName']));
216         $this->assertFalse(self::$helperObject->findFieldByNameFromEntryList($results['entry_list'],$seedData[1]['id'],'Accounts', $seedData[1]['fieldName']));
217         $this->assertEquals($seedData[2]['fieldValue'], self::$helperObject->findFieldByNameFromEntryList($results['entry_list'],$seedData[2]['id'],'Contacts', $seedData[2]['fieldName']));
218         $this->assertEquals($seedData[3]['fieldValue'], self::$helperObject->findFieldByNameFromEntryList($results['entry_list'],$seedData[3]['id'],'Opportunities', $seedData[3]['fieldName']));
219         $this->assertFalse(self::$helperObject->findFieldByNameFromEntryList($results['entry_list'],$seedData[4]['id'],'Opportunities', $seedData[4]['fieldName']));
220     }
221
222     public function testGetServerInformation()
223     {
224         require('sugar_version.php');
225
226         $result = $this->_login();
227         $session = $result['id'];
228
229         $result = $this->_makeRESTCall('get_server_info',array());
230
231         $this->assertEquals($sugar_version, $result['version'],'Unable to get server information');
232         $this->assertEquals($sugar_flavor, $result['flavor'],'Unable to get server information');
233     }
234
235     public function testGetModuleList()
236     {
237         $account = new Account();
238         $account->id = uniqid();
239         $account->new_with_id = TRUE;
240         $account->name = "Test " . $account->id;
241         $account->save();
242
243         $whereClause = "accounts.name='{$account->name}'";
244         $module = 'Accounts';
245         $orderBy = 'name';
246         $offset = 0;
247         $returnFields = array('name');
248
249         $result = $this->_login(); // Logging in just before the REST call as this will also commit any pending DB changes
250         $session = $result['id'];
251         $result = $this->_makeRESTCall('get_entry_list', array($session, $module, $whereClause, $orderBy,$offset, $returnFields));
252
253         $this->assertEquals($account->id, $result['entry_list'][0]['id'],'Unable to retrieve account list during search.');
254
255         $GLOBALS['db']->query("DELETE FROM accounts WHERE id = '{$account->id}'");
256
257     }
258
259     public function testLogin()
260     {
261         $result = $this->_login();
262         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
263     }
264
265     public static function _multipleModuleLayoutProvider()
266     {
267         return array(
268                         array(
269                             'module' => array('Accounts','Contacts'),
270                             'type' => array('default'),
271                             'view' => array('list'),
272                             'expected_file' => array(
273                                 'Accounts' => array( 'default' => array('list' => 'modules/Accounts/metadata/listviewdefs.php')),
274                                 'Contacts' => array( 'default' => array('list' => 'modules/Contacts/metadata/listviewdefs.php')))
275                         ),
276                         array(
277                             'module' => array('Accounts','Contacts'),
278                             'type' => array('default'),
279                             'view' => array('list','detail'),
280                             'expected_file' => array(
281                                 'Accounts' => array(
282                                     'default' => array(
283                                                 'list' => 'modules/Accounts/metadata/listviewdefs.php',
284                                                 'detail' => 'modules/Accounts/metadata/detailviewdefs.php')),
285                                 'Contacts' => array(
286                                     'default' => array(
287                                                 'list' => 'modules/Contacts/metadata/listviewdefs.php',
288                                                 'detail' => 'modules/Contacts/metadata/detailviewdefs.php'))
289                         ))
290         );
291     }
292
293     /**
294      * @dataProvider _multipleModuleLayoutProvider
295      */
296     public function testGetMultipleModuleLayout($a_module, $a_type, $a_view, $a_expected_file)
297     {
298         $result = $this->_login();
299         $session = $result['id'];
300
301         $results = $this->_makeRESTCall('get_module_layout',
302                         array(
303                             'session' => $session,
304                             'module' => $a_module,
305                             'type' => $a_type,
306                             'view' => $a_view)
307                         );
308
309         foreach ($results as $module => $moduleResults )
310         {
311             foreach ($moduleResults as $type => $viewResults)
312             {
313                 foreach ($viewResults as $view => $result)
314                 {
315                     $expected_file = $a_expected_file[$module][$type][$view];
316                     if ( is_file('custom'  . DIRECTORY_SEPARATOR . $expected_file) )
317                         require('custom'  . DIRECTORY_SEPARATOR . $expected_file);
318                     else
319                         require($expected_file);
320
321                     if($view == 'list')
322                         $expectedResults = $listViewDefs[$module];
323                     else
324                         $expectedResults = $viewdefs[$module][ucfirst($view) .'View' ];
325
326                     $this->assertEquals(md5(serialize($expectedResults)), md5(serialize($result)), "Unable to retrieve module layout: module {$module}, type $type, view $view");
327                 }
328                 }
329         }
330    }
331
332     public static function _moduleLayoutProvider()
333     {
334         return array(
335                     array('module' => 'Accounts','type' => 'default', 'view' => 'list','expected_file' => 'modules/Accounts/metadata/listviewdefs.php' ),
336                     array('module' => 'Accounts','type' => 'default', 'view' => 'edit','expected_file' => 'modules/Accounts/metadata/editviewdefs.php' ),
337                     array('module' => 'Accounts','type' => 'default', 'view' => 'detail','expected_file' => 'modules/Accounts/metadata/detailviewdefs.php' ),
338         );
339     }
340
341     /**
342      * @dataProvider _moduleLayoutProvider
343      */
344     public function testGetModuleLayout($module, $type, $view, $expected_file)
345     {
346         $result = $this->_login();
347         $session = $result['id'];
348
349         $result = $this->_makeRESTCall('get_module_layout',
350                         array(
351                             'session' => $session,
352                             'module' => array($module),
353                             'type' => array($type),
354                             'view' => array($view))
355                         );
356
357         if ( is_file('custom'  . DIRECTORY_SEPARATOR . $expected_file) )
358                 require('custom'  . DIRECTORY_SEPARATOR . $expected_file);
359         else
360             require($expected_file);
361
362         if($view == 'list')
363             $expectedResults = $listViewDefs[$module];
364         else
365             $expectedResults = $viewdefs[$module][ucfirst($view) .'View' ];
366
367         $a_expectedResults = array();
368         $a_expectedResults[$module][$type][$view] = $expectedResults;
369
370         $this->assertEquals(md5(serialize($a_expectedResults)), md5(serialize($result)), "Unable to retrieve module layout: module {$module}, type $type, view $view");
371     }
372
373      /**
374      * @dataProvider _moduleLayoutProvider
375      */
376     public function testGetModuleLayoutMD5($module, $type, $view, $expected_file)
377     {
378         $result = $this->_login();
379         $session = $result['id'];
380
381         $fullResult = $this->_makeRESTCall('get_module_layout_md5',
382                         array(
383                             'session' => $session,
384                             'module' => array($module),
385                             'type' => array($type),
386                             'view' => array($view) )
387                         );
388         $result = $fullResult['md5'];
389         if ( is_file('custom'  . DIRECTORY_SEPARATOR . $expected_file) )
390                 require('custom'  . DIRECTORY_SEPARATOR . $expected_file);
391         else
392             require($expected_file);
393
394         if($view == 'list')
395             $expectedResults = $listViewDefs[$module];
396         else
397             $expectedResults = $viewdefs[$module][ucfirst($view) .'View' ];
398
399         $a_expectedResults = array();
400         $a_expectedResults[$module][$type][$view] = $expectedResults;
401
402         $this->assertEquals(md5(serialize($expectedResults)), $result[$module][$type][$view], "Unable to retrieve module layout md5: module {$module}, type $type, view $view");
403
404     }
405
406     public function testGetAvailableModules()
407     {
408         $this->markTestIncomplete('Will be updated week of June 21, 2010');
409
410         $result = $this->_login();
411         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
412         $session = $result['id'];
413
414         $fullResult = $this->_makeRESTCall('get_available_modules', array('session' => $session, 'filter' => 'all' ));
415         $this->assertTrue(in_array('ACLFields', $fullResult['modules']), "Unable to get all available modules");
416         $this->assertTrue(in_array('Schedulers', $fullResult['modules']), "Unable to get all available modules");
417         $this->assertTrue(in_array('Roles', $fullResult['modules']), "Unable to get all available modules");
418
419         $sh = new SugarWebServiceUtilv3();
420
421
422         $defaultResult = $this->_makeRESTCall('get_available_modules', array('session' => $session, 'filter' => 'default' ));
423         $defaultResult = md5(serialize($defaultResult['modules']));
424         $defaultResultExpected = $sh->get_visible_modules($fullResult['modules']);
425         $defaultResultExpected = md5(serialize($defaultResultExpected));
426         $this->assertEquals($defaultResultExpected, $defaultResult, "Unable to get all visible default modules");
427
428     }
429
430     public function testGetVardefsMD5()
431     {
432         $GLOBALS['reload_vardefs'] = TRUE;
433         $result = $this->_login();
434         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
435         $session = $result['id'];
436
437         //Test a regular module
438         $fullResult = $this->_makeRESTCall('get_module_fields_md5', array('session' => $session, 'module' => 'Currencies' ));
439         $result = $fullResult['Currencies'];
440         $a = new Currency();
441         $soapHelper = new SugarWebServiceUtilv3();
442         $actualVardef = $soapHelper->get_return_module_fields($a,'Currencies','');
443         $actualMD5 = md5(serialize($actualVardef));
444         $this->assertEquals($actualMD5, $result, "Unable to retrieve vardef md5.");
445
446         //Test a fake module
447         $result = $this->_makeRESTCall('get_module_fields_md5', array('session' => $session, 'module' => 'BadModule' ));
448         $this->assertEquals('Module Does Not Exist', $result['name']);
449     }
450
451     public function testAddNewAccountAndThenDeleteIt()
452     {
453         $result = $this->_login();
454         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
455         $session = $result['id'];
456
457         $result = $this->_makeRESTCall('set_entry',
458             array(
459                 'session' => $session,
460                 'module' => 'Accounts',
461                 'name_value_list' => array(
462                     array('name' => 'name', 'value' => 'New Account'),
463                     array('name' => 'description', 'value' => 'This is an account created from a REST web services call'),
464                     ),
465                 )
466             );
467
468         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
469
470         $accountId = $result['id'];
471
472         // verify record was created
473         $result = $this->_makeRESTCall('get_entry',
474             array(
475                 'session' => $session,
476                 'module' => 'Accounts',
477                 'id' => $accountId,
478                 )
479             );
480
481         $this->assertEquals($result['entry_list'][0]['id'],$accountId,$this->_returnLastRawResponse());
482
483         // delete the record
484         $result = $this->_makeRESTCall('set_entry',
485             array(
486                 'session' => $session,
487                 'module' => 'Accounts',
488                 'name_value_list' => array(
489                     array('name' => 'id', 'value' => $accountId),
490                     array('name' => 'deleted', 'value' => '1'),
491                     ),
492                 )
493             );
494
495         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
496
497         // try to retrieve again to validate it is deleted
498         $result = $this->_makeRESTCall('get_entry',
499             array(
500                 'session' => $session,
501                 'module' => 'Accounts',
502                 'id' => $accountId,
503                 )
504             );
505
506         $GLOBALS['db']->query("DELETE FROM accounts WHERE id= '{$accountId}'");
507
508         $this->assertTrue(!empty($result['entry_list'][0]['id']) && $result['entry_list'][0]['id'] != -1,$this->_returnLastRawResponse());
509         $this->assertEquals($result['entry_list'][0]['name_value_list'][0]['name'],'warning',$this->_returnLastRawResponse());
510         $this->assertEquals($result['entry_list'][0]['name_value_list'][0]['value'],"Access to this object is denied since it has been deleted or does not exist",$this->_returnLastRawResponse());
511         $this->assertEquals($result['entry_list'][0]['name_value_list'][1]['name'],'deleted',$this->_returnLastRawResponse());
512         $this->assertEquals($result['entry_list'][0]['name_value_list'][1]['value'],1,$this->_returnLastRawResponse());
513     }
514
515     public function testRelateAccountToTwoContacts()
516     {
517         $result = $this->_login();
518         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
519         $session = $result['id'];
520
521         $result = $this->_makeRESTCall('set_entry',
522             array(
523                 'session' => $session,
524                 'module' => 'Accounts',
525                 'name_value_list' => array(
526                     array('name' => 'name', 'value' => 'New Account'),
527                     array('name' => 'description', 'value' => 'This is an account created from a REST web services call'),
528                     ),
529                 )
530             );
531
532         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
533
534         $accountId = $result['id'];
535
536         $result = $this->_makeRESTCall('set_entry',
537             array(
538                 'session' => $session,
539                 'module' => 'Contacts',
540                 'name_value_list' => array(
541                     array('name' => 'last_name', 'value' => 'New Contact 1'),
542                     array('name' => 'description', 'value' => 'This is a contact created from a REST web services call'),
543                     ),
544                 )
545             );
546
547         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
548
549         $contactId1 = $result['id'];
550
551         $result = $this->_makeRESTCall('set_entry',
552             array(
553                 'session' => $session,
554                 'module' => 'Contacts',
555                 'name_value_list' => array(
556                     array('name' => 'last_name', 'value' => 'New Contact 2'),
557                     array('name' => 'description', 'value' => 'This is a contact created from a REST web services call'),
558                     ),
559                 )
560             );
561
562         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
563
564         $contactId2 = $result['id'];
565
566         // now relate them together
567         $result = $this->_makeRESTCall('set_relationship',
568             array(
569                 'session' => $session,
570                 'module' => 'Accounts',
571                 'module_id' => $accountId,
572                 'link_field_name' => 'contacts',
573                 'related_ids' => array($contactId1,$contactId2),
574                 )
575             );
576
577         $this->assertEquals($result['created'],1,$this->_returnLastRawResponse());
578
579         // check the relationship
580         $result = $this->_makeRESTCall('get_relationships',
581             array(
582                 'session' => $session,
583                 'module' => 'Accounts',
584                 'module_id' => $accountId,
585                 'link_field_name' => 'contacts',
586                 'related_module_query' => '',
587                 'related_fields' => array('last_name','description'),
588                 'related_module_link_name_to_fields_array' => array(),
589                 'deleted' => false,
590                 )
591             );
592
593         $returnedValues = array();
594         $returnedValues[] = $result['entry_list'][0]['name_value_list']['last_name']['value'];
595         $returnedValues[] = $result['entry_list'][1]['name_value_list']['last_name']['value'];
596
597         $GLOBALS['db']->query("DELETE FROM accounts WHERE id= '{$accountId}'");
598         $GLOBALS['db']->query("DELETE FROM contacts WHERE id= '{$contactId1}'");
599         $GLOBALS['db']->query("DELETE FROM contacts WHERE id= '{$contactId2}'");
600         $GLOBALS['db']->query("DELETE FROM accounts_contacts WHERE account_id= '{$accountId}'");
601
602         $this->assertContains('New Contact 1',$returnedValues,$this->_returnLastRawResponse());
603         $this->assertContains('New Contact 2',$returnedValues,$this->_returnLastRawResponse());
604     }
605
606     /**
607      * @ticket 36658
608      */
609     public function testOrderByClauseOfGetRelationship()
610     {
611         $result = $this->_login();
612         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
613         $session = $result['id'];
614
615         $result = $this->_makeRESTCall('set_entry',
616             array(
617                 'session' => $session,
618                 'module' => 'Accounts',
619                 'name_value_list' => array(
620                     array('name' => 'name', 'value' => 'New Account'),
621                     array('name' => 'description', 'value' => 'This is an account created from a REST web services call'),
622                     ),
623                 )
624             );
625
626         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
627
628         $accountId = $result['id'];
629
630         $result = $this->_makeRESTCall('set_entry',
631             array(
632                 'session' => $session,
633                 'module' => 'Contacts',
634                 'name_value_list' => array(
635                     array('name' => 'last_name', 'value' => 'New Contact 1'),
636                     array('name' => 'description', 'value' => 'This is a contact created from a REST web services call'),
637                     ),
638                 )
639             );
640
641         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
642
643         $contactId1 = $result['id'];
644
645         $result = $this->_makeRESTCall('set_entry',
646             array(
647                 'session' => $session,
648                 'module' => 'Contacts',
649                 'name_value_list' => array(
650                     array('name' => 'last_name', 'value' => 'New Contact 3'),
651                     array('name' => 'description', 'value' => 'This is a contact created from a REST web services call'),
652                     ),
653                 )
654             );
655
656         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
657         $contactId3 = $result['id'];
658
659         $result = $this->_makeRESTCall('set_entry',
660             array(
661                 'session' => $session,
662                 'module' => 'Contacts',
663                 'name_value_list' => array(
664                     array('name' => 'last_name', 'value' => 'New Contact 2'),
665                     array('name' => 'description', 'value' => 'This is a contact created from a REST web services call'),
666                     ),
667                 )
668             );
669
670         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
671
672         $contactId2 = $result['id'];
673
674         // now relate them together
675         $result = $this->_makeRESTCall('set_relationship',
676             array(
677                 'session' => $session,
678                 'module' => 'Accounts',
679                 'module_id' => $accountId,
680                 'link_field_name' => 'contacts',
681                 'related_ids' => array($contactId1,$contactId3,$contactId2),
682                 )
683             );
684
685         $this->assertEquals($result['created'],1,$this->_returnLastRawResponse());
686
687         // check the relationship
688         $result = $this->_makeRESTCall('get_relationships',
689             array(
690                 'session' => $session,
691                 'module' => 'Accounts',
692                 'module_id' => $accountId,
693                 'link_field_name' => 'contacts',
694                 'related_module_query' => '',
695                 'related_fields' => array('last_name','description'),
696                 'related_module_link_name_to_fields_array' => array(),
697                 'deleted' => false,
698                 'order_by' => 'last_name',
699                 )
700             );
701
702         $GLOBALS['db']->query("DELETE FROM accounts WHERE id= '{$accountId}'");
703         $GLOBALS['db']->query("DELETE FROM contacts WHERE id= '{$contactId1}'");
704         $GLOBALS['db']->query("DELETE FROM contacts WHERE id= '{$contactId2}'");
705         $GLOBALS['db']->query("DELETE FROM contacts WHERE id= '{$contactId3}'");
706         $GLOBALS['db']->query("DELETE FROM accounts_contacts WHERE account_id= '{$accountId}'");
707
708         $this->assertEquals($result['entry_list'][0]['name_value_list']['last_name']['value'],'New Contact 1',$this->_returnLastRawResponse());
709         $this->assertEquals($result['entry_list'][1]['name_value_list']['last_name']['value'],'New Contact 2',$this->_returnLastRawResponse());
710         $this->assertEquals($result['entry_list'][2]['name_value_list']['last_name']['value'],'New Contact 3',$this->_returnLastRawResponse());
711     }
712
713     public static function _subpanelLayoutProvider()
714     {
715         return array(
716             array(
717                 'module' => 'Contacts',
718                 'type' => 'default',
719                 'view' => 'subpanel',
720             ),
721         );
722     }
723
724     /**
725      * @dataProvider _subpanelLayoutProvider
726      */
727     public function testGetSubpanelLayout($module, $type, $view)
728     {
729         $result = $this->_login();
730         $session = $result['id'];
731
732         $results = $this->_makeRESTCall('get_module_layout',
733             array(
734                 'session' => $session,
735                 'module' => array($module),
736                 'type' => array($type),
737                 'view' => array($view))
738         );
739
740         $this->assertTrue(isset($results[$module][$type][$view]), "Unable to get subpanel defs");
741     }
742      public function testGetUpcomingActivities()
743      {
744          $expected = $this->_createUpcomingActivities(); //Seed the data.
745
746          $result = $this->_login(); // Logging in just before the REST call as this will also commit any pending DB changes
747          $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
748          $session = $result['id'];
749          $results = $this->_makeRESTCall('get_upcoming_activities',
750                              array(
751                              'session' => $session,
752                              )
753          );
754
755          $ids = array();
756          foreach($results as $activity)
757          {
758              $ids[$activity['id']] = $activity['id'];
759          }
760
761          $this->assertArrayHasKey($expected[0] , $ids , "Unable to get upcoming activities");
762          $this->assertArrayHasKey($expected[1] ,$ids , "Unable to get upcoming activities");
763
764          $this->_removeUpcomingActivities();
765      }
766
767      private function _removeUpcomingActivities()
768      {
769          $GLOBALS['db']->query("DELETE FROM calls where name = 'UNIT TEST'");
770          $GLOBALS['db']->query("DELETE FROM tasks where name = 'UNIT TEST'");
771      }
772
773      private function _createUpcomingActivities()
774      {
775          $GLOBALS['current_user']->setPreference('datef','Y-m-d') ;
776          $GLOBALS['current_user']->setPreference('timef','H:i') ;
777
778          $date1 = $GLOBALS['timedate']->to_display_date_time(gmdate("Y-m-d H:i:s", (gmmktime() + (3600 * 24 * 2) ) ),true,true, $GLOBALS['current_user']) ; //Two days from today
779          $date2 = $GLOBALS['timedate']->to_display_date_time(gmdate("Y-m-d H:i:s", (gmmktime() + (3600 * 24 * 4) ) ),true,true, $GLOBALS['current_user']) ; //Two days from today
780
781          $callID = uniqid();
782          $c = new Call();
783          $c->id = $callID;
784          $c->new_with_id = TRUE;
785          $c->status = 'Not Planned';
786          $c->date_start = $date1;
787          $c->name = "UNIT TEST";
788          $c->assigned_user_id = $this->_user->id;
789          $c->save(FALSE);
790
791          $callID = uniqid();
792          $c = new Call();
793          $c->id = $callID;
794          $c->new_with_id = TRUE;
795          $c->status = 'Planned';
796          $c->date_start = $date1;
797          $c->name = "UNIT TEST";
798          $c->assigned_user_id = $this->_user->id;
799          $c->save(FALSE);
800
801          $taskID = uniqid();
802          $t = new Task();
803          $t->id = $taskID;
804          $t->new_with_id = TRUE;
805          $t->status = 'Not Started';
806          $t->date_due = $date2;
807          $t->name = "UNIT TEST";
808          $t->assigned_user_id = $this->_user->id;
809          $t->save(FALSE);
810
811          return array($callID, $taskID);
812      }
813 }