diff --git a/src/Concerns/MakesAssertions.php b/src/Concerns/MakesAssertions.php index d6175c201..b508fcdc3 100644 --- a/src/Concerns/MakesAssertions.php +++ b/src/Concerns/MakesAssertions.php @@ -792,6 +792,34 @@ public function assertAttributeContains($selector, $attribute, $value) return $this; } + /** + * Assert that the element matching the given selector does not contain the given value in the provided attribute. + * + * @param string $selector + * @param string $attribute + * @param string $value + * @return $this + */ + public function assertAttributeDoesntContain($selector, $attribute, $value) + { + $fullSelector = $this->resolver->format($selector); + + $actual = $this->resolver->findOrFail($selector)->getAttribute($attribute); + + PHPUnit::assertNotNull( + $actual, + "Did not see expected attribute [{$attribute}] within element [{$fullSelector}]." + ); + + PHPUnit::assertStringNotContainsString( + $value, + $actual, + "Attribute '$attribute' contains [{$value}]. Full attribute value was [$actual]." + ); + + return $this; + } + /** * Assert that the element matching the given selector has the given value in the provided aria attribute. * @@ -1087,6 +1115,19 @@ public function assertVueContains($key, $value, $componentSelector = null) return $this; } + /** + * Assert that a given Vue component data property is an array and does not contain the given value. + * + * @param string $key + * @param string $value + * @param string|null $componentSelector + * @return $this + */ + public function assertVueDoesntContain($key, $value, $componentSelector = null) + { + return $this->assertVueDoesNotContain($key, $value, $componentSelector); + } + /** * Assert that a given Vue component data property is an array and does not contain the given value. * diff --git a/tests/Unit/MakesAssertionsTest.php b/tests/Unit/MakesAssertionsTest.php index 189360ce6..091a1cb6d 100644 --- a/tests/Unit/MakesAssertionsTest.php +++ b/tests/Unit/MakesAssertionsTest.php @@ -635,6 +635,46 @@ public function test_assert_attribute_contains() } } + public function test_assert_attribute_does_not_contain() + { + $driver = m::mock(stdClass::class); + + $element = m::mock(stdClass::class); + $element->shouldReceive('getAttribute')->with('bar')->andReturn( + 'class-a class-b', + null, + 'class-1 class-2' + ); + + $resolver = m::mock(stdClass::class); + $resolver->shouldReceive('format')->with('foo')->andReturn('Foo'); + $resolver->shouldReceive('findOrFail')->with('foo')->andReturn($element); + + $browser = new Browser($driver, $resolver); + + $browser->assertAttributeDoesntContain('foo', 'bar', 'class-c'); + + try { + $browser->assertAttributeDoesntContain('foo', 'bar', 'class-c'); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertStringContainsString( + 'Did not see expected attribute [bar] within element [Foo].', + $e->getMessage() + ); + } + + try { + $browser->assertAttributeDoesntContain('foo', 'bar', 'class-1'); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertStringContainsString( + "Attribute 'bar' contains [class-1]. Full attribute value was [class-1 class-2].", + $e->getMessage() + ); + } + } + public function test_assert_data_attribute() { $driver = m::mock(stdClass::class);