Completed
Push — master ( 9dff7e...a05958 )
by Sam
07:31
created

CmsFormsContext::theCmsSettingsHasData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Framework\Tests\Behaviour;
4
5
use Behat\Behat\Context\Context;
6
use Behat\Mink\Exception\ElementHtmlException;
7
use Behat\Gherkin\Node\TableNode;
8
use SilverStripe\BehatExtension\Context\MainContextAwareTrait;
9
use Symfony\Component\DomCrawler\Crawler;
10
use Behat\Mink\Element\NodeElement;
11
use SilverStripe\SiteConfig\SiteConfig;
12
13
/**
14
 * CmsFormsContext
15
 *
16
 * Context used to define steps related to forms inside CMS.
17
 */
18
class CmsFormsContext implements Context
19
{
20
    use MainContextAwareTrait;
21
22
    /**
23
     * Get Mink session from MinkContext
24
     */
25
    public function getSession($name = null)
26
    {
27
        return $this->getMainContext()->getSession($name);
28
    }
29
30
    /**
31
     * Returns fixed step argument (with \\" replaced back to ").
32
     * Copied from {@see MinkContext}
33
     *
34
     * @param string $argument
35
     * @return string
36
     */
37
    protected function fixStepArgument($argument)
38
    {
39
        return str_replace('\\"', '"', $argument);
40
    }
41
42
    /**
43
     * @Then /^I should( not? |\s*)see an edit page form$/
44
     */
45
    public function stepIShouldSeeAnEditPageForm($negative)
46
    {
47
        $page = $this->getSession()->getPage();
48
49
        $form = $page->find('css', '#Form_EditForm');
50
        if (trim($negative)) {
51
            assertNull($form, 'I should not see an edit page form');
52
        } else {
53
            assertNotNull($form, 'I should see an edit page form');
54
        }
55
    }
56
57
    /**
58
     * @When /^I fill in the "(?P<field>(?:[^"]|\\")*)" HTML field with "(?P<value>(?:[^"]|\\")*)"$/
59
     * @When /^I fill in "(?P<value>(?:[^"]|\\")*)" for the "(?P<field>(?:[^"]|\\")*)" HTML field$/
60
     */
61
    public function stepIFillInTheHtmlFieldWith($field, $value)
62
    {
63
        $inputField = $this->getHtmlField($field);
64
        $value = $this->fixStepArgument($value);
65
66
        $this->getSession()->evaluateScript(sprintf(
67
            "jQuery('#%s').entwine('ss').getEditor().setContent('%s')",
68
            $inputField->getAttribute('id'),
69
            addcslashes($value, "'")
70
        ));
71
    }
72
73
    /**
74
     * @When /^I append "(?P<value>(?:[^"]|\\")*)" to the "(?P<field>(?:[^"]|\\")*)" HTML field$/
75
     */
76
    public function stepIAppendTotheHtmlField($field, $value)
77
    {
78
        $inputField = $this->getHtmlField($field);
79
        $value = $this->fixStepArgument($value);
80
81
        $this->getSession()->evaluateScript(sprintf(
82
            "jQuery('#%s').entwine('ss').getEditor().insertContent('%s')",
83
            $inputField->getAttribute('id'),
84
            addcslashes($value, "'")
85
        ));
86
    }
87
88
    /**
89
     * @Then /^the "(?P<locator>(?:[^"]|\\")*)" HTML field should(?P<negative> not? |\s*)contain "(?P<html>.*)"$/
90
     */
91
    public function theHtmlFieldShouldContain($locator, $negative, $html)
92
    {
93
        $element = $this->getHtmlField($locator);
94
        $actual = $element->getValue();
95
        $regex = '/'.preg_quote($html, '/').'/ui';
96
        $failed = false;
97
98
        if (trim($negative)) {
99
            if (preg_match($regex, $actual)) {
100
                $failed = true;
101
            }
102
        } else {
103
            if (!preg_match($regex, $actual)) {
104
                $failed = true;
105
            }
106
        }
107
108
        if ($failed) {
109
            $message = sprintf(
110
                'The string "%s" should%sbe found in the HTML of the element matching name "%s". Actual content: "%s"',
111
                $html,
112
                $negative,
113
                $locator,
114
                $actual
115
            );
116
            throw new ElementHtmlException($message, $this->getSession(), $element);
0 ignored issues
show
Bug introduced by
It seems like $element defined by $this->getHtmlField($locator) on line 93 can be null; however, Behat\Mink\Exception\Ele...xception::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
117
        }
118
    }
119
120
	// @codingStandardsIgnoreStart
121
	/**
122
	 * Checks formatting in the HTML field, by analyzing the HTML node surrounding
123
	 * the text for certain properties.
124
	 *
125
	 * Example: Given "my text" in the "Content" HTML field should be right aligned
126
	 * Example: Given "my text" in the "Content" HTML field should not be bold
127
	 *
128
	 * @todo Use an actual DOM parser for more accurate assertions
129
	 *
130
	 * @Given /^"(?P<text>([^"]*))" in the "(?P<field>(?:[^"]|\\")*)" HTML field should(?P<negate>(?: not)?) be (?P<formatting>(.*))$/
131
	 */
132
	public function stepContentInHtmlFieldShouldHaveFormatting($text, $field, $negate, $formatting) {
133
		$inputField = $this->getHtmlField($field);
134
135
		$crawler = new Crawler($inputField->getValue());
136
		$matchedNode = null;
137
		foreach($crawler->filterXPath('//*') as $node) {
138
			if(
139
				$node->firstChild
140
				&& $node->firstChild->nodeType == XML_TEXT_NODE
141
				&& stripos($node->firstChild->nodeValue, $text) !== FALSE
142
			) {
143
				$matchedNode = $node;
144
			}
145
		}
146
		assertNotNull($matchedNode);
147
148
		$assertFn = $negate ? 'assertNotEquals' : 'assertEquals';
149
		if($formatting == 'bold') {
150
			call_user_func($assertFn, 'strong', $matchedNode->nodeName);
151
		} else if($formatting == 'left aligned') {
152
			if($matchedNode->getAttribute('style')) {
153
				call_user_func($assertFn, 'text-align: left;', $matchedNode->getAttribute('style'));
154
			}
155
		} else if($formatting == 'right aligned') {
156
			call_user_func($assertFn, 'text-align: right;', $matchedNode->getAttribute('style'));
157
		}
158
	}
159
	// @codingStandardsIgnoreEnd
160
161
    /**
162
     * Selects the first textual match in the HTML editor. Does not support
163
     * selection across DOM node boundaries.
164
     *
165
     * @When /^I select "(?P<text>([^"]*))" in the "(?P<field>(?:[^"]|\\")*)" HTML field$/
166
     */
167
    public function stepIHighlightTextInHtmlField($text, $field)
168
    {
169
        $inputField = $this->getHtmlField($field);
170
        $inputFieldId = $inputField->getAttribute('id');
171
        $text = addcslashes($text, "'");
172
173
        $js = <<<JS
174
// TODO <IE9 support
175
// TODO Allow text matches across nodes
176
var editor = jQuery('#$inputFieldId').entwine('ss').getEditor(),
177
	doc = editor.getInstance().getDoc(),
178
	sel = editor.getInstance().selection,
179
	rng = document.createRange(),
180
	matched = false;
181
182
jQuery(doc).find('body *').each(function() {
183
	if(!matched) {
184
		for(var i=0;i<this.childNodes.length;i++) {
185
			if(!matched && this.childNodes[i].nodeValue && this.childNodes[i].nodeValue.match('$text')) {
186
				rng.setStart(this.childNodes[i], this.childNodes[i].nodeValue.indexOf('$text'));
187
				rng.setEnd(this.childNodes[i], this.childNodes[i].nodeValue.indexOf('$text') + '$text'.length);
188
				sel.setRng(rng);
189
				editor.getInstance().nodeChanged();
190
				matched = true;
191
				break;
192
			}
193
		}
194
	}
195
});
196
JS;
197
198
        $this->getSession()->executeScript($js);
199
    }
200
201
    /**
202
     * @Given /^I should( not? |\s*)see a "([^"]*)" field$/
203
     */
204
    public function iShouldSeeAField($negative, $text)
205
    {
206
        $page = $this->getSession()->getPage();
207
        $els = $page->findAll('named', array('field', "'$text'"));
208
        $matchedEl = null;
209
        foreach ($els as $el) {
210
            if ($el->isVisible()) {
211
                $matchedEl = $el;
212
            }
213
        }
214
215
        if (trim($negative)) {
216
            assertNull($matchedEl);
217
        } else {
218
            assertNotNull($matchedEl);
219
        }
220
    }
221
222
    /**
223
     * Click on the element with the provided CSS Selector
224
     *
225
     * @When /^I press the "([^"]*)" HTML field button$/
226
     */
227
    public function iClickOnTheHtmlFieldButton($button)
228
    {
229
        $xpath = "//*[@aria-label='".$button."']";
230
        $session = $this->getSession();
231
        $element = $session->getPage()->find('xpath', $xpath);
232
        if (null === $element) {
233
            throw new \InvalidArgumentException(sprintf('Could not find element with xpath %s', $xpath));
234
        }
235
236
        $element->click();
237
    }
238
239
    /*
240
	 * @example Given the CMS settings has the following data
241
	 *	| Title | My site title |
242
	 *	| Theme | My site theme |
243
	 * @Given /^the CMS settings have the following data$/
244
	 */
245
    public function theCmsSettingsHasData(TableNode $fieldsTable)
246
    {
247
        $fields = $fieldsTable->getRowsHash();
248
        $siteConfig = SiteConfig::get()->first();
249
        foreach ($fields as $field => $value) {
250
            $siteConfig->$field = $value;
251
        }
252
        $siteConfig->write();
253
        $siteConfig->flushCache();
254
    }
255
256
    /**
257
     * Locate an HTML editor field
258
     *
259
     * @param string $locator Raw html field identifier as passed from
260
     * @return NodeElement
261
     */
262
    protected function getHtmlField($locator)
263
    {
264
        $locator = $this->fixStepArgument($locator);
265
        $page = $this->getSession()->getPage();
266
        $element = $page->find('css', 'textarea.htmleditor[name=\'' . $locator . '\']');
267
        assertNotNull($element, sprintf('HTML field "%s" not found', $locator));
268
        return $element;
269
    }
270
}
271