Overview

Namespaces

  • GLFramework
    • Cache
    • Controller
    • DaMa
      • Manipulators
    • Database
    • HTTP
    • Mail
    • Middleware
    • Model
    • Module
    • Tests
    • Upload
    • Utils
  • None

Classes

  • GLFramework\Bootstrap
  • GLFramework\Cache\Cache
  • GLFramework\Cache\MemcachedCache
  • GLFramework\Cache\MemoryCache
  • GLFramework\Controller
  • GLFramework\Controller\AdminController
  • GLFramework\Controller\APIController
  • GLFramework\Controller\AuthController
  • GLFramework\Controller\ErrorController
  • GLFramework\Controller\ExceptionController
  • GLFramework\DaMa\Association
  • GLFramework\DaMa\DataManipulation
  • GLFramework\DaMa\Manipulator
  • GLFramework\DaMa\Manipulators\CSVManipulator
  • GLFramework\DaMa\Manipulators\ManipulatorCore
  • GLFramework\DaMa\Manipulators\XLSManipulator
  • GLFramework\DaMa\Manipulators\XLSXManipulator
  • GLFramework\Database\Connection
  • GLFramework\Database\MySQLConnection
  • GLFramework\DatabaseManager
  • GLFramework\DBStructure
  • GLFramework\Events
  • GLFramework\Filesystem
  • GLFramework\HTTP\API
  • GLFramework\Log
  • GLFramework\Mail
  • GLFramework\Mail\Mail
  • GLFramework\Mail\MailSystem
  • GLFramework\Mail\PHPMailer
  • GLFramework\MailView
  • GLFramework\Middleware\APIAuthorizationMiddleware
  • GLFramework\Middleware\ControllerMiddleware
  • GLFramework\Model
  • GLFramework\Model\Page
  • GLFramework\Model\User
  • GLFramework\Model\UserPage
  • GLFramework\ModelResult
  • GLFramework\Module\Module
  • GLFramework\Module\ModuleManager
  • GLFramework\Request
  • GLFramework\Response
  • GLFramework\Tests\DatabaseTestCase
  • GLFramework\Tests\TestCase
  • GLFramework\Upload\Upload
  • GLFramework\Upload\Uploads
  • GLFramework\Utils\DataTablesManager
  • GLFramework\Versions
  • GLFramework\View

Interfaces

  • GLFramework\Middleware

