10 |
11 |
12 |
13 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {% for type, files in tests %}
36 |
37 |
38 |
39 |
40 |
41 |
{{ type|capitalize }} Tests ({{ files|length }} available)
42 |
43 | {% if attribute(environments, type) is defined %}
44 | {% if attribute(environments, type)|length > 0 %}
45 |
46 |
47 |
Environments:
48 |
49 | {% for env in attribute(environments, type) %}
50 |
51 |
52 |
55 |
56 | {% endfor %}
57 |
58 |
59 |
60 |
61 | {% endif %}
62 | {% endif %}
63 |
64 |
76 |
77 | {% for row in files|batch(2, '') %}
78 |
79 |
80 |
81 | {% for file in row %}
82 |
83 | {% if file %}
84 |
85 |
86 |
87 |
99 |
100 |
101 | {% endif %}
102 |
103 | {% endfor %}
104 |
105 |
106 |
107 | {% endfor %}
108 |
109 | {# end: for row in files|batch(2, '') #}
110 |
111 |
112 |
113 | {% endfor %}
114 |
115 |
116 |
117 |
118 |
119 |
Console Results
120 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 | {% endif %}
148 |
149 | {% endblock %}
150 |
--------------------------------------------------------------------------------
/App/Tests/unit/SiteClassTestsTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | class SiteClassTestsTest extends \Codeception\TestCase\Test
13 | {
14 | /**
15 | * @var \CodeGuy
16 | */
17 | protected $codeGuy;
18 |
19 | private $config = FALSE;
20 | private $site = FALSE;
21 | private $site_1 = 'Webception';
22 | private $site_2 = 'Another Webception';
23 | private $multiple_sites = array();
24 | private $single_site = array();
25 |
26 | protected function _before()
27 | {
28 | // Default Site List
29 | $this->multiple_sites = array(
30 | 'Webception' => dirname(__FILE__) .'/../_config/codeception_pass.yml',
31 | 'Another Webception' => dirname(__FILE__) .'/../_config/codeception_pass.yml'
32 | );
33 |
34 | $this->single_site = array(
35 | 'Another Webception' => dirname(__FILE__) .'/../_config/codeception_pass.yml',
36 | );
37 |
38 | // Load the Codeception config
39 | $this->config = require(dirname(__FILE__) . '/../_config/codeception_pass.php');
40 |
41 | // Set the hashes!
42 | $this->hash_1 = md5($this->site_1);
43 | $this->hash_2 = md5($this->site_2);
44 | }
45 |
46 | protected function _after()
47 | {
48 | }
49 |
50 | public function testSettingNoSites()
51 | {
52 | $site = new \App\Lib\Site();
53 | $this->assertFalse($site->ready());
54 | $this->assertFalse($site->getHash());
55 | $this->assertFalse($site->hasChoices());
56 | $this->assertFalse($site->getName());
57 | $this->assertFalse($site->getConfig());
58 | $this->assertFalse($site->getConfigPath());
59 | $this->assertFalse($site->getConfigFile());
60 | $this->assertEquals(count($site->getSites()), 0);
61 | $this->assertEquals($site->getSites(), array());
62 | }
63 |
64 | public function testSettingSites()
65 | {
66 | $site = new \App\Lib\Site($this->config['sites']);
67 | $this->assertEquals(count($site->getSites()), 2);
68 | $filtered = $site->prepare($this->multiple_sites);
69 | $this->assertEquals($filtered, $site->getSites());
70 | }
71 |
72 | public function testSettingInvalidSite()
73 | {
74 | $site = new \App\Lib\Site($this->config['sites']);
75 | $this->assertFalse($site->ready());
76 | $site->set(md5('junk-site'));
77 | $this->assertFalse($site->ready());
78 | $this->assertFalse($site->getHash());
79 | $this->assertFalse($site->hasChoices());
80 | $this->assertFalse($site->getName());
81 | $this->assertFalse($site->getConfig());
82 | $this->assertFalse($site->getConfigPath());
83 | $this->assertFalse($site->getConfigFile());
84 | $this->assertEquals(count($site->getSites()), 2);
85 | }
86 |
87 | public function testSettingMultipleValidSites()
88 | {
89 | $site = new \App\Lib\Site($this->config['sites']);
90 |
91 | $filtered = $site->prepare($this->multiple_sites);
92 |
93 | $this->assertEquals(count($site->getSites()), 2);
94 |
95 | $this->assertFalse($site->hasChoices());
96 | $this->assertFalse($site->ready());
97 |
98 | // Set to first site.
99 | $site->set($this->hash_1);
100 | $this->assertTrue($site->ready());
101 | $this->assertEquals($site->getName(), $this->site_1);
102 | $this->assertEquals($this->hash_1, $site->getHash());
103 | $this->assertEquals($filtered[$this->hash_1]['path'], $site->getConfig());
104 | $this->assertEquals(basename($filtered[$this->hash_1]['path']), $site->getConfigFile());
105 | $this->assertEquals(dirname($filtered[$this->hash_1]['path']) .'/', $site->getConfigPath());
106 |
107 | // Swap the site over!
108 | $site->set($this->hash_2);
109 | $this->assertTrue($site->ready());
110 | $this->assertNotEquals($site->getName(), $this->site_1);
111 | $this->assertEquals($site->getName(), $this->site_2);
112 | $this->assertEquals($this->hash_2, $site->getHash());
113 | $this->assertEquals($filtered[$this->hash_2]['path'], $site->getConfig());
114 | $this->assertEquals(basename($filtered[$this->hash_2]['path']), $site->getConfigFile());
115 | $this->assertEquals(dirname($filtered[$this->hash_2]['path']) .'/', $site->getConfigPath());
116 | $this->assertEquals(count($site->getSites()), 2);
117 |
118 | // Sites are set and more than one site available
119 | $this->assertTrue($site->hasChoices());
120 |
121 | }
122 |
123 | public function testSettingSingleValidSites()
124 | {
125 | $sites = $this->config['sites'];
126 |
127 | // Remove the first site
128 | unset($sites[$this->site_1]);
129 |
130 | $site = new \App\Lib\Site($sites);
131 |
132 | $filtered = $site->prepare($this->single_site);
133 |
134 | // Confirm the single set has been set
135 | $this->assertEquals($filtered, $site->getSites());
136 | $this->assertEquals(count($site->getSites()), 1);
137 | $this->assertFalse($site->hasChoices());
138 | $this->assertFalse($site->ready());
139 |
140 | // Set to first site.
141 | $site->set($this->hash_2);
142 | $this->assertTrue($site->ready());
143 | $this->assertEquals($site->getName(), $this->site_2);
144 | $this->assertEquals($this->hash_2, $site->getHash());
145 | $this->assertEquals($filtered[$this->hash_2]['path'], $site->getConfig());
146 | $this->assertEquals(basename($filtered[$this->hash_2]['path']), $site->getConfigFile());
147 | $this->assertEquals(dirname($filtered[$this->hash_2]['path']) .'/', $site->getConfigPath());
148 |
149 | // Check there's only one site but we don't have choices
150 | $this->assertEquals(count($site->getSites()), 1);
151 | $this->assertFalse($site->hasChoices());
152 | }
153 |
154 | }
155 |
--------------------------------------------------------------------------------
/App/Templates/layout/master.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{ webception.name|striptags }} | Dashboard
7 |
8 |
9 |
10 |
11 |
12 |
13 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | {{ webception.name|raw }}
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | {% if not codeception.ready() %}
64 |
65 |
66 | Codeception config could not be fully loaded.
67 |
68 | {% if codeception.site.ready() %}
69 |
70 | The configuration for {{ codeception.site.getName() }} is currently set as:
71 |
72 |
73 | - {{ codeception.site.getConfig() }}
74 |
75 |
76 | You can set the location of the configuration in:
77 |
78 |
79 | - {{ codeception.config.location }}
80 |
81 | {% else %}
82 |
83 | It appears there are no settings in there at all. It may be worth re-downloading it from the {{ webception.name|raw }} repo.
84 |
85 |
86 | You can set the location of the Codeception configuration in the following:
87 |
88 |
89 | - {{ codeception.config.location }}
90 |
91 | {% endif %}
92 |
93 | Pro-tip: Once you've set that, just reload the page.
94 |
95 |
96 |
97 | {% endif %}
98 |
99 |
100 |
{{ random(["It appears we have a problem...", "Oh no, I don't believe it!", "What's wrong this time?", "Ah, that ain't right!"]) }}
101 |
102 |
105 |
106 | You can set the location of the config in the following file:
107 |
108 |
111 |
112 | Pro-tip: Once you've fixed that, just reload the page.
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | {% block content %}{% endblock %}
122 |
123 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
143 |
144 |
--------------------------------------------------------------------------------
/public/js/libs/foundation/foundation.dropdown.js:
--------------------------------------------------------------------------------
1 | ;(function ($, window, document, undefined) {
2 | 'use strict';
3 |
4 | Foundation.libs.dropdown = {
5 | name : 'dropdown',
6 |
7 | version : '5.0.0',
8 |
9 | settings : {
10 | active_class: 'open',
11 | is_hover: false,
12 | opened: function(){},
13 | closed: function(){}
14 | },
15 |
16 | init : function (scope, method, options) {
17 | Foundation.inherit(this, 'throttle');
18 |
19 | this.bindings(method, options);
20 | },
21 |
22 | events : function (scope) {
23 | var self = this;
24 |
25 | $(this.scope)
26 | .off('.dropdown')
27 | .on('click.fndtn.dropdown', '[data-dropdown]', function (e) {
28 | var settings = $(this).data('dropdown-init');
29 | e.preventDefault();
30 |
31 | if (!settings.is_hover || Modernizr.touch) self.toggle($(this));
32 | })
33 | .on('mouseenter.fndtn.dropdown', '[data-dropdown], [data-dropdown-content]', function (e) {
34 | var $this = $(this);
35 | clearTimeout(self.timeout);
36 |
37 | if ($this.data('dropdown')) {
38 | var dropdown = $('#' + $this.data('dropdown')),
39 | target = $this;
40 | } else {
41 | var dropdown = $this;
42 | target = $("[data-dropdown='" + dropdown.attr('id') + "']");
43 | }
44 |
45 | var settings = target.data('dropdown-init');
46 | if (settings.is_hover) self.open.apply(self, [dropdown, target]);
47 | })
48 | .on('mouseleave.fndtn.dropdown', '[data-dropdown], [data-dropdown-content]', function (e) {
49 | var $this = $(this);
50 | self.timeout = setTimeout(function () {
51 | if ($this.data('dropdown')) {
52 | var settings = $this.data('dropdown-init');
53 | if (settings.is_hover) self.close.call(self, $('#' + $this.data('dropdown')));
54 | } else {
55 | var target = $('[data-dropdown="' + $(this).attr('id') + '"]'),
56 | settings = target.data('dropdown-init');
57 | if (settings.is_hover) self.close.call(self, $this);
58 | }
59 | }.bind(this), 150);
60 | })
61 | .on('click.fndtn.dropdown', function (e) {
62 | var parent = $(e.target).closest('[data-dropdown-content]');
63 |
64 | if ($(e.target).data('dropdown') || $(e.target).parent().data('dropdown')) {
65 | return;
66 | }
67 | if (!($(e.target).data('revealId')) &&
68 | (parent.length > 0 && ($(e.target).is('[data-dropdown-content]') ||
69 | $.contains(parent.first()[0], e.target)))) {
70 | e.stopPropagation();
71 | return;
72 | }
73 |
74 | self.close.call(self, $('[data-dropdown-content]'));
75 | })
76 | .on('opened.fndtn.dropdown', '[data-dropdown-content]', this.settings.opened)
77 | .on('closed.fndtn.dropdown', '[data-dropdown-content]', this.settings.closed);
78 |
79 | $(window)
80 | .off('.dropdown')
81 | .on('resize.fndtn.dropdown', self.throttle(function () {
82 | self.resize.call(self);
83 | }, 50)).trigger('resize');
84 | },
85 |
86 | close: function (dropdown) {
87 | var self = this;
88 | dropdown.each(function () {
89 | if ($(this).hasClass(self.settings.active_class)) {
90 | $(this)
91 | .css(Foundation.rtl ? 'right':'left', '-99999px')
92 | .removeClass(self.settings.active_class);
93 | $(this).trigger('closed');
94 | }
95 | });
96 | },
97 |
98 | open: function (dropdown, target) {
99 | this
100 | .css(dropdown
101 | .addClass(this.settings.active_class), target);
102 | dropdown.trigger('opened');
103 | },
104 |
105 | toggle : function (target) {
106 | var dropdown = $('#' + target.data('dropdown'));
107 | if (dropdown.length === 0) {
108 | // No dropdown found, not continuing
109 | return;
110 | }
111 |
112 | this.close.call(this, $('[data-dropdown-content]').not(dropdown));
113 |
114 | if (dropdown.hasClass(this.settings.active_class)) {
115 | this.close.call(this, dropdown);
116 | } else {
117 | this.close.call(this, $('[data-dropdown-content]'))
118 | this.open.call(this, dropdown, target);
119 | }
120 | },
121 |
122 | resize : function () {
123 | var dropdown = $('[data-dropdown-content].open'),
124 | target = $("[data-dropdown='" + dropdown.attr('id') + "']");
125 |
126 | if (dropdown.length && target.length) {
127 | this.css(dropdown, target);
128 | }
129 | },
130 |
131 | css : function (dropdown, target) {
132 | var offset_parent = dropdown.offsetParent(),
133 | position = target.offset();
134 |
135 | position.top -= offset_parent.offset().top;
136 | position.left -= offset_parent.offset().left;
137 |
138 | if (this.small()) {
139 | dropdown.css({
140 | position : 'absolute',
141 | width: '95%',
142 | 'max-width': 'none',
143 | top: position.top + target.outerHeight()
144 | });
145 | dropdown.css(Foundation.rtl ? 'right':'left', '2.5%');
146 | } else {
147 | if (!Foundation.rtl && $(window).width() > dropdown.outerWidth() + target.offset().left) {
148 | var left = position.left;
149 | if (dropdown.hasClass('right')) {
150 | dropdown.removeClass('right');
151 | }
152 | } else {
153 | if (!dropdown.hasClass('right')) {
154 | dropdown.addClass('right');
155 | }
156 | var left = position.left - (dropdown.outerWidth() - target.outerWidth());
157 | }
158 |
159 | dropdown.attr('style', '').css({
160 | position : 'absolute',
161 | top: position.top + target.outerHeight(),
162 | left: left
163 | });
164 | }
165 |
166 | return dropdown;
167 | },
168 |
169 | small : function () {
170 | return matchMedia(Foundation.media_queries.small).matches &&
171 | !matchMedia(Foundation.media_queries.medium).matches;
172 | },
173 |
174 | off: function () {
175 | $(this.scope).off('.fndtn.dropdown');
176 | $('html, body').off('.fndtn.dropdown');
177 | $(window).off('.fndtn.dropdown');
178 | $('[data-dropdown-content]').off('.fndtn.dropdown');
179 | this.settings.init = false;
180 | },
181 |
182 | reflow : function () {}
183 | };
184 | }(jQuery, this, this.document));
185 |
--------------------------------------------------------------------------------
/public/js/libs/foundation/foundation.tooltip.js:
--------------------------------------------------------------------------------
1 | ;(function ($, window, document, undefined) {
2 | 'use strict';
3 |
4 | Foundation.libs.tooltip = {
5 | name : 'tooltip',
6 |
7 | version : '5.0.0',
8 |
9 | settings : {
10 | additional_inheritable_classes : [],
11 | tooltip_class : '.tooltip',
12 | append_to: 'body',
13 | touch_close_text: 'Tap To Close',
14 | disable_for_touch: false,
15 | tip_template : function (selector, content) {
16 | return '
' + content + '';
19 | }
20 | },
21 |
22 | cache : {},
23 |
24 | init : function (scope, method, options) {
25 | this.bindings(method, options);
26 | },
27 |
28 | events : function () {
29 | var self = this;
30 |
31 | if (Modernizr.touch) {
32 | $(this.scope)
33 | .off('.tooltip')
34 | .on('click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip',
35 | '[data-tooltip]', function (e) {
36 | var settings = $.extend({}, self.settings, self.data_options($(this)));
37 | if (!settings.disable_for_touch) {
38 | e.preventDefault();
39 | $(settings.tooltip_class).hide();
40 | self.showOrCreateTip($(this));
41 | }
42 | })
43 | .on('click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip',
44 | this.settings.tooltip_class, function (e) {
45 | e.preventDefault();
46 | $(this).fadeOut(150);
47 | });
48 | } else {
49 | $(this.scope)
50 | .off('.tooltip')
51 | .on('mouseenter.fndtn.tooltip mouseleave.fndtn.tooltip',
52 | '[data-tooltip]', function (e) {
53 | var $this = $(this);
54 |
55 | if (/enter|over/i.test(e.type)) {
56 | self.showOrCreateTip($this);
57 | } else if (e.type === 'mouseout' || e.type === 'mouseleave') {
58 | self.hide($this);
59 | }
60 | });
61 | }
62 | },
63 |
64 | showOrCreateTip : function ($target) {
65 | var $tip = this.getTip($target);
66 |
67 | if ($tip && $tip.length > 0) {
68 | return this.show($target);
69 | }
70 |
71 | return this.create($target);
72 | },
73 |
74 | getTip : function ($target) {
75 | var selector = this.selector($target),
76 | tip = null;
77 |
78 | if (selector) {
79 | tip = $('span[data-selector="' + selector + '"]' + this.settings.tooltip_class);
80 | }
81 |
82 | return (typeof tip === 'object') ? tip : false;
83 | },
84 |
85 | selector : function ($target) {
86 | var id = $target.attr('id'),
87 | dataSelector = $target.attr('data-tooltip') || $target.attr('data-selector');
88 |
89 | if ((id && id.length < 1 || !id) && typeof dataSelector != 'string') {
90 | dataSelector = 'tooltip' + Math.random().toString(36).substring(7);
91 | $target.attr('data-selector', dataSelector);
92 | }
93 |
94 | return (id && id.length > 0) ? id : dataSelector;
95 | },
96 |
97 | create : function ($target) {
98 | var $tip = $(this.settings.tip_template(this.selector($target), $('
').html($target.attr('title')).html())),
99 | classes = this.inheritable_classes($target);
100 |
101 | $tip.addClass(classes).appendTo(this.settings.append_to);
102 | if (Modernizr.touch) {
103 | $tip.append('
'+this.settings.touch_close_text+'');
104 | }
105 | $target.removeAttr('title').attr('title','');
106 | this.show($target);
107 | },
108 |
109 | reposition : function (target, tip, classes) {
110 | var width, nub, nubHeight, nubWidth, column, objPos;
111 |
112 | tip.css('visibility', 'hidden').show();
113 |
114 | width = target.data('width');
115 | nub = tip.children('.nub');
116 | nubHeight = nub.outerHeight();
117 | nubWidth = nub.outerHeight();
118 |
119 | objPos = function (obj, top, right, bottom, left, width) {
120 | return obj.css({
121 | 'top' : (top) ? top : 'auto',
122 | 'bottom' : (bottom) ? bottom : 'auto',
123 | 'left' : (left) ? left : 'auto',
124 | 'right' : (right) ? right : 'auto',
125 | 'width' : (width) ? width : 'auto'
126 | }).end();
127 | };
128 |
129 | objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', target.offset().left, width);
130 |
131 | if (this.small()) {
132 | objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', 12.5, $(this.scope).width());
133 | tip.addClass('tip-override');
134 | objPos(nub, -nubHeight, 'auto', 'auto', target.offset().left);
135 | } else {
136 | var left = target.offset().left;
137 | if (Foundation.rtl) {
138 | left = target.offset().left + target.offset().width - tip.outerWidth();
139 | }
140 | objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', left, width);
141 | tip.removeClass('tip-override');
142 | if (classes && classes.indexOf('tip-top') > -1) {
143 | objPos(tip, (target.offset().top - tip.outerHeight()), 'auto', 'auto', left, width)
144 | .removeClass('tip-override');
145 | } else if (classes && classes.indexOf('tip-left') > -1) {
146 | objPos(tip, (target.offset().top + (target.outerHeight() / 2) - nubHeight*2.5), 'auto', 'auto', (target.offset().left - tip.outerWidth() - nubHeight), width)
147 | .removeClass('tip-override');
148 | } else if (classes && classes.indexOf('tip-right') > -1) {
149 | objPos(tip, (target.offset().top + (target.outerHeight() / 2) - nubHeight*2.5), 'auto', 'auto', (target.offset().left + target.outerWidth() + nubHeight), width)
150 | .removeClass('tip-override');
151 | }
152 | }
153 |
154 | tip.css('visibility', 'visible').hide();
155 | },
156 |
157 | small : function () {
158 | return matchMedia(Foundation.media_queries.small).matches;
159 | },
160 |
161 | inheritable_classes : function (target) {
162 | var inheritables = ['tip-top', 'tip-left', 'tip-bottom', 'tip-right', 'noradius'].concat(this.settings.additional_inheritable_classes),
163 | classes = target.attr('class'),
164 | filtered = classes ? $.map(classes.split(' '), function (el, i) {
165 | if ($.inArray(el, inheritables) !== -1) {
166 | return el;
167 | }
168 | }).join(' ') : '';
169 |
170 | return $.trim(filtered);
171 | },
172 |
173 | show : function ($target) {
174 | var $tip = this.getTip($target);
175 |
176 | this.reposition($target, $tip, $target.attr('class'));
177 | $tip.fadeIn(150);
178 | },
179 |
180 | hide : function ($target) {
181 | var $tip = this.getTip($target);
182 |
183 | $tip.fadeOut(150);
184 | },
185 |
186 | // deprecate reload
187 | reload : function () {
188 | var $self = $(this);
189 |
190 | return ($self.data('fndtn-tooltips')) ? $self.foundationTooltips('destroy').foundationTooltips('init') : $self.foundationTooltips('init');
191 | },
192 |
193 | off : function () {
194 | $(this.scope).off('.fndtn.tooltip');
195 | $(this.settings.tooltip_class).each(function (i) {
196 | $('[data-tooltip]').get(i).attr('title', $(this).text());
197 | }).remove();
198 | },
199 |
200 | reflow : function () {}
201 | };
202 | }(jQuery, this, this.document));
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Webception
2 |
3 | [](https://gitter.im/jayhealey/Webception?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 |
5 | #### Web Interface for running [Codeception](http://codeception.com) tests.
6 |
7 | Built with [Slim PHP framework](http://www.slimframework.com/) and [Foundation CSS framework](http://foundation.zurb.com/).
8 |
9 | ------------
10 |
11 | **What does it do?**
12 |
13 | Webception is a deployable web-application that allows you to run all your Codeception tests in the browser.
14 |
15 | You can access multiple test suites and decide which tests to include in a run. It allows you start, stop and restart the process whilst watching the test results in the Console.
16 |
17 | **What does it look like?**
18 |
19 | I'm glad you asked...
20 |
21 |

22 |
23 | **What's the ideal usage?**
24 |
25 | If you're a web developer, it's likely you run a staging server that hosts work in progress for your clients.
26 |
27 | Webception's ideal setup would be on a sub-domain on your staging server (`webception.your-staging-domain.com`) so it could have access to all of your test suites.
28 |
29 | **What it will it do?**
30 |
31 | Webception is a work in progress. Check out the [roadmap](#roadmap) for short-term goals.
32 |
33 | Check out how to [contribute](#contribute) if you want to get involved.
34 |
35 | ------------
36 |
37 | ## Requirements
38 |
39 | A web-server running PHP 5.3.0+ and [Composer](http://getcomposer.org/download/). Codeception will be installed via Composer.
40 |
41 | ------------
42 |
43 | ## Installation
44 |
45 | Out of the box, Webception is configured to run it's own Codeception tests.
46 |
47 | You'll need [Composer](http://getcomposer.org/download/) to be installed and the Codeception executable and logs directory need full read/write permissions.
48 |
49 | To configure Webception for your needs (i.e. to tun your own tests) copy `App/Config/codeception-local-sample.php` to `App/Config/codeception-local.php` and override settings from `App/Config/codeception.php`. It's here where you add references to the `codeception.yml` configurations.
50 |
51 | Also note Webception's `codeception.yml` is setup to use `http://webception:80` as it's host. Change this to be whatever host and port you decide to run Webception on.
52 |
53 | ### 1. Deploy Webception
54 |
55 | You can either install Webception using Composer:
56 |
57 | `composer create-project jayhealey/webception --stability=dev`
58 |
59 | Or [downloaded Webception](https://github.com/jayhealey/Webception/archive/master.zip) and unzip it. Once you've unzipped it, you need to install the Composer dependancies with:
60 |
61 | `composer install`
62 |
63 | Now you can do the following:
64 |
65 | 1. Ensure Codeception has permissions:
66 |
67 | `sudo chmod a+x vendor/bin/codecept`
68 |
69 | 2. Set permissions so Codeception can write out the log files:
70 |
71 | `sudo chmod -R 777 App/Tests/_log`
72 |
73 | 3. Set permissions so Slim PHP can write to the template cache:
74 |
75 | `sudo chmod -R 777 App/Templates/_cache`
76 |
77 | 4. Point your new server to the `public` path of where you unzipped Webception.
78 |
79 | You'll now be able to load Webception in your browser.
80 |
81 | If there are any issues Webception will do it's best to tell what you need to do.
82 |
83 | ### 2. Customise the Webception configuration
84 |
85 | There are a few configuration files you can play with in `/App/Config/codeception.php`.
86 |
87 | #### Adding your own tests to Webception
88 |
89 | You can add as many Codeception test suites as you need by adding to the `sites` array:
90 |
91 | ```
92 | 'sites' => array(
93 | 'Webception' => dirname(__FILE__) .'/../../codeception.yml',
94 | ),
95 | ```
96 | Put them in order you want to see in the dropdown. And if you only have one entry, you won't see the dropdown.
97 |
98 | Feel free to remove/replace the `Webception` entry with one of your own suites.
99 |
100 | If you have more than one site in the configuration, you can use the site picker on the top-left of Webception to swap between test suites.
101 |
102 | **And remember**: it's important you set `sudo chmod -R 777 /path/to/logs` on the log directories declared in your `codeception.yml` configurations. If you don't, Webception will fail to run the tests.
103 |
104 | *Note*: You may experience issues using `$_SERVER['DOCUMENT_ROOT']` to define the configuration path. It may be best to put the absolute path to your application root or a relative path using `dirname(__FILE__)`.
105 |
106 | ### 3. Run your tests!
107 |
108 | If you've configured everything correctly, Webception will show all your available tests. Just click **START** to run everything!
109 |
110 | That's it! **Happy Testing!**
111 |
112 | ------------
113 |
114 |
115 | ## Want to Contribute?
116 | There's a few ways you can get in touch:
117 |
118 | * **Chat on Twitter**. Follow [@WebceptionApp](https://www.twitter.com/WebceptionApp) for release updates or follow [@JayHealey](https://www.twitter.com/JayHealey) for everything else.
119 |
120 | * **Post bugs, issues, feature requests** via [GitHub Issues](https://github.com/jayhealey/webception/issues).
121 |
122 | * **Pull & Fork** on [GitHub](https://github.com/jayhealey/Webception/pulls) if you want to get your hands dirty. Please ensure that any new features you add have assosciated tests with them, and where possible point yuor feature request at the appropriate version (as per the [Roadmap](https://github.com/jayhealey/Webception/wiki))
123 |
124 | And **please let me know** if you use Webception. I'm keen to understand how you'd *like* to use it and if there's anything you'd like to see in future releases.
125 |
126 | I'm open to any feedback on how to improve Webception. From tips on SlimPHP, to how best to improve the Codeception handling to improving the UI. I'd be happy to hear it!
127 |
128 | ------------
129 |
130 | ## Infrequently Asked Questions (IAQs)
131 |
132 | **Why would I use Webception?**
133 |
134 | The aim of Webception is to open the test suites up to anyone involved in a web-development project. This could be a team leader, another developer (who might not be a PHP developer), client manager or even the client.
135 |
136 | The plan is to grow the tool to be a worthwhile part of your process. Potentially integrating CI tools or part of a bug reporting process.
137 |
138 | And selfishly, I couldn't find anything else that acted as a web interface for Codeception, so it was a problem worth solving.
139 |
140 | **Is Webception made by the same people as Codeception?**
141 |
142 | No. It's completely un-official. It's not affiliated or sponsored in anyway by the people who built Codeception.
143 |
144 | So, raise all issues about Webception on the Webception [GitHub Issues](https://github.com/jayhealey/Webception/issues) page.
145 |
146 | ------------
147 |
148 |
149 | ## Roadmap
150 |
151 | * **Automated/Interactive Setup**: I'd like to replace the manual setup with an interactive installation that asks for the Codeception test suites whilst verifying the details as you enter them. You'll should also be able to add/remove test suites via the app instead of modifying configuration files. It's possible to find all available `codeception.yml` files which would help automate installation.
152 |
153 | * **Logs and Screenshots**: When Codeception runs, it creates HTML snapshots and screenshots of where a test fails. It'd be useful for Webception to copy those files across and make them accessible via the console.
154 |
155 | * **Security**: At the moment, you can just secure the installation with .htaccess - but it might be worth adding built-in security via a Slim module.
156 |
157 | * **Exposed Unit Tests**: Unit tests contain multiple tests in a single file, so it'd be nice to scan Unit tests to expose them - and then allow the ability to run each of these tests individually (is that even possible in Codeception?).
158 |
159 | * **More Webception Tests**: It feels fitting that an application that runs tests should be drowning in tests. So, there'll be more of them in future.
160 |
161 | There's also the [TODO](TODO.md) list which contains a list of things I'd like to improve.
162 |
163 | If you have any ideas or issues, jump on [GitHub Issues](https://github.com/jayhealey/Webception/issues) or [@WebceptionApp](https://www.twitter.com/WebceptionApp) on Twitter.
164 |
--------------------------------------------------------------------------------
/public/js/libs/foundation/foundation.abide.js:
--------------------------------------------------------------------------------
1 | ;(function ($, window, document, undefined) {
2 | 'use strict';
3 |
4 | Foundation.libs.abide = {
5 | name : 'abide',
6 |
7 | version : '5.0.0',
8 |
9 | settings : {
10 | focus_on_invalid : true,
11 | timeout : 1000,
12 | patterns : {
13 | alpha: /[a-zA-Z]+/,
14 | alpha_numeric : /[a-zA-Z0-9]+/,
15 | integer: /-?\d+/,
16 | number: /-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?/,
17 |
18 | // generic password: upper-case, lower-case, number/special character, and min 8 characters
19 | password : /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/,
20 |
21 | // amex, visa, diners
22 | card : /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/,
23 | cvv : /^([0-9]){3,4}$/,
24 |
25 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
26 | email : /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,
27 |
28 | url: /(https?|ftp|file|ssh):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?/,
29 | // abc.de
30 | domain: /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/,
31 |
32 | datetime: /([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))/,
33 | // YYYY-MM-DD
34 | date: /(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))/,
35 | // HH:MM:SS
36 | time : /(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}/,
37 | dateISO: /\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/,
38 | // MM/DD/YYYY
39 | month_day_year : /(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/,
40 |
41 | // #FFF or #FFFFFF
42 | color: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
43 | }
44 | },
45 |
46 | timer : null,
47 |
48 | init : function (scope, method, options) {
49 | this.bindings(method, options);
50 | },
51 |
52 | events : function (scope) {
53 | var self = this,
54 | form = $(scope).attr('novalidate', 'novalidate'),
55 | settings = form.data('abide-init');
56 |
57 | form
58 | .off('.abide')
59 | .on('submit.fndtn.abide validate.fndtn.abide', function (e) {
60 | var is_ajax = /ajax/i.test($(this).attr('data-abide'));
61 | return self.validate($(this).find('input, textarea, select').get(), e, is_ajax);
62 | })
63 | .find('input, textarea, select')
64 | .off('.abide')
65 | .on('blur.fndtn.abide change.fndtn.abide', function (e) {
66 | self.validate([this], e);
67 | })
68 | .on('keydown.fndtn.abide', function (e) {
69 | var settings = $(this).closest('form').data('abide-init');
70 | clearTimeout(self.timer);
71 | self.timer = setTimeout(function () {
72 | self.validate([this], e);
73 | }.bind(this), settings.timeout);
74 | });
75 | },
76 |
77 | validate : function (els, e, is_ajax) {
78 | var validations = this.parse_patterns(els),
79 | validation_count = validations.length,
80 | form = $(els[0]).closest('form'),
81 | submit_event = /submit/.test(e.type);
82 |
83 | for (var i=0; i < validation_count; i++) {
84 | if (!validations[i] && (submit_event || is_ajax)) {
85 | if (this.settings.focus_on_invalid) els[i].focus();
86 | form.trigger('invalid');
87 | $(els[i]).closest('form').attr('data-invalid', '');
88 | return false;
89 | }
90 | }
91 |
92 | if (submit_event || is_ajax) {
93 | form.trigger('valid');
94 | }
95 |
96 | form.removeAttr('data-invalid');
97 |
98 | if (is_ajax) return false;
99 |
100 | return true;
101 | },
102 |
103 | parse_patterns : function (els) {
104 | var count = els.length,
105 | el_patterns = [];
106 |
107 | for (var i = count - 1; i >= 0; i--) {
108 | el_patterns.push(this.pattern(els[i]));
109 | }
110 |
111 | return this.check_validation_and_apply_styles(el_patterns);
112 | },
113 |
114 | pattern : function (el) {
115 | var type = el.getAttribute('type'),
116 | required = typeof el.getAttribute('required') === 'string';
117 |
118 | if (this.settings.patterns.hasOwnProperty(type)) {
119 | return [el, this.settings.patterns[type], required];
120 | }
121 |
122 | var pattern = el.getAttribute('pattern') || '';
123 |
124 | if (this.settings.patterns.hasOwnProperty(pattern) && pattern.length > 0) {
125 | return [el, this.settings.patterns[pattern], required];
126 | } else if (pattern.length > 0) {
127 | return [el, new RegExp(pattern), required];
128 | }
129 |
130 | pattern = /.*/;
131 |
132 | return [el, pattern, required];
133 | },
134 |
135 | check_validation_and_apply_styles : function (el_patterns) {
136 | var count = el_patterns.length,
137 | validations = [];
138 |
139 | for (var i = count - 1; i >= 0; i--) {
140 | var el = el_patterns[i][0],
141 | required = el_patterns[i][2],
142 | value = el.value,
143 | is_equal = el.getAttribute('data-equalto'),
144 | is_radio = el.type === "radio",
145 | valid_length = (required) ? (el.value.length > 0) : true;
146 |
147 | if (is_radio && required) {
148 | validations.push(this.valid_radio(el, required));
149 | } else if (is_equal && required) {
150 | validations.push(this.valid_equal(el, required));
151 | } else {
152 | if (el_patterns[i][1].test(value) && valid_length ||
153 | !required && el.value.length < 1) {
154 | $(el).removeAttr('data-invalid').parent().removeClass('error');
155 | validations.push(true);
156 | } else {
157 | $(el).attr('data-invalid', '').parent().addClass('error');
158 | validations.push(false);
159 | }
160 | }
161 | }
162 |
163 | return validations;
164 | },
165 |
166 | valid_radio : function (el, required) {
167 | var name = el.getAttribute('name'),
168 | group = document.getElementsByName(name),
169 | count = group.length,
170 | valid = false;
171 |
172 | for (var i=0; i < count; i++) {
173 | if (group[i].checked) valid = true;
174 | }
175 |
176 | for (var i=0; i < count; i++) {
177 | if (valid) {
178 | $(group[i]).removeAttr('data-invalid').parent().removeClass('error');
179 | } else {
180 | $(group[i]).attr('data-invalid', '').parent().addClass('error');
181 | }
182 | }
183 |
184 | return valid;
185 | },
186 |
187 | valid_equal: function(el, required) {
188 | var from = document.getElementById(el.getAttribute('data-equalto')).value,
189 | to = el.value,
190 | valid = (from === to);
191 |
192 | if (valid) {
193 | $(el).removeAttr('data-invalid').parent().removeClass('error');
194 | } else {
195 | $(el).attr('data-invalid', '').parent().addClass('error');
196 | }
197 |
198 | return valid;
199 | }
200 | };
201 | }(jQuery, this, this.document));
202 |
--------------------------------------------------------------------------------
/public/js/libs/modernizr.js:
--------------------------------------------------------------------------------
1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD
2 | * Build: http://modernizr.com/download/#-inlinesvg-svg-svgclippaths-touch-shiv-mq-cssclasses-teststyles-prefixes-ie8compat-load
3 | */
4 | ;window.Modernizr=function(a,b,c){function y(a){j.cssText=a}function z(a,b){return y(m.join(a+";")+(b||""))}function A(a,b){return typeof a===b}function B(a,b){return!!~(""+a).indexOf(b)}function C(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:A(f,"function")?f.bind(d||b):f}return!1}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n={svg:"http://www.w3.org/2000/svg"},o={},p={},q={},r=[],s=r.slice,t,u=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["",'"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},v=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return u("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},w={}.hasOwnProperty,x;!A(w,"undefined")&&!A(w.call,"undefined")?x=function(a,b){return w.call(a,b)}:x=function(a,b){return b in a&&A(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=s.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(s.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(s.call(arguments)))};return e}),o.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:u(["@media (",m.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},o.svg=function(){return!!b.createElementNS&&!!b.createElementNS(n.svg,"svg").createSVGRect},o.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="
",(a.firstChild&&a.firstChild.namespaceURI)==n.svg},o.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(l.call(b.createElementNS(n.svg,"clipPath")))};for(var D in o)x(o,D)&&(t=D.toLowerCase(),e[t]=o[D](),r.push((e[t]?"":"no-")+t));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)x(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},y(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e
",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=m,e.mq=v,e.testStyles=u,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+r.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},v=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return u("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},w={}.hasOwnProperty,x;!A(w,"undefined")&&!A(w.call,"undefined")?x=function(a,b){return w.call(a,b)}:x=function(a,b){return b in a&&A(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=s.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(s.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(s.call(arguments)))};return e}),o.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:u(["@media (",m.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},o.svg=function(){return!!b.createElementNS&&!!b.createElementNS(n.svg,"svg").createSVGRect},o.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==n.svg},o.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(l.call(b.createElementNS(n.svg,"clipPath")))};for(var D in o)x(o,D)&&(t=D.toLowerCase(),e[t]=o[D](),r.push((e[t]?"":"no-")+t));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)x(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},y(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=m,e.mq=v,e.testStyles=u,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+r.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | class CodeceptionClassTestsTest extends \Codeception\TestCase\Test
13 | {
14 | /**
15 | * @var \CodeGuy
16 | */
17 | protected $codeGuy;
18 |
19 | private $codeception = FALSE;
20 | private $config = FALSE;
21 |
22 | private $test_filename = 'WebceptionTestClassTest.php';
23 | private $test_file;
24 | private $pass_filename = 'TheTestThatPassesCept.php';
25 | private $fail_filename = 'TheTestThatFailsCept';
26 | private $test;
27 | private $type = 'unit';
28 | private $site_name = 'Webception';
29 |
30 | protected function _before()
31 | {
32 | // Load the Codeception config
33 | $this->config = require(dirname(__FILE__) . '/../_config/codeception_pass.php');
34 |
35 | // Load up a working Site class
36 | $this->site = new \App\Lib\Site($this->config['sites']);
37 |
38 | $this->site->set(md5($this->site_name));
39 |
40 | // Load up Codeception class
41 | $this->codeception = new \App\Lib\Codeception($this->config, $this->site);
42 |
43 | // Load up a blank test
44 | $this->test = new \App\Lib\Test();
45 |
46 | // Load up the current test file as an example test.
47 | $this->test_file = new SplFileInfo($this->test_filename);
48 | }
49 |
50 | protected function _after()
51 | {
52 | }
53 |
54 | /**
55 | * Test the Codeception class without passing in a configuration
56 | *
57 | */
58 | public function testCodeceptionWithNoConfig()
59 | {
60 | $codeception = new \App\Lib\Codeception();
61 | $this->assertFalse($codeception->ready());
62 | }
63 |
64 | /**
65 | * Test the Codeception class with configuration where
66 | * is completely empty.
67 | */
68 | public function testCodeceptionWithEmptyConfig()
69 | {
70 | $config = require(dirname(__FILE__) . '/../_config/codeception_fail.php');
71 |
72 | $site = new \App\Lib\Site($config['sites']);
73 | $site->set(md5($this->site_name));
74 | $codeception = new \App\Lib\Codeception($config, $site);
75 | $this->assertFalse($codeception->ready());
76 | }
77 |
78 | public function testCodeceptionWithInvalidExecutable()
79 | {
80 | $config = require(dirname(__FILE__) . '/../_config/codeception_executable_fail.php');
81 | $site = new \App\Lib\Site($this->config['sites']);
82 | $site->set(md5($this->site_name));
83 | $codeception = new \App\Lib\Codeception($config, $site);
84 | $response = $codeception->checkExecutable($config['executable'], $config['location']);
85 | $this->assertFalse($response['ready']);
86 | }
87 |
88 | public function testCodeceptionWithValidConfig()
89 | {
90 | $codeception = $this->codeception;
91 | $config = $this->config;
92 | $this->assertTrue($codeception->ready());
93 |
94 | $response = $codeception->checkExecutable($config['executable'], $config['location']);
95 | $this->assertTrue($response['ready']);
96 | }
97 |
98 | public function testCodeceptionCommandPath()
99 | {
100 | $codeception = $this->codeception;
101 | $config = $this->config;
102 |
103 | $params = array(
104 | $this->config['executable'], // Codeception Executable
105 | "run", // Command to Codeception
106 | "--no-colors", // Forcing Codeception to not use colors, if enabled in codeception.yml
107 | "--config=\"{$codeception->site->getConfig()}\"", // Full path & file of Codeception
108 | $this->type, // Test Type (Acceptance, Unit, Functional)
109 | $this->test_filename, // Filename of the Codeception test
110 | "2>&1" // Added to force output of running executable to be streamed out
111 | );
112 |
113 | $mock_command = implode(' ', $params);
114 | $codeception_command = $codeception->getCommandPath($this->type, $this->test_filename);
115 |
116 | $this->assertEquals($mock_command, $codeception_command);
117 | }
118 |
119 | /**
120 | * Test the adding and getting of tests when they're loaded.
121 | */
122 | public function testAddingAndGettingTests()
123 | {
124 | $test = $this->test;
125 | $codeception = $this->codeception;
126 | $tally_before = $codeception->getTestTally();
127 | $type = 'awesome'; // Fake type. So we don't clash with the loaded tests.
128 |
129 | // Initialize the test as per usual
130 | $test->init($type, $this->test_file);
131 |
132 | // Check the adding tally works
133 | $codeception->addTest($test);
134 | $tally_after = $codeception->getTestTally();
135 | $this->assertGreaterThan($tally_before, $tally_after);
136 |
137 | // Check the test can be recieved again
138 | $test_back = $codeception->getTest($type, $test->getHash());
139 | $this->assertEquals($test_back->getTitle(), $test->getTitle());
140 | }
141 |
142 | /**
143 | * Testing the getRunResponse used in the run route for a test that wasn't found.
144 | */
145 | public function testResponseForNotFoundTest()
146 | {
147 | $codeception = $this->codeception;
148 | $response = $codeception->getRunResponse('lol', md5("notgoingtofindthis"));
149 |
150 | $this->assertFalse($response['run']);
151 | $this->assertFalse($response['passed']);
152 | $this->assertEquals($response['message'], 'The test could not be found.');
153 | $this->assertNull($response['log']);
154 | $this->assertEquals($response['state'], 'error');
155 | }
156 |
157 | /**
158 | * Testing the run() function on the Test class with a passing test.
159 | */
160 | public function testTheTestThatPasses()
161 | {
162 | $codeception = $this->codeception;
163 |
164 | // Get the test that we know fails.
165 | $test = $codeception->getTest('acceptance', md5("acceptanceTheTestThatPasses"));
166 |
167 | // Confirm the test hasn't been or passed yet
168 | $this->assertFalse($test->ran());
169 | $this->assertFalse($test->passed());
170 |
171 | // Run the test, which generates the log and analyes the log as it gets added.
172 | $test = $codeception->run($test);
173 |
174 | // Confirm the test was run & passed!
175 | $this->assertTrue($test->ran());
176 | $this->assertTrue($test->passed());
177 | }
178 |
179 | /**
180 | * Testing the getRunResponse used in the run route for a passing test.
181 | */
182 | public function testResponseForTheTestThatPasses()
183 | {
184 | $codeception = $this->codeception;
185 | $response = $codeception->getRunResponse('acceptance', md5("acceptanceTheTestThatPasses"));
186 |
187 | $this->assertTrue($response['run']);
188 | $this->assertTrue($response['passed']);
189 | $this->assertNull($response['message']);
190 | $this->assertNotNull($response['log']);
191 | $this->assertEquals($response['state'], 'passed');
192 | }
193 |
194 | /**
195 | * Testing the run() function on the Test class with a failing test.
196 | */
197 | public function testTheTestThatFails()
198 | {
199 | $codeception = $this->codeception;
200 |
201 | // Get the test that we know fails.
202 | $test = $codeception->getTest('acceptance', md5("acceptanceTheTestThatFails"));
203 |
204 | // Confirm the test hasn't been or passed yet
205 | $this->assertFalse($test->ran());
206 | $this->assertFalse($test->passed());
207 |
208 | // Run the test, which generates the log and analyes the log as it gets added.
209 | $test = $codeception->run($test);
210 |
211 | // Confirm the test was run but it's not passed
212 | $this->assertTrue($test->ran());
213 | $this->assertFalse($test->passed());
214 | }
215 |
216 | /**
217 | * Testing the getRunResponse used in the run route for a failing test.
218 | */
219 | public function testResponseForTheTestThatFails()
220 | {
221 | $codeception = $this->codeception;
222 | $response = $codeception->getRunResponse('acceptance', md5("acceptanceTheTestThatFails"));
223 |
224 | $this->assertTrue($response['run']);
225 | $this->assertFalse($response['passed']);
226 | $this->assertNull($response['message']);
227 | $this->assertNotNull($response['log']);
228 | $this->assertEquals($response['state'], 'failed');
229 | }
230 |
231 | }
232 |
--------------------------------------------------------------------------------
/public/js/libs/foundation/foundation.interchange.js:
--------------------------------------------------------------------------------
1 | ;(function ($, window, document, undefined) {
2 | 'use strict';
3 |
4 | Foundation.libs.interchange = {
5 | name : 'interchange',
6 |
7 | version : '5.0.0',
8 |
9 | cache : {},
10 |
11 | images_loaded : false,
12 | nodes_loaded : false,
13 |
14 | settings : {
15 | load_attr : 'interchange',
16 |
17 | named_queries : {
18 | 'default' : Foundation.media_queries.small,
19 | small : Foundation.media_queries.small,
20 | medium : Foundation.media_queries.medium,
21 | large : Foundation.media_queries.large,
22 | xlarge : Foundation.media_queries.xlarge,
23 | xxlarge: Foundation.media_queries.xxlarge,
24 | landscape : 'only screen and (orientation: landscape)',
25 | portrait : 'only screen and (orientation: portrait)',
26 | retina : 'only screen and (-webkit-min-device-pixel-ratio: 2),' +
27 | 'only screen and (min--moz-device-pixel-ratio: 2),' +
28 | 'only screen and (-o-min-device-pixel-ratio: 2/1),' +
29 | 'only screen and (min-device-pixel-ratio: 2),' +
30 | 'only screen and (min-resolution: 192dpi),' +
31 | 'only screen and (min-resolution: 2dppx)'
32 | },
33 |
34 | directives : {
35 | replace: function (el, path, trigger) {
36 | // The trigger argument, if called within the directive, fires
37 | // an event named after the directive on the element, passing
38 | // any parameters along to the event that you pass to trigger.
39 | //
40 | // ex. trigger(), trigger([a, b, c]), or trigger(a, b, c)
41 | //
42 | // This allows you to bind a callback like so:
43 | // $('#interchangeContainer').on('replace', function (e, a, b, c) {
44 | // console.log($(this).html(), a, b, c);
45 | // });
46 |
47 | if (/IMG/.test(el[0].nodeName)) {
48 | var orig_path = el[0].src;
49 |
50 | if (new RegExp(path, 'i').test(orig_path)) return;
51 |
52 | el[0].src = path;
53 |
54 | return trigger(el[0].src);
55 | }
56 | var last_path = el.data('interchange-last-path');
57 |
58 | if (last_path == path) return;
59 |
60 | return $.get(path, function (response) {
61 | el.html(response);
62 | el.data('interchange-last-path', path);
63 | trigger();
64 | });
65 |
66 | }
67 | }
68 | },
69 |
70 | init : function (scope, method, options) {
71 | Foundation.inherit(this, 'throttle');
72 |
73 | this.data_attr = 'data-' + this.settings.load_attr;
74 |
75 | this.bindings(method, options);
76 | this.load('images');
77 | this.load('nodes');
78 | },
79 |
80 | events : function () {
81 | var self = this;
82 |
83 | $(window)
84 | .off('.interchange')
85 | .on('resize.fndtn.interchange', self.throttle(function () {
86 | self.resize.call(self);
87 | }, 50));
88 |
89 | return this;
90 | },
91 |
92 | resize : function () {
93 | var cache = this.cache;
94 |
95 | if(!this.images_loaded || !this.nodes_loaded) {
96 | setTimeout($.proxy(this.resize, this), 50);
97 | return;
98 | }
99 |
100 | for (var uuid in cache) {
101 | if (cache.hasOwnProperty(uuid)) {
102 | var passed = this.results(uuid, cache[uuid]);
103 |
104 | if (passed) {
105 | this.settings.directives[passed
106 | .scenario[1]](passed.el, passed.scenario[0], function () {
107 | if (arguments[0] instanceof Array) {
108 | var args = arguments[0];
109 | } else {
110 | var args = Array.prototype.slice.call(arguments, 0);
111 | }
112 |
113 | passed.el.trigger(passed.scenario[1], args);
114 | });
115 | }
116 | }
117 | }
118 |
119 | },
120 |
121 | results : function (uuid, scenarios) {
122 | var count = scenarios.length;
123 |
124 | if (count > 0) {
125 | var el = this.S('[data-uuid="' + uuid + '"]');
126 |
127 | for (var i = count - 1; i >= 0; i--) {
128 | var mq, rule = scenarios[i][2];
129 | if (this.settings.named_queries.hasOwnProperty(rule)) {
130 | mq = matchMedia(this.settings.named_queries[rule]);
131 | } else {
132 | mq = matchMedia(rule);
133 | }
134 | if (mq.matches) {
135 | return {el: el, scenario: scenarios[i]};
136 | }
137 | }
138 | }
139 |
140 | return false;
141 | },
142 |
143 | load : function (type, force_update) {
144 | if (typeof this['cached_' + type] === 'undefined' || force_update) {
145 | this['update_' + type]();
146 | }
147 |
148 | return this['cached_' + type];
149 | },
150 |
151 | update_images : function () {
152 | var images = this.S('img[' + this.data_attr + ']'),
153 | count = images.length,
154 | loaded_count = 0,
155 | data_attr = this.data_attr;
156 |
157 | this.cache = {};
158 | this.cached_images = [];
159 | this.images_loaded = (count === 0);
160 |
161 | for (var i = count - 1; i >= 0; i--) {
162 | loaded_count++;
163 | if (images[i]) {
164 | var str = images[i].getAttribute(data_attr) || '';
165 |
166 | if (str.length > 0) {
167 | this.cached_images.push(images[i]);
168 | }
169 | }
170 |
171 | if(loaded_count === count) {
172 | this.images_loaded = true;
173 | this.enhance('images');
174 | }
175 | }
176 |
177 | return this;
178 | },
179 |
180 | update_nodes : function () {
181 | var nodes = this.S('[' + this.data_attr + ']:not(img)'),
182 | count = nodes.length,
183 | loaded_count = 0,
184 | data_attr = this.data_attr;
185 |
186 | this.cached_nodes = [];
187 | // Set nodes_loaded to true if there are no nodes
188 | // this.nodes_loaded = false;
189 | this.nodes_loaded = (count === 0);
190 |
191 |
192 | for (var i = count - 1; i >= 0; i--) {
193 | loaded_count++;
194 | var str = nodes[i].getAttribute(data_attr) || '';
195 |
196 | if (str.length > 0) {
197 | this.cached_nodes.push(nodes[i]);
198 | }
199 |
200 | if(loaded_count === count) {
201 | this.nodes_loaded = true;
202 | this.enhance('nodes');
203 | }
204 | }
205 |
206 | return this;
207 | },
208 |
209 | enhance : function (type) {
210 | var count = this['cached_' + type].length;
211 |
212 | for (var i = count - 1; i >= 0; i--) {
213 | this.object($(this['cached_' + type][i]));
214 | }
215 |
216 | return $(window).trigger('resize');
217 | },
218 |
219 | parse_params : function (path, directive, mq) {
220 | return [this.trim(path), this.convert_directive(directive), this.trim(mq)];
221 | },
222 |
223 | convert_directive : function (directive) {
224 | var trimmed = this.trim(directive);
225 |
226 | if (trimmed.length > 0) {
227 | return trimmed;
228 | }
229 |
230 | return 'replace';
231 | },
232 |
233 | object : function(el) {
234 | var raw_arr = this.parse_data_attr(el),
235 | scenarios = [], count = raw_arr.length;
236 |
237 | if (count > 0) {
238 | for (var i = count - 1; i >= 0; i--) {
239 | var split = raw_arr[i].split(/\((.*?)(\))$/);
240 |
241 | if (split.length > 1) {
242 | var cached_split = split[0].split(','),
243 | params = this.parse_params(cached_split[0],
244 | cached_split[1], split[1]);
245 |
246 | scenarios.push(params);
247 | }
248 | }
249 | }
250 |
251 | return this.store(el, scenarios);
252 | },
253 |
254 | uuid : function (separator) {
255 | var delim = separator || "-";
256 |
257 | function S4() {
258 | return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
259 | }
260 |
261 | return (S4() + S4() + delim + S4() + delim + S4()
262 | + delim + S4() + delim + S4() + S4() + S4());
263 | },
264 |
265 | store : function (el, scenarios) {
266 | var uuid = this.uuid(),
267 | current_uuid = el.data('uuid');
268 |
269 | if (current_uuid) return this.cache[current_uuid];
270 |
271 | el.attr('data-uuid', uuid);
272 |
273 | return this.cache[uuid] = scenarios;
274 | },
275 |
276 | trim : function(str) {
277 | if (typeof str === 'string') {
278 | return $.trim(str);
279 | }
280 |
281 | return str;
282 | },
283 |
284 | parse_data_attr : function (el) {
285 | var raw = el.data(this.settings.load_attr).split(/\[(.*?)\]/),
286 | count = raw.length, output = [];
287 |
288 | for (var i = count - 1; i >= 0; i--) {
289 | if (raw[i].replace(/[\W\d]+/, '').length > 4) {
290 | output.push(raw[i]);
291 | }
292 | }
293 |
294 | return output;
295 | },
296 |
297 | reflow : function () {
298 | this.load('images', true);
299 | this.load('nodes', true);
300 | }
301 |
302 | };
303 |
304 | }(jQuery, this, this.document));
305 |
--------------------------------------------------------------------------------
/App/Lib/Test.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | class Test
13 | {
14 | /**
15 | * MD5 of the file name
16 | *
17 | * @var string
18 | */
19 | private $hash;
20 |
21 | /**
22 | * Filename of the test.
23 | *
24 | * @var string
25 | */
26 | private $filename;
27 |
28 | /**
29 | * Readable version of the filename
30 | *
31 | * @var string
32 | */
33 | private $title;
34 |
35 | /**
36 | * The file object.
37 | *
38 | * @var SplFileInfo
39 | */
40 | private $file;
41 |
42 | /**
43 | * Test Type: Functional, Acceptance or Unit.
44 | *
45 | * @var string
46 | */
47 | private $type;
48 |
49 | /**
50 | * Log of the test result
51 | *
52 | * @var array Each array entry is a console log line.
53 | */
54 | private $log = array();
55 |
56 | /**
57 | * Result of running the test.
58 | *
59 | * @var bool
60 | */
61 | private $passed = FALSE;
62 |
63 | /**
64 | * Possible test states
65 | */
66 | const STATE_PASSED = 'passed';
67 | const STATE_FAILED = 'failed';
68 | const STATE_ERROR = 'error';
69 | const STATE_READY = 'ready';
70 |
71 | /**
72 | * List of responses that can occur from Codeception.
73 | *
74 | * Using these, we scan the result when log is added to the test.
75 | *
76 | * @var array
77 | */
78 | private $responses = array(
79 | 'timeout' => 'Operation timed out after',
80 | 'writeable' => 'Path for logs is not writable',
81 | 'passed' => array(
82 | 'PASSED', // Functional & Acceptance Test
83 | 'OK \(' // Unit Test
84 | ),
85 | 'failed' => 'FAILURES',
86 | );
87 |
88 | /**
89 | * On Test __construct, the passed matches are turned into a regex.
90 | *
91 | * @var string
92 | */
93 | private $passed_regex;
94 |
95 | /**
96 | * Colour tags from Codeception's coloured output.
97 | *
98 | * @var array
99 | */
100 | private $colour_codes = array(
101 | "[37;45m",
102 | "[2K",
103 | "[1m",
104 | "[0m",
105 | "[30;42m",
106 | "[37;41m",
107 | "[33m",
108 | "[36m",
109 | "[35;1m",
110 | "-",
111 | );
112 |
113 | /**
114 | * File extensions to remove from the output.
115 | *
116 | * @var array
117 | */
118 | private $filtered_files = array(
119 | 'Cept.php',
120 | 'Cest.php',
121 | 'Test.php',
122 | );
123 |
124 | public function __construct()
125 | {
126 | // Declare the regex string containing all the responses that
127 | // can indicate that as a passed test.
128 | $this->passed_regex = implode('|', $this->responses['passed']);
129 |
130 | // maybe there will be any more failures? Then we are going to need this
131 | $this->failure_regex = $this->responses['failed'];
132 | }
133 |
134 | /**
135 | * Initialization of the Test
136 | *
137 | * @param string $type Type of Test
138 | * @param object $file File for the Test
139 | */
140 | public function init($type, $file)
141 | {
142 | $filename = $this->filterFileName($file->getFileName());
143 | $posTypePath = strpos($file->getPathname(), DIRECTORY_SEPARATOR.$type.DIRECTORY_SEPARATOR)
144 | + strlen(DIRECTORY_SEPARATOR.$type.DIRECTORY_SEPARATOR);
145 |
146 | $this->hash = $this->makeHash($type . $filename);
147 | $this->title = $this->filterTitle($filename);
148 | $this->filename = substr($file->getPathname(), $posTypePath);
149 | $this->file = $file;
150 | $this->type = $type;
151 | $this->state = self::STATE_READY; // Not used yet.
152 | }
153 |
154 | /**
155 | * Filter out content from a title any to improve readability of the test name
156 | *
157 | * @param string $filename
158 | * @return string
159 | */
160 | public function filterFileName($filename)
161 | {
162 | return str_ireplace($this->filtered_files, '', $filename);
163 | }
164 |
165 | /**
166 | * Generate a unique hash for the test.
167 | *
168 | * @param string $string
169 | * @return string MD5 of $string
170 | */
171 | public function makeHash($string)
172 | {
173 | return md5($string);
174 | }
175 |
176 | /**
177 | * Turn a "CamelCasedString" into "Camel Cased String".
178 | * This is to improve readability of the test list.
179 | *
180 | * @param string $title
181 | * @return string
182 | */
183 | public function filterTitle($title)
184 | {
185 | return camel_to_sentance($title);
186 | }
187 |
188 | /**
189 | * Get the Test title
190 | *
191 | * @return string
192 | */
193 | public function getTitle()
194 | {
195 | return $this->title;
196 | }
197 |
198 | /**
199 | * Get the Test Hash
200 | *
201 | * The hash is the Test title that's been md5'd.
202 | *
203 | * @return string
204 | */
205 | public function getHash()
206 | {
207 | return $this->hash;
208 | }
209 |
210 | /**
211 | * Get the Test type
212 | *
213 | * @return string
214 | */
215 | public function getType()
216 | {
217 | return $this->type;
218 | }
219 |
220 | /**
221 | * Get the file Filename
222 | *
223 | * @return string
224 | */
225 | public function getFilename()
226 | {
227 | return $this->filename;
228 | }
229 |
230 | /**
231 | * Set if the test has been passed.
232 | *
233 | * @return boolean
234 | */
235 | public function setPassed()
236 | {
237 | $this->passed = TRUE;
238 | }
239 |
240 | /**
241 | * Sets passed to false if test fails
242 | */
243 | public function setFailed()
244 | {
245 | $this->passed = false;
246 | }
247 |
248 | /**
249 | * Return if the test was run and passed
250 | *
251 | * @return boolean
252 | */
253 | public function passed()
254 | {
255 | return $this->passed;
256 | }
257 |
258 | /**
259 | * Return if the test was successfully run.
260 | *
261 | * This is deteremined by simply checking the length of the log.
262 | *
263 | * @return boolean
264 | */
265 | public function ran()
266 | {
267 | return sizeof($this->log) > 0;
268 | }
269 |
270 | /**
271 | * Get the Test state based on if the test has run or passed.
272 | *
273 | * @return boolean
274 | */
275 | public function getState()
276 | {
277 | return ($this->passed() ? self::STATE_PASSED :
278 | ($this->ran() ? self::STATE_FAILED : self::STATE_ERROR));
279 | }
280 |
281 | /**
282 | * Add a new line entry to the Test log.
283 | *
284 | * Also check the log line may indicate if the Test has passed.
285 | *
286 | * @param String $line
287 | */
288 | public function setLog($lines = array())
289 | {
290 | $failed = false;
291 | foreach ($lines as $line) {
292 |
293 | if ($this->checkLogForTestPass($line) && $failed==false)
294 | $this->setPassed();
295 |
296 | if ($this->checkLogForTestFailure($line)) {
297 | $this->setFailed();
298 | $failed = true;
299 | }
300 |
301 | // Filter the line of any junk and add to the log.
302 | $this->log[] = $this->filterLog($line);
303 | }
304 | }
305 |
306 | /**
307 | * Return the log as a HTML string.
308 | *
309 | * @param $format Split the array into HTML with linebreaks or return as-is if false.
310 | * @return HTML/Array
311 | */
312 | public function getLog($format = TRUE)
313 | {
314 | return $format ? implode($this->log, PHP_EOL) : $this->log;
315 | }
316 |
317 | /**
318 | * Filter out junk content from a log line.
319 | *
320 | * @param String $line
321 | */
322 | private function filterLog($line)
323 | {
324 | return str_replace($this->colour_codes, '', $line);
325 | }
326 |
327 | /**
328 | * Check if it contains any text that indiciates that the test has passed.
329 | *
330 | * @param string $line
331 | * @return boolean
332 | */
333 | public function checkLogForTestPass($line)
334 | {
335 | return count(preg_grep("/({$this->passed_regex})/", array($line))) > 0;
336 | }
337 |
338 | /**
339 | * Checks if line contains failure regex
340 | *
341 | * @param string $line
342 | * @return bool
343 | */
344 | public function checkLogForTestFailure($line)
345 | {
346 | return count(preg_grep("/({$this->failure_regex})/", array($line))) > 0;
347 | }
348 |
349 | /**
350 | * Reset a Test back to default.
351 | */
352 | public function reset()
353 | {
354 | $this->log = array();
355 | $this->passed = FALSE;
356 | }
357 | }
358 |
--------------------------------------------------------------------------------
/public/css/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v2.1.2 | MIT License | git.io/normalize */
2 |
3 | /* ==========================================================================
4 | HTML5 display definitions
5 | ========================================================================== */
6 |
7 | /**
8 | * Correct `block` display not defined in IE 8/9.
9 | */
10 |
11 | article,
12 | aside,
13 | details,
14 | figcaption,
15 | figure,
16 | footer,
17 | header,
18 | hgroup,
19 | main,
20 | nav,
21 | section,
22 | summary {
23 | display: block;
24 | }
25 |
26 | /**
27 | * Correct `inline-block` display not defined in IE 8/9.
28 | */
29 |
30 | audio,
31 | canvas,
32 | video {
33 | display: inline-block;
34 | }
35 |
36 | /**
37 | * Prevent modern browsers from displaying `audio` without controls.
38 | * Remove excess height in iOS 5 devices.
39 | */
40 |
41 | audio:not([controls]) {
42 | display: none;
43 | height: 0;
44 | }
45 |
46 | /**
47 | * Address `[hidden]` styling not present in IE 8/9.
48 | * Hide the `template` element in IE, Safari, and Firefox < 22.
49 | */
50 |
51 | [hidden],
52 | template {
53 | display: none;
54 | }
55 |
56 | script {
57 | display: none !important;
58 | }
59 |
60 | /* ==========================================================================
61 | Base
62 | ========================================================================== */
63 |
64 | /**
65 | * 1. Set default font family to sans-serif.
66 | * 2. Prevent iOS text size adjust after orientation change, without disabling
67 | * user zoom.
68 | */
69 |
70 | html {
71 | font-family: sans-serif; /* 1 */
72 | -ms-text-size-adjust: 100%; /* 2 */
73 | -webkit-text-size-adjust: 100%; /* 2 */
74 | }
75 |
76 | /**
77 | * Remove default margin.
78 | */
79 |
80 | body {
81 | margin: 0;
82 | }
83 |
84 | /* ==========================================================================
85 | Links
86 | ========================================================================== */
87 |
88 | /**
89 | * Remove the gray background color from active links in IE 10.
90 | */
91 |
92 | a {
93 | background: transparent;
94 | }
95 |
96 | /**
97 | * Address `outline` inconsistency between Chrome and other browsers.
98 | */
99 |
100 | a:focus {
101 | outline: thin dotted;
102 | }
103 |
104 | /**
105 | * Improve readability when focused and also mouse hovered in all browsers.
106 | */
107 |
108 | a:active,
109 | a:hover {
110 | outline: 0;
111 | }
112 |
113 | /* ==========================================================================
114 | Typography
115 | ========================================================================== */
116 |
117 | /**
118 | * Address variable `h1` font-size and margin within `section` and `article`
119 | * contexts in Firefox 4+, Safari 5, and Chrome.
120 | */
121 |
122 | h1 {
123 | font-size: 2em;
124 | margin: 0.67em 0;
125 | }
126 |
127 | /**
128 | * Address styling not present in IE 8/9, Safari 5, and Chrome.
129 | */
130 |
131 | abbr[title] {
132 | border-bottom: 1px dotted;
133 | }
134 |
135 | /**
136 | * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
137 | */
138 |
139 | b,
140 | strong {
141 | font-weight: bold;
142 | }
143 |
144 | /**
145 | * Address styling not present in Safari 5 and Chrome.
146 | */
147 |
148 | dfn {
149 | font-style: italic;
150 | }
151 |
152 | /**
153 | * Address differences between Firefox and other browsers.
154 | */
155 |
156 | hr {
157 | -moz-box-sizing: content-box;
158 | box-sizing: content-box;
159 | height: 0;
160 | }
161 |
162 | /**
163 | * Address styling not present in IE 8/9.
164 | */
165 |
166 | mark {
167 | background: #ff0;
168 | color: #000;
169 | }
170 |
171 | /**
172 | * Correct font family set oddly in Safari 5 and Chrome.
173 | */
174 |
175 | code,
176 | kbd,
177 | pre,
178 | samp {
179 | font-family: monospace, serif;
180 | font-size: 1em;
181 | }
182 |
183 | /**
184 | * Improve readability of pre-formatted text in all browsers.
185 | */
186 |
187 | pre {
188 | white-space: pre-wrap;
189 | }
190 |
191 | /**
192 | * Set consistent quote types.
193 | */
194 |
195 | q {
196 | quotes: "\201C" "\201D" "\2018" "\2019";
197 | }
198 |
199 | /**
200 | * Address inconsistent and variable font size in all browsers.
201 | */
202 |
203 | small {
204 | font-size: 80%;
205 | }
206 |
207 | /**
208 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
209 | */
210 |
211 | sub,
212 | sup {
213 | font-size: 75%;
214 | line-height: 0;
215 | position: relative;
216 | vertical-align: baseline;
217 | }
218 |
219 | sup {
220 | top: -0.5em;
221 | }
222 |
223 | sub {
224 | bottom: -0.25em;
225 | }
226 |
227 | /* ==========================================================================
228 | Embedded content
229 | ========================================================================== */
230 |
231 | /**
232 | * Remove border when inside `a` element in IE 8/9.
233 | */
234 |
235 | img {
236 | border: 0;
237 | }
238 |
239 | /**
240 | * Correct overflow displayed oddly in IE 9.
241 | */
242 |
243 | svg:not(:root) {
244 | overflow: hidden;
245 | }
246 |
247 | /* ==========================================================================
248 | Figures
249 | ========================================================================== */
250 |
251 | /**
252 | * Address margin not present in IE 8/9 and Safari 5.
253 | */
254 |
255 | figure {
256 | margin: 0;
257 | }
258 |
259 | /* ==========================================================================
260 | Forms
261 | ========================================================================== */
262 |
263 | /**
264 | * Define consistent border, margin, and padding.
265 | */
266 |
267 | fieldset {
268 | border: 1px solid #c0c0c0;
269 | margin: 0 2px;
270 | padding: 0.35em 0.625em 0.75em;
271 | }
272 |
273 | /**
274 | * 1. Correct `color` not being inherited in IE 8/9.
275 | * 2. Remove padding so people aren't caught out if they zero out fieldsets.
276 | */
277 |
278 | legend {
279 | border: 0; /* 1 */
280 | padding: 0; /* 2 */
281 | }
282 |
283 | /**
284 | * 1. Correct font family not being inherited in all browsers.
285 | * 2. Correct font size not being inherited in all browsers.
286 | * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
287 | */
288 |
289 | button,
290 | input,
291 | select,
292 | textarea {
293 | font-family: inherit; /* 1 */
294 | font-size: 100%; /* 2 */
295 | margin: 0; /* 3 */
296 | }
297 |
298 | /**
299 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in
300 | * the UA stylesheet.
301 | */
302 |
303 | button,
304 | input {
305 | line-height: normal;
306 | }
307 |
308 | /**
309 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
310 | * All other form control elements do not inherit `text-transform` values.
311 | * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
312 | * Correct `select` style inheritance in Firefox 4+ and Opera.
313 | */
314 |
315 | button,
316 | select {
317 | text-transform: none;
318 | }
319 |
320 | /**
321 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
322 | * and `video` controls.
323 | * 2. Correct inability to style clickable `input` types in iOS.
324 | * 3. Improve usability and consistency of cursor style between image-type
325 | * `input` and others.
326 | */
327 |
328 | button,
329 | html input[type="button"], /* 1 */
330 | input[type="reset"],
331 | input[type="submit"] {
332 | -webkit-appearance: button; /* 2 */
333 | cursor: pointer; /* 3 */
334 | }
335 |
336 | /**
337 | * Re-set default cursor for disabled elements.
338 | */
339 |
340 | button[disabled],
341 | html input[disabled] {
342 | cursor: default;
343 | }
344 |
345 | /**
346 | * 1. Address box sizing set to `content-box` in IE 8/9.
347 | * 2. Remove excess padding in IE 8/9.
348 | */
349 |
350 | input[type="checkbox"],
351 | input[type="radio"] {
352 | box-sizing: border-box; /* 1 */
353 | padding: 0; /* 2 */
354 | }
355 |
356 | /**
357 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
358 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
359 | * (include `-moz` to future-proof).
360 | */
361 |
362 | input[type="search"] {
363 | -webkit-appearance: textfield; /* 1 */
364 | -moz-box-sizing: content-box;
365 | -webkit-box-sizing: content-box; /* 2 */
366 | box-sizing: content-box;
367 | }
368 |
369 | /**
370 | * Remove inner padding and search cancel button in Safari 5 and Chrome
371 | * on OS X.
372 | */
373 |
374 | input[type="search"]::-webkit-search-cancel-button,
375 | input[type="search"]::-webkit-search-decoration {
376 | -webkit-appearance: none;
377 | }
378 |
379 | /**
380 | * Remove inner padding and border in Firefox 4+.
381 | */
382 |
383 | button::-moz-focus-inner,
384 | input::-moz-focus-inner {
385 | border: 0;
386 | padding: 0;
387 | }
388 |
389 | /**
390 | * 1. Remove default vertical scrollbar in IE 8/9.
391 | * 2. Improve readability and alignment in all browsers.
392 | */
393 |
394 | textarea {
395 | overflow: auto; /* 1 */
396 | vertical-align: top; /* 2 */
397 | }
398 |
399 | /* ==========================================================================
400 | Tables
401 | ========================================================================== */
402 |
403 | /**
404 | * Remove most spacing between table cells.
405 | */
406 |
407 | table {
408 | border-collapse: collapse;
409 | border-spacing: 0;
410 | }
411 |
--------------------------------------------------------------------------------
/public/js/libs/foundation/foundation.reveal.js:
--------------------------------------------------------------------------------
1 | ;(function ($, window, document, undefined) {
2 | 'use strict';
3 |
4 | Foundation.libs.reveal = {
5 | name : 'reveal',
6 |
7 | version : '5.0.0',
8 |
9 | locked : false,
10 |
11 | settings : {
12 | animation: 'fadeAndPop',
13 | animation_speed: 250,
14 | close_on_background_click: true,
15 | close_on_esc: true,
16 | dismiss_modal_class: 'close-reveal-modal',
17 | bg_class: 'reveal-modal-bg',
18 | open: function(){},
19 | opened: function(){},
20 | close: function(){},
21 | closed: function(){},
22 | bg : $('.reveal-modal-bg'),
23 | css : {
24 | open : {
25 | 'opacity': 0,
26 | 'visibility': 'visible',
27 | 'display' : 'block'
28 | },
29 | close : {
30 | 'opacity': 1,
31 | 'visibility': 'hidden',
32 | 'display': 'none'
33 | }
34 | }
35 | },
36 |
37 | init : function (scope, method, options) {
38 | Foundation.inherit(this, 'delay');
39 |
40 | this.bindings(method, options);
41 | },
42 |
43 | events : function (scope) {
44 | var self = this;
45 |
46 | $('[data-reveal-id]', this.scope)
47 | .off('.reveal')
48 | .on('click.fndtn.reveal', function (e) {
49 | e.preventDefault();
50 |
51 | if (!self.locked) {
52 | var element = $(this),
53 | ajax = element.data('reveal-ajax');
54 |
55 | self.locked = true;
56 |
57 | if (typeof ajax === 'undefined') {
58 | self.open.call(self, element);
59 | } else {
60 | var url = ajax === true ? element.attr('href') : ajax;
61 |
62 | self.open.call(self, element, {url: url});
63 | }
64 | }
65 | });
66 |
67 | $(this.scope)
68 | .off('.reveal')
69 | .on('click.fndtn.reveal', this.close_targets(), function (e) {
70 |
71 | e.preventDefault();
72 |
73 | if (!self.locked) {
74 | var settings = $('[data-reveal].open').data('reveal-init'),
75 | bg_clicked = $(e.target)[0] === $('.' + settings.bg_class)[0];
76 |
77 | if (bg_clicked && !settings.close_on_background_click) {
78 | return;
79 | }
80 |
81 | self.locked = true;
82 | self.close.call(self, bg_clicked ? $('[data-reveal].open') : $(this).closest('[data-reveal]'));
83 | }
84 | });
85 |
86 | if($('[data-reveal]', this.scope).length > 0) {
87 | $(this.scope)
88 | // .off('.reveal')
89 | .on('open.fndtn.reveal', this.settings.open)
90 | .on('opened.fndtn.reveal', this.settings.opened)
91 | .on('opened.fndtn.reveal', this.open_video)
92 | .on('close.fndtn.reveal', this.settings.close)
93 | .on('closed.fndtn.reveal', this.settings.closed)
94 | .on('closed.fndtn.reveal', this.close_video);
95 | } else {
96 | $(this.scope)
97 | // .off('.reveal')
98 | .on('open.fndtn.reveal', '[data-reveal]', this.settings.open)
99 | .on('opened.fndtn.reveal', '[data-reveal]', this.settings.opened)
100 | .on('opened.fndtn.reveal', '[data-reveal]', this.open_video)
101 | .on('close.fndtn.reveal', '[data-reveal]', this.settings.close)
102 | .on('closed.fndtn.reveal', '[data-reveal]', this.settings.closed)
103 | .on('closed.fndtn.reveal', '[data-reveal]', this.close_video);
104 | }
105 |
106 | $('body').on('keyup.fndtn.reveal', function ( event ) {
107 | var open_modal = $('[data-reveal].open'),
108 | settings = open_modal.data('reveal-init');
109 | if ( event.which === 27 && settings.close_on_esc) { // 27 is the keycode for the Escape key
110 | open_modal.foundation('reveal', 'close');
111 | }
112 | });
113 |
114 | return true;
115 | },
116 |
117 | open : function (target, ajax_settings) {
118 | if (target) {
119 | if (typeof target.selector !== 'undefined') {
120 | var modal = $('#' + target.data('reveal-id'));
121 | } else {
122 | var modal = $(this.scope);
123 |
124 | ajax_settings = target;
125 | }
126 | } else {
127 | var modal = $(this.scope);
128 | }
129 |
130 | if (!modal.hasClass('open')) {
131 | var open_modal = $('[data-reveal].open');
132 |
133 | if (typeof modal.data('css-top') === 'undefined') {
134 | modal.data('css-top', parseInt(modal.css('top'), 10))
135 | .data('offset', this.cache_offset(modal));
136 | }
137 |
138 | modal.trigger('open');
139 |
140 | if (open_modal.length < 1) {
141 | this.toggle_bg();
142 | }
143 |
144 | if (typeof ajax_settings === 'undefined' || !ajax_settings.url) {
145 | this.hide(open_modal, this.settings.css.close);
146 | this.show(modal, this.settings.css.open);
147 | } else {
148 | var self = this,
149 | old_success = typeof ajax_settings.success !== 'undefined' ? ajax_settings.success : null;
150 |
151 | $.extend(ajax_settings, {
152 | success: function (data, textStatus, jqXHR) {
153 | if ( $.isFunction(old_success) ) {
154 | old_success(data, textStatus, jqXHR);
155 | }
156 |
157 | modal.html(data);
158 | $(modal).foundation('section', 'reflow');
159 |
160 | self.hide(open_modal, self.settings.css.close);
161 | self.show(modal, self.settings.css.open);
162 | }
163 | });
164 |
165 | $.ajax(ajax_settings);
166 | }
167 | }
168 | },
169 |
170 | close : function (modal) {
171 |
172 | var modal = modal && modal.length ? modal : $(this.scope),
173 | open_modals = $('[data-reveal].open');
174 |
175 | if (open_modals.length > 0) {
176 | this.locked = true;
177 | modal.trigger('close');
178 | this.toggle_bg();
179 | this.hide(open_modals, this.settings.css.close);
180 | }
181 | },
182 |
183 | close_targets : function () {
184 | var base = '.' + this.settings.dismiss_modal_class;
185 |
186 | if (this.settings.close_on_background_click) {
187 | return base + ', .' + this.settings.bg_class;
188 | }
189 |
190 | return base;
191 | },
192 |
193 | toggle_bg : function () {
194 | if ($('.' + this.settings.bg_class).length === 0) {
195 | this.settings.bg = $('', {'class': this.settings.bg_class})
196 | .appendTo('body');
197 | }
198 |
199 | if (this.settings.bg.filter(':visible').length > 0) {
200 | this.hide(this.settings.bg);
201 | } else {
202 | this.show(this.settings.bg);
203 | }
204 | },
205 |
206 | show : function (el, css) {
207 | // is modal
208 | if (css) {
209 | if (el.parent('body').length === 0) {
210 | var placeholder = el.wrap('').parent();
211 | el.on('closed.fndtn.reveal.wrapped', function() {
212 | el.detach().appendTo(placeholder);
213 | el.unwrap().unbind('closed.fndtn.reveal.wrapped');
214 | });
215 |
216 | el.detach().appendTo('body');
217 | }
218 |
219 | if (/pop/i.test(this.settings.animation)) {
220 | css.top = $(window).scrollTop() - el.data('offset') + 'px';
221 | var end_css = {
222 | top: $(window).scrollTop() + el.data('css-top') + 'px',
223 | opacity: 1
224 | };
225 |
226 | return this.delay(function () {
227 | return el
228 | .css(css)
229 | .animate(end_css, this.settings.animation_speed, 'linear', function () {
230 | this.locked = false;
231 | el.trigger('opened');
232 | }.bind(this))
233 | .addClass('open');
234 | }.bind(this), this.settings.animation_speed / 2);
235 | }
236 |
237 | if (/fade/i.test(this.settings.animation)) {
238 | var end_css = {opacity: 1};
239 |
240 | return this.delay(function () {
241 | return el
242 | .css(css)
243 | .animate(end_css, this.settings.animation_speed, 'linear', function () {
244 | this.locked = false;
245 | el.trigger('opened');
246 | }.bind(this))
247 | .addClass('open');
248 | }.bind(this), this.settings.animation_speed / 2);
249 | }
250 |
251 | return el.css(css).show().css({opacity: 1}).addClass('open').trigger('opened');
252 | }
253 |
254 | // should we animate the background?
255 | if (/fade/i.test(this.settings.animation)) {
256 | return el.fadeIn(this.settings.animation_speed / 2);
257 | }
258 |
259 | return el.show();
260 | },
261 |
262 | hide : function (el, css) {
263 | // is modal
264 | if (css) {
265 | if (/pop/i.test(this.settings.animation)) {
266 | var end_css = {
267 | top: - $(window).scrollTop() - el.data('offset') + 'px',
268 | opacity: 0
269 | };
270 |
271 | return this.delay(function () {
272 | return el
273 | .animate(end_css, this.settings.animation_speed, 'linear', function () {
274 | this.locked = false;
275 | el.css(css).trigger('closed');
276 | }.bind(this))
277 | .removeClass('open');
278 | }.bind(this), this.settings.animation_speed / 2);
279 | }
280 |
281 | if (/fade/i.test(this.settings.animation)) {
282 | var end_css = {opacity: 0};
283 |
284 | return this.delay(function () {
285 | return el
286 | .animate(end_css, this.settings.animation_speed, 'linear', function () {
287 | this.locked = false;
288 | el.css(css).trigger('closed');
289 | }.bind(this))
290 | .removeClass('open');
291 | }.bind(this), this.settings.animation_speed / 2);
292 | }
293 |
294 | return el.hide().css(css).removeClass('open').trigger('closed');
295 | }
296 |
297 | // should we animate the background?
298 | if (/fade/i.test(this.settings.animation)) {
299 | return el.fadeOut(this.settings.animation_speed / 2);
300 | }
301 |
302 | return el.hide();
303 | },
304 |
305 | close_video : function (e) {
306 | var video = $(this).find('.flex-video'),
307 | iframe = video.find('iframe');
308 |
309 | if (iframe.length > 0) {
310 | iframe.attr('data-src', iframe[0].src);
311 | iframe.attr('src', 'about:blank');
312 | video.hide();
313 | }
314 | },
315 |
316 | open_video : function (e) {
317 | var video = $(this).find('.flex-video'),
318 | iframe = video.find('iframe');
319 |
320 | if (iframe.length > 0) {
321 | var data_src = iframe.attr('data-src');
322 | if (typeof data_src === 'string') {
323 | iframe[0].src = iframe.attr('data-src');
324 | } else {
325 | var src = iframe[0].src;
326 | iframe[0].src = undefined;
327 | iframe[0].src = src;
328 | }
329 | video.show();
330 | }
331 | },
332 |
333 | cache_offset : function (modal) {
334 | var offset = modal.show().height() + parseInt(modal.css('top'), 10);
335 |
336 | modal.hide();
337 |
338 | return offset;
339 | },
340 |
341 | off : function () {
342 | $(this.scope).off('.fndtn.reveal');
343 | },
344 |
345 | reflow : function () {}
346 | };
347 | }(jQuery, this, this.document));
348 |
--------------------------------------------------------------------------------
/App/Tests/functional/TestGuy.php:
--------------------------------------------------------------------------------
1 | scenario->runStep(new \Codeception\Step\Condition('amInPath', func_get_args()));
40 | }
41 |
42 |
43 | /**
44 | * [!] Method is generated. Documentation taken from corresponding module.
45 | *
46 | * Opens a file and stores it's content.
47 | *
48 | * Usage:
49 | *
50 | * ``` php
51 | * openFile('composer.json');
53 | * $I->seeInThisFile('codeception/codeception');
54 | * ?>
55 | * ```
56 | *
57 | * @param $filename
58 | * @see \Codeception\Module\Filesystem::openFile()
59 | */
60 | public function openFile($filename) {
61 | return $this->scenario->runStep(new \Codeception\Step\Action('openFile', func_get_args()));
62 | }
63 |
64 |
65 | /**
66 | * [!] Method is generated. Documentation taken from corresponding module.
67 | *
68 | * Deletes a file
69 | *
70 | * ``` php
71 | * deleteFile('composer.lock');
73 | * ?>
74 | * ```
75 | *
76 | * @param $filename
77 | * @see \Codeception\Module\Filesystem::deleteFile()
78 | */
79 | public function deleteFile($filename) {
80 | return $this->scenario->runStep(new \Codeception\Step\Action('deleteFile', func_get_args()));
81 | }
82 |
83 |
84 | /**
85 | * [!] Method is generated. Documentation taken from corresponding module.
86 | *
87 | * Deletes directory with all subdirectories
88 | *
89 | * ``` php
90 | * deleteDir('vendor');
92 | * ?>
93 | * ```
94 | *
95 | * @param $dirname
96 | * @see \Codeception\Module\Filesystem::deleteDir()
97 | */
98 | public function deleteDir($dirname) {
99 | return $this->scenario->runStep(new \Codeception\Step\Action('deleteDir', func_get_args()));
100 | }
101 |
102 |
103 | /**
104 | * [!] Method is generated. Documentation taken from corresponding module.
105 | *
106 | * Copies directory with all contents
107 | *
108 | * ``` php
109 | * copyDir('vendor','old_vendor');
111 | * ?>
112 | * ```
113 | *
114 | * @param $src
115 | * @param $dst
116 | * @see \Codeception\Module\Filesystem::copyDir()
117 | */
118 | public function copyDir($src, $dst) {
119 | return $this->scenario->runStep(new \Codeception\Step\Action('copyDir', func_get_args()));
120 | }
121 |
122 |
123 | /**
124 | * [!] Method is generated. Documentation taken from corresponding module.
125 | *
126 | * Checks If opened file has `text` in it.
127 | *
128 | * Usage:
129 | *
130 | * ``` php
131 | * openFile('composer.json');
133 | * $I->seeInThisFile('codeception/codeception');
134 | * ?>
135 | * ```
136 | *
137 | * @param $text
138 | * Conditional Assertion: Test won't be stopped on fail
139 | * @see \Codeception\Module\Filesystem::seeInThisFile()
140 | */
141 | public function canSeeInThisFile($text) {
142 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeInThisFile', func_get_args()));
143 | }
144 | /**
145 | * [!] Method is generated. Documentation taken from corresponding module.
146 | *
147 | * Checks If opened file has `text` in it.
148 | *
149 | * Usage:
150 | *
151 | * ``` php
152 | * openFile('composer.json');
154 | * $I->seeInThisFile('codeception/codeception');
155 | * ?>
156 | * ```
157 | *
158 | * @param $text
159 | * @see \Codeception\Module\Filesystem::seeInThisFile()
160 | */
161 | public function seeInThisFile($text) {
162 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeInThisFile', func_get_args()));
163 | }
164 |
165 |
166 | /**
167 | * [!] Method is generated. Documentation taken from corresponding module.
168 | *
169 | * Checks the strict matching of file contents.
170 | * Unlike `seeInThisFile` will fail if file has something more than expected lines.
171 | * Better to use with HEREDOC strings.
172 | * Matching is done after removing "\r" chars from file content.
173 | *
174 | * ``` php
175 | * openFile('process.pid');
177 | * $I->seeFileContentsEqual('3192');
178 | * ?>
179 | * ```
180 | *
181 | * @param $text
182 | * Conditional Assertion: Test won't be stopped on fail
183 | * @see \Codeception\Module\Filesystem::seeFileContentsEqual()
184 | */
185 | public function canSeeFileContentsEqual($text) {
186 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeFileContentsEqual', func_get_args()));
187 | }
188 | /**
189 | * [!] Method is generated. Documentation taken from corresponding module.
190 | *
191 | * Checks the strict matching of file contents.
192 | * Unlike `seeInThisFile` will fail if file has something more than expected lines.
193 | * Better to use with HEREDOC strings.
194 | * Matching is done after removing "\r" chars from file content.
195 | *
196 | * ``` php
197 | * openFile('process.pid');
199 | * $I->seeFileContentsEqual('3192');
200 | * ?>
201 | * ```
202 | *
203 | * @param $text
204 | * @see \Codeception\Module\Filesystem::seeFileContentsEqual()
205 | */
206 | public function seeFileContentsEqual($text) {
207 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeFileContentsEqual', func_get_args()));
208 | }
209 |
210 |
211 | /**
212 | * [!] Method is generated. Documentation taken from corresponding module.
213 | *
214 | * Checks If opened file doesn't contain `text` in it
215 | *
216 | * ``` php
217 | * openFile('composer.json');
219 | * $I->dontSeeInThisFile('codeception/codeception');
220 | * ?>
221 | * ```
222 | *
223 | * @param $text
224 | * Conditional Assertion: Test won't be stopped on fail
225 | * @see \Codeception\Module\Filesystem::dontSeeInThisFile()
226 | */
227 | public function cantSeeInThisFile($text) {
228 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInThisFile', func_get_args()));
229 | }
230 | /**
231 | * [!] Method is generated. Documentation taken from corresponding module.
232 | *
233 | * Checks If opened file doesn't contain `text` in it
234 | *
235 | * ``` php
236 | * openFile('composer.json');
238 | * $I->dontSeeInThisFile('codeception/codeception');
239 | * ?>
240 | * ```
241 | *
242 | * @param $text
243 | * @see \Codeception\Module\Filesystem::dontSeeInThisFile()
244 | */
245 | public function dontSeeInThisFile($text) {
246 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeInThisFile', func_get_args()));
247 | }
248 |
249 |
250 | /**
251 | * [!] Method is generated. Documentation taken from corresponding module.
252 | *
253 | * Deletes a file
254 | * @see \Codeception\Module\Filesystem::deleteThisFile()
255 | */
256 | public function deleteThisFile() {
257 | return $this->scenario->runStep(new \Codeception\Step\Action('deleteThisFile', func_get_args()));
258 | }
259 |
260 |
261 | /**
262 | * [!] Method is generated. Documentation taken from corresponding module.
263 | *
264 | * Checks if file exists in path.
265 | * Opens a file when it's exists
266 | *
267 | * ``` php
268 | * seeFileFound('UserModel.php','app/models');
270 | * ?>
271 | * ```
272 | *
273 | * @param $filename
274 | * @param string $path
275 | * Conditional Assertion: Test won't be stopped on fail
276 | * @see \Codeception\Module\Filesystem::seeFileFound()
277 | */
278 | public function canSeeFileFound($filename, $path = null) {
279 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeFileFound', func_get_args()));
280 | }
281 | /**
282 | * [!] Method is generated. Documentation taken from corresponding module.
283 | *
284 | * Checks if file exists in path.
285 | * Opens a file when it's exists
286 | *
287 | * ``` php
288 | * seeFileFound('UserModel.php','app/models');
290 | * ?>
291 | * ```
292 | *
293 | * @param $filename
294 | * @param string $path
295 | * @see \Codeception\Module\Filesystem::seeFileFound()
296 | */
297 | public function seeFileFound($filename, $path = null) {
298 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeFileFound', func_get_args()));
299 | }
300 |
301 |
302 | /**
303 | * [!] Method is generated. Documentation taken from corresponding module.
304 | *
305 | * Checks if file does not exists in path
306 | *
307 | * @param $filename
308 | * @param string $path
309 | * Conditional Assertion: Test won't be stopped on fail
310 | * @see \Codeception\Module\Filesystem::dontSeeFileFound()
311 | */
312 | public function cantSeeFileFound($filename, $path = null) {
313 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeFileFound', func_get_args()));
314 | }
315 | /**
316 | * [!] Method is generated. Documentation taken from corresponding module.
317 | *
318 | * Checks if file does not exists in path
319 | *
320 | * @param $filename
321 | * @param string $path
322 | * @see \Codeception\Module\Filesystem::dontSeeFileFound()
323 | */
324 | public function dontSeeFileFound($filename, $path = null) {
325 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeFileFound', func_get_args()));
326 | }
327 |
328 |
329 | /**
330 | * [!] Method is generated. Documentation taken from corresponding module.
331 | *
332 | * Erases directory contents
333 | *
334 | * ``` php
335 | * cleanDir('logs');
337 | * ?>
338 | * ```
339 | *
340 | * @param $dirname
341 | * @see \Codeception\Module\Filesystem::cleanDir()
342 | */
343 | public function cleanDir($dirname) {
344 | return $this->scenario->runStep(new \Codeception\Step\Action('cleanDir', func_get_args()));
345 | }
346 |
347 |
348 | /**
349 | * [!] Method is generated. Documentation taken from corresponding module.
350 | *
351 | * Saves contents to file
352 | *
353 | * @param $filename
354 | * @param $contents
355 | * @see \Codeception\Module\Filesystem::writeToFile()
356 | */
357 | public function writeToFile($filename, $contents) {
358 | return $this->scenario->runStep(new \Codeception\Step\Action('writeToFile', func_get_args()));
359 | }
360 | }
361 |
--------------------------------------------------------------------------------
/App/Tests/_helpers/_generated/TestGuyActions.php:
--------------------------------------------------------------------------------
1 | getScenario()->runStep(new \Codeception\Step\Condition('amInPath', func_get_args()));
30 | }
31 |
32 |
33 | /**
34 | * [!] Method is generated. Documentation taken from corresponding module.
35 | *
36 | * Opens a file and stores it's content.
37 | *
38 | * Usage:
39 | *
40 | * ``` php
41 | * openFile('composer.json');
43 | * $I->seeInThisFile('codeception/codeception');
44 | * ?>
45 | * ```
46 | *
47 | * @param $filename
48 | * @see \Codeception\Module\Filesystem::openFile()
49 | */
50 | public function openFile($filename) {
51 | return $this->getScenario()->runStep(new \Codeception\Step\Action('openFile', func_get_args()));
52 | }
53 |
54 |
55 | /**
56 | * [!] Method is generated. Documentation taken from corresponding module.
57 | *
58 | * Deletes a file
59 | *
60 | * ``` php
61 | * deleteFile('composer.lock');
63 | * ?>
64 | * ```
65 | *
66 | * @param $filename
67 | * @see \Codeception\Module\Filesystem::deleteFile()
68 | */
69 | public function deleteFile($filename) {
70 | return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteFile', func_get_args()));
71 | }
72 |
73 |
74 | /**
75 | * [!] Method is generated. Documentation taken from corresponding module.
76 | *
77 | * Deletes directory with all subdirectories
78 | *
79 | * ``` php
80 | * deleteDir('vendor');
82 | * ?>
83 | * ```
84 | *
85 | * @param $dirname
86 | * @see \Codeception\Module\Filesystem::deleteDir()
87 | */
88 | public function deleteDir($dirname) {
89 | return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteDir', func_get_args()));
90 | }
91 |
92 |
93 | /**
94 | * [!] Method is generated. Documentation taken from corresponding module.
95 | *
96 | * Copies directory with all contents
97 | *
98 | * ``` php
99 | * copyDir('vendor','old_vendor');
101 | * ?>
102 | * ```
103 | *
104 | * @param $src
105 | * @param $dst
106 | * @see \Codeception\Module\Filesystem::copyDir()
107 | */
108 | public function copyDir($src, $dst) {
109 | return $this->getScenario()->runStep(new \Codeception\Step\Action('copyDir', func_get_args()));
110 | }
111 |
112 |
113 | /**
114 | * [!] Method is generated. Documentation taken from corresponding module.
115 | *
116 | * Checks If opened file has `text` in it.
117 | *
118 | * Usage:
119 | *
120 | * ``` php
121 | * openFile('composer.json');
123 | * $I->seeInThisFile('codeception/codeception');
124 | * ?>
125 | * ```
126 | *
127 | * @param $text
128 | * Conditional Assertion: Test won't be stopped on fail
129 | * @see \Codeception\Module\Filesystem::seeInThisFile()
130 | */
131 | public function canSeeInThisFile($text) {
132 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInThisFile', func_get_args()));
133 | }
134 | /**
135 | * [!] Method is generated. Documentation taken from corresponding module.
136 | *
137 | * Checks If opened file has `text` in it.
138 | *
139 | * Usage:
140 | *
141 | * ``` php
142 | * openFile('composer.json');
144 | * $I->seeInThisFile('codeception/codeception');
145 | * ?>
146 | * ```
147 | *
148 | * @param $text
149 | * @see \Codeception\Module\Filesystem::seeInThisFile()
150 | */
151 | public function seeInThisFile($text) {
152 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInThisFile', func_get_args()));
153 | }
154 |
155 |
156 | /**
157 | * [!] Method is generated. Documentation taken from corresponding module.
158 | *
159 | * Checks If opened file has the `number` of new lines.
160 | *
161 | * Usage:
162 | *
163 | * ``` php
164 | * openFile('composer.json');
166 | * $I->seeNumberNewLines(5);
167 | * ?>
168 | * ```
169 | *
170 | * @param int $number New lines
171 | * Conditional Assertion: Test won't be stopped on fail
172 | * @see \Codeception\Module\Filesystem::seeNumberNewLines()
173 | */
174 | public function canSeeNumberNewLines($number) {
175 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberNewLines', func_get_args()));
176 | }
177 | /**
178 | * [!] Method is generated. Documentation taken from corresponding module.
179 | *
180 | * Checks If opened file has the `number` of new lines.
181 | *
182 | * Usage:
183 | *
184 | * ``` php
185 | * openFile('composer.json');
187 | * $I->seeNumberNewLines(5);
188 | * ?>
189 | * ```
190 | *
191 | * @param int $number New lines
192 | * @see \Codeception\Module\Filesystem::seeNumberNewLines()
193 | */
194 | public function seeNumberNewLines($number) {
195 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumberNewLines', func_get_args()));
196 | }
197 |
198 |
199 | /**
200 | * [!] Method is generated. Documentation taken from corresponding module.
201 | *
202 | * Checks the strict matching of file contents.
203 | * Unlike `seeInThisFile` will fail if file has something more than expected lines.
204 | * Better to use with HEREDOC strings.
205 | * Matching is done after removing "\r" chars from file content.
206 | *
207 | * ``` php
208 | * openFile('process.pid');
210 | * $I->seeFileContentsEqual('3192');
211 | * ?>
212 | * ```
213 | *
214 | * @param $text
215 | * Conditional Assertion: Test won't be stopped on fail
216 | * @see \Codeception\Module\Filesystem::seeFileContentsEqual()
217 | */
218 | public function canSeeFileContentsEqual($text) {
219 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeFileContentsEqual', func_get_args()));
220 | }
221 | /**
222 | * [!] Method is generated. Documentation taken from corresponding module.
223 | *
224 | * Checks the strict matching of file contents.
225 | * Unlike `seeInThisFile` will fail if file has something more than expected lines.
226 | * Better to use with HEREDOC strings.
227 | * Matching is done after removing "\r" chars from file content.
228 | *
229 | * ``` php
230 | * openFile('process.pid');
232 | * $I->seeFileContentsEqual('3192');
233 | * ?>
234 | * ```
235 | *
236 | * @param $text
237 | * @see \Codeception\Module\Filesystem::seeFileContentsEqual()
238 | */
239 | public function seeFileContentsEqual($text) {
240 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeFileContentsEqual', func_get_args()));
241 | }
242 |
243 |
244 | /**
245 | * [!] Method is generated. Documentation taken from corresponding module.
246 | *
247 | * Checks If opened file doesn't contain `text` in it
248 | *
249 | * ``` php
250 | * openFile('composer.json');
252 | * $I->dontSeeInThisFile('codeception/codeception');
253 | * ?>
254 | * ```
255 | *
256 | * @param $text
257 | * Conditional Assertion: Test won't be stopped on fail
258 | * @see \Codeception\Module\Filesystem::dontSeeInThisFile()
259 | */
260 | public function cantSeeInThisFile($text) {
261 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInThisFile', func_get_args()));
262 | }
263 | /**
264 | * [!] Method is generated. Documentation taken from corresponding module.
265 | *
266 | * Checks If opened file doesn't contain `text` in it
267 | *
268 | * ``` php
269 | * openFile('composer.json');
271 | * $I->dontSeeInThisFile('codeception/codeception');
272 | * ?>
273 | * ```
274 | *
275 | * @param $text
276 | * @see \Codeception\Module\Filesystem::dontSeeInThisFile()
277 | */
278 | public function dontSeeInThisFile($text) {
279 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInThisFile', func_get_args()));
280 | }
281 |
282 |
283 | /**
284 | * [!] Method is generated. Documentation taken from corresponding module.
285 | *
286 | * Deletes a file
287 | * @see \Codeception\Module\Filesystem::deleteThisFile()
288 | */
289 | public function deleteThisFile() {
290 | return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteThisFile', func_get_args()));
291 | }
292 |
293 |
294 | /**
295 | * [!] Method is generated. Documentation taken from corresponding module.
296 | *
297 | * Checks if file exists in path.
298 | * Opens a file when it's exists
299 | *
300 | * ``` php
301 | * seeFileFound('UserModel.php','app/models');
303 | * ?>
304 | * ```
305 | *
306 | * @param $filename
307 | * @param string $path
308 | * Conditional Assertion: Test won't be stopped on fail
309 | * @see \Codeception\Module\Filesystem::seeFileFound()
310 | */
311 | public function canSeeFileFound($filename, $path = null) {
312 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeFileFound', func_get_args()));
313 | }
314 | /**
315 | * [!] Method is generated. Documentation taken from corresponding module.
316 | *
317 | * Checks if file exists in path.
318 | * Opens a file when it's exists
319 | *
320 | * ``` php
321 | * seeFileFound('UserModel.php','app/models');
323 | * ?>
324 | * ```
325 | *
326 | * @param $filename
327 | * @param string $path
328 | * @see \Codeception\Module\Filesystem::seeFileFound()
329 | */
330 | public function seeFileFound($filename, $path = null) {
331 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeFileFound', func_get_args()));
332 | }
333 |
334 |
335 | /**
336 | * [!] Method is generated. Documentation taken from corresponding module.
337 | *
338 | * Checks if file does not exist in path
339 | *
340 | * @param $filename
341 | * @param string $path
342 | * Conditional Assertion: Test won't be stopped on fail
343 | * @see \Codeception\Module\Filesystem::dontSeeFileFound()
344 | */
345 | public function cantSeeFileFound($filename, $path = null) {
346 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeFileFound', func_get_args()));
347 | }
348 | /**
349 | * [!] Method is generated. Documentation taken from corresponding module.
350 | *
351 | * Checks if file does not exist in path
352 | *
353 | * @param $filename
354 | * @param string $path
355 | * @see \Codeception\Module\Filesystem::dontSeeFileFound()
356 | */
357 | public function dontSeeFileFound($filename, $path = null) {
358 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeFileFound', func_get_args()));
359 | }
360 |
361 |
362 | /**
363 | * [!] Method is generated. Documentation taken from corresponding module.
364 | *
365 | * Erases directory contents
366 | *
367 | * ``` php
368 | * cleanDir('logs');
370 | * ?>
371 | * ```
372 | *
373 | * @param $dirname
374 | * @see \Codeception\Module\Filesystem::cleanDir()
375 | */
376 | public function cleanDir($dirname) {
377 | return $this->getScenario()->runStep(new \Codeception\Step\Action('cleanDir', func_get_args()));
378 | }
379 |
380 |
381 | /**
382 | * [!] Method is generated. Documentation taken from corresponding module.
383 | *
384 | * Saves contents to file
385 | *
386 | * @param $filename
387 | * @param $contents
388 | * @see \Codeception\Module\Filesystem::writeToFile()
389 | */
390 | public function writeToFile($filename, $contents) {
391 | return $this->getScenario()->runStep(new \Codeception\Step\Action('writeToFile', func_get_args()));
392 | }
393 | }
394 |
--------------------------------------------------------------------------------