PluginProbe
Extendify / 3.1.0
Extendify v3.1.0
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / tests / Integration / QuickEdit / Schemas / ButtonTest.php

ButtonTest.php in Extendify 3.1.0, at tests/Integration/QuickEdit/Schemas/ButtonTest.php

118 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Extendify\Tests\Integration\QuickEdit\Schemas;
4
5 use Extendify\QuickEdit\Schemas\Button;
6 use WP_UnitTestCase;
7
8 class ButtonTest extends WP_UnitTestCase
9 {
10 public function test_fields_returns_text_then_url()
11 {
12 $fields = (new Button())->fields();
13
14 $this->assertCount(2, $fields);
15 $this->assertSame('text', $fields[0]['key']);
16 $this->assertSame('text', $fields[0]['control']);
17 $this->assertSame('url', $fields[1]['key']);
18 $this->assertSame('link', $fields[1]['control']);
19 }
20
21 public function test_apply_text_replaces_anchor_text_preserving_anchor_attrs()
22 {
23 $html = '<div class="wp-block-button"><a class="wp-block-button__link" href="/about" target="_blank">Old label</a></div>';
24 $block = $this->buttonBlock($html);
25
26 $result = (new Button())->apply($block, 'text', 'New label');
27
28 $this->assertStringContainsString('>New label<', $result['innerHTML']);
29 $this->assertStringContainsString('href="/about"', $result['innerHTML']);
30 $this->assertStringContainsString('target="_blank"', $result['innerHTML']);
31 }
32
33 public function test_apply_text_treats_regex_backreferences_in_user_text_as_literal()
34 {
35 $inputs = ['Try $1 for size', 'Use \\1 here', '$0 free', 'Mixed $1 and \\2'];
36 $html = '<div class="wp-block-button"><a class="wp-block-button__link" href="/about">old</a></div>';
37
38 foreach ($inputs as $input) {
39 $result = (new Button())->apply($this->buttonBlock($html), 'text', $input);
40
41 $this->assertStringContainsString('>' . $input . '<', $result['innerHTML'], "input: {$input}");
42 $this->assertStringContainsString('href="/about"', $result['innerHTML']);
43 }
44 }
45
46 public function test_apply_url_sets_anchor_href()
47 {
48 $html = '<div class="wp-block-button"><a class="wp-block-button__link" href="/old">x</a></div>';
49 $block = $this->buttonBlock($html);
50
51 $result = (new Button())->apply($block, 'url', 'https://example.test/new');
52
53 $this->assertStringContainsString('href="https://example.test/new"', $result['innerHTML']);
54 $this->assertStringNotContainsString('href="/old"', $result['innerHTML']);
55 }
56
57 public function test_apply_url_strips_dangerous_schemes()
58 {
59 $html = '<div class="wp-block-button"><a class="wp-block-button__link" href="/old">x</a></div>';
60
61 foreach (['javascript:alert(1)', 'jAvAsCrIpt:alert(1)', 'data:text/html,<script>x</script>', 'vbscript:msgbox(1)'] as $url) {
62 $result = (new Button())->apply($this->buttonBlock($html), 'url', $url);
63
64 // esc_url_raw rejects the scheme entirely, so the href is dropped.
65 $this->assertStringNotContainsString('href=', $result['innerHTML'], "url: {$url}");
66 $this->assertStringNotContainsString('javascript', strtolower($result['innerHTML']), "url: {$url}");
67 }
68 }
69
70 public function test_apply_text_runs_through_wp_kses_post()
71 {
72 $html = '<div class="wp-block-button"><a class="wp-block-button__link" href="/x">old</a></div>';
73 $result = (new Button())->apply($this->buttonBlock($html), 'text', 'hi<script>alert(1)</script>');
74
75 $this->assertStringContainsString('hi', $result['innerHTML']);
76 $this->assertStringNotContainsString('<script', $result['innerHTML']);
77 }
78
79 public function test_apply_url_empty_string_removes_href()
80 {
81 $html = '<div class="wp-block-button"><a class="wp-block-button__link" href="/old">x</a></div>';
82 $block = $this->buttonBlock($html);
83
84 $result = (new Button())->apply($block, 'url', '');
85
86 $this->assertStringNotContainsString('href=', $result['innerHTML']);
87 }
88
89 public function test_apply_url_does_not_mutate_attrs()
90 {
91 $html = '<div class="wp-block-button"><a href="/x">y</a></div>';
92 $block = $this->buttonBlock($html);
93
94 $result = (new Button())->apply($block, 'url', 'https://example.test');
95
96 // The button's canonical link target is the inner <a href>, not a block attribute.
97 $this->assertSame($block['attrs'], $result['attrs']);
98 }
99
100 public function test_apply_with_unknown_field_returns_block_unchanged()
101 {
102 $block = $this->buttonBlock('<div><a href="/x">y</a></div>');
103
104 $this->assertSame($block, (new Button())->apply($block, 'bogus', 'z'));
105 }
106
107 private function buttonBlock(string $innerHTML): array
108 {
109 return [
110 'blockName' => 'core/button',
111 'attrs' => [],
112 'innerBlocks' => [],
113 'innerHTML' => $innerHTML,
114 'innerContent' => [$innerHTML],
115 ];
116 }
117 }
118