diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 0000000..0990819 --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,39 @@ +name: Unit Tests + +on: [push, pull_request] + +jobs: + run: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: [ubuntu-latest] + php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + name: PHP ${{ matrix.php-versions }} + + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-interaction --prefer-dist --no-suggest --no-progress + + - name: Run test suite + run: composer test diff --git a/.gitignore b/.gitignore index c6d1959..384aae8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ -composer.lock tests/coverage vendor +.phpunit.result.cache + +# The composer.lock file is not needed, as this is a library whose dependencies +# will depend on the version of PHP being used. +composer.lock diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index af2584a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: php - -php: - - 7.0 - - 7.1 - - 7.2 - - 7.3 - - 7.4 - -sudo: false - -env: - matrix: - - PREFER_LOWEST="--prefer-lowest --prefer-stable" - - PREFER_LOWEST="" - -install: - - wget https://github.com/php-coveralls/php-coveralls/releases/download/v1.0.0/coveralls.phar - - chmod +x coveralls.phar - - composer update --no-interaction --prefer-dist $PREFER_LOWEST - -script: - - mkdir -p build/logs - - vendor/bin/phpunit --coverage-clover build/logs/clover.xml - -after_success: - - travis_retry php coveralls.phar diff --git a/CHANGELOG.md b/CHANGELOG.md index 042a879..80ff798 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,34 @@ # Changelog + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.3.1] — 2020-01-14 + +* Fix PHPUnit warnings regarding `assertContains()` and `assertRegExp()`. Props [@jakobbuis](https://github.com/jakobbuis) ([#20], [#27], [#28]) +* Refactor the internal test scaffolding, including a move from Travis CI to GitHub Actions. Props [@peter279k](https://github.com/peter279k) for the assist with GitHub Actions ([#24]) +* Added PHP 8.0 support ([#26]) + ## [1.3.0] — 2020-01-27 -* Replace `zendframework/zend-dom` with `laminas/laminas-dom` ([#16]). -* Update Composer dependencies, add a `composer test` script ([#15]). +* Replace `zendframework/zend-dom` with `laminas/laminas-dom` ([#16]) +* Update Composer dependencies, add a `composer test` script ([#15]) + ## [1.2.0] - 2018-03-27 * Bumped the minimum version of zendframework/zend-dom to 2.7, which includes a fix for attribute values that include spaces ([#13]). + ## [1.1.0] - 2018-01-14 -* Added the `assertElementContains()`, `assertElementNotContains()`, `assertElementRegExp()`, and `assertElementNotRegExp()` assertions, for verifying the contents of elements that match the given DOM query ([#6]). -* Moved the `Tests` namespace into a development-only autoloader, to prevent them from potentially being included in projects using this library ([#7]). -* [Based on this article by Martin Hujer](https://blog.martinhujer.cz/17-tips-for-using-composer-efficiently/#tip-%236%3A-put-%60composer.lock%60-into-%60.gitignore%60-in-libraries), remove the `composer.lock` file from the library ([#8]). -* _Lower_ the minimum version of [zendframework/zend-dom](https://packagist.org/packages/zendframework/zend-dom) to 2.2.5 for maximum portability ([#9]). +* Added the `assertElementContains()`, `assertElementNotContains()`, `assertElementRegExp()`, and `assertElementNotRegExp()` assertions, for verifying the contents of elements that match the given DOM query ([#6]) +* Moved the `Tests` namespace into a development-only autoloader, to prevent them from potentially being included in projects using this library ([#7]) +* [Based on this article by Martin Hujer](https://blog.martinhujer.cz/17-tips-for-using-composer-efficiently/#tip-%236%3A-put-%60composer.lock%60-into-%60.gitignore%60-in-libraries), remove the `composer.lock` file from the library ([#8]) +* _Lower_ the minimum version of [zendframework/zend-dom](https://packagist.org/packages/zendframework/zend-dom) to 2.2.5 for maximum portability ([#9]) + ## [1.0.0] - 2017-10-24 @@ -26,6 +36,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [Unreleased]: https://github.com/stevegrunwell/phpunit-markup-assertions/compare/master...develop +[1.3.1]: https://github.com/stevegrunwell/phpunit-markup-assertions/releases/tag/v1.3.1 [1.3.0]: https://github.com/stevegrunwell/phpunit-markup-assertions/releases/tag/v1.3.0 [1.2.0]: https://github.com/stevegrunwell/phpunit-markup-assertions/releases/tag/v1.2.0 [1.1.0]: https://github.com/stevegrunwell/phpunit-markup-assertions/releases/tag/v1.1.0 @@ -37,3 +48,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [#13]: https://github.com/stevegrunwell/phpunit-markup-assertions/issues/13 [#15]: https://github.com/stevegrunwell/phpunit-markup-assertions/pull/15 [#16]: https://github.com/stevegrunwell/phpunit-markup-assertions/issues/16 +[#20]: https://github.com/stevegrunwell/phpunit-markup-assertions/pull/20 +[#24]: https://github.com/stevegrunwell/phpunit-markup-assertions/pull/24 +[#26]: https://github.com/stevegrunwell/phpunit-markup-assertions/pull/26 +[#27]: https://github.com/stevegrunwell/phpunit-markup-assertions/pull/27 +[#28]: https://github.com/stevegrunwell/phpunit-markup-assertions/pull/28 diff --git a/README.md b/README.md index 8c66e88..7a5a113 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # PHPUnit Markup Assertions -[![Build Status](https://travis-ci.org/stevegrunwell/phpunit-markup-assertions.svg?branch=develop)](https://travis-ci.org/stevegrunwell/phpunit-markup-assertions) -[![Coverage Status](https://coveralls.io/repos/github/stevegrunwell/phpunit-markup-assertions/badge.svg?branch=develop)](https://coveralls.io/github/stevegrunwell/phpunit-markup-assertions?branch=develop) +![Build Status](https://github.com/stevegrunwell/phpunit-markup-assertions/workflows/Unit%20Tests/badge.svg) [![GitHub release](https://img.shields.io/github/release/stevegrunwell/phpunit-markup-assertions.svg)](https://github.com/stevegrunwell/phpunit-markup-assertions/releases) This library introduces the `MarkupAssertionsTrait` trait for use in [PHPUnit](https://phpunit.de) tests. diff --git a/composer.json b/composer.json index c30d59c..c8d2ae6 100644 --- a/composer.json +++ b/composer.json @@ -15,10 +15,11 @@ "source": "https://github.com/stevegrunwell/phpunit-markup-assertions/" }, "require": { - "laminas/laminas-dom": "^2.7" + "php": "^5.6 || ^7.0 || ^8.0", + "laminas/laminas-dom": "~2.7.2 || ^2.8" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "symfony/phpunit-bridge": "^5.2" }, "autoload": { "psr-4": { @@ -32,10 +33,10 @@ }, "scripts": { "test": [ - "phpunit" + "simple-phpunit --testdox" ], "test-coverage": [ - "phpunit --coverage-html=tests/coverage" + "phpdbg -qrr -d memory_limit=-1 ./vendor/bin/simple-phpunit --coverage-html=tests/coverage --colors=always" ] }, "scripts-descriptions": { @@ -44,7 +45,6 @@ }, "config": { "preferred-install": "dist", - "sort-packages": true, - "optimize-autoloader": true + "sort-packages": true } } diff --git a/src/MarkupAssertionsTrait.php b/src/MarkupAssertionsTrait.php index 14767a7..2af9fe6 100644 --- a/src/MarkupAssertionsTrait.php +++ b/src/MarkupAssertionsTrait.php @@ -114,7 +114,11 @@ public function assertNotHasElementWithAttributes($attributes = [], $output = '' */ public function assertElementContains($contents, $selector = '', $output = '', $message = '') { - $this->assertContains( + $method = method_exists($this, 'assertStringContainsString') + ? 'assertStringContainsString' + : 'assertContains'; + + $this->$method( $contents, $this->getInnerHtmlOfMatchedElements($output, $selector), $message @@ -133,7 +137,11 @@ public function assertElementContains($contents, $selector = '', $output = '', $ */ public function assertElementNotContains($contents, $selector = '', $output = '', $message = '') { - $this->assertNotContains( + $method = method_exists($this, 'assertStringNotContainsString') + ? 'assertStringNotContainsString' + : 'assertNotContains'; + + $this->$method( $contents, $this->getInnerHtmlOfMatchedElements($output, $selector), $message @@ -152,7 +160,11 @@ public function assertElementNotContains($contents, $selector = '', $output = '' */ public function assertElementRegExp($regexp, $selector = '', $output = '', $message = '') { - $this->assertRegExp( + $method = method_exists($this, 'assertMatchesRegularExpression') + ? 'assertMatchesRegularExpression' + : 'assertRegExp'; + + $this->$method( $regexp, $this->getInnerHtmlOfMatchedElements($output, $selector), $message @@ -171,7 +183,11 @@ public function assertElementRegExp($regexp, $selector = '', $output = '', $mess */ public function assertElementNotRegExp($regexp, $selector = '', $output = '', $message = '') { - $this->assertNotRegExp( + $method = method_exists($this, 'assertDoesNotMatchRegularExpression') + ? 'assertDoesNotMatchRegularExpression' + : 'assertNotRegExp'; + + $this->$method( $regexp, $this->getInnerHtmlOfMatchedElements($output, $selector), $message diff --git a/tests/MarkupAssertionsTraitTest.php b/tests/MarkupAssertionsTraitTest.php index a8ef54c..4692388 100644 --- a/tests/MarkupAssertionsTraitTest.php +++ b/tests/MarkupAssertionsTraitTest.php @@ -5,65 +5,73 @@ use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\RiskyTestError; use PHPUnit\Framework\TestCase; -use ReflectionMethod; -use Tests\TestFiles\TestCaseWithMarkupAssertions; +use SteveGrunwell\PHPUnit_Markup_Assertions\MarkupAssertionsTrait; +/** + * @covers SteveGrunwell\PHPUnit_Markup_Assertions\MarkupAssertionsTrait + */ class MarkupAssertionsTraitTest extends TestCase { - /** - * Holds a clean instance of TestCaseWithMarkupAssertions. - * - * @var TestCaseWithMarkupAssertions - */ - protected $testcase; - - public function setUp() - { - $this->testcase = new TestCaseWithMarkupAssertions; - } + use MarkupAssertionsTrait; /** - * @dataProvider selectorVariantProvider() + * @test + * @testdox assertContainsSelector() should find matching selectors + * @dataProvider provideSelectorVariants */ - public function testAssertContainsSelector($selector) + public function assertContainsSelector_should_find_matching_selectors($selector) { - $this->testcase->assertContainsSelector( + $this->assertContainsSelector( $selector, 'Example' ); } - public function testAssertContainsWithMultipleMatches() + /** + * @test + * @testdox assertContainsSelector() should pick up multiple instances of a selector + */ + public function assertContainsSelector_should_pick_up_multiple_instances() { - $this->testcase->assertContainsSelector( + $this->assertContainsSelector( 'a', 'Home | About | Contact' ); } /** - * @dataProvider selectorVariantProvider() + * @test + * @testdox assertNotContainsSelector() should verify that the given selector does not exist + * @dataProvider provideSelectorVariants */ - public function testAssertNotContainsSelector($selector) + public function assertNotContainsSelector_should_verify_that_the_given_selector_does_not_exist($selector) { - $this->testcase->assertNotContainsSelector( + $this->assertNotContainsSelector( $selector, '

