Completed
Pull Request — 3.4 (#6410)
by Damian
07:06
created

HtmlEditorFieldTest   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 179
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 0
Metric Value
dl 0
loc 179
rs 10
c 0
b 0
f 0
wmc 11
lcom 1
cbo 12

10 Methods

Rating   Name   Duplication   Size   Complexity  
A testCasting() 0 13 1
A testBasicSaving() 0 12 1
A testNullSaving() 0 8 1
A testImageInsertion() 0 21 1
B testResizedImageInsertion() 0 36 1
A testMultiLineSaving() 0 7 1
A testSavingLinksWithoutHref() 0 11 1
B testGetAnchors() 0 35 2
A testHtmlEditorFieldFileLocal() 0 7 1
A testHtmlEditorFieldFileRemote() 0 7 1
1
<?php
2
/**
3
 * @package framework
4
 * @subpackage tests
5
 */
6
class HtmlEditorFieldTest extends FunctionalTest {
7
8
	protected static $fixture_file = 'HtmlEditorFieldTest.yml';
9
10
	protected static $use_draft_site = true;
11
12
	protected $requiredExtensions = array(
13
		'HtmlEditorField_Toolbar' => array('HtmlEditorFieldTest_DummyMediaFormFieldExtension')
14
	);
15
16
	protected $extraDataObjects = array('HtmlEditorFieldTest_Object');
17
18
	public function testCasting() {
19
		// Test special characters
20
		$inputText = "These are some unicodes: ä, ö, & ü";
21
		$field = new HTMLEditorField("Test", "Test");
22
		$field->setValue($inputText);
23
		$this->assertContains('These are some unicodes: &auml;, &ouml;, &amp; &uuml;', $field->Field());
24
25
		// Test shortcodes
26
		$inputText = "Shortcode: [file_link id=4]";
27
		$field = new HTMLEditorField("Test", "Test");
28
		$field->setValue($inputText);
29
		$this->assertContains('Shortcode: [file_link id=4]', $field->Field());
30
	}
31
32
	public function testBasicSaving() {
33
		$obj = new HtmlEditorFieldTest_Object();
34
		$editor   = new HtmlEditorField('Content');
35
36
		$editor->setValue('<p class="foo">Simple Content</p>');
37
		$editor->saveInto($obj);
38
		$this->assertEquals('<p class="foo">Simple Content</p>', $obj->Content, 'Attributes are preserved.');
39
40
		$editor->setValue('<p>Unclosed Tag');
41
		$editor->saveInto($obj);
42
		$this->assertEquals('<p>Unclosed Tag</p>', $obj->Content, 'Unclosed tags are closed.');
43
	}
44
45
	public function testNullSaving() {
46
		$obj = new HtmlEditorFieldTest_Object();
47
		$editor = new HtmlEditorField('Content');
48
49
		$editor->setValue(null);
50
		$editor->saveInto($obj);
51
		$this->assertEquals('', $obj->Content, "Doesn't choke on empty/null values.");
52
	}
53
54
	public function testImageInsertion() {
55
		$obj = new HtmlEditorFieldTest_Object();
56
		$editor = new HtmlEditorField('Content');
57
58
		$editor->setValue('<img src="assets/HTMLEditorFieldTest_example.jpg" />');
59
		$editor->saveInto($obj);
60
61
		$parser = new CSSContentParser($obj->Content);
62
		$xml = $parser->getByXpath('//img');
63
		$this->assertEquals('', (string)$xml[0]['alt'], 'Alt tags are added by default.');
64
		$this->assertEquals('', (string)$xml[0]['title'], 'Title tags are added by default.');
65
66
		$editor->setValue('<img src="assets/HTMLEditorFieldTest_example.jpg" alt="foo" title="bar" />');
67
		$editor->saveInto($obj);
68
69
		$parser = new CSSContentParser($obj->Content);
70
		$xml = $parser->getByXpath('//img');
71
		$this->assertEquals('foo', (string)$xml[0]['alt'], 'Alt tags are preserved.');
72
		$this->assertEquals('bar', (string)$xml[0]['title'], 'Title tags are preserved.');
73
		$this->assertEquals(false, $obj->HasBrokenFile, 'Referenced image file exists.');
74
	}
75
76
	public function testResizedImageInsertion() {
77
		$obj = new HtmlEditorFieldTest_Object();
78
		$editor = new HtmlEditorField('Content');
79
80
		/*
81
		 * Following stuff is neccessary to
82
		 *     a) use the proper filename for the image we are referencing
83
		 *     b) not confuse the "existing" filesystem by our test
84
		 */
85
		$imageFile = $this->objFromFixture('Image', 'example_image');
86
		$imageFile->Filename = FRAMEWORK_DIR . '/' . $imageFile->Filename;
0 ignored issues
show
Documentation introduced by
The property Filename does not exist on object<DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
87
		$origUpdateFilesystem = Config::inst()->get('File', 'update_filesystem');
88
		Config::inst()->update('File', 'update_filesystem', false);
89
		$imageFile->write();
90
		Config::inst()->update('File', 'update_filesystem', $origUpdateFilesystem);
91
		/*
92
		 * End of test bet setting
93
		 */
94
95
		$editor->setValue('<img src="assets/HTMLEditorFieldTest_example.jpg" width="10" height="20" />');
96
		$editor->saveInto($obj);
97
98
		$parser = new CSSContentParser($obj->Content);
99
		$xml = $parser->getByXpath('//img');
100
		$this->assertEquals('', (string)$xml[0]['alt'], 'Alt tags are added by default.');
101
		$this->assertEquals('', (string)$xml[0]['title'], 'Title tags are added by default.');
102
		$this->assertEquals(10, (int)$xml[0]['width'], 'Width tag of resized image is set.');
103
		$this->assertEquals(20, (int)$xml[0]['height'], 'Height tag of resized image is set.');
104
105
		$neededFilename = 'assets/_resampled/ResizedImage' . Convert::base64url_encode(array(10,20)) .
106
			'/HTMLEditorFieldTest_example.jpg';
107
108
		$this->assertEquals($neededFilename, (string)$xml[0]['src'], 'Correct URL of resized image is set.');
109
		$this->assertTrue(file_exists(BASE_PATH.DIRECTORY_SEPARATOR.$neededFilename), 'File for resized image exists');
110
		$this->assertEquals(false, $obj->HasBrokenFile, 'Referenced image file exists.');
111
	}
112
113
	public function testMultiLineSaving() {
114
		$obj = $this->objFromFixture('HtmlEditorFieldTest_Object', 'home');
115
		$editor   = new HtmlEditorField('Content');
116
		$editor->setValue('<p>First Paragraph</p><p>Second Paragraph</p>');
117
		$editor->saveInto($obj);
0 ignored issues
show
Bug introduced by
It seems like $obj defined by $this->objFromFixture('H...ldTest_Object', 'home') on line 114 can be null; however, HtmlEditorField::saveInto() 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...
118
		$this->assertEquals('<p>First Paragraph</p><p>Second Paragraph</p>', $obj->Content);
119
	}
120
121
	public function testSavingLinksWithoutHref() {
122
		$obj = $this->objFromFixture('HtmlEditorFieldTest_Object', 'home');
123
		$editor   = new HtmlEditorField('Content');
124
125
		$editor->setValue('<p><a name="example-anchor"></a></p>');
126
		$editor->saveInto($obj);
0 ignored issues
show
Bug introduced by
It seems like $obj defined by $this->objFromFixture('H...ldTest_Object', 'home') on line 122 can be null; however, HtmlEditorField::saveInto() 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...
127
128
		$this->assertEquals (
129
			'<p><a name="example-anchor"></a></p>', $obj->Content, 'Saving a link without a href attribute works'
130
		);
131
	}
132
133
	public function testGetAnchors() {
134
		if (!class_exists('Page')) {
135
			$this->markTestSkipped();
136
		}
137
		$html = '<div name="foo"></div>
138
<div name=\'bar\'></div>
139
<div id="baz"></div>
140
<div id=\'bam\'></div>
141
<div id = "baz"></div>
142
<div id = ""></div>
143
<div id="some\'id"></div>
144
<div id=bar></div>';
145
		$expected = array(
146
			'foo',
147
			'bar',
148
			'baz',
149
			'bam',
150
			"some&#039;id",
151
		);
152
		$page = new Page();
153
		$page->Title = 'Test';
154
		$page->Content = $html;
155
		$page->write();
156
		$this->useDraftSite(true);
157
158
		$request = new SS_HTTPRequest('GET', '/', array(
159
			'PageID' => $page->ID,
160
		));
161
162
		$toolBar = new HtmlEditorField_Toolbar(new Controller(), 'test');
163
		$toolBar->setRequest($request);
164
165
		$results = json_decode($toolBar->getanchors(), true);
166
		$this->assertEquals($expected, $results);
167
	}
168
169
	public function testHtmlEditorFieldFileLocal() {
170
		$file = new HtmlEditorField_File('http://domain.com/folder/my_image.jpg?foo=bar');
171
		$this->assertEquals('http://domain.com/folder/my_image.jpg?foo=bar', $file->URL);
172
		$this->assertEquals('my_image.jpg', $file->Name);
173
		$this->assertEquals('jpg', $file->Extension);
0 ignored issues
show
Bug introduced by
The property Extension does not seem to exist. Did you mean extensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
174
		// TODO Can't easily test remote file dimensions
175
	}
176
177
	public function testHtmlEditorFieldFileRemote() {
178
		$fileFixture = new File(array('Name' => 'my_local_image.jpg', 'Filename' => 'folder/my_local_image.jpg'));
179
		$file = new HtmlEditorField_File('http://localdomain.com/folder/my_local_image.jpg', $fileFixture);
180
		$this->assertEquals('http://localdomain.com/folder/my_local_image.jpg', $file->URL);
181
		$this->assertEquals('my_local_image.jpg', $file->Name);
182
		$this->assertEquals('jpg', $file->Extension);
0 ignored issues
show
Bug introduced by
The property Extension does not seem to exist. Did you mean extensions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
183
	}
184
}
185
186
/**
187
 * @package framework
188
 * @subpackage tests
189
 */
190
class HtmlEditorFieldTest_DummyMediaFormFieldExtension extends Extension implements TestOnly {
191
	public static $fields = null;
192
	public static $update_called = false;
193
194
	public function updateImageForm($form) {
195
		self::$update_called = true;
196
		self::$fields = $form->Fields();
197
	}
198
}
199
200
class HtmlEditorFieldTest_Object extends DataObject implements TestOnly {
201
	private static $db = array(
202
		'Title' => 'Varchar',
203
		'Content' => 'HTMLText',
204
		'HasBrokenFile' => 'Boolean'
205
	);
206
}
207