Completed
Pull Request — 3.7 (#8434)
by Sam
08:55
created

CmsFormsContext::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 27 and the first side effect is on line 19.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
namespace SilverStripe\Framework\Test\Behaviour;
4
5
use Behat\Behat\Context\ClosuredContextInterface,
6
	Behat\Behat\Context\TranslatedContextInterface,
7
	Behat\Behat\Context\BehatContext,
8
	Behat\Behat\Context\Step,
9
	Behat\Behat\Exception\PendingException,
10
	Behat\Mink\Exception\ElementHtmlException,
11
	Behat\Gherkin\Node\PyStringNode,
12
	Behat\Gherkin\Node\TableNode,
13
	Behat\MinkExtension\Context\MinkContext as MinkContext;
14
15
use Behat\Mink\Element\NodeElement;
16
use Symfony\Component\DomCrawler\Crawler;
17
18
// PHPUnit
19
require_once 'PHPUnit/Autoload.php';
20
require_once 'PHPUnit/Framework/Assert/Functions.php';
21
22
/**
23
 * CmsFormsContext
24
 *
25
 * Context used to define steps related to forms inside CMS.
26
 */
27
class CmsFormsContext extends BehatContext {
28
	protected $context;
29
30
	/**
31
	 * Initializes context.
32
	 * Every scenario gets it's own context object.
33
	 *
34
	 * @param   array   $parameters     context parameters (set them up through behat.yml)
35
	 */
36
	public function __construct(array $parameters) {
37
		// Initialize your context here
38
		$this->context = $parameters;
39
	}
40
41
	/**
42
	 * Get Mink session from MinkContext
43
	 */
44
	public function getSession($name = null) {
45
		return $this->getMainContext()->getSession($name);
46
	}
47
48
	/**
49
	 * Returns fixed step argument (with \\" replaced back to ").
50
	 * Copied from {@see MinkContext}
51
	 *
52
	 * @param string $argument
53
	 * @return string
54
	 */
55
	protected function fixStepArgument($argument) {
56
		return str_replace('\\"', '"', $argument);
57
	}
58
59
	/**
60
	 * @Then /^I should( not? |\s*)see an edit page form$/
61
	 */
62
	public function stepIShouldSeeAnEditPageForm($negative) {
63
		$page = $this->getSession()->getPage();
64
65
		$form = $page->find('css', '#Form_EditForm');
66
		if(trim($negative)) {
67
			assertNull($form, 'I should not see an edit page form');
68
		} else {
69
			assertNotNull($form, 'I should see an edit page form');
70
		}
71
	}
72
73
	/**
74
	 * @When /^I fill in the "(?P<field>(?:[^"]|\\")*)" HTML field with "(?P<value>(?:[^"]|\\")*)"$/
75
	 * @When /^I fill in "(?P<value>(?:[^"]|\\")*)" for the "(?P<field>(?:[^"]|\\")*)" HTML field$/
76
	 */
77
	public function stepIFillInTheHtmlFieldWith($field, $value) {
78
		$inputField = $this->getHtmlField($field);
79
		$value = $this->fixStepArgument($value);
80
81
		$this->getSession()->evaluateScript(sprintf(
82
			"jQuery('#%s').entwine('ss').getEditor().setContent('%s')",
83
			$inputField->getAttribute('id'),
84
			addcslashes($value, "'")
85
		));
86
	}
87
88
	/**
89
	 * @When /^I append "(?P<value>(?:[^"]|\\")*)" to the "(?P<field>(?:[^"]|\\")*)" HTML field$/
90
	 */
91
	public function stepIAppendTotheHtmlField($field, $value) {
92
		$inputField = $this->getHtmlField($field);
93
		$value = $this->fixStepArgument($value);
94
95
		$this->getSession()->evaluateScript(sprintf(
96
			"jQuery('#%s').entwine('ss').getEditor().insertContent('%s')",
97
			$inputField->getAttribute('id'),
98
			addcslashes($value, "'")
99
		));
100
	}
101
102
	/**
103
	 * @Then /^the "(?P<locator>(?:[^"]|\\")*)" HTML field should(?P<negative> not? |\s*)contain (["\/]?P<html>.*)["\/]$/
104
	 */
105
	public function theHtmlFieldShouldContain($locator, $negative, $html) {
106
		// Allow both regex and string literal input
107
		$stringType = $html[0];
108
		$html = substr($html, 1);
109
		if ($stringType === '/') {
110
			$regex = '/' . $html . '/ui';
111
		} else {
112
			$regex = '/'.preg_quote($html, '/').'/ui';
113
		}
114
115
		$element = $this->getHtmlField($locator);
116
		$actual = $element->getValue();
117
		$failed = false;
118
119
		if(trim($negative)) {
120
			if (preg_match($regex, $actual)) {
121
				$failed = true;
122
			}
123
		} else {
124
			if (!preg_match($regex, $actual)) {
125
				$failed = true;
126
			}
127
		}
128
129
		if($failed) {
130
			$message = sprintf(
131
				'The string "%s" should%sbe found in the HTML of the element matching name "%s". Actual content: "%s"',
132
				$html,
133
				$negative,
134
				$locator,
135
				$actual
136
			);
137
			throw new ElementHtmlException($message, $this->getSession(), $element);
138
		}
139
	}
140
141
	// @codingStandardsIgnoreStart
142
	/**
143
	 * Checks formatting in the HTML field, by analyzing the HTML node surrounding
144
	 * the text for certain properties.
145
	 *
146
	 * Example: Given "my text" in the "Content" HTML field should be right aligned
147
	 * Example: Given "my text" in the "Content" HTML field should not be bold
148
	 *
149
	 * @todo Use an actual DOM parser for more accurate assertions
150
	 *
151
	 * @Given /^"(?P<text>([^"]*))" in the "(?P<field>(?:[^"]|\\")*)" HTML field should(?P<negate>(?: not)?) be (?P<formatting>(.*))$/
152
	 */
153
	public function stepContentInHtmlFieldShouldHaveFormatting($text, $field, $negate, $formatting) {
154
		$inputField = $this->getHtmlField($field);
155
156
		$crawler = new Crawler($inputField->getValue());
157
		$matchedNode = null;
158
		foreach($crawler->filterXPath('//*') as $node) {
159
			if(
160
				$node->firstChild
161
				&& $node->firstChild->nodeType == XML_TEXT_NODE
162
				&& stripos($node->firstChild->nodeValue, $text) !== FALSE
163
			) {
164
				$matchedNode = $node;
165
			}
166
		}
167
		assertNotNull($matchedNode);
168
169
		$assertFn = $negate ? 'assertNotEquals' : 'assertEquals';
170
		if($formatting == 'bold') {
171
			call_user_func($assertFn, 'strong', $matchedNode->nodeName);
172
		} else if($formatting == 'left aligned') {
173
			if($matchedNode->getAttribute('style')) {
174
				call_user_func($assertFn, 'text-align: left;', $matchedNode->getAttribute('style'));
175
			}
176
		} else if($formatting == 'right aligned') {
177
			call_user_func($assertFn, 'text-align: right;', $matchedNode->getAttribute('style'));
178
		}
179
	}
180
	// @codingStandardsIgnoreEnd
181
182
	/**
183
	 * Selects the first textual match in the HTML editor. Does not support
184
	 * selection across DOM node boundaries.
185
	 *
186
	 * @When /^I select "(?P<text>([^"]*))" in the "(?P<field>(?:[^"]|\\")*)" HTML field$/
187
	 */
188
	public function stepIHighlightTextInHtmlField($text, $field) {
189
		$inputField = $this->getHtmlField($field);
190
		$inputFieldId = $inputField->getAttribute('id');
191
		$text = addcslashes($text, "'");
192
193
		$js = <<<JS
194
// TODO <IE9 support
195
// TODO Allow text matches across nodes
196
var editor = jQuery('#$inputFieldId').entwine('ss').getEditor(),
197
	doc = editor.getDOM().doc,
198
	sel = editor.getInstance().selection,
199
	rng = document.createRange(),
200
	matched = false;
201
202
jQuery(doc).find('body *').each(function() {
203
	if(!matched) {
204
		for(var i=0;i<this.childNodes.length;i++) {
205
			if(!matched && this.childNodes[i].nodeValue && this.childNodes[i].nodeValue.match('$text')) {
206
				rng.setStart(this.childNodes[i], this.childNodes[i].nodeValue.indexOf('$text'));
207
				rng.setEnd(this.childNodes[i], this.childNodes[i].nodeValue.indexOf('$text') + '$text'.length);
208
				sel.setRng(rng);
209
				editor.getInstance().nodeChanged();
210
				matched = true;
211
				break;
212
			}
213
		}
214
	}
215
});
216
JS;
217
218
		$this->getSession()->executeScript($js);
219
	}
220
221
	/**
222
	 * Example: I should see a "Submit" button
223
	 * Example: I should not see a "Delete" button
224
	 *
225
	 * @Given /^I should( not? |\s*)see a "([^"]*)" button$/
226
	 */
227
	public function iShouldSeeAButton($negative, $text) {
228
		$page = $this->getSession()->getPage();
229
		$els = $page->findAll('named', array('link_or_button', "'$text'"));
230
		$matchedEl = null;
231
		foreach($els as $el) {
232
			if($el->isVisible()) $matchedEl = $el;
233
		}
234
235
		if(trim($negative)) {
236
			assertNull($matchedEl, sprintf('%s button found', $text));
237
		} else {
238
			assertNotNull($matchedEl, sprintf('%s button not found', $text));
239
		}
240
	}
241
242
	/**
243
	 * @Given /^I should( not? |\s*)see a "([^"]*)" field$/
244
	 */
245
	public function iShouldSeeAField($negative, $text) {
246
		$page = $this->getSession()->getPage();
247
		$els = $page->findAll('named', array('field', "'$text'"));
248
		$matchedEl = null;
249
		foreach($els as $el) {
250
			if($el->isVisible()) $matchedEl = $el;
251
		}
252
253
		if(trim($negative)) {
254
			assertNull($matchedEl);
255
		} else {
256
			assertNotNull($matchedEl);
257
		}
258
	}
259
260
	/**
261
	 * @example Given the CMS settings has the following data
262
	 *	| Title | My site title |
263
	 *	| Theme | My site theme |
264
	 * @Given /^the CMS settings have the following data$/
265
	 */
266
	public function theCmsSettingsHasData(TableNode $fieldsTable) {
267
		$fields = $fieldsTable->getRowsHash();
268
		$siteConfig = \SiteConfig::get()->first();
269
		foreach($fields as $field => $value) {
270
			$siteConfig->$field = $value;
271
		}
272
		$siteConfig->write();
273
		$siteConfig->flushCache();
274
	}
275
276
	/**
277
	 * Locate an HTML editor field
278
	 *
279
	 * @param string $locator Raw html field identifier as passed from
280
	 * @return NodeElement
281
	 */
282
	protected function getHtmlField($locator)
283
	{
284
		$locator = $this->fixStepArgument($locator);
285
		$page = $this->getSession()->getPage();
286
		$element = $page->find('css', 'textarea.htmleditor[name=\'' . $locator . '\']');
287
		assertNotNull($element, sprintf('HTML field "%s" not found', $locator));
288
		return $element;
289
	}
290
291
}
292