',
+ ),
+ 'unsafe additional classes' => array(
+ 'message' => 'A notice with unsafe additional classes.',
+ 'args' => array(
+ 'additional_classes' => array( '">
alert( "Howdy, admin!" );
A notice with unsafe additional classes.
',
+ ),
+ 'a type that is not a string' => array(
+ 'message' => 'A notice with a type that is not a string.',
+ 'args' => array(
+ 'type' => array(),
+ ),
+ 'expected' => '
A notice with a type that is not a string.
',
+ ),
+ 'a type with only empty space' => array(
+ 'message' => 'A notice with a type with only empty space.',
+ 'args' => array(
+ 'type' => " \t\r\n",
+ ),
+ 'expected' => '
A notice with a type with only empty space.
',
+ ),
+ 'an ID that is not a string' => array(
+ 'message' => 'A notice with an ID that is not a string.',
+ 'args' => array(
+ 'id' => array( 'message' ),
+ ),
+ 'expected' => '
A notice with an ID that is not a string.
',
+ ),
+ 'an ID with only empty space' => array(
+ 'message' => 'A notice with an ID with only empty space.',
+ 'args' => array(
+ 'id' => " \t\r\n",
+ ),
+ 'expected' => '
A notice with an ID with only empty space.
',
+ ),
+ 'dismissible as a truthy value rather than (bool) true' => array(
+ 'message' => 'A notice with dismissible as a truthy value rather than (bool) true.',
+ 'args' => array(
+ 'dismissible' => 1,
+ ),
+ 'expected' => '
A notice with dismissible as a truthy value rather than (bool) true.
',
+ ),
+ 'additional classes that are not an array' => array(
+ 'message' => 'A notice with additional classes that are not an array.',
+ 'args' => array(
+ 'additional_classes' => 'class-1 class-2 class-3',
+ ),
+ 'expected' => '
A notice with additional classes that are not an array.
',
+ ),
+ 'paragraph wrapping as a falsy value rather than (bool) false' => array(
+ 'message' => 'A notice with paragraph wrapping as a falsy value rather than (bool) false.',
+ 'args' => array(
+ 'paragraph_wrap' => 0,
+ ),
+ 'expected' => '
A notice with paragraph wrapping as a falsy value rather than (bool) false.
',
+ ),
+ );
+ }
+
+ /**
+ * Tests that `_doing_it_wrong()` is thrown when a 'type' containing spaces is passed.
+ *
+ * @ticket 57791
+ *
+ * @expectedIncorrectUsage wp_get_admin_notice
+ */
+ public function test_should_throw_doing_it_wrong_with_a_type_containing_spaces() {
+ ob_start();
+ wp_admin_notice(
+ 'A type containing spaces.',
+ array( 'type' => 'first second third fourth' )
+ );
+ $actual = ob_get_clean();
+
+ $this->assertSame(
+ '
A type containing spaces.
',
+ $actual
+ );
+ }
+
+ /**
+ * Tests that `wp_admin_notice()` fires the 'wp_admin_notice' action.
+ *
+ * @ticket 57791
+ */
+ public function test_should_fire_wp_admin_notice_action() {
+ $action = new MockAction();
+ add_action( 'wp_admin_notice', array( $action, 'action' ) );
+
+ ob_start();
+ wp_admin_notice( 'A notice.', array( 'type' => 'success' ) );
+ ob_end_clean();
+
+ $this->assertSame( 1, $action->get_call_count() );
+ }
+}
diff --git a/tests/phpunit/tests/admin/wpGetAdminNotice.php b/tests/phpunit/tests/admin/wpGetAdminNotice.php
new file mode 100644
index 0000000000..b5ba311338
--- /dev/null
+++ b/tests/phpunit/tests/admin/wpGetAdminNotice.php
@@ -0,0 +1,268 @@
+assertSame( $expected, wp_get_admin_notice( $message, $args ) );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array[]
+ */
+ public function data_should_return_admin_notice() {
+ return array(
+ 'defaults' => array(
+ 'message' => 'A notice with defaults.',
+ 'args' => array(),
+ 'expected' => '
',
+ ),
+ 'an empty message (used for templates)' => array(
+ 'message' => '',
+ 'args' => array(
+ 'type' => 'error',
+ 'dismissible' => true,
+ 'id' => 'message',
+ 'additional_classes' => array( 'inline', 'hidden' ),
+ ),
+ 'expected' => '
',
+ ),
+ 'an empty message (used for templates) without paragraph wrapping' => array(
+ 'message' => '',
+ 'args' => array(
+ 'type' => 'error',
+ 'dismissible' => true,
+ 'id' => 'message',
+ 'additional_classes' => array( 'inline', 'hidden' ),
+ 'paragraph_wrap' => false,
+ ),
+ 'expected' => '
',
+ ),
+ 'an "error" notice' => array(
+ 'message' => 'An "error" notice.',
+ 'args' => array(
+ 'type' => 'error',
+ ),
+ 'expected' => '
',
+ ),
+ 'a "success" notice' => array(
+ 'message' => 'A "success" notice.',
+ 'args' => array(
+ 'type' => 'success',
+ ),
+ 'expected' => '
',
+ ),
+ 'a "warning" notice' => array(
+ 'message' => 'A "warning" notice.',
+ 'args' => array(
+ 'type' => 'warning',
+ ),
+ 'expected' => '
',
+ ),
+ 'an "info" notice' => array(
+ 'message' => 'An "info" notice.',
+ 'args' => array(
+ 'type' => 'info',
+ ),
+ 'expected' => '
',
+ ),
+ 'a type that already starts with "notice-"' => array(
+ 'message' => 'A type that already starts with "notice-".',
+ 'args' => array(
+ 'type' => 'notice-info',
+ ),
+ 'expected' => '
A type that already starts with "notice-".
',
+ ),
+ 'a dismissible notice' => array(
+ 'message' => 'A dismissible notice.',
+ 'args' => array(
+ 'dismissible' => true,
+ ),
+ 'expected' => '
',
+ ),
+ 'no type and an ID' => array(
+ 'message' => 'A notice with an ID.',
+ 'args' => array(
+ 'id' => 'message',
+ ),
+ 'expected' => '
',
+ ),
+ 'a type and an ID' => array(
+ 'message' => 'A warning notice with an ID.',
+ 'args' => array(
+ 'type' => 'warning',
+ 'id' => 'message',
+ ),
+ 'expected' => '
A warning notice with an ID.
',
+ ),
+ 'no type and additional classes' => array(
+ 'message' => 'A notice with additional classes.',
+ 'args' => array(
+ 'additional_classes' => array( 'error', 'notice-alt' ),
+ ),
+ 'expected' => '
A notice with additional classes.
',
+ ),
+ 'a type and additional classes' => array(
+ 'message' => 'A warning notice with additional classes.',
+ 'args' => array(
+ 'type' => 'warning',
+ 'additional_classes' => array( 'error', 'notice-alt' ),
+ ),
+ 'expected' => '
A warning notice with additional classes.
',
+ ),
+ 'a dismissible notice with a type and additional classes' => array(
+ 'message' => 'A dismissible warning notice with a type and additional classes.',
+ 'args' => array(
+ 'type' => 'warning',
+ 'dismissible' => true,
+ 'additional_classes' => array( 'error', 'notice-alt' ),
+ ),
+ 'expected' => '
A dismissible warning notice with a type and additional classes.
',
+ ),
+ 'a notice without paragraph wrapping' => array(
+ 'message' => '
A notice without paragraph wrapping.',
+ 'args' => array(
+ 'paragraph_wrap' => false,
+ ),
+ 'expected' => '
A notice without paragraph wrapping.
',
+ ),
+ 'an unsafe type' => array(
+ 'message' => 'A notice with an unsafe type.',
+ 'args' => array(
+ 'type' => '">',
+ ),
+ 'expected' => '
">
A notice with an unsafe type.
',
+ ),
+ 'an unsafe ID' => array(
+ 'message' => 'A notice with an unsafe ID.',
+ 'args' => array(
+ 'id' => '">
A notice with an unsafe ID.
',
+ ),
+ 'unsafe additional classes' => array(
+ 'message' => 'A notice with unsafe additional classes.',
+ 'args' => array(
+ 'additional_classes' => array( '">
A notice with unsafe additional classes.
',
+ ),
+ 'a type that is not a string' => array(
+ 'message' => 'A notice with a type that is not a string.',
+ 'args' => array(
+ 'type' => array(),
+ ),
+ 'expected' => '
A notice with a type that is not a string.
',
+ ),
+ 'a type with only empty space' => array(
+ 'message' => 'A notice with a type with only empty space.',
+ 'args' => array(
+ 'type' => " \t\r\n",
+ ),
+ 'expected' => '
A notice with a type with only empty space.
',
+ ),
+ 'an ID that is not a string' => array(
+ 'message' => 'A notice with an ID that is not a string.',
+ 'args' => array(
+ 'id' => array( 'message' ),
+ ),
+ 'expected' => '
A notice with an ID that is not a string.
',
+ ),
+ 'an ID with only empty space' => array(
+ 'message' => 'A notice with an ID with only empty space.',
+ 'args' => array(
+ 'id' => " \t\r\n",
+ ),
+ 'expected' => '
A notice with an ID with only empty space.
',
+ ),
+ 'dismissible as a truthy value rather than (bool) true' => array(
+ 'message' => 'A notice with dismissible as a truthy value rather than (bool) true.',
+ 'args' => array(
+ 'dismissible' => 1,
+ ),
+ 'expected' => '
A notice with dismissible as a truthy value rather than (bool) true.
',
+ ),
+ 'additional classes that are not an array' => array(
+ 'message' => 'A notice with additional classes that are not an array.',
+ 'args' => array(
+ 'additional_classes' => 'class-1 class-2 class-3',
+ ),
+ 'expected' => '
A notice with additional classes that are not an array.
',
+ ),
+ 'paragraph wrapping as a falsy value rather than (bool) false' => array(
+ 'message' => 'A notice with paragraph wrapping as a falsy value rather than (bool) false.',
+ 'args' => array(
+ 'paragraph_wrap' => 0,
+ ),
+ 'expected' => '
A notice with paragraph wrapping as a falsy value rather than (bool) false.
',
+ ),
+ );
+ }
+
+ /**
+ * Tests that `wp_get_admin_notice()` throws a `_doing_it_wrong()` when
+ * a 'type' containing spaces is passed.
+ *
+ * @ticket 57791
+ *
+ * @expectedIncorrectUsage wp_get_admin_notice
+ */
+ public function test_should_throw_doing_it_wrong_with_a_type_containing_spaces() {
+ $this->assertSame(
+ '
A type containing spaces.
',
+ wp_get_admin_notice(
+ 'A type containing spaces.',
+ array( 'type' => 'first second third fourth' )
+ )
+ );
+ }
+
+ /**
+ * Tests that `wp_get_admin_notice()` applies filters.
+ *
+ * @ticket 57791
+ *
+ * @dataProvider data_should_apply_filters
+ *
+ * @param string $hook_name The name of the filter hook.
+ */
+ public function test_should_apply_filters( $hook_name ) {
+ $filter = new MockAction();
+ add_filter( $hook_name, array( $filter, 'filter' ) );
+
+ wp_get_admin_notice( 'A notice.', array( 'type' => 'success' ) );
+
+ $this->assertSame( 1, $filter->get_call_count() );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array[]
+ */
+ public function data_should_apply_filters() {
+ return array(
+ 'wp_admin_notice_args' => array( 'hook_name' => 'wp_admin_notice_args' ),
+ 'wp_admin_notice_markup' => array( 'hook_name' => 'wp_admin_notice_markup' ),
+ );
+ }
+}