| Commit | Line | Data |
|---|---|---|
| 67189554 | 1 | <?php |
| 4b3cbfb4 OT |
2 | // $Id$ |
| 3 | /** | |
| 4 | * @file | |
| 5 | * Test file for privatemsg.module | |
| 6 | * | |
| 7 | */ | |
| 67189554 TGGM |
8 | |
| 9 | class PrivatemsgTestCase extends DrupalWebTestCase { | |
| 10 | /** | |
| 11 | * Implementation of getInfo(). | |
| 12 | */ | |
| 13 | function getInfo() { | |
| 4b3cbfb4 OT |
14 | return array |
| 15 | ( | |
| 67189554 TGGM |
16 | // 'name' should start with what is being tested (menu item) followed by what about it |
| 17 | // is being tested (creation/deletion). | |
| 18 | 'name' => t('Privatemsg functionality.'), | |
| 19 | // 'description' should be one or more complete sentences that provide more details on what | |
| 20 | // exactly is being tested. | |
| 21 | 'description' => t('Test sending, receiving, listing, deleting messages and other features.'), | |
| 22 | // 'group' should be a logical grouping of test cases, like a category. In most cases, that | |
| 23 | // is the module the test case is for. | |
| 24 | 'group' => t('Privatemsg'), | |
| 25 | ); | |
| 26 | } | |
| 27 | ||
| 28 | /** | |
| 29 | * Implementation of setUp(). | |
| 30 | */ | |
| 31 | function setUp() { | |
| 32 | parent::setUp('privatemsg'); | |
| 33 | } | |
| 34 | ||
| 35 | /** | |
| 36 | * Test user access to /messages | |
| 37 | * Create user with no 'read privatemsg' permission. Try to access mailbox and see if it gives access denied error | |
| 38 | * Create user with 'read privatemsg' permission. Try to access mailbox and see if it gives allows access | |
| 39 | */ | |
| 40 | function testPrivatemsgReadPrivatemsgPermission() { | |
| 41 | $user_no_read_msg = $this->drupalCreateUser(); // set up user with default permissions (meaning: no read privatemsg permission | |
| 42 | $this->drupalLogin($user_no_read_msg); | |
| 43 | $this->drupalGet('messages'); | |
| 44 | $this->assertResponse(403, t('HTTP Response 403: Access to mailbox was blocked to user without "<em>read privatemsg</em>" permission')); | |
| 45 | ||
| 46 | $user_read_msg = $this->drupalCreateUser(array('read privatemsg')); // set up user with default permissions (meaning: no read privatemsg permission | |
| 47 | $this->drupalLogin($user_read_msg); | |
| 48 | $this->drupalGet('messages'); | |
| 49 | $this->assertResponse(200, t('HTTP Response 200: Access to mailbox was authorized to user with "<em>read privatemsg</em>" permission')); | |
| 50 | } | |
| 51 | /** | |
| 52 | * Test user access to /messages/new | |
| 53 | * Create user with no 'write privatemsg' permission. Try to access Write New Message page and see if it gives access denied error | |
| 54 | * Create user with 'write privatemsg' permission. Try to access Write New Message page and see if it gives allows access | |
| 55 | */ | |
| 56 | function testPrivatemsgWritePrivatemsgPermission() { | |
| 57 | $user_no_write_msg = $this->drupalCreateUser(); // set up user with default permissions (meaning: no read privatemsg permission | |
| 58 | $this->drupalLogin($user_no_write_msg); | |
| 59 | $this->drupalGet('messages/new'); | |
| 60 | $this->assertResponse(403, t('HTTP Response 403: Access to Write New Message page was blocked to user without "<em>write privatemsg</em>" permission')); | |
| 61 | ||
| 62 | $user_write_msg = $this->drupalCreateUser(array('write privatemsg')); // set up user with default permissions (meaning: no read privatemsg permission | |
| 63 | $this->drupalLogin($user_write_msg); | |
| 64 | $this->drupalGet('messages/new'); | |
| 65 | $this->assertResponse(200, t('HTTP Response 200: Access to Write New Message page was authorized to user with "<em>write privatemsg</em>" permission')); | |
| 66 | } | |
| 67 | ||
| 68 | /** | |
| 69 | * Test sending message from the /messages/new page between two people | |
| 70 | */ | |
| 86ee5a80 SG |
71 | function testWriteReplyPrivatemsg() { |
| 72 | // Create a author and two recipients. | |
| 67189554 TGGM |
73 | $author = $this->drupalCreateUser(array('write privatemsg')); |
| 74 | $recipient = $this->drupalCreateUser(array('read privatemsg')); | |
| 86ee5a80 | 75 | $recipient2 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg')); |
| 67189554 | 76 | |
| 86ee5a80 | 77 | // Login author and go to new message form. |
| 67189554 TGGM |
78 | $this->drupalLogin($author); |
| 79 | $this->drupalGet('messages/new'); | |
| 80 | ||
| 86ee5a80 SG |
81 | // Prepare edit arrays, single recipient. |
| 82 | $edit = array( | |
| 83 | 'recipient' => $recipient->name, | |
| 84 | 'subject' => $this->randomName(20), | |
| 85 | 'body' => $this->randomName(100), | |
| 86 | ); | |
| 87 | // Two recipients. | |
| 88 | $edit2 = array( | |
| 89 | 'recipient' => $recipient->name . ', ' . $recipient2->name, | |
| 90 | 'subject' => $this->randomName(20), | |
| 91 | 'body' => $this->randomName(100), | |
| 92 | ); | |
| 93 | // No recipients. | |
| 94 | $editnone = array( | |
| 95 | 'recipient' => '', | |
| 96 | 'subject' => $this->randomName(20), | |
| 97 | 'body' => $this->randomName(100), | |
| 98 | ); | |
| 99 | // Invalid recipient | |
| 100 | $editinvalid = array( | |
| 101 | 'recipient' => $this->randomName(5), | |
| 102 | 'subject' => $this->randomName(20), | |
| 103 | 'body' => $this->randomName(100), | |
| 104 | ); | |
| 105 | // Empty body. | |
| 106 | $editnobody = array( | |
| 107 | 'recipient' => $recipient->name, | |
| 108 | 'subject' => $this->randomName(20), | |
| 109 | 'body' => '', | |
| 110 | ); | |
| 111 | // Empty subject. | |
| 112 | $editnosubject = array( | |
| 113 | 'recipient' => $recipient->name, | |
| 114 | 'subject' => '', | |
| 115 | 'body' => $this->randomName(100), | |
| 116 | ); | |
| 117 | // Empty subject and body. | |
| 118 | $editempty = array( | |
| 119 | 'recipient' => $recipient->name, | |
| 120 | 'subject' => '', | |
| 121 | 'body' => '', | |
| 122 | ); | |
| 123 | // Invalid and valid recipient | |
| 124 | $editmixed = array( | |
| 125 | 'recipient' => ($invalidmixed = $this->randomName(5)) . ', ' . $recipient->name, | |
| 126 | 'subject' => $this->randomName(20), | |
| 127 | 'body' => $this->randomName(100), | |
| 128 | ); | |
| 129 | ||
| 130 | // Submit the messages. | |
| 131 | $this->drupalPost('messages/new', $edit, t('Send message')); | |
| 132 | $this->assertText(t('A message has been sent to @recipients.', array('@recipients' => $recipient->name)), 'Message sent confirmation displayed.'); | |
| 133 | ||
| 134 | $this->drupalPost('messages/new', $edit2, t('Send message')); | |
| 135 | $this->assertText(t('A message has been sent to @recipients.', array('@recipients' => implode(', ', array($recipient->name, $recipient2->name)))), 'Message sent confirmation displayed.'); | |
| 136 | ||
| 137 | $this->drupalPost('messages/new', $editnone, t('Send message')); | |
| 138 | $this->assertText(t('Disallowed to send a message without atleast one valid recipient'), 'Message was not sent.'); | |
| 139 | ||
| 140 | $this->drupalPost('messages/new', $editinvalid, t('Send message')); | |
| 141 | $this->assertText(t('Disallowed to send a message without atleast one valid recipient'), 'Message was not sent.'); | |
| 142 | $this->assertText(t('The following users will not receive this private message: @recipients', array('@recipients' => $editinvalid['recipient'])), 'Message about non-existing user displayed.'); | |
| 143 | ||
| 144 | $this->drupalPost('messages/new', $editnobody, t('Send message')); | |
| 145 | $this->assertText(t('A message has been sent to @recipients.', array('@recipients' => $recipient->name)), 'Message sent confirmation displayed.'); | |
| 146 | ||
| 147 | $this->drupalPost('messages/new', $editnosubject, t('Send message')); | |
| 148 | $this->assertText(t('A message has been sent to @recipients.', array('@recipients' => $recipient->name)), 'Message sent confirmation displayed.'); | |
| 149 | ||
| 150 | $this->drupalPost('messages/new', $editempty, t('Send message')); | |
| 151 | $this->assertText(t('Disallowed to send a message without subject'), 'Empty subject message displayed.'); | |
| 152 | ||
| 153 | $this->drupalPost('messages/new', $editmixed, t('Send message')); | |
| 154 | $this->assertText(t('A message has been sent to @recipients.', array('@recipients' => $recipient->name)), 'Message sent confirmation displayed.'); | |
| 155 | $this->assertText(t('The following users will not receive this private message: @recipients', array('@recipients' => $invalidmixed)), 'Message about non-existing user displayed.'); | |
| 156 | ||
| 157 | // Login as recipient2 and try to write some replies. | |
| 158 | $this->drupalLogin($recipient2); | |
| 159 | $this->drupalGet('messages'); | |
| 160 | ||
| 161 | $this->assertNoText($edit['subject'], 'Sent message subject found.'); | |
| 162 | $this->assertText($edit2['subject'], 'Sent message subject found.'); | |
| 163 | $this->clickLink($edit2['subject']); | |
| 164 | ||
| 165 | $this->assertText($edit2['body'], 'Found message body.'); | |
| 166 | ||
| 167 | // Prepare replies. | |
| 168 | $reply = array( | |
| 169 | 'body' => $this->randomName(100), | |
| 170 | ); | |
| 171 | // Empty body. | |
| 172 | $replyempty = array( | |
| 173 | 'body' => '', | |
| 174 | ); | |
| 175 | ||
| 176 | $this->drupalPost(NULL, $reply, t('Send message')); | |
| 177 | $this->assertText(t('A message has been sent to @recipient, @author.', array('@recipient' => $recipient->name, '@author' => $author->name)), 'Reply has been sent.'); | |
| 178 | $this->assertText($reply['body'], 'New message body displayed.'); | |
| 179 | ||
| 180 | $this->drupalPost(NULL, $replyempty, t('Send message')); | |
| 181 | $this->assertText(t('Disallowed to send reply without a message.')); | |
| 182 | ||
| 183 | // Login using recipient and try to read the message by going to inbox first. | |
| 184 | $this->drupalLogin($recipient); | |
| 185 | $this->drupalGet('messages'); | |
| 186 | ||
| 187 | // Assert if we see the subject of the messages. | |
| 188 | $this->assertText($edit['subject'], 'Sent message subject found.'); | |
| 189 | $this->assertText($edit2['subject'], 'Sent message subject found.'); | |
| 190 | $this->assertText($editnobody['subject'], 'Sent message subject found.'); | |
| 191 | $this->assertText(trim(truncate_utf8(strip_tags($editnosubject['body']), 50, TRUE, TRUE)), 'Sent message subject found.'); | |
| 192 | $this->assertText($editmixed['subject'], 'Sent message subject found.'); | |
| 193 | ||
| 194 | // Assert that we don't see those that were invalid. | |
| 195 | $this->assertNoText($editnone['subject'], 'Invalid message subject not found.'); | |
| 196 | $this->assertNoText($editinvalid['subject'], 'Invalid message subject not found.'); | |
| 197 | ||
| 198 | // Navigate into the message. | |
| 199 | $this->clickLink($edit['subject']); | |
| 200 | // Confirm that we can read the message that was sent. | |
| 201 | $this->assertText($edit['body'], 'Found message body.'); | |
| 202 | $this->assertNoText(t('Reply to thread:'), 'Reply form is not displayed.'); | |
| 203 | ||
| 204 | // Navigate into the message. | |
| 205 | $this->drupalGet('messages'); | |
| 206 | $this->clickLink($edit2['subject']); | |
| 207 | // Confirm that we can read the message that was sent. | |
| 208 | $this->assertText($edit2['body'], 'Found message body.'); | |
| 209 | // Confirm that we can read the reply that was sent. | |
| 210 | $this->assertText($reply['body'], 'Found reply body.'); | |
| 67189554 TGGM |
211 | } |
| 212 | ||
| 7bfff1e7 | 213 | /** |
| de0db33f SG |
214 | * Test correct handling of read all permissions. |
| 215 | */ | |
| 216 | function testReadAllPermission() { | |
| 217 | $author = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg')); | |
| 218 | $recipient = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg')); | |
| 219 | $admin = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg', 'read all private messages')); | |
| 220 | ||
| 221 | // Create new message. | |
| 222 | $edit = array( | |
| 223 | 'recipient' => $recipient->name, | |
| 224 | 'subject' => $this->randomName(20), | |
| 225 | 'body' => $this->randomName(100), | |
| 226 | ); | |
| 227 | $this->drupalLogin($author); | |
| 228 | $this->drupalPost('messages/new', $edit, t('Send message')); | |
| 229 | ||
| 230 | $this->assertText(t('A message has been sent to @recipients.', array('@recipients' => $recipient->name)), t('Message sent confirmation displayed')); | |
| 231 | ||
| 232 | $this->drupalLogin($admin); | |
| 233 | $this->drupalGet('messages/view/1'); | |
| 234 | ||
| 235 | $this->assertText(t('This conversation is being viewed with escalated priviledges and may not be the same as shown to normal users.'), t('Notice about read all mode displayed.')); | |
| 236 | ||
| 237 | // Send a first response. | |
| 238 | $admin_edit = array( | |
| 239 | 'body' => $this->randomName(100), | |
| 240 | ); | |
| 241 | $this->drupalPost('messages/view/1', $admin_edit, t('Send message')); | |
| 242 | ||
| 243 | // Make sure that the notice is not displayed anymore. | |
| 244 | // @tod: Commented out because this does not work as expected. | |
| 245 | $this->assertNoText(t('This conversation is being viewed with escalated priviledges and may not be the same as shown to normal users.'), t('Notice about read all mode not displayed.')); | |
| 246 | ||
| 247 | // Make sure that both the existing message body and the new one are displayed. | |
| 248 | $this->assertText($edit['body'], t('First message body displayed.')); | |
| 249 | $this->assertText($admin_edit['body'], t('New message body displayed.')); | |
| 250 | ||
| 251 | $admin_recipient_count = db_result(db_query("SELECT COUNT(*) FROM {pm_index} WHERE uid = %d AND thread_id = %d", $admin->uid, 1)); | |
| 252 | $this->assertEqual($admin_recipient_count, 2, t('Admin is listed as recipient for every message once.')); | |
| 253 | ||
| 254 | ||
| 255 | // Send a second response. | |
| 256 | $admin_edit2 = array( | |
| 257 | 'body' => $this->randomName(100), | |
| 258 | ); | |
| 259 | $this->drupalPost('messages/view/1', $admin_edit2, t('Send message')); | |
| 260 | ||
| 261 | // Make sure that both the existing message body and the new one are displayed. | |
| 262 | $this->assertText($edit['body'], t('First message body displayed.')); | |
| 263 | $this->assertText($admin_edit['body'], t('Second response body displayed.')); | |
| 264 | $this->assertText($admin_edit2['body'], t('Third message body displayed.')); | |
| 265 | ||
| 266 | $admin_recipient_count = db_result(db_query("SELECT COUNT(*) FROM {pm_index} WHERE uid = %d AND thread_id = %d", $admin->uid, 1)); | |
| 267 | $this->assertEqual($admin_recipient_count, 3, t('Admin is listed as recipient for every message once.')); | |
| 268 | ||
| 269 | } | |
| 270 | ||
| 271 | /** | |
| 7bfff1e7 SG |
272 | * Tests for the flush feature |
| 273 | */ | |
| 274 | function testPrivatemsgFlush() | |
| 275 | { | |
| 276 | $author = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg')); | |
| 277 | $recipient = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg')); | |
| 278 | ||
| 279 | // Send 10 messages. | |
| 280 | for ($i = 0; $i < 10; $i++) { | |
| 281 | privatemsg_new_thread(array($recipient), 'Message #'. $i, 'This is the body', array('author' => $author)); | |
| 282 | } | |
| 283 | ||
| 284 | // Delete message 1, 3, 4, 6, 9 for author. | |
| 285 | foreach (array(1, 3, 4, 6, 9) as $pmid) { | |
| 286 | privatemsg_message_change_delete($pmid, TRUE, $author); | |
| 287 | } | |
| 288 | ||
| 289 | // Delete message 1, 2, 4, 6, 8 for recipient. | |
| 290 | foreach (array(1, 3, 4, 6, 9) as $pmid) { | |
| 291 | privatemsg_message_change_delete($pmid, TRUE, $recipient); | |
| 292 | } | |
| 293 | ||
| 294 | // Now, mid 1, 4 and 6 have been deleted by both. | |
| 295 | ||
| 296 | // Flush configuration, enable, delay is default, 30 days | |
| 297 | variable_set('privatemsg_flush_enabled', TRUE); | |
| 298 | ||
| 299 | // Set back the deleted timestamp 35 days back of mid 4. | |
| 300 | db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = 4', time() - 35 * 86400); | |
| 301 | // Set back the deleted timestamp of mid 6, but only 20 back. | |
| 302 | db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = 6', time() - 20 * 86400); | |
| 303 | ||
| 304 | // Run flush. | |
| 305 | privatemsg_cron(); | |
| 306 | ||
| 307 | // Check if the undeleted messages are still there. | |
| 308 | foreach (array(2, 3, 5, 7, 8, 9, 10) as $pmid) { | |
| 22ae69fd | 309 | $message = privatemsg_message_load($pmid, $author); |
| 7bfff1e7 SG |
310 | $this->assertTrue(!empty($message), t('Undeleted message #%id is still in the system', array('%id' => $pmid))); |
| 311 | } | |
| 312 | ||
| 313 | // Check if the "recently" deleted messages are still there. | |
| 314 | foreach (array(1, 6) as $pmid) { | |
| 22ae69fd | 315 | $message = privatemsg_message_load($pmid, $author); |
| 7bfff1e7 SG |
316 | $this->assertTrue(!empty($message), t('Deleted message #%id is still in the system', array('%id' => $pmid))); |
| 317 | } | |
| 318 | ||
| 319 | // Mid 4 should have been flushed. | |
| 22ae69fd | 320 | $message = privatemsg_message_load(4, $author); |
| 7bfff1e7 SG |
321 | $this->assertTrue(empty($message), t('Message #4 has been flushed')); |
| 322 | } | |
| 67189554 | 323 | |
| ca5ce8f9 SG |
324 | function testDelete() { |
| 325 | // Create users. | |
| 326 | $author = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg', 'delete privatemsg')); | |
| 327 | $recipient = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg', 'delete privatemsg')); | |
| 328 | $recipient2 = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg')); | |
| 329 | $admin = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg', 'delete privatemsg', 'read all private messages')); | |
| 330 | ||
| 331 | // Create texts. | |
| 332 | $subject = $this->randomName(20); | |
| 333 | $body1 = $this->randomName(100); | |
| 334 | $body2 = $this->randomName(100); | |
| 335 | ||
| 336 | // Create message and response. | |
| 337 | $return = privatemsg_new_thread(array($recipient, $recipient2), $subject, $body1, array('author' => $author)); | |
| 338 | privatemsg_reply($return['message']['thread_id'], $body2, array('author' => $recipient)); | |
| 339 | ||
| 340 | // Check with user without delete permission. | |
| 341 | $this->drupalLogin($recipient2); | |
| 342 | $this->drupalGet('messages/view/' . $return['message']['thread_id']); | |
| 343 | $this->assertText($subject, 'Subject is displayed'); | |
| 344 | $this->assertText($body1, 'First message is displayed'); | |
| 345 | $this->assertText($body2, 'Second message is displayed'); | |
| 346 | $this->assertNoText(t('Delete message'), 'Delete message is link is not displayed for user without permission'); | |
| 347 | ||
| 348 | // Check if access for that user is denied. | |
| 349 | $this->drupalGet('messages/delete/' . $return['message']['thread_id'] . '/' . $return['message']['mid']); | |
| 350 | $this->assertText(t('Access denied')); | |
| 351 | ||
| 352 | // Check with user with delete access. | |
| 353 | $this->drupalLogin($recipient); | |
| 354 | $this->drupalGet('messages/view/' . $return['message']['thread_id']); | |
| 355 | $this->assertText(t('Delete message'), 'Delete message is link is displayed for user without permission'); | |
| 356 | ||
| 357 | // Click delete link of the second message and cancel. | |
| 358 | $this->clickLink(t('Delete message'), 1); | |
| 359 | $this->assertText(t('Are you sure you want to delete this message?'), 'Confirmation message displayed'); | |
| 360 | $this->clickLink(t('Cancel')); | |
| 361 | $this->assertText($body2, 'Second message is still displayed'); | |
| 362 | ||
| 363 | // Confirm message deletion. | |
| 364 | $this->clickLink(t('Delete message'), 1); | |
| 365 | $this->assertText(t('Are you sure you want to delete this message?'), 'Confirmation message displayed'); | |
| 366 | $this->drupalPost(NULL, array(), t('Delete')); | |
| 367 | $this->assertText(t('Message has been deleted.'), 'Message deleted has been deleted'); | |
| 368 | $this->assertText($body1, 'First message is still displayed'); | |
| 369 | $this->assertNoText($body2, 'Second message was deleted'); | |
| 370 | ||
| 371 | // Click delete link of the first message and cancel. | |
| 372 | $this->clickLink(t('Delete message')); | |
| 373 | $this->assertText(t('Are you sure you want to delete this message?'), 'Confirmation message displayed'); | |
| 374 | $this->clickLink(t('Cancel')); | |
| 375 | $this->assertText($body1, 'Second message is still displayed'); | |
| 376 | ||
| 377 | // Confirm message deletion. | |
| 378 | $this->clickLink(t('Delete message')); | |
| 379 | $this->assertText(t('Are you sure you want to delete this message?'), 'Confirmation message displayed'); | |
| 380 | $this->drupalPost(NULL, array(), t('Delete')); | |
| 381 | $this->assertText(t('Message has been deleted.'), 'Message deleted has been deleted'); | |
| 382 | $this->assertNoText($subject, 'All messages of that thread have been deleted'); | |
| 383 | ||
| 384 | // Test if the message has not been deleted for other users. | |
| 385 | $this->drupalLogin($recipient2); | |
| 386 | $this->drupalGet('messages/view/' . $return['message']['thread_id']); | |
| 387 | $this->assertText($body1, 'First message is still displayed'); | |
| 388 | $this->assertText($body2,'First message is still displayed'); | |
| 389 | ||
| 390 | // Test delete all checkbox. | |
| 391 | $this->drupalLogin($admin); | |
| 392 | $this->drupalGet('messages/view/' . $return['message']['thread_id']); | |
| 393 | $this->clickLink(t('Delete message'), 1); | |
| 394 | $this->drupalPost(NULL, array('delete_options' => TRUE), t('Delete')); | |
| 395 | $this->assertText(t('Message has been deleted for all users.'), 'Message deleted has been deleted'); | |
| 396 | ||
| 397 | // Test if the message has been deleted for all users. | |
| 398 | $this->drupalLogin($recipient2); | |
| 399 | $this->drupalGet('messages/view/' . $return['message']['thread_id']); | |
| 400 | $this->assertText($body1, 'First message is still displayed'); | |
| 401 | $this->assertNoText($body2, 'Second message has been deleted for all users'); | |
| 402 | ||
| 403 | } | |
| 404 | ||
| 67189554 TGGM |
405 | /** |
| 406 | * Implementation of tearDown(). | |
| 407 | */ | |
| 408 | function tearDown() { | |
| 409 | //we dont really need to do this. i'm adding it just to keep it in front of my eyes so i can memorize it. | |
| 410 | parent::tearDown(); | |
| 411 | } | |
| 412 | ||
| 413 | } | |
| 414 | ||
| 415 | ||
| 416 | ||
| 417 | ||
| 418 | ||
| 419 | ||
| 420 | ||
| 421 | ||
| 422 | ||
| 423 | ||
| 424 | ||
| 425 | ||
| 426 | ||
| 427 | ||
| 428 | ||
| 429 | ||
| 430 | ||
| 431 |