Functions

  • array_merge_recursive_ex
  • e
  • file_get_php_classes
  • fix_date
  • fix_date_format
  • fix_decimal
  • fix_url
  • get
  • get_php_classes
  • http_response_code
  • instance_method
  • is_module_enabled
  • now
  • post
  • print_array
  • print_brief_debug
  • print_debug
  • random_str
  • reArrayFiles
  • reArrayPost
  • today
  • Overview
  • Namespace
  • Class
  1: <?php
  2: 
  3: namespace GLFramework\Tests;
  4: 
  5: use Exception;
  6: use GLFramework\DatabaseManager;
  7: use GLFramework\DBStructure;
  8: use GLFramework\Model;
  9: use GLFramework\Module\ModuleManager;
 10: use GLFramework\Response;
 11: use InvalidArgumentException;
 12: use GLFramework\Bootstrap;
 13: use Symfony\Component\DomCrawler\Crawler;
 14: use Symfony\Component\DomCrawler\Form;
 15: 
 16: /**
 17:  * Created by PhpStorm.
 18:  * User: manus
 19:  * Date: 16/03/16
 20:  * Time: 9:59
 21:  */
 22: class TestCase extends \PHPUnit_Framework_TestCase
 23: {
 24: 
 25: 
 26:     private $internal_host = "http://localhost";
 27:     /**
 28:      * @var Crawler
 29:      */
 30:     protected $crawler;
 31: 
 32:     /**
 33:      * @var Response
 34:      */
 35:     protected $response;
 36: 
 37:     protected $inputs = array();
 38: 
 39:     protected $uploads = array();
 40: 
 41:     private $redirections = array();
 42: 
 43:     private $models_delete = array();
 44: 
 45:     private $database;
 46: 
 47:     public function requireDatabase()
 48:     {
 49:         if($this->database == null)
 50:         {
 51:             $this->database = new DatabaseManager();
 52: 
 53:             $this->assertTrue($this->database->connect(), "Can not connect to database for testing!");
 54: 
 55:             $db2 = new DBStructure();
 56:             $db2->setDatabaseUpdate();
 57:             $models = Bootstrap::getSingleton()->getModels();
 58:             foreach ($models as $model) {
 59: 
 60:                 $instance = new $model(null);
 61:                 if ($instance instanceof Model) {
 62:                     $diff = $instance->getStructureDifferences();
 63:                     foreach ($diff as $action) {
 64:                         $this->database->exec($action['sql']);
 65:                     }
 66: 
 67:                 }
 68:             }
 69: 
 70:         }
 71:     }
 72: 
 73:     protected function tearDown()
 74:     {
 75:         parent::tearDown(); // TODO: Change the autogenerated stub
 76:         foreach($this->models_delete as $model)
 77:         {
 78:             $model->delete();
 79:         }
 80:     }
 81: 
 82: 
 83:     public function removeLater($model)
 84:     {
 85:         if(!is_array($model))
 86:         {
 87:             $model = array($model);
 88:         }
 89:         foreach($model as $m)
 90:             $this->models_delete[] = $m;
 91:     }
 92: 
 93:     /**
 94:      * @return DatabaseManager
 95:      */
 96:     public function getDatabase()
 97:     {
 98:         return $this->database;
 99:     }
100: 
101: 
102:     public function visit($url)
103:     {
104:         return $this->call("GET", $url);
105:     }
106: 
107:     /**
108:      * @param $form Form
109:      * @param array $uploads
110:      * @return $this|TestCase
111:      */
112:     public function makeRequestUsingForm($form, $uploads = array())
113:     {
114:         $method = $form->getMethod();
115:         $uri = $form->getUri();
116:         parse_str(http_build_query($form->getValues()), $parameters);
117:         return $this->call($method, $uri, $parameters, [], $uploads);
118:     }
119: 
120:     public function call($method, $uri, $params = array(), $cookies = array(), $files = array())
121:     {
122:         $uri = str_replace($this->internal_host, "", $uri);
123:         if(strpos($uri, "/") !== 0) $uri = "/" . $uri;
124:         $bs = Bootstrap::getSingleton();
125:         $_COOKIE = $cookies;
126:         $_REQUEST = $params;
127:         $_POST = $params;
128:         $_FILES = $this->buildFilesForm($files);
129:         $_SERVER['REQUEST_URI'] = $this->internal_host . $uri;
130:         $this->response = $bs->run($uri, $method);
131:         $this->followRedirects();
132:         $this->crawler = new Crawler($this->response->getContent(), $this->internal_host . $uri);
133: 
134:         return $this;
135:     }
136: 
137:     public function followRedirects()
138:     {
139:         if($this->response->isRedirect())
140:         {
141:             $this->redirections[$this->response->getRedirection()] += 1;
142:             $this->assertLessThan(10, $this->redirections[$this->response->getRedirection()], "Ciclic redirection: " . $this->response->getRedirection());
143:             $this->call('GET', $this->response->getRedirection());
144:         }
145:         return $this;
146:     }
147: 
148:     public function buildFilesForm($files)
149:     {
150:         $result = array();
151:         if(is_array($files))
152:         {
153:             foreach($files as $file)
154:             {
155:                 if(is_string($file))
156:                 {
157:                     if(file_exists($file))
158:                     {
159:                         $this->buildFile(0, $result, $file);
160:                     }
161:                     else if($file == "")
162:                     {
163:                         $this->buildFile(4, $result);
164:                     }
165:                 }
166: 
167:             }
168:         }
169:         else{
170:             if(file_exists($files))
171:             {
172:                 $this->buildFile(0, $result, $files);
173:             }
174:             else if($files == "")
175:             {
176:                 $this->buildFile(4, $result);
177:             }
178:         }
179:         return $result;
180:     }
181: 
182:     private function buildFile($error, &$array = array(), $tmp_name = "", $name = "",  $type = "", $size = "")
183:     {
184:         if($tmp_name != "" && $name == "")
185:         {
186:             $name = basename($tmp_name);
187:         }
188:         if($tmp_name != "" && $type == "")
189:         {
190:             $type = mime_content_type($tmp_name);
191:         }
192:         if($tmp_name != "" && $size == "")
193:         {
194:             $size = filesize($tmp_name);
195:         }
196:         if(isset($array['error']))
197:         {
198:             $array['error'][] = $error;
199:             $array['name'][] = $name;
200:             $array['tmp_name'][] = $tmp_name;
201:             $array['type'][] = $type;
202:             $array['size'][] = $size;
203: 
204:         }
205:         else
206:         {
207:             $array['error'] = $error;
208:             $array['name'] = $name;
209:             $array['tmp_name'] = $tmp_name;
210:             $array['type'] = $type;
211:             $array['size'] = $size;
212:         }
213:         return $array;
214:     }
215: 
216:     public function getContent()
217:     {
218:         return $this->response->getContent();
219:     }
220: 
221: 
222:     public function see($text, $negate = false)
223:     {
224:         $method = $negate ? 'assertNotRegExp' : 'assertRegExp';
225:         $rawPattern = preg_quote($text, '/');
226:         $escapedPattern = preg_quote(e($text), '/');
227:         $pattern = $rawPattern == $escapedPattern
228:             ? $rawPattern : "({$rawPattern}|{$escapedPattern})";
229:         $this->$method("/$pattern/i", $this->getContent());
230:         return $this;
231:     }
232: 
233:     protected function dontSee($text)
234:     {
235:         return $this->see($text, true);
236:     }
237: 
238:     protected function seeInElement($element, $text, $negate = false)
239:     {
240:         $method = $negate ? 'assertNotRegExp' : 'assertRegExp';
241:         $rawPattern = preg_quote($text, '/');
242:         $escapedPattern = preg_quote(e($text), '/');
243:         $content = $this->crawler->filter($element)->html();
244:         $pattern = $rawPattern == $escapedPattern
245:             ? $rawPattern : "({$rawPattern}|{$escapedPattern})";
246:         $this->$method("/$pattern/i", $content);
247:         return $this;
248:     }
249:     /**
250:      * Assert that a given link is seen on the page.
251:      *
252:      * @param  string  $text
253:      * @param  string|null  $url
254:      * @return $this
255:      */
256:     public function seeLink($text, $url = null)
257:     {
258:         $message = "No links were found with expected text [{$text}]";
259:         if ($url) {
260:             $message .= " and URL [{$url}]";
261:         }
262:         $this->assertTrue($this->hasLink($text, $url), "{$message}.");
263:         return $this;
264:     }
265:     /**
266:      * Assert that a given link is not seen on the page.
267:      *
268:      * @param  string  $text
269:      * @param  string|null  $url
270:      * @return $this
271:      */
272:     public function dontSeeLink($text, $url = null)
273:     {
274:         $message = "A link was found with expected text [{$text}]";
275:         if ($url) {
276:             $message .= " and URL [{$url}]";
277:         }
278:         $this->assertFalse($this->hasLink($text, $url), "{$message}.");
279:         return $this;
280:     }
281: 
282:     /**
283:      * Assert that an input field contains the given value.
284:      *
285:      * @param  string  $selector
286:      * @param  string  $expected
287:      * @return $this
288:      */
289:     public function seeInField($selector, $expected)
290:     {
291:         $this->assertSame(
292:             $expected, $this->getInputOrTextAreaValue($selector),
293:             "The field [{$selector}] does not contain the expected value [{$expected}]."
294:         );
295:         return $this;
296:     }
297:     /**
298:      * Assert that an input field does not contain the given value.
299:      *
300:      * @param  string  $selector
301:      * @param  string  $value
302:      * @return $this
303:      */
304:     public function dontSeeInField($selector, $value)
305:     {
306:         $this->assertNotSame(
307:             $this->getInputOrTextAreaValue($selector), $value,
308:             "The input [{$selector}] should not contain the value [{$value}]."
309:         );
310:         return $this;
311:     }
312:     /**
313:      * Assert that the given checkbox is selected.
314:      *
315:      * @param  string  $selector
316:      * @return $this
317:      */
318:     public function seeIsChecked($selector)
319:     {
320:         $this->assertTrue(
321:             $this->isChecked($selector),
322:             "The checkbox [{$selector}] is not checked."
323:         );
324:         return $this;
325:     }
326:     /**
327:      * Assert that the given checkbox is not selected.
328:      *
329:      * @param  string  $selector
330:      * @return $this
331:      */
332:     public function dontSeeIsChecked($selector)
333:     {
334:         $this->assertFalse(
335:             $this->isChecked($selector),
336:             "The checkbox [{$selector}] is checked."
337:         );
338:         return $this;
339:     }
340:     /**
341:      * Assert that the expected value is selected.
342:      *
343:      * @param  string  $selector
344:      * @param  string  $expected
345:      * @return $this
346:      */
347:     public function seeIsSelected($selector, $expected)
348:     {
349:         $this->assertEquals(
350:             $expected, $this->getSelectedValue($selector),
351:             "The field [{$selector}] does not contain the selected value [{$expected}]."
352:         );
353:         return $this;
354:     }
355:     /**
356:      * Assert that the given value is not selected.
357:      *
358:      * @param  string  $selector
359:      * @param  string  $value
360:      * @return $this
361:      */
362:     public function dontSeeIsSelected($selector, $value)
363:     {
364:         $this->assertNotEquals(
365:             $value, $this->getSelectedValue($selector),
366:             "The field [{$selector}] contains the selected value [{$value}]."
367:         );
368:         return $this;
369:     }
370:     /**
371:      * Get the value of an input or textarea.
372:      *
373:      * @param  string  $selector
374:      * @return string
375:      *
376:      * @throws \Exception
377:      */
378:     protected function getInputOrTextAreaValue($selector)
379:     {
380:         $field = $this->filterByNameOrId($selector, ['input', 'textarea']);
381:         if ($field->count() == 0) {
382:             throw new Exception("There are no elements with the name or ID [$selector].");
383:         }
384:         $element = $field->nodeName();
385:         if ($element == 'input') {
386:             return $field->attr('value');
387:         }
388:         if ($element == 'textarea') {
389:             return $field->text();
390:         }
391:         throw new Exception("Given selector [$selector] is not an input or textarea.");
392:     }
393:     /**
394:      * Get the selected value of a select field or radio group.
395:      *
396:      * @param  string  $selector
397:      * @return string|null
398:      *
399:      * @throws \Exception
400:      */
401:     protected function getSelectedValue($selector)
402:     {
403:         $field = $this->filterByNameOrId($selector);
404:         if ($field->count() == 0) {
405:             throw new Exception("There are no elements with the name or ID [$selector].");
406:         }
407:         $element = $field->nodeName();
408:         if ($element == 'select') {
409:             return $this->getSelectedValueFromSelect($field);
410:         }
411:         if ($element == 'input') {
412:             return $this->getCheckedValueFromRadioGroup($field);
413:         }
414:         throw new Exception("Given selector [$selector] is not a select or radio group.");
415:     }
416:     /**
417:      * Get the selected value from a select field.
418:      *
419:      * @param  \Symfony\Component\DomCrawler\Crawler  $field
420:      * @return string|null
421:      *
422:      * @throws \Exception
423:      */
424:     protected function getSelectedValueFromSelect(Crawler $field)
425:     {
426:         if ($field->nodeName() !== 'select') {
427:             throw new Exception('Given element is not a select element.');
428:         }
429:         foreach ($field->children() as $option) {
430:             if ($option->hasAttribute('selected')) {
431:                 return $option->getAttribute('value');
432:             }
433:         }
434:         return;
435:     }
436:     /**
437:      * Get the checked value from a radio group.
438:      *
439:      * @param  \Symfony\Component\DomCrawler\Crawler  $radioGroup
440:      * @return string|null
441:      *
442:      * @throws \Exception
443:      */
444:     protected function getCheckedValueFromRadioGroup(Crawler $radioGroup)
445:     {
446:         if ($radioGroup->nodeName() !== 'input' || $radioGroup->attr('type') !== 'radio') {
447:             throw new Exception('Given element is not a radio button.');
448:         }
449:         foreach ($radioGroup as $radio) {
450:             if ($radio->hasAttribute('checked')) {
451:                 return $radio->getAttribute('value');
452:             }
453:         }
454:         return;
455:     }
456:     /**
457:      * Return true if the given checkbox is checked, false otherwise.
458:      *
459:      * @param  string  $selector
460:      * @return bool
461:      *
462:      * @throws \Exception
463:      */
464:     protected function isChecked($selector)
465:     {
466:         $checkbox = $this->filterByNameOrId($selector, "input[type='checkbox']");
467:         if ($checkbox->count() == 0) {
468:             throw new Exception("There are no checkbox elements with the name or ID [$selector].");
469:         }
470:         return $checkbox->attr('checked') !== null;
471:     }
472:     /**
473:      * Click a link with the given body, name, or ID attribute.
474:      *
475:      * @param  string  $name
476:      * @return $this
477:      *
478:      * @throws \InvalidArgumentException
479:      */
480:     protected function click($name)
481:     {
482:         $link = $this->crawler->selectLink($name);
483:         if (! count($link)) {
484:             $link = $this->filterByNameOrId($name, 'a');
485:             if (! count($link)) {
486:                 throw new InvalidArgumentException(
487:                     "Could not find a link with a body, name, or ID attribute of [{$name}]."
488:                 );
489:             }
490:         }
491:         $this->visit($link->link()->getUri());
492:         return $this;
493:     }
494: 
495: 
496:     /**
497:      * Fill an input field with the given text.
498:      *
499:      * @param  string  $text
500:      * @param  string  $element
501:      * @return $this
502:      */
503:     protected function type($text, $element)
504:     {
505:         return $this->storeInput($element, $text);
506:     }
507:     /**
508:      * Check a checkbox on the page.
509:      *
510:      * @param  string  $element
511:      * @return $this
512:      */
513:     protected function check($element)
514:     {
515:         return $this->storeInput($element, true);
516:     }
517:     /**
518:      * Uncheck a checkbox on the page.
519:      *
520:      * @param  string  $element
521:      * @return $this
522:      */
523:     protected function uncheck($element)
524:     {
525:         return $this->storeInput($element, false);
526:     }
527:     /**
528:      * Select an option from a drop-down.
529:      *
530:      * @param  string  $option
531:      * @param  string  $element
532:      * @return $this
533:      */
534:     protected function select($option, $element)
535:     {
536:         return $this->storeInput($element, $option);
537:     }
538:     /**
539:      * Attach a file to a form field on the page.
540:      *
541:      * @param  string  $absolutePath
542:      * @param  string  $element
543:      * @return $this
544:      */
545:     protected function attach($absolutePath, $element)
546:     {
547:         $this->uploads[$element] = $absolutePath;
548:         return $this->storeInput($element, $absolutePath);
549:     }
550:     /**
551:      * Submit a form using the button with the given text value.
552:      *
553:      * @param  string  $buttonText
554:      * @return $this
555:      */
556:     protected function press($buttonText)
557:     {
558:         return $this->submitForm($buttonText, $this->inputs, $this->uploads);
559:     }
560:     /**
561:      * Submit a form on the page with the given input.
562:      *
563:      * @param  string  $buttonText
564:      * @param  array  $inputs
565:      * @param  array  $uploads
566:      * @return $this
567:      */
568:     protected function submitForm($buttonText, $inputs = [], $uploads = [])
569:     {
570:         $this->makeRequestUsingForm($this->fillForm($buttonText, $inputs), $uploads);
571:         return $this;
572:     }
573:     /**
574:      * Fill the form with the given data.
575:      *
576:      * @param  string  $buttonText
577:      * @param  array  $inputs
578:      * @return \Symfony\Component\DomCrawler\Form
579:      */
580:     protected function fillForm($buttonText, $inputs = [])
581:     {
582:         if (! is_string($buttonText)) {
583:             $inputs = $buttonText;
584:             $buttonText = null;
585:         }
586:         return $this->getForm($buttonText)->setValues($inputs);
587:     }
588:     /**
589:      * Get the form from the page with the given submit button text.
590:      *
591:      * @param  string|null  $buttonText
592:      * @return \Symfony\Component\DomCrawler\Form
593:      *
594:      * @throws \InvalidArgumentException
595:      */
596:     protected function getForm($buttonText = null)
597:     {
598:         try {
599:             if ($buttonText) {
600:                 return $this->crawler->selectButton($buttonText)->form();
601:             }
602:             return $this->crawler->filter('form')->form();
603:         } catch (InvalidArgumentException $e) {
604:             throw new InvalidArgumentException(
605:                 "Could not find a form that has submit button [{$buttonText}]."
606:             );
607:         }
608:     }
609:     /**
610:      * Store a form input in the local array.
611:      *
612:      * @param  string  $element
613:      * @param  string  $text
614:      * @return $this
615:      */
616:     protected function storeInput($element, $text)
617:     {
618:         $this->assertFilterProducesResults($element);
619:         $element = str_replace('#', '', $element);
620:         $this->inputs[$element] = $text;
621:         return $this;
622:     }
623:     /**
624:      * Assert that a filtered Crawler returns nodes.
625:      *
626:      * @param  string  $filter
627:      * @return void
628:      *
629:      * @throws \InvalidArgumentException
630:      */
631:     protected function assertFilterProducesResults($filter)
632:     {
633:         $crawler = $this->filterByNameOrId($filter);
634:         if (! count($crawler)) {
635:             throw new InvalidArgumentException(
636:                 "Nothing matched the filter [{$filter}] CSS query provided for [{$this->currentUri}]."
637:             );
638:         }
639:     }
640:     /**
641:      * Filter elements according to the given name or ID attribute.
642:      *
643:      * @param  string  $name
644:      * @param  array|string  $elements
645:      * @return \Symfony\Component\DomCrawler\Crawler
646:      */
647:     protected function filterByNameOrId($name, $elements = '*')
648:     {
649:         $name = str_replace('#', '', $name);
650:         $id = str_replace(['[', ']'], ['\\[', '\\]'], $name);
651:         $elements = is_array($elements) ? $elements : [$elements];
652:         array_walk($elements, function (&$element) use ($name, $id) {
653:             $element = "{$element}#{$id}, {$element}[name='{$name}']";
654:         });
655:         return $this->crawler->filter(implode(', ', $elements));
656:     }
657: }
API documentation generated by ApiGen