diff --git a/includes/rules/empty_link.php b/includes/rules/empty_link.php
index 38bb151f..8d875034 100644
--- a/includes/rules/empty_link.php
+++ b/includes/rules/empty_link.php
@@ -45,25 +45,32 @@ function edac_rule_empty_link( $content, $post ) { // phpcs:ignore -- $post is r
// does not have a name.
$image = $link->find( 'img' );
- if ( ! $error && isset( $input[0] ) && empty( trim( $image[0]->getAttribute( 'alt' ) ) ) ) {
+ $input = $link->find( 'input' );
+ $i = $link->find( 'i' );
+
+ // If there's no image, input or i tag it's just an empty link and should be flagged.
+ if ( empty( $image ) && empty( $input ) && empty( $i ) ) {
+ $error = $a_tag_code;
+ }
+
+ if ( ! $error && isset( $image[0] ) && empty( trim( $image[0]->getAttribute( 'alt' ) ) ) ) {
// The first image inside the link does not have an alt.
// Throw error.
$error = $a_tag_code;
}
- $input = $link->find( 'input' );
- if ( ! $error && isset( $input[0] ) && empty( trim( $image[0]->getAttribute( 'value' ) ) ) ) {
+ if ( ! $error && isset( $input[0] ) && empty( trim( $input[0]->getAttribute( 'value' ) ) ) ) {
// The first input inside the link does not have a value.
// Throw error.
$error = $a_tag_code;
}
- $i = $link->find( 'i' );
- if ( ! $error && isset( $input[0] ) &&
- empty( trim( $i[0]->getAttribute( 'title' ) ) ) &&
- empty( trim( $i[0]->getAttribute( 'aria-label' ) ) )
+ if ( ! $error &&
+ isset( $i[0] ) &&
+ empty( trim( $i[0]->getAttribute( 'title' ) ) ) &&
+ empty( trim( $i[0]->getAttribute( 'aria-label' ) ) )
) {
// The first i inside the link does not have a title &
diff --git a/tests/phpunit/includes/rules/EmptyLinkTest.php b/tests/phpunit/includes/rules/EmptyLinkTest.php
new file mode 100644
index 00000000..7137177b
--- /dev/null
+++ b/tests/phpunit/includes/rules/EmptyLinkTest.php
@@ -0,0 +1,111 @@
+';
+
+ $not_expected_error = 'Some content';
+
+
+ $dom = new EDAC_Dom();
+ $dom->load( $expected_error . PHP_EOL . $not_expected_error );
+
+ $errors = edac_rule_empty_link( [ 'html' => $dom ], null );
+
+ $this->assertContains( $expected_error, $errors );
+ $this->assertNotContains( $not_expected_error, $errors );
+ }
+
+ /**
+ * Test that a link with no content, no aria-label, no title, no id, no name, and no alt text throws an error.
+ */
+ public function test_empty_link_with_img() {
+ $expected_errors = [
+ '
',
+ '
',
+ ];
+
+ $not_expected_error = '
';
+
+ $dom = new EDAC_Dom();
+ $dom->load( implode( PHP_EOL, $expected_errors ) . PHP_EOL . $not_expected_error );
+
+ $errors = edac_rule_empty_link( [ 'html' => $dom ], null );
+
+ foreach ( $expected_errors as $expected_error ) {
+ $this->assertContains( $expected_error, $errors );
+ }
+
+ $this->assertNotContains( $not_expected_error, $errors );
+ }
+
+ /**
+ * Test that a link with no content, no aria-label, no title, no id, no name, and no alt text throws an error.
+ */
+ public function test_empty_link_with_input() {
+
+ $expected_errors = [
+ '',
+ '',
+ '', // whitespace should be stripped, this is still empty.
+ ];
+
+ $not_expected_error = '';
+
+ $dom = new EDAC_Dom();
+ $dom->load( implode( PHP_EOL, $expected_errors ) . PHP_EOL . $not_expected_error );
+
+ $errors = edac_rule_empty_link( [ 'html' => $dom ], null );
+
+ foreach ( $expected_errors as $expected_error ) {
+ $this->assertContains( $expected_error, $errors );
+ }
+ $this->assertNotContains( $not_expected_error, $errors );
+ }
+
+ /**
+ * Test that a link with no content, no aria-label, no title, no id, no name, and no alt text throws an error.
+ */
+ public function test_empty_link_with_i() {
+ $expected_errors = [
+ '',
+ '',
+ '',
+ '', // whitespace should be stripped, this is still empty.
+ '', // whitespace should be stripped, this is still empty.
+ ];
+
+ $not_expected_errors = [
+ '',
+ '',
+ '',
+ ];
+
+ $dom = new EDAC_Dom();
+ $dom->load( implode( PHP_EOL, $expected_errors ) . PHP_EOL . implode( PHP_EOL, $not_expected_errors ) );
+
+ $errors = edac_rule_empty_link( [ 'html' => $dom ], null );
+
+ foreach ( $expected_errors as $expected_error ) {
+ $this->assertContains( $expected_error, $errors );
+ }
+ foreach ( $not_expected_errors as $not_expected_error ) {
+ $this->assertNotContains( $not_expected_error, $errors );
+ }
+ }
+}