Completed
Push — master ( 3b4314...83c2af )
by Sam
12:26
created

HTMLEditorFieldTest::testResizedImageInsertion()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 22
nc 1
nop 0
dl 0
loc 29
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
use Filesystem as SS_Filesystem;
4
use SilverStripe\ORM\DataObject;
5
use SilverStripe\ORM\FieldType\DBHTMLText;
6
7
8
/**
9
 * @package framework
10
 * @subpackage tests
11
 */
12
class HTMLEditorFieldTest extends FunctionalTest {
13
14
	protected static $fixture_file = 'HTMLEditorFieldTest.yml';
15
16
	protected static $use_draft_site = true;
17
18
	protected $requiredExtensions = array(
19
		'HTMLEditorField_Toolbar' => array('HTMLEditorFieldTest_DummyMediaFormFieldExtension')
20
	);
21
22
	protected $extraDataObjects = array('HTMLEditorFieldTest_Object');
23
24
	public function setUp() {
25
		parent::setUp();
26
27
		// Set backend root to /HTMLEditorFieldTest
28
		AssetStoreTest_SpyStore::activate('HTMLEditorFieldTest');
29
30
		// Set the File Name Filter replacements so files have the expected names
31
        Config::inst()->update('FileNameFilter', 'default_replacements', array(
32
            '/\s/' => '-', // remove whitespace
33
            '/_/' => '-', // underscores to dashes
34
            '/[^A-Za-z0-9+.\-]+/' => '', // remove non-ASCII chars, only allow alphanumeric plus dash and dot
35
            '/[\-]{2,}/' => '-', // remove duplicate dashes
36
            '/^[\.\-_]+/' => '', // Remove all leading dots, dashes or underscores
37
        ));
38
39
		// Create a test files for each of the fixture references
40
		$files = File::get()->exclude('ClassName', 'Folder');
41
		foreach($files as $file) {
42
			$fromPath = BASE_PATH . '/framework/tests/forms/images/' . $file->Name;
43
			$destPath = AssetStoreTest_SpyStore::getLocalPath($file); // Only correct for test asset store
44
			SS_Filesystem::makeFolder(dirname($destPath));
45
			copy($fromPath, $destPath);
46
		}
47
	}
48
49
	public function tearDown() {
50
		AssetStoreTest_SpyStore::reset();
51
		parent::tearDown();
52
	}
53
54
	public function testBasicSaving() {
55
		$obj = new HTMLEditorFieldTest_Object();
56
		$editor   = new HTMLEditorField('Content');
57
58
		$editor->setValue('<p class="foo">Simple Content</p>');
59
		$editor->saveInto($obj);
60
		$this->assertEquals('<p class="foo">Simple Content</p>', $obj->Content, 'Attributes are preserved.');
61
62
		$editor->setValue('<p>Unclosed Tag');
63
		$editor->saveInto($obj);
64
		$this->assertEquals('<p>Unclosed Tag</p>', $obj->Content, 'Unclosed tags are closed.');
65
	}
66
67
	public function testNullSaving() {
68
		$obj = new HTMLEditorFieldTest_Object();
69
		$editor = new HTMLEditorField('Content');
70
71
		$editor->setValue(null);
72
		$editor->saveInto($obj);
73
		$this->assertEquals('', $obj->Content, "Doesn't choke on empty/null values.");
74
	}
75
76
	public function testResizedImageInsertion() {
77
		$obj = new HTMLEditorFieldTest_Object();
78
		$editor = new HTMLEditorField('Content');
79
80
		$fileID = $this->idFromFixture('Image', 'example_image');
81
		$editor->setValue(sprintf(
82
			'[image src="assets/HTMLEditorFieldTest_example.jpg" width="10" height="20" id="%d"]',
83
			$fileID
84
		));
85
		$editor->saveInto($obj);
86
87
		$parser = new CSSContentParser($obj->dbObject('Content')->forTemplate());
88
		$xml = $parser->getByXpath('//img');
89
		$this->assertEquals(
90
			'HTMLEditorFieldTest example',
91
			(string)$xml[0]['alt'],
92
			'Alt tags are added by default based on filename'
93
		);
94
		$this->assertEquals('', (string)$xml[0]['title'], 'Title tags are added by default.');
95
		$this->assertEquals(10, (int)$xml[0]['width'], 'Width tag of resized image is set.');
96
		$this->assertEquals(20, (int)$xml[0]['height'], 'Height tag of resized image is set.');
97
98
		$neededFilename
99
			= '/assets/HTMLEditorFieldTest/f5c7c2f814/HTMLEditorFieldTest-example__ResizedImageWyIxMCIsIjIwIl0.jpg';
100
101
		$this->assertEquals($neededFilename, (string)$xml[0]['src'], 'Correct URL of resized image is set.');
102
		$this->assertTrue(file_exists(BASE_PATH.DIRECTORY_SEPARATOR.$neededFilename), 'File for resized image exists');
103
		$this->assertEquals(false, $obj->HasBrokenFile, 'Referenced image file exists.');
104
	}
105
106
	public function testMultiLineSaving() {
107
		$obj = $this->objFromFixture('HTMLEditorFieldTest_Object', 'home');
108
		$editor   = new HTMLEditorField('Content');
109
		$editor->setValue('<p>First Paragraph</p><p>Second Paragraph</p>');
110
		$editor->saveInto($obj);
0 ignored issues
show
Bug introduced by
It seems like $obj defined by $this->objFromFixture('H...ldTest_Object', 'home') on line 107 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...
111
		$this->assertEquals('<p>First Paragraph</p><p>Second Paragraph</p>', $obj->Content);
112
	}
113
114
	public function testSavingLinksWithoutHref() {
115
		$obj = $this->objFromFixture('HTMLEditorFieldTest_Object', 'home');
116
		$editor   = new HTMLEditorField('Content');
117
118
		$editor->setValue('<p><a name="example-anchor"></a></p>');
119
		$editor->saveInto($obj);
0 ignored issues
show
Bug introduced by
It seems like $obj defined by $this->objFromFixture('H...ldTest_Object', 'home') on line 115 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...
120
121
		$this->assertEquals (
122
			'<p><a name="example-anchor"></a></p>', $obj->Content, 'Saving a link without a href attribute works'
123
		);
124
	}
125
126
	public function testGetAnchors() {
127
		if (!class_exists('Page')) {
128
			$this->markTestSkipped();
129
		}
130
		$linkedPage = new Page();
131
		$linkedPage->Title = 'Dummy';
132
		$linkedPage->write();
133
134
		$html = <<<EOS
135
<div name="foo"></div>
136
<div name='bar'></div>
137
<div id="baz"></div>
138
[sitetree_link id="{$linkedPage->ID}"]
139
<div id='bam'></div>
140
<div id = "baz"></div>
141
<div id = ""></div>
142
<div id="some'id"></div>
143
<div id=bar></div>
144
EOS
145
	;
146
		$expected = array(
147
			'foo',
148
			'bar',
149
			'baz',
150
			'bam',
151
			"some&#039;id",
152
		);
153
		$page = new Page();
154
		$page->Title = 'Test';
155
		$page->Content = $html;
156
		$page->write();
157
		$this->useDraftSite(true);
158
159
		$request = new SS_HTTPRequest('GET', '/', array(
160
			'PageID' => $page->ID,
161
		));
162
163
		$toolBar = new HTMLEditorField_Toolbar(new Controller(), 'test');
164
		$toolBar->setRequest($request);
165
166
		$results = json_decode($toolBar->getanchors(), true);
167
		$this->assertEquals($expected, $results);
168
	}
169
170
	public function testHTMLEditorFieldFileLocal() {
171
		$file = new HTMLEditorField_Image('http://domain.com/folder/my_image.jpg?foo=bar');
172
		$this->assertEquals('http://domain.com/folder/my_image.jpg?foo=bar', $file->URL);
173
		$this->assertEquals('my_image.jpg', $file->Name);
174
		$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...
175
		// TODO Can't easily test remote file dimensions
176
	}
177
178
	public function testHTMLEditorFieldFileRemote() {
179
		$fileFixture = new File(array('Name' => 'my_local_image.jpg', 'Filename' => 'folder/my_local_image.jpg'));
180
		$file = new HTMLEditorField_Image('http://localdomain.com/folder/my_local_image.jpg', $fileFixture);
181
		$this->assertEquals('http://localdomain.com/folder/my_local_image.jpg', $file->URL);
182
		$this->assertEquals('my_local_image.jpg', $file->Name);
183
		$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...
184
	}
185
186
	public function testReadonlyField() {
187
		$editor = new HTMLEditorField('Content');
188
		$fileID = $this->idFromFixture('Image', 'example_image');
189
		$editor->setValue(sprintf(
190
			'[image src="assets/HTMLEditorFieldTest_example.jpg" width="10" height="20" id="%d"]',
191
			$fileID
192
		));
193
		/** @var HTMLReadonlyField $readonly */
194
		$readonly = $editor->performReadonlyTransformation();
195
		/** @var DBHTMLText $readonlyContent */
196
		$readonlyContent = $readonly->Field();
197
198
		$this->assertEquals( <<<EOS
199
<span class="readonly typography" id="Content">
200
	<img src="/assets/HTMLEditorFieldTest/f5c7c2f814/HTMLEditorFieldTest-example__ResizedImageWyIxMCIsIjIwIl0.jpg" alt="HTMLEditorFieldTest example" width="10" height="20">
201
</span>
202
203
204
EOS
205
			,
206
			$readonlyContent->getValue()
207
		);
208
209
		// Test with include input tag
210
		$readonly = $editor->performReadonlyTransformation()
211
			->setIncludeHiddenField(true);
212
		/** @var DBHTMLText $readonlyContent */
213
		$readonlyContent = $readonly->Field();
214
		$this->assertEquals( <<<EOS
215
<span class="readonly typography" id="Content">
216
	<img src="/assets/HTMLEditorFieldTest/f5c7c2f814/HTMLEditorFieldTest-example__ResizedImageWyIxMCIsIjIwIl0.jpg" alt="HTMLEditorFieldTest example" width="10" height="20">
217
</span>
218
219
	<input type="hidden" name="Content" value="[image src=&quot;/assets/HTMLEditorFieldTest/f5c7c2f814/HTMLEditorFieldTest-example.jpg&quot; width=&quot;10&quot; height=&quot;20&quot; id=&quot;{$fileID}&quot;]" />
220
221
222
EOS
223
			,
224
			$readonlyContent->getValue()
225
		);
226
	}
227
}
228
229
/**
230
 * @package framework
231
 * @subpackage tests
232
 */
233
class HTMLEditorFieldTest_DummyMediaFormFieldExtension extends Extension implements TestOnly {
234
	public static $fields = null;
235
	public static $update_called = false;
236
237
	public function updateImageForm($form) {
238
		self::$update_called = true;
239
		self::$fields = $form->Fields();
240
	}
241
}
242
243
class HTMLEditorFieldTest_Object extends DataObject implements TestOnly {
244
	private static $db = array(
245
		'Title' => 'Varchar',
246
		'Content' => 'HTMLText',
247
		'HasBrokenFile' => 'Boolean'
248
	);
249
}
250