Merge remote-tracking branch 'upstream/4.4' into 4.4-master-2014-01-08-12-03-28
[civicrm-core.git] / tests / phpunit / WebTest / Contribute / OfflineContributionTest.php
1 <?php
2
3 /*
4 +--------------------------------------------------------------------+
5 | CiviCRM version 4.4 |
6 +--------------------------------------------------------------------+
7 | Copyright CiviCRM LLC (c) 2004-2013 |
8 +--------------------------------------------------------------------+
9 | This file is a part of CiviCRM. |
10 | |
11 | CiviCRM is free software; you can copy, modify, and distribute it |
12 | under the terms of the GNU Affero General Public License |
13 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | |
15 | CiviCRM is distributed in the hope that it will be useful, but |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
18 | See the GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public |
21 | License along with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 require_once 'CiviTest/CiviSeleniumTestCase.php';
29
30 class WebTest_Contribute_OfflineContributionTest extends CiviSeleniumTestCase {
31
32 protected function setUp() {
33 parent::setUp();
34 }
35
36 function testStandaloneContributeAdd() {
37 $this->webtestLogin();
38
39 // Create a contact to be used as soft creditor
40 $softCreditFname = substr(sha1(rand()), 0, 7);
41 $softCreditLname = substr(sha1(rand()), 0, 7);
42 $this->webtestAddContact($softCreditFname, $softCreditLname, FALSE);
43
44 //financial account for check
45 $this->openCiviPage("admin/options/payment_instrument", "group=payment_instrument&reset=1");
46 $financialAccount = $this->getText("xpath=//div[@id='payment_instrument']/div[2]/table/tbody//tr/td[1][text()='Check']/../td[3]");
47
48 // Add new Financial Account
49 $orgName = 'Alberta ' . substr(sha1(rand()), 0, 7);
50 $financialAccountTitle = 'Financial Account ' . substr(sha1(rand()), 0, 4);
51 $financialAccountDescription = "{$financialAccountTitle} Description";
52 $accountingCode = 1033;
53 $financialAccountType = 'Asset';
54 $taxDeductible = FALSE;
55 $isActive = FALSE;
56 $isTax = TRUE;
57 $taxRate = 9;
58 $isDefault = FALSE;
59
60 //Add new organisation
61 if ($orgName) {
62 $this->webtestAddOrganization($orgName);
63 }
64
65 $this->_testAddFinancialAccount($financialAccountTitle,
66 $financialAccountDescription,
67 $accountingCode,
68 $orgName,
69 $financialAccountType,
70 $taxDeductible,
71 $isActive,
72 $isTax,
73 $taxRate,
74 $isDefault
75 );
76
77 $firstName = 'John' . substr(sha1(rand()), 0, 7);
78 $lastName = 'Dsouza' . substr(sha1(rand()), 0, 7);
79 $this->webtestAddContact($firstName, $lastName);
80
81 $this->waitForElementPresent("css=li#tab_contribute a");
82 $this->click("css=li#tab_contribute a");
83 $this->waitForElementPresent("link=Record Contribution (Check, Cash, EFT ...)");
84 $this->click("link=Record Contribution (Check, Cash, EFT ...)");
85 $this->waitForPageToLoad($this->getTimeoutMsec());
86
87 // select financial type
88 $this->select("financial_type_id", "value=1");
89
90 // fill in Received Date
91 $this->webtestFillDate('receive_date');
92
93 // source
94 $this->type("source", "Mailer 1");
95
96 // total amount
97 $this->type("total_amount", "100");
98
99 // select payment instrument type = Check and enter chk number
100 $this->select("payment_instrument_id", "value=4");
101 $this->waitForElementPresent("check_number");
102 $this->type("check_number", "check #1041");
103
104 $this->type("trxn_id", "P20901X1" . rand(100, 10000));
105
106 // create first soft credit
107 $this->webtestFillAutocomplete("{$softCreditLname}, {$softCreditFname}", 'soft_credit_contact_1');
108 $this->type("soft_credit_amount_1", "50");
109
110 // add second soft credit field
111 $this->click("addMoreSoftCredit");
112 $this->waitForElementPresent("soft_credit_amount_2");
113 // create new individual via soft credit
114 $softCreditSecondFname = substr(sha1(rand()), 0, 7);
115 $softCreditSecondLname = substr(sha1(rand()), 0, 7);
116 $this->webtestNewDialogContact($softCreditSecondFname, $softCreditSecondLname, NULL, 4, 'soft_credit_profiles_2', 'soft_credit_1');
117 // enter the second soft credit
118 $this->verifyText("soft_credit_amount_2", ""); // it should be blank cause first soft credit != total_amount
119 $this->type("soft_credit_amount_2", "100"); //the sum of the soft credit amounts can exceed total_amount
120 $this->select("soft_credit_type[2]", "In Honor of");
121
122 //Custom Data
123 // $this->click('CIVICRM_QFID_3_6');
124
125 //Additional Detail section
126 $this->click("AdditionalDetail");
127 $this->waitForElementPresent("thankyou_date");
128
129 $this->type("note", "This is a test note.");
130 $this->type("non_deductible_amount", "10.00");
131 $this->type("fee_amount", "0");
132 $this->type("net_amount", "0");
133 $this->type("invoice_id", time());
134 $this->webtestFillDate('thankyou_date');
135
136 //Honoree section
137 $this->click("Honoree");
138 $this->waitForElementPresent("honor_email");
139
140 $this->click("CIVICRM_QFID_1_2");
141 $this->select("honor_prefix_id", "label=Ms.");
142 $this->type("honor_first_name", "Foo");
143 $this->type("honor_last_name", "Bar");
144 $this->type("honor_email", "foo@bar.com");
145
146 //Premium section
147 $this->click("Premium");
148 $this->waitForElementPresent("fulfilled_date");
149 $this->select("product_name[0]", "label=Coffee Mug ( MUG-101 )");
150 $this->select("product_name[1]", "label=Black");
151 $this->webtestFillDate('fulfilled_date');
152
153 // Clicking save.
154 $this->click("_qf_Contribution_upload");
155 $this->waitForPageToLoad($this->getTimeoutMsec());
156
157 // Is status message correct?
158 //$this->assertTrue($this->isTextPresent("The contribution record has been saved."), "Status message didn't show up after saving!");
159
160 // verify if Contribution is created
161 $this->waitForElementPresent("xpath=//div[@id='Contributions']//table//tbody/tr[1]/td[8]/span/a[text()='View']");
162
163 //click through to the Contribution view screen
164 $this->click("xpath=//div[@id='Contributions']//table/tbody/tr[1]/td[8]/span/a[text()='View']");
165 $this->waitForElementPresent("_qf_ContributionView_cancel-bottom");
166
167 $expected = array(
168 'Financial Type' => 'Donation',
169 'Total Amount' => '100.00',
170 'Contribution Status' => 'Completed',
171 'Paid By' => 'Check',
172 'Check Number' => 'check #1041',
173 'Non-deductible Amount' => '10.00',
174 'Received Into' => $financialAccount,
175 );
176
177 $this->waitForElementPresent("xpath=/html/body/div[3]/div/div[2]/div/div[3]/div/div[2]/div/div/div/form/div[2]");
178 foreach ($expected as $value) {
179 $this->verifyText("xpath=/html/body/div[3]/div/div[2]/div/div[3]/div/div[2]/div/div/div/form/div[2]", preg_quote($value));
180 }
181
182 // verify if soft credit was created successfully
183 $expected = array(
184 'Soft Credit To 1' => "{$softCreditFname} {$softCreditLname}",
185 'Soft Credit To 2' => "{$softCreditSecondFname} {$softCreditSecondLname}",
186 'Amount (Soft Credit Type)' => '50.00 (Solicited)',
187 'Amount (Soft Credit Type)' => '100.00 (In Honor of)',
188 );
189
190 foreach ($expected as $value) {
191 $this->verifyText("css=table.crm-soft-credit-listing", preg_quote($value));
192 }
193
194 // go to first soft creditor contact view page
195 $this->click("css=table.crm-soft-credit-listing tbody tr td a");
196
197 // go to contribution tab
198 $this->waitForElementPresent("css=li#tab_contribute a");
199 $this->click("css=li#tab_contribute a");
200 $this->waitForElementPresent("link=Record Contribution (Check, Cash, EFT ...)");
201
202 // verify soft credit details
203 $expected = array(
204 3 => 'Solicited',
205 4 => 'Donation',
206 2 => '50.00',
207 6 => 'Completed',
208 1 => "{$firstName} {$lastName}"
209 );
210 foreach ($expected as $value => $label) {
211 $this->verifyText("xpath=id('Search')/div[2]/table[2]/tbody/tr[2]/td[$value]", preg_quote($label));
212 }
213 }
214
215 function testDeductibleAmount() {
216 $this->webtestLogin();
217
218 //add authorize .net payment processor
219 $processorName = 'Webtest AuthNet' . substr(sha1(rand()), 0, 7);
220 $this->webtestAddPaymentProcessor($processorName, 'AuthNet');
221
222 $this->openCiviPage("admin/contribute/managePremiums", "action=add&reset=1");
223 $premiumName = 'test Premium' . substr(sha1(rand()), 0, 7);
224 $this->addPremium($premiumName, 'SKU', 3, 12, NULL, NULL);
225
226 $firstName = 'John' . substr(sha1(rand()), 0, 7);
227 $lastName = 'Dsouza' . substr(sha1(rand()), 0, 7);
228 $this->webtestAddContact($firstName, $lastName);
229
230 //scenario 1 : is_deductible = 0 and non deductible amount is entered
231 $scenario1 = array(
232 'financial_type' => 'Campaign Contribution',
233 'total_amount' => 111,
234 'non_deductible_amount' => 15,
235 'sort_name' => "$lastName, $firstName",
236 );
237 $this->_doOfflineContribution($scenario1, $firstName, $lastName, $processorName);
238
239 $checkScenario1 = array(
240 'From' => "{$firstName} {$lastName}",
241 'Financial Type' => 'Campaign Contribution',
242 'Total Amount' => 111,
243 'Non-deductible Amount' => 15,
244 'sort_name' => "$lastName, $firstName",
245 );
246 $this->_verifyAmounts($checkScenario1);
247
248 //scenario 2 : is_deductible = TRUE and premium is set and premium is greater than total amount
249 $scenario2 = array(
250 'financial_type' => 'Donation',
251 'total_amount' => 10,
252 'premium' => "{$premiumName} ( SKU )",
253 'sort_name' => "$lastName, $firstName",
254 );
255 $this->_doOfflineContribution($scenario2, $firstName, $lastName, $processorName);
256
257 $checkScenario2 = array(
258 'From' => "{$firstName} {$lastName}",
259 'Financial Type' => 'Donation',
260 'Total Amount' => 10,
261 'Non-deductible Amount' => 10,
262 'sort_name' => "$lastName, $firstName",
263 );
264 $this->_verifyAmounts($checkScenario2);
265
266 //scenario 3 : is_deductible = TRUE and premium is set and premium is less than total amount
267 $scenario3 = array(
268 'financial_type' => 'Donation',
269 'total_amount' => 123,
270 'premium' => "{$premiumName} ( SKU )",
271 'sort_name' => "$lastName, $firstName",
272 );
273 $this->_doOfflineContribution($scenario3, $firstName, $lastName, $processorName);
274
275 $checkScenario3 = array(
276 'From' => "{$firstName} {$lastName}",
277 'Financial Type' => 'Donation',
278 'Total Amount' => 123,
279 'Non-deductible Amount' => 12,
280 'sort_name' => "$lastName, $firstName",
281 );
282 $this->_verifyAmounts($checkScenario3);
283
284 //scenario 4 : is_deductible = TRUE and premium is not set
285 $scenario4 = array(
286 'financial_type' => 'Donation',
287 'total_amount' => 123,
288 'sort_name' => "$lastName, $firstName",
289 );
290 $this->_doOfflineContribution($scenario4, $firstName, $lastName, $processorName);
291
292 $checkScenario4 = array(
293 'From' => "{$firstName} {$lastName}",
294 'Financial Type' => 'Donation',
295 'Total Amount' => 123,
296 'Non-deductible Amount' => '0.00',
297 'sort_name' => "$lastName, $firstName",
298 );
299 $this->_verifyAmounts($checkScenario4);
300
301 //scenario 5 : is_deductible = FALSE, non_deductible_amount = the total amount
302 $scenario5 = array(
303 'financial_type' => 'Campaign Contribution',
304 'total_amount' => 555,
305 'sort_name' => "$lastName, $firstName",
306 );
307 $this->_doOfflineContribution($scenario5, $firstName, $lastName, $processorName);
308
309 $checkScenario5 = array(
310 'From' => "{$firstName} {$lastName}",
311 'Financial Type' => 'Campaign Contribution',
312 'Total Amount' => 555,
313 'Non-deductible Amount' => 555,
314 'sort_name' => "$lastName, $firstName",
315 );
316 $this->_verifyAmounts($checkScenario5);
317 }
318
319 //common function for doing offline contribution
320 function _doOfflineContribution($params, $firstName, $lastName, $processorName) {
321
322 $this->waitForElementPresent("css=li#tab_contribute a");
323 $this->click("css=li#tab_contribute a");
324 $this->waitForElementPresent("link=Submit Credit Card Contribution");
325 $this->click("link=Submit Credit Card Contribution");
326 $this->waitForPageToLoad($this->getTimeoutMsec());
327
328 // since we don't have live credentials we will switch to test mode
329 $url = $this->getLocation();
330 $url = str_replace('mode=live', 'mode=test', $url);
331 $this->open($url);
332 $this->waitForPageToLoad($this->getTimeoutMsec());
333
334 // start filling out contribution form
335 $this->waitForElementPresent('payment_processor_id');
336 $this->select('payment_processor_id', "label={$processorName}");
337
338 // select financial type
339 $this->select("financial_type_id", "label={$params['financial_type']}");
340
341 // total amount
342 $this->type("total_amount", "{$params['total_amount']}");
343
344 // enter credit card info on form
345 $this->webtestAddCreditCardDetails();
346
347 // billing address
348 $this->webtestAddBillingDetails($firstName, NULL, $lastName);
349
350 if ($nonDeductibleAmt = CRM_Utils_Array::value('non_deductible_amount', $params)) {
351 $this->click("AdditionalDetail");
352 $this->waitForElementPresent("thankyou_date");
353 $this->type("note", "This is a test note.");
354 $this->type("non_deductible_amount", "{$nonDeductibleAmt}");
355 }
356
357 if (CRM_Utils_Array::value('premium', $params)) {
358 //Premium section
359 $this->click("Premium");
360 $this->waitForElementPresent("fulfilled_date");
361 $this->select("product_name[0]", "label={$params['premium']}");
362 }
363 // Clicking save.
364 $this->click("_qf_Contribution_upload");
365 $this->waitForPageToLoad($this->getTimeoutMsec());
366
367 // Is status message correct?
368 $this->assertTrue($this->isTextPresent("The contribution record has been processed."), "Status message didn't show up after saving!");
369 }
370
371 //common function for verifing total_amount, and non_deductible_amount
372 function _verifyAmounts($verifyData) {
373 // since we are doing test contributions we need to search for test contribution and select first contribution
374 // record for the contact
375 $this->openCiviPage("contribute/search", "reset=1", "contribution_date_low");
376 $this->type("sort_name", $verifyData['sort_name']);
377
378 // select show test contributions
379 $this->click("contribution_test", "value=1");
380 $this->clickLink("_qf_Search_refresh", "xpath=//div[@id='contributionSearch']//table//tbody/tr[1]/td[11]/span/a[text()='View']");
381 $this->clickLink("xpath=//div[@id='contributionSearch']//table//tbody/tr[1]/td[11]/span/a[text()='View']", "_qf_ContributionView_cancel-bottom");
382
383 foreach ($verifyData as $label => $value) {
384 if ( $label == 'sort_name' ) {
385 continue;
386 }
387 $this->verifyText("xpath=//form[@id='ContributionView']//table/tbody/tr/td[text()='{$label}']/following-sibling::td",
388 preg_quote($value)
389 );
390 }
391
392 // now find contact and go back to contact summary
393 $this->openCiviPage("contact/search", "reset=1", "sort_name");
394 $this->type("sort_name", $verifyData['sort_name']);
395 $this->clickLink("_qf_Basic_refresh",
396 "xpath=//form[@id='Basic']/div[3]/div[1]/div[2]/table/tbody/tr[1]/td[11]/span/a[text()='View']");
397
398 $this->clickLink("xpath=//form[@id='Basic']/div[3]/div[1]/div[2]/table/tbody/tr[1]/td[11]/span/a[text()='View']",
399 'crm-contact-actions-link');
400 }
401
402 function testOnlineContributionWithZeroAmount() {
403 $this->webtestLogin();
404
405 // Create a contact to be used as soft creditor
406 $firstName = 'John' . substr(sha1(rand()), 0, 7);
407 $lastName = 'Peterson' . substr(sha1(rand()), 0, 7);
408 $this->webtestAddContact($firstName, $lastName);
409 $this->waitForElementPresent("css=li#tab_contribute a");
410 $this->click("css=li#tab_contribute a");
411 $this->waitForElementPresent("link=Record Contribution (Check, Cash, EFT ...)");
412 $this->clickLink("link=Record Contribution (Check, Cash, EFT ...)");
413
414 // select financial type
415 $this->select("financial_type_id", "value=1");
416
417 // total amount
418 $this->type("total_amount", "0.00");
419
420 // select payment instrument
421 $this->select("payment_instrument_id", "value=1");
422
423 $this->type("trxn_id", "X20901X1" . rand(100, 10000));
424 $this->clickLink('_qf_Contribution_upload-bottom');
425 $this->waitForText("crm-notification-container", "The contribution record has been saved.");
426
427 $this->waitForElementPresent("xpath=//div[@id='Contributions']//table//tbody/tr[1]/td[8]/span/a[text()='View']");
428 $this->clickLink("xpath=//div[@id='Contributions']//table/tbody/tr[1]/td[8]/span/a[text()='View']");
429 $expected = array(
430 'Financial Type' => 'Donation',
431 'Total Amount' => '0.00',
432 'Contribution Status' => 'Completed',
433 'Paid By' => 'Credit Card'
434 );
435 $this->webtestVerifyTabularData($expected);
436 }
437 }