2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
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.
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
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
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.
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.
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 ********************************************************************************/
38 require_once 'include/Smarty/plugins/function.sugar_button.php';
39 require_once 'include/Smarty/plugins/function.sugar_menu.php';
40 require_once 'include/SugarHtml/SugarHtml.php';
41 require_once 'include/Sugar_Smarty.php';
43 class FunctionSugarButtonTest extends Sugar_PHPUnit_Framework_TestCase
45 public function setUp()
47 $this->_smarty = new Sugar_Smarty;
51 public function providerCustomCode() {
52 $onclick = 'this.form.module.value=\'Contacts\';';
53 $expected_onclick = 'var _form = document.getElementById(\'DetailView\');_form.module.value=\'Contacts\';_form.submit();';
56 //set #0: simple input code
58 '<input type="submit" value="{$APP.BUTTON_LABEL}" onclick="'.$onclick.'">',
62 'self_closing' => true,
63 'onclick' => $onclick,
64 'value' => '{$APP.BUTTON_LABEL}'
66 '<input type="button" value="{$APP.BUTTON_LABEL}" onclick="'.$expected_onclick.'"/>',
70 '<input type="submit" disabled value="{$APP.BUTTON_LABEL}" onclick="'.$onclick.'">',
74 'self_closing' => true,
75 'onclick' => $onclick,
76 'value' => '{$APP.BUTTON_LABEL}',
79 '<input type="button" disabled value="{$APP.BUTTON_LABEL}" onclick="'.$expected_onclick.'"/>',
82 //set #2: custom code contains smarty conditional statement
84 '<input type="submit" value="{$APP.BUTTON_LABEL}" onclick="{if $bean->access(\'edit\')}'.$onclick.'{/if}">',
88 'self_closing' => true,
89 'onclick' => '{if $bean->access(\'edit\')}'.$onclick.'{/if}',
90 'value' => '{$APP.BUTTON_LABEL}'
92 '<input type="button" value="{$APP.BUTTON_LABEL}" onclick="var _form = document.getElementById(\'DetailView\');{if $bean->access(\'edit\')}_form.module.value=\'Contacts\';{/if};_form.submit();"/>',
94 //set #3: attributes wrapped with smarty
97 '<input {if $bean->access(\'edit\')}type="submit"{else}type="hidden"{/if} value="{$APP.BUTTON_LABEL}" {if $bean->access(\'edit\')}onclick="'.$onclick.'"{else}onclick="alert(\'nope\');"{/if} id="button_submit">',
100 'id' => 'button_submit',
102 'self_closing' => true,
105 'template' => '{if $bean->access(\'edit\')}[CONTENT0]{else}[CONTENT1]{/if}',
106 '[CONTENT0]' => array(
109 '[CONTENT1]' => array(
114 'template' => '{if $bean->access(\'edit\')}[CONTENT0]{else}[CONTENT1]{/if}',
115 '[CONTENT0]' => array(
116 'onclick' => $onclick
118 '[CONTENT1]' => array(
119 'onclick' => 'alert(\'nope\');'
124 'value' => '{$APP.BUTTON_LABEL}'
126 '<input {if $bean->access(\'edit\')}type="submit"{else}type="hidden"{/if} {if $bean->access(\'edit\')}onclick="'.$expected_onclick.'"{else}onclick="alert(\'nope\');"{/if} value="{$APP.BUTTON_LABEL}" id="button_submit"/>',
129 //set #4: attributes wrapped with smarty
132 '<input type="submit"{if $bean->access(\'edit\')}onclick="'.$onclick.'"{else}onclick="this.form.module.value=\'{$APP.MODULE}\';this.form.action.value=\'{$APP.ACTION}\';"{/if} value="{$APP.BUTTON_LABEL}" id="button_submit">',
135 'id' => 'button_submit',
138 'self_closing' => true,
141 'template' => '{if $bean->access(\'edit\')}[CONTENT0]{else}[CONTENT1]{/if}',
142 '[CONTENT0]' => array(
143 'onclick' => $onclick
145 '[CONTENT1]' => array(
146 'onclick' => 'this.form.module.value=\'{$APP.MODULE}\';this.form.action.value=\'{$APP.ACTION}\';'
151 'value' => '{$APP.BUTTON_LABEL}'
153 '<input {if $bean->access(\'edit\')}onclick="'.$expected_onclick.'"{else}onclick="var _form = document.getElementById(\'DetailView\');_form.module.value=\'{$APP.MODULE}\';_form.action.value=\'{$APP.ACTION}\';_form.submit();"{/if} type="button" value="{$APP.BUTTON_LABEL}" id="button_submit"/>',
156 //set #5: recursive smarty wrapper within the attributes
158 '<input type="submit" value="{$APP.BUTTON_LABEL}" {$APP.DISABLED} {if $bean->access(\'edit\')}{if $APP.CONTAINER = true}onclick="'.$onclick.'"{/if}{else if $bean->access(\'delete\') }onclick="del();"{else}onclick="alert(\'nope\');"{/if} id="button_submit">',
160 'id' => 'button_submit',
163 'self_closing' => true,
164 'value' => '{$APP.BUTTON_LABEL}',
167 'template' => '{$APP.DISABLED}'
170 'template' => '{if $bean->access(\'edit\')}[CONTENT0]{else if $bean->access(\'delete\') }[CONTENT1]{else}[CONTENT2]{/if}',
171 '[CONTENT0]' => array(
174 'template' => '{if $APP.CONTAINER = true}[CONTENT0]{/if}',
175 '[CONTENT0]' => array(
176 'onclick' => $onclick
181 '[CONTENT1]' => array(
182 'onclick' => 'del();'
184 '[CONTENT2]' => array(
185 'onclick' => 'alert(\'nope\');'
190 '<input {$APP.DISABLED} {if $bean->access(\'edit\')}{if $APP.CONTAINER = true}onclick="'.$expected_onclick.'"{/if}{else if $bean->access(\'delete\') }onclick="del();"{else}onclick="alert(\'nope\');"{/if} type="button" value="{$APP.BUTTON_LABEL}" id="button_submit"/>',
192 //set #6: Begins with smarty conditional statement
194 '{if $fields.status.value != "Held"} <input title="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}" class="button" onclick="'.$onclick.'" value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}" type="submit">{/if}',
198 'template' => '{if $fields.status.value != "Held"}[CONTENT0]{/if}',
199 '[CONTENT0]' => array(
202 'self_closing' => true,
203 'title' => '{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}',
205 'onclick' => $onclick,
206 'value' => '{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}'
211 '{if $fields.status.value != "Held"}<input title="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}" class="button" onclick="'.$expected_onclick.'" value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}" type="button"/>{/if}'
213 //set #7: Begins with smarty conditional statement and contains recursive conditional statement inside the context
215 '{ if($fields.status.value != "Held") } <input title="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}" {if $bean->access(\'edit\')}{if $APP.CONTAINER = true}onclick="'.$onclick.'"{/if}{else if $bean->access(\'delete\') }onclick="del();"{else}onclick="alert(\'nope\');"{/if} class="button" onclick="'.$onclick.'" value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}" type="submit">{/if}',
219 'template' => '{ if($fields.status.value != "Held") }[CONTENT0]{/if}',
220 '[CONTENT0]' => array(
224 'value' => '{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}',
225 'onclick' => $onclick,
226 'self_closing' => true,
227 'title' => '{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}',
230 'template' => '{if $bean->access(\'edit\')}[CONTENT0]{else if $bean->access(\'delete\') }[CONTENT1]{else}[CONTENT2]{/if}',
231 '[CONTENT0]' => array(
234 'template' => '{if $APP.CONTAINER = true}[CONTENT0]{/if}',
235 '[CONTENT0]' => array(
236 'onclick' => $onclick
241 '[CONTENT1]' => array(
242 'onclick' => 'del();'
244 '[CONTENT2]' => array(
245 'onclick' => 'alert(\'nope\');'
254 '{ if($fields.status.value != "Held") }<input {if $bean->access(\'edit\')}{if $APP.CONTAINER = true}onclick="'.$expected_onclick.'"{/if}{else if $bean->access(\'delete\') }onclick="del();"{else}onclick="alert(\'nope\');"{/if} title="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}" class="button" onclick="'.$expected_onclick.'" value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}" type="button"/>{/if}'
256 //set #8: The submit button is encapsulated with another form
258 '<form name="blah"> <input type="hidden" name="id1"> <input type="hidden" name="id2"> <input type="submit" onclick="'.$onclick.'"></form>',
262 'self_closing' => false,
263 'container' => array(
268 'self_closing' => true,
274 'self_closing' => true,
279 'onclick' => $onclick,
280 'self_closing' => true,
284 '<form name="blah"><input type="hidden" name="id1"/><input type="hidden" name="id2"/><input type="submit" onclick="'.$onclick.'"/></form>',
287 //set #9: custom code encapsulated smarty conditional statement, and contains additional hidden fields
289 '{if $fields.status.value != "Held"} <input type="hidden" name="id1" value="true"> <input type="hidden" name="id2"> <input type="submit" {if $APP.CONTAINER = true}onclick="'.$onclick.'"{else}onclick="stop();"{/if} value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}">{/if}',
293 'template' => '{if $fields.status.value != "Held"}[CONTENT0]{/if}',
294 '[CONTENT0]' => array(
299 'self_closing' => true,
306 'self_closing' => true,
311 'value' => '{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}',
312 'self_closing' => true,
315 'template' => '{if $APP.CONTAINER = true}[CONTENT0]{else}[CONTENT1]{/if}',
316 '[CONTENT0]' => array(
317 'onclick' => $onclick
319 '[CONTENT1]' => array(
320 'onclick' => 'stop();'
329 '{if $fields.status.value != "Held"}<input type="hidden" name="id1" value="true"/><input type="hidden" name="id2"/><input {if $APP.CONTAINER = true}onclick="'.$expected_onclick.'"{else}onclick="stop();"{/if} type="button" value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}"/>{/if}'
331 //set #10: empty spaces after the equal sign
333 '<input title="{$APP.LBL_SAVE_BUTTON_TITLE}" id= "SAVE" disabled onclick="SUGAR.meetings.fill_invitees();document.EditView.action.value=\'Save\'; document.EditView.return_action.value=\'DetailView\'; {if isset($smarty.request.isDuplicate) && $smarty.request.isDuplicate eq "true"}document.EditView.return_id.value=\'\'; {/if} formSubmitCheck();"type="button" name="button" value="{$APP.LBL_SAVE_BUTTON_LABEL}">',
336 'title' => '{$APP.LBL_SAVE_BUTTON_TITLE}',
339 'onclick' => 'SUGAR.meetings.fill_invitees();document.EditView.action.value=\'Save\'; document.EditView.return_action.value=\'DetailView\'; {if isset($smarty.request.isDuplicate) && $smarty.request.isDuplicate eq "true"}document.EditView.return_id.value=\'\'; {/if} formSubmitCheck();',
342 'value' => '{$APP.LBL_SAVE_BUTTON_LABEL}',
343 'self_closing' => true,
345 '<input title="{$APP.LBL_SAVE_BUTTON_TITLE}" id="SAVE" disabled onclick="SUGAR.meetings.fill_invitees();document.EditView.action.value=\'Save\'; document.EditView.return_action.value=\'DetailView\'; {if isset($smarty.request.isDuplicate) && $smarty.request.isDuplicate eq "true"}document.EditView.return_id.value=\'\'; {/if} formSubmitCheck();" type="button" name="button" value="{$APP.LBL_SAVE_BUTTON_LABEL}"/>',
347 //set #11: empty spaces before the equal sign
349 '<input title="{$APP.LBL_SAVE_BUTTON_TITLE}" id = "SAVE" disabled onclick="SUGAR.meetings.fill_invitees();document.EditView.action.value=\'Save\'; document.EditView.return_action.value=\'DetailView\'; {if isset($smarty.request.isDuplicate) && $smarty.request.isDuplicate eq "true"}document.EditView.return_id.value=\'\'; {/if} formSubmitCheck();"type="button" name="button" value="{$APP.LBL_SAVE_BUTTON_LABEL}">',
352 'title' => '{$APP.LBL_SAVE_BUTTON_TITLE}',
355 'onclick' => 'SUGAR.meetings.fill_invitees();document.EditView.action.value=\'Save\'; document.EditView.return_action.value=\'DetailView\'; {if isset($smarty.request.isDuplicate) && $smarty.request.isDuplicate eq "true"}document.EditView.return_id.value=\'\'; {/if} formSubmitCheck();',
358 'value' => '{$APP.LBL_SAVE_BUTTON_LABEL}',
359 'self_closing' => true,
361 '<input title="{$APP.LBL_SAVE_BUTTON_TITLE}" id="SAVE" disabled onclick="SUGAR.meetings.fill_invitees();document.EditView.action.value=\'Save\'; document.EditView.return_action.value=\'DetailView\'; {if isset($smarty.request.isDuplicate) && $smarty.request.isDuplicate eq "true"}document.EditView.return_id.value=\'\'; {/if} formSubmitCheck();" type="button" name="button" value="{$APP.LBL_SAVE_BUTTON_LABEL}"/>',
366 * @dataProvider providerCustomCode
368 public function testCustomCode($customCode, $expected_parsed_array, $expected_customCode)
370 //Test for parseHtmlTag
371 $this->assertEquals($expected_parsed_array, SugarHtml::parseHtmlTag($customCode));
373 'module' => 'Accounts',
374 'view' => 'DetailView',
376 'customCode' => $customCode
378 'form_id' => 'DetailView'
381 //Test for smarty_function_sugar_button for customCode
382 $this->assertEquals($expected_customCode, smarty_function_sugar_button($params, $this->_smarty));
386 public function providerCustomCodeWithHidden() {
388 $onclick = 'this.form.module.value=\'Contacts\';this.form.action.value=\'DetailView\';';
389 $expected_onclick = 'var _form = document.getElementById(\'DetailView\');_form.module.value=\'Contacts\';_form.action.value=\'DetailView\';_form.submit();';
392 //set #0: Button with hidden field
394 '<input type="hidden" name="id2" value="2"> <input type="submit"onclick="'.$onclick.'"value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}">',
395 '<input type="hidden" name="id2" value="2"/><input type="button" onclick="'.$expected_onclick.'" value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}"/>',
397 '<input type="hidden" name="id2" value="2"/>'
400 //set #1: Button with hidden field wrapping with conditional smarty statement
402 '{if $fields.status.value != "Held"} <input type="hidden" name="id1" value="true"> <input type="hidden" name="id2"> <input type="submit" {if $APP.CONTAINER = true}onclick="'.$onclick.'"{else}onclick="stop();"{/if} value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}">{/if}',
403 '{if $fields.status.value != "Held"}<input type="hidden" name="id1" value="true"/><input type="hidden" name="id2"/><input {if $APP.CONTAINER = true}onclick="'.$expected_onclick.'"{else}onclick="stop();"{/if} type="button" value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}"/>{/if}',
405 '{if $fields.status.value != "Held"}<input type="hidden" name="id1" value="true"/><input type="hidden" name="id2"/>{/if}',
408 //set #2: wrapping with conditional smarty statement great equal than two phases
410 '{if $fields.status.value != "Held"}<input type="hidden" name="id1" value="true"><input type="hidden" name="id2"><input type="submit" onclick="'.$onclick.'">{else}<input type="hidden" name="id3" value="true"><input type="submit" onclick="'.$onclick.'">{/if}',
411 '{if $fields.status.value != "Held"}<input type="hidden" name="id1" value="true"/><input type="hidden" name="id2"/><input type="button" onclick="'.$expected_onclick.'"/>{else}<input type="hidden" name="id3" value="true"/><input type="button" onclick="'.$expected_onclick.'"/>{/if}',
413 '{if $fields.status.value != "Held"}<input type="hidden" name="id1" value="true"/><input type="hidden" name="id2"/>{else}<input type="hidden" name="id3" value="true"/>{/if}',
417 //set #3: hidden fields wrapped with the additional form element
419 '<form name="blah"> <input type="hidden" name="id1"> <input type="hidden" name="id2"> <input type="submit" onclick="'.$onclick.'"></form>',
420 '<form name="blah"><input type="hidden" name="id1"/><input type="hidden" name="id2"/><input type="submit" onclick="'.$onclick.'"/></form>',
426 * @dataProvider providerCustomCodeWithHidden
428 public function testCustomCodeWithHidden($customCode, $expected_customCode, $expected_hidden_array) {
431 'module' => 'Accounts',
432 'view' => 'DetailView',
434 'customCode' => $customCode
436 'form_id' => 'DetailView'
438 $this->assertEquals($expected_customCode, smarty_function_sugar_button($params, $this->_smarty));
439 $form = $this->_smarty->get_template_vars('form');
441 $this->assertEquals($expected_hidden_array, $form['hidden']);
445 public function testBuildSugarHtml() {
448 'value' => '{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}',
449 'htmlOptions' => array(
450 'title' => '{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}',
453 'onclick' => 'this.form.isSaveFromDetailView.value=true; this.form.status.value=\'Held\'; this.form.action.value=\'Save\';this.form.return_module.value=\'Meetings\';this.form.isDuplicate.value=true;this.form.isSaveAndNew.value=true;this.form.return_action.value=\'EditView\'; this.form.isDuplicate.value=true;this.form.return_id.value=\'{$fields.id.value}\';',
456 'template' => '{if $fields.status.value != "Held"}[CONTENT]{/if}',
458 $expected_html = '{if $fields.status.value != "Held"}<input title="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}" name="button" class="button" onclick="var _form = document.getElementById(\'DetailView\');_form.isSaveFromDetailView.value=true; _form.status.value=\'Held\'; _form.action.value=\'Save\';_form.return_module.value=\'Meetings\';_form.isDuplicate.value=true;_form.isSaveAndNew.value=true;_form.return_action.value=\'EditView\'; _form.isDuplicate.value=true;_form.return_id.value=\'{$fields.id.value}\';_form.submit();" type="button" value="{$APP.LBL_CLOSE_AND_CREATE_BUTTON_TITLE}"/>{/if}';
461 'module' => 'Accounts',
462 'view' => 'DetailView',
464 'sugar_html' => $sugar_html
466 'form_id' => 'DetailView'
468 //Test for smarty_function_sugar_button for sugar_html
469 $this->assertEquals($expected_html, smarty_function_sugar_button($params, $this->_smarty));