Fix token subscriber to format the display of the custom tokens
[civicrm-core.git] / tests / phpunit / api / v3 / MailingABTest.php
1 <?php
2 /*
3 * File for the TestMailing class
4 *
5 * (PHP 5)
6 *
7 * @package CiviCRM
8 *
9 * This file is part of CiviCRM
10 *
11 * CiviCRM is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Affero General Public License
13 * as published by the Free Software Foundation; either version 3 of
14 * the License, or (at your option) any later version.
15 *
16 * CiviCRM is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Affero General Public License for more details.
20 *
21 * You should have received a copy of the GNU Affero General Public
22 * License along with this program. If not, see
23 * <http://www.gnu.org/licenses/>.
24 */
25
26 /**
27 * Test APIv3 civicrm_mailingab_* functions
28 *
29 * @package CiviCRM
30 * @group headless
31 */
32 class api_v3_MailingABTest extends CiviUnitTestCase {
33 protected $_mailingID_A;
34 protected $_mailingID_B;
35 protected $_mailingID_C;
36 protected $_params;
37 protected $_apiversion = 3;
38 protected $_entity = 'MailingAB';
39 protected $_groupID;
40
41 public function setUp() {
42 parent::setUp();
43 $this->useTransaction(TRUE);
44 $this->createLoggedInUser();
45 $this->_mailingID_A = $this->createMailing([
46 'subject' => 'subject a ' . time(),
47 'body_text' => 'body_text a ' . time(),
48 ]);
49 $this->_mailingID_B = $this->createMailing([
50 'subject' => 'subject b ' . time(),
51 'body_text' => 'body_text b ' . time(),
52 ]);
53 $this->_mailingID_C = $this->createMailing([
54 'subject' => 'not yet ' . time(),
55 'body_text' => 'not yet ' . time(),
56 ]);
57 $this->_groupID = $this->groupCreate();
58
59 $this->_params = [
60 'mailing_id_a' => $this->_mailingID_A,
61 'mailing_id_b' => $this->_mailingID_B,
62 'mailing_id_c' => $this->_mailingID_C,
63 'testing_criteria' => 'subject',
64 'winner_criteria' => 'open',
65 'declare_winning_time' => '+2 days',
66 'group_percentage' => 10,
67 ];
68 }
69
70 /**
71 * Test civicrm_mailing_create.
72 */
73 public function testMailingABCreateSuccess() {
74 $result = $this->callAPIAndDocument($this->_entity, 'create', $this->_params, __FUNCTION__, __FILE__);
75 $this->assertTrue(is_numeric($result['id']), "In line " . __LINE__);
76 $this->assertEquals($this->_params['group_percentage'], $result['values'][$result['id']]['group_percentage']);
77 }
78
79 /**
80 * Test civicrm_mailing_delete.
81 */
82 public function testMailerDeleteSuccess() {
83 $result = $this->callAPISuccess($this->_entity, 'create', $this->_params);
84
85 $this->assertDBQuery(1, "SELECT count(*) FROM civicrm_mailing_abtest WHERE id = %1", [
86 1 => [$result['id'], 'Integer'],
87 ]);
88 $this->assertDBQuery(3, "SELECT count(*) FROM civicrm_mailing WHERE id IN (%1,%2,%3)", [
89 1 => [$this->_mailingID_A, 'Integer'],
90 2 => [$this->_mailingID_B, 'Integer'],
91 3 => [$this->_mailingID_C, 'Integer'],
92 ]);
93
94 $this->callAPISuccess($this->_entity, 'delete', ['id' => $result['id']]);
95
96 $this->assertDBQuery(0, "SELECT count(*) FROM civicrm_mailing_abtest WHERE id = %1", [
97 1 => [$result['id'], 'Integer'],
98 ]);
99 $this->assertDBQuery(0, "SELECT count(*) FROM civicrm_mailing WHERE id IN (%1,%2,%3)", [
100 1 => [$this->_mailingID_A, 'Integer'],
101 2 => [$this->_mailingID_B, 'Integer'],
102 3 => [$this->_mailingID_C, 'Integer'],
103 ]);
104 }
105
106 /**
107 * @return array
108 */
109 public function groupPctProvider() {
110 // array(int $totalSize, int $groupPct, int $expectedCountA, $expectedCountB, $expectedCountC)
111 $cases = [];
112 $cases[] = [400, 7, 28, 28, 344];
113 $cases[] = [100, 10, 10, 10, 80];
114 $cases[] = [50, 20, 10, 10, 30];
115 $cases[] = [50, 10, 5, 5, 40];
116 $cases[] = [3, 10, 1, 1, 1];
117 $cases[] = [2, 10, 1, 1, 0];
118 $cases[] = [1, 10, 1, 0, 0];
119 return $cases;
120 }
121
122 /**
123 * Create a test and ensure that all three mailings (A/B/C) wind up with the correct
124 * number of recipients.
125 *
126 * @param $totalGroupContacts
127 * @param $groupPct
128 * @param $expectedCountA
129 * @param $expectedCountB
130 * @param $expectedCountC
131 * @dataProvider groupPctProvider
132 */
133 public function testDistribution($totalGroupContacts, $groupPct, $expectedCountA, $expectedCountB, $expectedCountC) {
134 $result = $this->groupContactCreate($this->_groupID, $totalGroupContacts, TRUE);
135 $this->assertEquals($totalGroupContacts, $result['added'], "in line " . __LINE__);
136
137 $params = $this->_params;
138 $params['group_percentage'] = $groupPct;
139 $result = $this->callAPISuccess($this->_entity, 'create', $params);
140
141 $this->callAPISuccess('Mailing', 'create', [
142 'id' => $this->_mailingID_A,
143 'groups' => ['include' => [$this->_groupID]],
144 ]);
145 $this->assertJobCounts(0, 0, 0);
146
147 $this->callAPISuccess('MailingAB', 'submit', [
148 'id' => $result['id'],
149 'status' => 'Testing',
150 'scheduled_date' => date('YmdHis'),
151 'approval_date' => date('YmdHis'),
152 ]);
153 $this->assertRecipientCounts($expectedCountA, $expectedCountB, $expectedCountC);
154 $this->assertJobCounts(1, 1, 0);
155
156 $this->callAPISuccess('MailingAB', 'submit', [
157 'id' => $result['id'],
158 'status' => 'Final',
159 'scheduled_date' => date('YmdHis'),
160 'approval_date' => date('YmdHis'),
161 ]);
162 $this->assertRecipientCounts($expectedCountA, $expectedCountB, $expectedCountC);
163 $this->assertJobCounts(1, 1, 1);
164 }
165
166 /**
167 * Create a test. Declare the second mailing a winner. Ensure that key
168 * fields propagate to the final mailing.
169 */
170 public function testSubmitWinnderId() {
171 $checkSyncFields = ['subject', 'body_text'];
172
173 $result = $this->groupContactCreate($this->_groupID, 20, TRUE);
174 $this->assertEquals(20, $result['added'], "in line " . __LINE__);
175
176 $params = $this->_params;
177 $params['group_percentage'] = 10;
178 $result = $this->callAPISuccess($this->_entity, 'create', $params);
179
180 $this->callAPISuccess('Mailing', 'create', [
181 'id' => $this->_mailingID_A,
182 'groups' => ['include' => [$this->_groupID]],
183 ]);
184 $this->assertJobCounts(0, 0, 0);
185
186 $this->callAPISuccess('MailingAB', 'submit', [
187 'id' => $result['id'],
188 'status' => 'Testing',
189 'scheduled_date' => 'now',
190 'approval_date' => 'now',
191 ]);
192 $this->assertJobCounts(1, 1, 0);
193
194 $b = $this->getApiValues('Mailing', ['id' => $this->_mailingID_B], $checkSyncFields);
195 $c = $this->getApiValues('Mailing', ['id' => $this->_mailingID_C], $checkSyncFields);
196 $this->assertNotEquals($b, $c);
197
198 $this->callAPISuccess('MailingAB', 'submit', [
199 'id' => $result['id'],
200 'status' => 'Final',
201 'winner_id' => $this->_mailingID_B,
202 'scheduled_date' => 'now',
203 'approval_date' => 'now',
204 ]);
205 $this->assertJobCounts(1, 1, 1);
206
207 $b = $this->getApiValues('Mailing', ['id' => $this->_mailingID_B], $checkSyncFields);
208 $c = $this->getApiValues('Mailing', ['id' => $this->_mailingID_C], $checkSyncFields);
209 $this->assertEquals($b, $c);
210 }
211
212 /**
213 * Lookup a record via API. Return *only* the expected values.
214 *
215 * @param $entity
216 * @param $filter
217 * @param $return
218 * @return array
219 */
220 protected function getApiValues($entity, $filter, $return) {
221 $rec = $this->callAPISuccess($entity, 'getsingle', $filter + ['return' => $return]);
222 return CRM_Utils_Array::subset($rec, $return);
223 }
224
225 /**
226 * @param $expectedCountA
227 * @param $expectedCountB
228 * @param $expectedCountC
229 */
230 protected function assertRecipientCounts($expectedCountA, $expectedCountB, $expectedCountC) {
231 $countA = $this->callAPISuccess('MailingRecipients', 'getcount', ['mailing_id' => $this->_mailingID_A]);
232 $countB = $this->callAPISuccess('MailingRecipients', 'getcount', ['mailing_id' => $this->_mailingID_B]);
233 $countC = $this->callAPISuccess('MailingRecipients', 'getcount', ['mailing_id' => $this->_mailingID_C]);
234 $this->assertEquals($expectedCountA, $countA, "check mailing recipients A in line " . __LINE__);
235 $this->assertEquals($expectedCountB, $countB, "check mailing recipients B in line " . __LINE__);
236 $this->assertEquals($expectedCountC, $countC, "check mailing recipients C in line " . __LINE__);
237 }
238
239 /**
240 * @param $expectedA
241 * @param $expectedB
242 * @param $expectedC
243 */
244 protected function assertJobCounts($expectedA, $expectedB, $expectedC) {
245 $this->assertDBQuery($expectedA, 'SELECT count(*) FROM civicrm_mailing_job WHERE mailing_id = %1', [
246 1 => [
247 $this->_mailingID_A,
248 'Integer',
249 ],
250 ]);
251 $this->assertDBQuery($expectedB, 'SELECT count(*) FROM civicrm_mailing_job WHERE mailing_id = %1', [
252 1 => [
253 $this->_mailingID_B,
254 'Integer',
255 ],
256 ]);
257 $this->assertDBQuery($expectedC, 'SELECT count(*) FROM civicrm_mailing_job WHERE mailing_id = %1', [
258 1 => [
259 $this->_mailingID_C,
260 'Integer',
261 ],
262 ]);
263 }
264
265 }