This element has little to do with the link.

' ); } - public function testAssertSelectorCount() + /** + * @test + * @testdox assertSelectorCount() should count the instances of a selector + */ + public function assertSelectorCount_should_count_the_number_of_instances() { - $this->testcase->assertSelectorCount( + $this->assertSelectorCount( 3, 'li', '' ); } - public function testAssertHasElementWithAttributes() + /** + * @test + * @testdox assertHasElementWithAttributes() should find an element with the given attributes + */ + public function assertHasElementWithAttributes_should_find_elements_with_matching_attributes() { - $this->testcase->assertHasElementWithAttributes( + $this->assertHasElementWithAttributes( [ 'type' => 'email', 'value' => 'test@example.com', @@ -73,11 +81,13 @@ public function testAssertHasElementWithAttributes() } /** - * @link https://github.com/stevegrunwell/phpunit-markup-assertions/issues/13 + * @test + * @testdox assertHasElementWithAttributes() should be able to parse spaces in attribute values + * @ticket https://github.com/stevegrunwell/phpunit-markup-assertions/issues/13 */ - public function testAssertHasElementWithAttributesWithSpacesInTheAttributeValue() + public function assertHasElementWithAttributes_should_be_able_to_handle_spaces() { - $this->testcase->assertHasElementWithAttributes( + $this->assertHasElementWithAttributes( [ 'data-attr' => 'foo bar baz', ], @@ -85,9 +95,13 @@ public function testAssertHasElementWithAttributesWithSpacesInTheAttributeValue( ); } - public function testAssertNotHasElementWithAttributes() + /** + * @test + * @testdox assertNotHasElementWithAttributes() should ensure no element has the provided attributes + */ + public function assertNotHasElementWithAttributes_should_find_no_elements_with_matching_attributes() { - $this->testcase->assertNotHasElementWithAttributes( + $this->assertNotHasElementWithAttributes( [ 'type' => 'email', 'value' => 'test@example.com', @@ -96,30 +110,42 @@ public function testAssertNotHasElementWithAttributes() ); } - public function testAssertElementContains() + /** + * @test + * @testdox assertElementContains() should be able to search for a selector + */ + public function assertElementContains_can_match_a_selector() { - $this->testcase->assertElementContains( + $this->assertElementContains( 'ipsum', '#main', '
Lorem ipsum
Lorem ipsum
' ); } - public function testAssertElementContainsMultipleSelectors() + /** + * @test + * @testdox assertElementContains() should be able to chain multiple selectors + */ + public function assertElementContains_can_chain_multiple_selectors() { - $this->testcase->assertElementContains( + $this->assertElementContains( 'ipsum', '#main .foo', '
Lorem ipsum
' ); } - public function testAssertElementContainsScopesToSelector() + /** + * @test + * @testdox assertElementContains() should scope text to the selected element + */ + public function assertElementContains_should_scope_matches_to_selector() { $this->expectException(AssertionFailedError::class); $this->expectExceptionMessage('The #main div does not contain the string "ipsum".'); - $this->testcase->assertElementContains( + $this->assertElementContains( 'ipsum', '#main', '
Lorem ipsum
Foo bar baz
', @@ -127,78 +153,102 @@ public function testAssertElementContainsScopesToSelector() ); } - public function testAssertElementNotContains() + /** + * @test + * @testdox assertElementNotContains() should be able to search for a selector + */ + public function assertElementNotContains_can_match_a_selector() { - $this->testcase->assertElementNotContains( + $this->assertElementNotContains( 'ipsum', '#main', '
Foo bar baz
Some string
' ); } - public function testAssertElementRegExp() + /** + * @test + * @testdox assertElementRegExp() should use regular expression matching + */ + public function assertElementRegExp_should_use_regular_expression_matching() { - $this->testcase->assertElementRegExp( + $this->assertElementRegExp( '/[A-Z0-9-]+/', '#main', '
Lorem ipsum
ABC123
' ); } - public function testAssertElementRegExpWithNestedElements() + /** + * @test + * @testdox assertElementRegExp() should be able to search for nested contents + */ + public function assertElementRegExp_should_be_able_to_match_nested_contents() { - $this->testcase->assertElementRegExp( + $this->assertElementRegExp( '/[A-Z]+/', '#main', '
Lorem ipsum
ABC
' ); } + /** + * @test + * @testdox assertElementNotRegExp() should use regular expression matching + */ public function testAssertElementNotRegExp() { - $this->testcase->assertElementNotRegExp( + $this->assertElementNotRegExp( '/[0-9-]+/', '#main', '
Foo bar baz
ABC
' ); } + /** - * @dataProvider attributeProvider() + * @test + * @testdox flattenAttributeArray() should flatten an array of attributes + * @dataProvider provideAttributes */ - public function testFlattenAttributeArray($attributes, $expected) + public function flattenArrayAttribute_should_flatten_arrays_of_attributes($attributes, $expected) { - $method = new ReflectionMethod($this->testcase, 'flattenAttributeArray'); + $method = new \ReflectionMethod($this, 'flattenAttributeArray'); $method->setAccessible(true); - $this->assertEquals($expected, $method->invoke($this->testcase, $attributes)); + $this->assertSame($expected, $method->invoke($this, $attributes)); } /** - * @expectedException PHPUnit\Framework\RiskyTestError + * @test + * @testdox flattenAttributeArray() should throw a RiskyTestError if the array is empty + * @dataProvider provideAttributes */ - public function testFlattenAttributeArrayThrowsRiskyTestError() + public function flattenAttributeArray_should_throw_a_RiskyTestError_if_given_an_empty_array() { - $method = new ReflectionMethod($this->testcase, 'flattenAttributeArray'); - $method->setAccessible(true); + $this->expectException(RiskyTestError::class); - $method->invoke($this->testcase, []); + $method = new \ReflectionMethod($this, 'flattenAttributeArray'); + $method->setAccessible(true); + $method->invoke($this, []); } /** - * @dataProvider innerHtmlProvider(). + * @test + * @testdox getInnerHtmlOfMatchedElements() should retrieve the inner HTML + * @dataProvider provideInnerHtml */ - public function testGetInnerHtmlOfMatchedElements($markup, $selector, $expected) { - $method = new ReflectionMethod($this->testcase, 'getInnerHtmlOfMatchedElements'); + public function getInnerHtmlOfMatchedElements_should_retrieve_the_inner_HTML($markup, $selector, $expected) { + $method = new \ReflectionMethod($this, 'getInnerHtmlOfMatchedElements'); $method->setAccessible(true); - $this->assertEquals($expected, $method->invoke($this->testcase, $markup, $selector)); + $this->assertEquals($expected, $method->invoke($this, $markup, $selector)); } /** * Data provider for testFlattenAttributeArray(). */ - public function attributeProvider() + public function provideAttributes() { return [ 'Single attribute' => [ @@ -238,7 +288,7 @@ public function attributeProvider() /** * Data provider for testGetInnerHtmlOfMatchedElements(). */ - public function innerHtmlProvider() + public function provideInnerHtml() { return [ 'A single match' => [ @@ -262,7 +312,7 @@ public function innerHtmlProvider() /** * Data provider for testAssertContainsSelector(). */ - public function selectorVariantProvider() + public function provideSelectorVariants() { return [ 'Simple tag name' => ['a'], diff --git a/tests/TestFiles/TestCaseWithMarkupAssertions.php b/tests/TestFiles/TestCaseWithMarkupAssertions.php deleted file mode 100644 index b794515..0000000 --- a/tests/TestFiles/TestCaseWithMarkupAssertions.php +++ /dev/null @@ -1,11 +0,0 @@ -