From f9df76957ec465d9f649da769a78a260161ce19c Mon Sep 17 00:00:00 2001 From: reganlawton Date: Fri, 22 Aug 2025 12:18:39 +1000 Subject: [PATCH 01/14] Update SimpleSharing plugin for Craft CMS 5.x compatibility and fix sharing URLs --- CHANGELOG.md | 6 + README.md | 48 +++++++- codeception.yml | 21 ++++ composer.json | 16 ++- src/SimpleSharing.php | 2 +- .../simplesharing/SimpleSharingAsset.php | 2 +- src/controllers/DefaultController.php | 6 +- src/models/Settings.php | 2 +- src/templates/settings.twig | 2 +- src/variables/SimpleSharingVariable.php | 2 +- tests/_bootstrap.php | 19 +++ tests/_craft/.gitignore | 2 + tests/_craft/config/test.php | 5 + tests/_craft/templates/index.twig | 1 + tests/_craft/templates/test-sharing.twig | 12 ++ tests/_data/.gitkeepa | 0 tests/_output/.gitignore | 2 + tests/_support/.gitignore | 1 + tests/_support/FunctionalTester.php | 27 +++++ tests/_support/Helper/Functional.php | 15 +++ tests/_support/Helper/Unit.php | 15 +++ tests/_support/UnitTester.php | 27 +++++ tests/functional.suite.yml | 11 ++ tests/functional/ExampleFunctionalCest.php | 22 ++++ .../SimpleSharingControllerCest.php | 61 ++++++++++ tests/unit.suite.yml | 10 ++ tests/unit/ExampleUnitTest.php | 20 ++++ tests/unit/SimpleSharingVariableTest.php | 109 ++++++++++++++++++ tests/unit/_bootstrap.php | 1 + 29 files changed, 452 insertions(+), 15 deletions(-) create mode 100644 codeception.yml create mode 100644 tests/_bootstrap.php create mode 100644 tests/_craft/.gitignore create mode 100644 tests/_craft/config/test.php create mode 100644 tests/_craft/templates/index.twig create mode 100644 tests/_craft/templates/test-sharing.twig create mode 100644 tests/_data/.gitkeepa create mode 100644 tests/_output/.gitignore create mode 100644 tests/_support/.gitignore create mode 100644 tests/_support/FunctionalTester.php create mode 100644 tests/_support/Helper/Functional.php create mode 100644 tests/_support/Helper/Unit.php create mode 100644 tests/_support/UnitTester.php create mode 100644 tests/functional.suite.yml create mode 100644 tests/functional/ExampleFunctionalCest.php create mode 100644 tests/functional/SimpleSharingControllerCest.php create mode 100644 tests/unit.suite.yml create mode 100644 tests/unit/ExampleUnitTest.php create mode 100644 tests/unit/SimpleSharingVariableTest.php create mode 100644 tests/unit/_bootstrap.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 2746d3d..5a0c845 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Simple Sharing Changelog +## 3.0.0 - 2024-XX-XX +### Updated +- Craft5.x Support Added (^3.0.0 is not backward compatible with Craft4.x, use 2.x branch). +- Fixed LinkedIn sharing URL to use correct endpoint +- Updated Tumblr sharing URL format + ## 2.0.0 - 2022-11-17 ### Updated - Craft4.x Support Added (^2.0.0 is not backward compatible with Craft3.x, use 1.x branch). diff --git a/README.md b/README.md index 163cdda..5b892ab 100755 --- a/README.md +++ b/README.md @@ -6,12 +6,14 @@ Simple Sharing is a CraftCMS plugin that generates social media share links with the Craft CP page, allowing you to quickly and easily share entries. ## Requirements -Current Version: 2.0.0\ -This plugin requires Craft CMS ^4.0.0. +Current Version: 3.0.0\ +This plugin requires Craft CMS ^5.0.0. -If you are looking for CraftCMS 3.x support, use current project [Version 1.0.8](https://github.com/wrav/SimpleSharing/tree/1.0.8) +If you are looking for CraftCMS 4.x support, use [Version 2.1.0](https://github.com/wrav/SimpleSharing/tree/master) -If you are looking for CraftCMS 2.5 support, use previous project [version 1.1.5](https://github.com/hut6/SimpleSharing/tree/1.1.5) +If you are looking for CraftCMS 3.x support, use [Version 1.0.8](https://github.com/wrav/SimpleSharing/tree/1.0.8) + +If you are looking for CraftCMS 2.5 support, use [version 1.1.5](https://github.com/hut6/SimpleSharing/tree/1.1.5) ## Installing @@ -40,6 +42,44 @@ Your able to generate share links on the fly in a template as followed. {{ craft.simpleSharing.link(url, 'reddit') }} ``` +## Testing + +The plugin includes a comprehensive test suite using Codeception for both unit and functional testing. + +### Running Tests + +```bash +# Install dev dependencies +composer install --dev + +# Run all tests +vendor/bin/codecept run + +# Run only unit tests +vendor/bin/codecept run unit + +# Run only functional tests +vendor/bin/codecept run functional + +# Run with coverage report +vendor/bin/codecept run --coverage +``` + +### Test Coverage + +- **Unit Tests**: URL generation, input validation, platform support +- **Functional Tests**: Controller endpoints, Craft integration +- **Template Tests**: Twig variable availability and output + +### Development Setup + +For plugin development: + +1. Clone the repository +2. Run `composer install --dev` +3. Configure your test environment in `tests/_craft/config/test.php` +4. Run tests with `vendor/bin/codecept run` + ## Credits Original built while at working at [HutSix](https://hutsix.com.au/) I've since been granted permission to continue development here. diff --git a/codeception.yml b/codeception.yml new file mode 100644 index 0000000..cba5998 --- /dev/null +++ b/codeception.yml @@ -0,0 +1,21 @@ +namespace: SimpleSharing\Tests +actor: Tester +paths: + tests: tests + output: tests/_output + data: tests/_data + support: tests/_support + envs: tests/_envs +actor_suffix: Tester +extensions: + enabled: + - Codeception\Extension\RunFailed + config: + Codeception\Extension\RunFailed: + file: tests/_output/failed +coverage: + enabled: true + include: + - src/* + exclude: + - src/assetbundles/* \ No newline at end of file diff --git a/composer.json b/composer.json index 8afd465..bd7fa0d 100755 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "wrav/simplesharing", "description": "Simple Sharing generates social media share links within CP entry pages, allowing you to quickly & easily share entries.", "type": "craft-plugin", - "version": "2.0.0", + "version": "3.0.0", "keywords": [ "craft", "cms", @@ -31,8 +31,9 @@ } ], "require": { - "php": ">=8.0.0", - "craftcms/cms": "^4.0.0" + "php": "^8.2", + "craftcms/cms": "^5.0.0", + "vlucas/phpdotenv": "^5.6" }, "repositories": [ { @@ -56,9 +57,18 @@ "class": "wrav\\simplesharing\\SimpleSharing" }, "config": { + "platform": { + "php": "8.2" + }, "allow-plugins": { "yiisoft/yii2-composer": true, "craftcms/plugin-installer": true } + }, + "require-dev": { + "phpunit/phpunit": "^11.4", + "codeception/module-yii2": "^1.1", + "codeception/module-phpbrowser": "^3.0", + "codeception/module-asserts": "^3.0" } } diff --git a/src/SimpleSharing.php b/src/SimpleSharing.php index f25a92d..c9a768b 100755 --- a/src/SimpleSharing.php +++ b/src/SimpleSharing.php @@ -1,6 +1,6 @@ 'Facebook', 'twitter' => 'Twitter', - 'linkedin' => 'LinkedIn', + 'linkedin' => 'LinkedIn', //'pinterest' => 'Pinterest', 'mix' => 'Mix', - 'tumblr' => 'Tumblr', + 'tumblr' => 'Tumblr', 'reddit' => 'Reddit', ]; diff --git a/src/models/Settings.php b/src/models/Settings.php index 24feec8..cf5cd4c 100755 --- a/src/models/Settings.php +++ b/src/models/Settings.php @@ -1,6 +1,6 @@ amOnPage('?p=/'); + $I->seeResponseCodeIs(200); + } + + public function testPluginTwigVariableExists(FunctionalTester $I): void + { + // Test that the simpleSharing Twig variable is available + $I->amOnPage('?p=/'); + // This would need a test template that uses {{ craft.simpleSharing }} + $I->seeResponseCodeIs(200); + } +} diff --git a/tests/functional/SimpleSharingControllerCest.php b/tests/functional/SimpleSharingControllerCest.php new file mode 100644 index 0000000..ace0896 --- /dev/null +++ b/tests/functional/SimpleSharingControllerCest.php @@ -0,0 +1,61 @@ +sendGet('/actions/simple-sharing/default/url', [ + 'id' => 1, + 'sectionId' => 1 + ]); + + // Should return 200 if entry exists and has URL + $I->seeResponseCodeIsSuccessful(); + } + + public function testControllerActionWithInvalidEntry(FunctionalTester $I): void + { + // Test with non-existent entry + $I->sendGet('/actions/simple-sharing/default/url', [ + 'id' => 99999, + 'sectionId' => 1 + ]); + + // Should return 404 for non-existent entry + $I->seeResponseCodeIs(404); + } + + public function testControllerActionWithMissingParameters(FunctionalTester $I): void + { + // Test without required parameters + $I->sendGet('/actions/simple-sharing/default/url'); + + // Should handle missing parameters gracefully + $I->seeResponseCodeIs(404); + } + + public function testControllerReturnsHtmlLinks(FunctionalTester $I): void + { + // Test that response contains expected HTML structure + $I->sendGet('/actions/simple-sharing/default/url', [ + 'id' => 1, + 'sectionId' => 1 + ]); + + if ($I->grabResponse() !== '') { + // If we get a response, check it contains sharing links + $I->seeInResponse('target="_blank"'); + $I->seeInResponse('href="https://'); + } + } +} \ No newline at end of file diff --git a/tests/unit.suite.yml b/tests/unit.suite.yml new file mode 100644 index 0000000..a8f6a92 --- /dev/null +++ b/tests/unit.suite.yml @@ -0,0 +1,10 @@ +# Codeception Test Suite Configuration +# +# Suite for unit tests + +actor: UnitTester +modules: + enabled: + - Asserts + - \SimpleSharing\Tests\Helper\Unit + step_decorators: ~ \ No newline at end of file diff --git a/tests/unit/ExampleUnitTest.php b/tests/unit/ExampleUnitTest.php new file mode 100644 index 0000000..68a2385 --- /dev/null +++ b/tests/unit/ExampleUnitTest.php @@ -0,0 +1,20 @@ +assertTrue(class_exists(SimpleSharing::class)); + } + + public function testPluginExtendsBasePlugin(): void + { + $reflection = new \ReflectionClass(SimpleSharing::class); + $this->assertTrue($reflection->isSubclassOf(\craft\base\Plugin::class)); + } +} diff --git a/tests/unit/SimpleSharingVariableTest.php b/tests/unit/SimpleSharingVariableTest.php new file mode 100644 index 0000000..187303f --- /dev/null +++ b/tests/unit/SimpleSharingVariableTest.php @@ -0,0 +1,109 @@ +variable = new SimpleSharingVariable(); + } + + public function testFacebookLink(): void + { + $url = 'https://example.com/test-page'; + $result = $this->variable->link($url, 'facebook'); + + $this->assertSame( + 'https://www.facebook.com/sharer/sharer.php?u=' . urlencode($url), + $result + ); + } + + public function testTwitterLink(): void + { + $url = 'https://example.com/test-page'; + $result = $this->variable->link($url, 'twitter'); + + $this->assertSame( + 'https://twitter.com/intent/tweet?text=' . urlencode($url), + $result + ); + } + + public function testLinkedInLink(): void + { + $url = 'https://example.com/test-page'; + $result = $this->variable->link($url, 'linkedin'); + + $this->assertSame( + 'https://www.linkedin.com/shareArticle?mini=true&title=&summary=&source=&url=' . urlencode($url), + $result + ); + } + + public function testMixLink(): void + { + $url = 'https://example.com/test-page'; + $result = $this->variable->link($url, 'mix'); + + $this->assertSame( + 'https://mix.com/add?url=' . urlencode($url), + $result + ); + } + + public function testTumblrLink(): void + { + $url = 'https://example.com/test-page'; + $result = $this->variable->link($url, 'tumblr'); + + $this->assertSame( + 'https://www.tumblr.com/share/link?url=' . urlencode($url), + $result + ); + } + + public function testRedditLink(): void + { + $url = 'https://example.com/test-page'; + $result = $this->variable->link($url, 'reddit'); + + $this->assertSame( + 'http://www.reddit.com/submit?url=' . urlencode($url), + $result + ); + } + + public function testUnsupportedService(): void + { + $url = 'https://example.com/test-page'; + $result = $this->variable->link($url, 'unsupported-service'); + + $this->assertNull($result); + } + + public function testEmptyUrl(): void + { + $result = $this->variable->link('', 'facebook'); + $this->assertNull($result); + + $result = $this->variable->link(' ', 'facebook'); + $this->assertNull($result); + } + + public function testUrlEncoding(): void + { + $url = 'https://example.com/test page with spaces & symbols'; + $result = $this->variable->link($url, 'facebook'); + + $this->assertStringContainsString(urlencode($url), $result); + $this->assertStringNotContainsString(' ', $result); + $this->assertStringNotContainsString('&', $result); + } +} \ No newline at end of file diff --git a/tests/unit/_bootstrap.php b/tests/unit/_bootstrap.php new file mode 100644 index 0000000..a814366 --- /dev/null +++ b/tests/unit/_bootstrap.php @@ -0,0 +1 @@ + Date: Fri, 22 Aug 2025 13:04:26 +1000 Subject: [PATCH 02/14] Add GitHub Actions workflow for Craft 5.x and Craft 4.x tests --- .github/workflows/tests.yml | 121 ++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..be5f425 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,121 @@ +name: Tests + +on: + pull_request: + branches: [ master, v2 ] + push: + branches: [ master, v2 ] + +jobs: + # Craft 5.x tests (master branch) - PHP 8.2+ + craft5-tests: + if: github.ref == 'refs/heads/master' || github.base_ref == 'master' + runs-on: ubuntu-latest + + strategy: + matrix: + php: [8.2, 8.3] + + name: Craft 5.x - PHP ${{ matrix.php }} Tests + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv + coverage: xdebug + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: craft5-${{ runner.os }}-php-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + craft5-${{ runner.os }}-php-${{ matrix.php }}- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress --dev + + - name: Build Codeception + run: vendor/bin/codecept build + + - name: Run unit tests + run: vendor/bin/codecept run unit --coverage --coverage-xml + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + if: matrix.php == '8.2' + with: + files: ./tests/_output/coverage.xml + fail_ci_if_error: false + verbose: true + + # Craft 4.x tests (v2 branch) - PHP 8.0+ + craft4-tests: + if: github.ref == 'refs/heads/v2' || github.base_ref == 'v2' + runs-on: ubuntu-latest + + strategy: + matrix: + php: [8.0, 8.1, 8.2] + + name: Craft 4.x - PHP ${{ matrix.php }} Tests + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv + coverage: xdebug + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: craft4-${{ runner.os }}-php-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + craft4-${{ runner.os }}-php-${{ matrix.php }}- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress --dev + + - name: Build Codeception (if exists) + run: | + if [ -f "vendor/bin/codecept" ]; then + vendor/bin/codecept build + fi + + - name: Run unit tests (if exists) + run: | + if [ -f "vendor/bin/codecept" ]; then + vendor/bin/codecept run unit + else + echo "No tests configured for this branch" + fi + + code-quality: + runs-on: ubuntu-latest + name: Code Quality + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv + + - name: Install dependencies + run: composer install --prefer-dist --no-progress --dev + + - name: Check PHP syntax + run: find src tests -name "*.php" -exec php -l {} \; \ No newline at end of file From 7363a727975f41488a2d31e1811c4532642d1240 Mon Sep 17 00:00:00 2001 From: reganlawton Date: Fri, 22 Aug 2025 13:29:46 +1000 Subject: [PATCH 03/14] Refactor test namespaces and add coverage reporting for GitHub Actions --- .github/workflows/tests.yml | 14 ++++++++++++++ codeception.yml | 2 +- tests/_support/FunctionalTester.php | 2 +- tests/_support/Helper/Functional.php | 2 +- tests/_support/Helper/Unit.php | 2 +- tests/_support/UnitTester.php | 2 +- tests/functional.suite.yml | 2 +- ...FunctionalCest.php => CraftIntegrationCest.php} | 4 ++-- tests/functional/SimpleSharingControllerCest.php | 4 ++-- tests/unit.suite.yml | 2 +- tests/unit/{ExampleUnitTest.php => PluginTest.php} | 2 +- tests/unit/SimpleSharingVariableTest.php | 2 +- 12 files changed, 27 insertions(+), 13 deletions(-) rename tests/functional/{ExampleFunctionalCest.php => CraftIntegrationCest.php} (85%) rename tests/unit/{ExampleUnitTest.php => PluginTest.php} (92%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index be5f425..1881b58 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -53,6 +53,20 @@ jobs: files: ./tests/_output/coverage.xml fail_ci_if_error: false verbose: true + + - name: Comment PR with coverage + uses: marocchino/sticky-pull-request-comment@v2 + if: github.event_name == 'pull_request' && matrix.php == '8.2' + with: + recreate: true + message: | + ## 📊 Test Coverage Report + + Coverage report for PHP ${{ matrix.php }}: + + ``` + $(vendor/bin/codecept run unit --coverage-text | grep -A 20 "Code Coverage Report") + ``` # Craft 4.x tests (v2 branch) - PHP 8.0+ craft4-tests: diff --git a/codeception.yml b/codeception.yml index cba5998..056f82a 100644 --- a/codeception.yml +++ b/codeception.yml @@ -1,4 +1,4 @@ -namespace: SimpleSharing\Tests +namespace: tests actor: Tester paths: tests: tests diff --git a/tests/_support/FunctionalTester.php b/tests/_support/FunctionalTester.php index 638391e..aa482fa 100644 --- a/tests/_support/FunctionalTester.php +++ b/tests/_support/FunctionalTester.php @@ -1,6 +1,6 @@ Date: Fri, 22 Aug 2025 13:37:20 +1000 Subject: [PATCH 04/14] Add coverage text report generation for pull requests in GitHub Actions --- .github/workflows/tests.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1881b58..0e1d80f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -54,6 +54,15 @@ jobs: fail_ci_if_error: false verbose: true + - name: Generate coverage text report + if: github.event_name == 'pull_request' && matrix.php == '8.2' + id: coverage + run: | + coverage_output=$(vendor/bin/codecept run unit --coverage-text 2>&1 | grep -A 50 "Code Coverage Report" || echo "No coverage data available") + echo "coverage-text<> $GITHUB_OUTPUT + echo "$coverage_output" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + - name: Comment PR with coverage uses: marocchino/sticky-pull-request-comment@v2 if: github.event_name == 'pull_request' && matrix.php == '8.2' @@ -65,7 +74,7 @@ jobs: Coverage report for PHP ${{ matrix.php }}: ``` - $(vendor/bin/codecept run unit --coverage-text | grep -A 20 "Code Coverage Report") + ${{ steps.coverage.outputs.coverage-text }} ``` # Craft 4.x tests (v2 branch) - PHP 8.0+ From 41ce379f3d937a9dc46dff11120dd315bcce820f Mon Sep 17 00:00:00 2001 From: reganlawton Date: Fri, 22 Aug 2025 13:40:44 +1000 Subject: [PATCH 05/14] Enhance GitHub Actions coverage reporting by extracting summary metrics and test results --- .github/workflows/tests.yml | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0e1d80f..430cb3d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -58,10 +58,22 @@ jobs: if: github.event_name == 'pull_request' && matrix.php == '8.2' id: coverage run: | - coverage_output=$(vendor/bin/codecept run unit --coverage-text 2>&1 | grep -A 50 "Code Coverage Report" || echo "No coverage data available") - echo "coverage-text<> $GITHUB_OUTPUT - echo "$coverage_output" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT + # Run coverage and strip ANSI color codes + raw_output=$(vendor/bin/codecept run unit --coverage-text --no-ansi 2>&1) + + # Extract just the coverage summary + summary=$(echo "$raw_output" | sed -n '/Summary:/,/^$/p' | head -4) + classes=$(echo "$summary" | grep "Classes:" | sed 's/.*Classes: //' | sed 's/ .*//') + methods=$(echo "$summary" | grep "Methods:" | sed 's/.*Methods: //' | sed 's/ .*//') + lines=$(echo "$summary" | grep "Lines:" | sed 's/.*Lines: //' | sed 's/ .*//') + + # Get test results + test_result=$(echo "$raw_output" | grep "OK (" || echo "Tests failed") + + echo "classes=$classes" >> $GITHUB_OUTPUT + echo "methods=$methods" >> $GITHUB_OUTPUT + echo "lines=$lines" >> $GITHUB_OUTPUT + echo "test-result=$test_result" >> $GITHUB_OUTPUT - name: Comment PR with coverage uses: marocchino/sticky-pull-request-comment@v2 @@ -69,13 +81,15 @@ jobs: with: recreate: true message: | - ## 📊 Test Coverage Report + ## 📊 Test Coverage Report (PHP ${{ matrix.php }}) - Coverage report for PHP ${{ matrix.php }}: + | Metric | Coverage | + |--------|----------| + | **Classes** | `${{ steps.coverage.outputs.classes }}` | + | **Methods** | `${{ steps.coverage.outputs.methods }}` | + | **Lines** | `${{ steps.coverage.outputs.lines }}` | - ``` - ${{ steps.coverage.outputs.coverage-text }} - ``` + **Test Results:** ${{ steps.coverage.outputs.test-result }} # Craft 4.x tests (v2 branch) - PHP 8.0+ craft4-tests: From f097d6a7babab8d8397d121d83de0a65d349df0e Mon Sep 17 00:00:00 2001 From: reganlawton Date: Fri, 22 Aug 2025 13:43:14 +1000 Subject: [PATCH 06/14] Refactor coverage summary extraction in unit test output --- .github/workflows/tests.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 430cb3d..684ccbe 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -62,10 +62,9 @@ jobs: raw_output=$(vendor/bin/codecept run unit --coverage-text --no-ansi 2>&1) # Extract just the coverage summary - summary=$(echo "$raw_output" | sed -n '/Summary:/,/^$/p' | head -4) - classes=$(echo "$summary" | grep "Classes:" | sed 's/.*Classes: //' | sed 's/ .*//') - methods=$(echo "$summary" | grep "Methods:" | sed 's/.*Methods: //' | sed 's/ .*//') - lines=$(echo "$summary" | grep "Lines:" | sed 's/.*Lines: //' | sed 's/ .*//') + classes=$(echo "$raw_output" | grep "Classes:" | sed 's/.*Classes: \([0-9.]*%\).*/\1/') + methods=$(echo "$raw_output" | grep "Methods:" | sed 's/.*Methods: \([0-9.]*%\).*/\1/') + lines=$(echo "$raw_output" | grep "Lines:" | sed 's/.*Lines: \([0-9.]*%\).*/\1/') # Get test results test_result=$(echo "$raw_output" | grep "OK (" || echo "Tests failed") From c3921b23cab8985f4ccc6ed30e76b994239b9a83 Mon Sep 17 00:00:00 2001 From: reganlawton Date: Fri, 22 Aug 2025 13:48:51 +1000 Subject: [PATCH 07/14] Fix regex patterns for coverage summary extraction in unit test output --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 684ccbe..f92704c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -62,9 +62,9 @@ jobs: raw_output=$(vendor/bin/codecept run unit --coverage-text --no-ansi 2>&1) # Extract just the coverage summary - classes=$(echo "$raw_output" | grep "Classes:" | sed 's/.*Classes: \([0-9.]*%\).*/\1/') - methods=$(echo "$raw_output" | grep "Methods:" | sed 's/.*Methods: \([0-9.]*%\).*/\1/') - lines=$(echo "$raw_output" | grep "Lines:" | sed 's/.*Lines: \([0-9.]*%\).*/\1/') + classes=$(echo "$raw_output" | grep "Classes:" | sed 's/.*Classes: \([0-9.%]*\).*/\1/') + methods=$(echo "$raw_output" | grep "Methods:" | sed 's/.*Methods: \([0-9.%]*\).*/\1/') + lines=$(echo "$raw_output" | grep "Lines:" | sed 's/.*Lines: \([0-9.%]*\).*/\1/') # Get test results test_result=$(echo "$raw_output" | grep "OK (" || echo "Tests failed") From 58ce6e1a2d74c9015dc13d597129f5bcfc6dd37a Mon Sep 17 00:00:00 2001 From: reganlawton Date: Fri, 22 Aug 2025 13:56:51 +1000 Subject: [PATCH 08/14] Simplify coverage summary extraction in GitHub Actions workflow --- .github/workflows/tests.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f92704c..85d8d5d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -61,18 +61,21 @@ jobs: # Run coverage and strip ANSI color codes raw_output=$(vendor/bin/codecept run unit --coverage-text --no-ansi 2>&1) - # Extract just the coverage summary - classes=$(echo "$raw_output" | grep "Classes:" | sed 's/.*Classes: \([0-9.%]*\).*/\1/') - methods=$(echo "$raw_output" | grep "Methods:" | sed 's/.*Methods: \([0-9.%]*\).*/\1/') - lines=$(echo "$raw_output" | grep "Lines:" | sed 's/.*Lines: \([0-9.%]*\).*/\1/') + # Extract just the coverage summary with simpler approach + classes=$(echo "$raw_output" | grep "Classes:" | cut -d' ' -f3) + methods=$(echo "$raw_output" | grep "Methods:" | cut -d' ' -f3) + lines=$(echo "$raw_output" | grep "Lines:" | cut -d' ' -f3) # Get test results test_result=$(echo "$raw_output" | grep "OK (" || echo "Tests failed") - echo "classes=$classes" >> $GITHUB_OUTPUT - echo "methods=$methods" >> $GITHUB_OUTPUT - echo "lines=$lines" >> $GITHUB_OUTPUT - echo "test-result=$test_result" >> $GITHUB_OUTPUT + # Use simple variable assignment to avoid special characters + { + echo "classes=${classes}" + echo "methods=${methods}" + echo "lines=${lines}" + echo "test-result=${test_result}" + } >> "$GITHUB_OUTPUT" - name: Comment PR with coverage uses: marocchino/sticky-pull-request-comment@v2 From 917471452103e7f753cd2aa352dac780f87665d8 Mon Sep 17 00:00:00 2001 From: reganlawton Date: Fri, 22 Aug 2025 14:00:20 +1000 Subject: [PATCH 09/14] Improve coverage summary extraction in GitHub Actions workflow for reliability --- .github/workflows/tests.yml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 85d8d5d..aa05622 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -61,21 +61,23 @@ jobs: # Run coverage and strip ANSI color codes raw_output=$(vendor/bin/codecept run unit --coverage-text --no-ansi 2>&1) - # Extract just the coverage summary with simpler approach - classes=$(echo "$raw_output" | grep "Classes:" | cut -d' ' -f3) - methods=$(echo "$raw_output" | grep "Methods:" | cut -d' ' -f3) - lines=$(echo "$raw_output" | grep "Lines:" | cut -d' ' -f3) + # Debug: show the actual lines + echo "Raw coverage lines:" + echo "$raw_output" | grep -E "(Classes|Methods|Lines):" + + # Extract coverage percentages more reliably + classes=$(echo "$raw_output" | grep "Classes:" | grep -o '[0-9]*\.[0-9]*%' | head -1) + methods=$(echo "$raw_output" | grep "Methods:" | grep -o '[0-9]*\.[0-9]*%' | head -1) + lines=$(echo "$raw_output" | grep "Lines:" | grep -o '[0-9]*\.[0-9]*%' | head -1) # Get test results test_result=$(echo "$raw_output" | grep "OK (" || echo "Tests failed") - # Use simple variable assignment to avoid special characters - { - echo "classes=${classes}" - echo "methods=${methods}" - echo "lines=${lines}" - echo "test-result=${test_result}" - } >> "$GITHUB_OUTPUT" + # Use simple variable assignment + echo "classes=${classes:-N/A}" >> "$GITHUB_OUTPUT" + echo "methods=${methods:-N/A}" >> "$GITHUB_OUTPUT" + echo "lines=${lines:-N/A}" >> "$GITHUB_OUTPUT" + echo "test-result=${test_result:-Tests failed}" >> "$GITHUB_OUTPUT" - name: Comment PR with coverage uses: marocchino/sticky-pull-request-comment@v2 From c4c4313e37be9f0a42fd12663149e2559213a5b1 Mon Sep 17 00:00:00 2001 From: reganlawton Date: Fri, 22 Aug 2025 14:02:43 +1000 Subject: [PATCH 10/14] Improve reliability of coverage percentage extraction in GitHub Actions workflow --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index aa05622..db9c2d0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -66,9 +66,9 @@ jobs: echo "$raw_output" | grep -E "(Classes|Methods|Lines):" # Extract coverage percentages more reliably - classes=$(echo "$raw_output" | grep "Classes:" | grep -o '[0-9]*\.[0-9]*%' | head -1) - methods=$(echo "$raw_output" | grep "Methods:" | grep -o '[0-9]*\.[0-9]*%' | head -1) - lines=$(echo "$raw_output" | grep "Lines:" | grep -o '[0-9]*\.[0-9]*%' | head -1) + classes=$(echo "$raw_output" | grep "Classes:" | grep -o '[0-9]*\.[0-9]*%' | head -1 || echo "N/A") + methods=$(echo "$raw_output" | grep "Methods:" | grep -o '[0-9]*\.[0-9]*%' | head -1 || echo "N/A") + lines=$(echo "$raw_output" | grep "Lines:" | grep -o '[0-9]*\.[0-9]*%' | head -1 || echo "N/A") # Get test results test_result=$(echo "$raw_output" | grep "OK (" || echo "Tests failed") From d96e309b7ad9e9219faf725fc6b00f4159c9daa3 Mon Sep 17 00:00:00 2001 From: Siyabulela Date: Wed, 14 Jan 2026 07:29:50 +0200 Subject: [PATCH 11/14] Fix Craft 5 compatibility: Update sections service to entries In Craft 5, the sections service has been moved to the entries service. This updates the call from Craft::$app->sections->getAllSections() to Craft::$app->entries->getAllSections() to fix the plugin settings page. Fixes #22 --- src/SimpleSharing.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SimpleSharing.php b/src/SimpleSharing.php index c9a768b..3fe1b5d 100755 --- a/src/SimpleSharing.php +++ b/src/SimpleSharing.php @@ -96,7 +96,7 @@ protected function createSettingsModel(): ?Model */ protected function settingsHtml(): string { - $sections = Craft::$app->sections->getAllSections(); + $sections = Craft::$app->entries->getAllSections(); $optionsSections = []; foreach ($sections as $section) { From 7592ed7a3e8077b1af7770a22d75d3afce38399d Mon Sep 17 00:00:00 2001 From: Regan Lawton Date: Wed, 14 Jan 2026 20:14:48 +1100 Subject: [PATCH 12/14] Add integration testing environment with Docker and PostgreSQL; remove functional tests; update documentation and CI workflows --- .github/workflows/tests.yml | 110 +++++++++++------- .gitignore | 2 + AGENTS.md | 35 ++++++ CHANGELOG.md | 5 +- CLAUDE.md | 65 +++++++++++ README.md | 5 +- codeception.yml | 25 +++- docker-compose.yml | 26 +++++ tests/.env.example | 7 ++ tests/_craft/config/db.php | 9 ++ tests/_craft/config/test.php | 2 +- tests/_support/IntegrationTester.php | 10 ++ .../SimpleSharingControllerCest.php | 61 ---------- tests/integration.suite.yml | 11 ++ tests/integration/PluginIntegrationTest.php | 64 ++++++++++ tests/integration/_bootstrap.php | 4 + tests/unit.suite.yml | 2 +- tests/unit/PluginTest.php | 23 ++++ 18 files changed, 353 insertions(+), 113 deletions(-) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 docker-compose.yml create mode 100644 tests/.env.example create mode 100644 tests/_craft/config/db.php create mode 100644 tests/_support/IntegrationTester.php delete mode 100644 tests/functional/SimpleSharingControllerCest.php create mode 100644 tests/integration.suite.yml create mode 100644 tests/integration/PluginIntegrationTest.php create mode 100644 tests/integration/_bootstrap.php diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index db9c2d0..317ef68 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,23 +11,38 @@ jobs: craft5-tests: if: github.ref == 'refs/heads/master' || github.base_ref == 'master' runs-on: ubuntu-latest - + + services: + postgres: + image: postgres:13-alpine + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + strategy: matrix: php: [8.2, 8.3] - + name: Craft 5.x - PHP ${{ matrix.php }} Tests - + steps: - uses: actions/checkout@v4 - + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, pdo_pgsql, bcmath, soap, intl, gd, exif, iconv coverage: xdebug - + - name: Cache Composer packages id: composer-cache uses: actions/cache@v3 @@ -36,16 +51,28 @@ jobs: key: craft5-${{ runner.os }}-php-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} restore-keys: | craft5-${{ runner.os }}-php-${{ matrix.php }}- - + - name: Install dependencies run: composer install --prefer-dist --no-progress --dev - + + - name: Setup test environment + run: | + cp tests/.env.example tests/.env + sed -i 's/host=postgres/host=localhost/' tests/.env + - name: Build Codeception run: vendor/bin/codecept build - - - name: Run unit tests - run: vendor/bin/codecept run unit --coverage --coverage-xml - + + - name: Run all tests + run: vendor/bin/codecept run --coverage --coverage-xml + env: + CRAFT_DB_DSN: "pgsql:host=localhost;port=5432;dbname=postgres" + CRAFT_DB_USER: postgres + CRAFT_DB_PASSWORD: postgres + CRAFT_DB_SCHEMA: public + CRAFT_DB_TABLE_PREFIX: craft + CRAFT_SECURITY_KEY: test-security-key-for-github-actions + - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 if: matrix.php == '8.2' @@ -53,32 +80,31 @@ jobs: files: ./tests/_output/coverage.xml fail_ci_if_error: false verbose: true - + - name: Generate coverage text report if: github.event_name == 'pull_request' && matrix.php == '8.2' id: coverage run: | - # Run coverage and strip ANSI color codes raw_output=$(vendor/bin/codecept run unit --coverage-text --no-ansi 2>&1) - - # Debug: show the actual lines - echo "Raw coverage lines:" - echo "$raw_output" | grep -E "(Classes|Methods|Lines):" - - # Extract coverage percentages more reliably + classes=$(echo "$raw_output" | grep "Classes:" | grep -o '[0-9]*\.[0-9]*%' | head -1 || echo "N/A") methods=$(echo "$raw_output" | grep "Methods:" | grep -o '[0-9]*\.[0-9]*%' | head -1 || echo "N/A") lines=$(echo "$raw_output" | grep "Lines:" | grep -o '[0-9]*\.[0-9]*%' | head -1 || echo "N/A") - - # Get test results - test_result=$(echo "$raw_output" | grep "OK (" || echo "Tests failed") - - # Use simple variable assignment + + test_result=$(echo "$raw_output" | grep "OK (" || echo "Tests completed") + echo "classes=${classes:-N/A}" >> "$GITHUB_OUTPUT" echo "methods=${methods:-N/A}" >> "$GITHUB_OUTPUT" echo "lines=${lines:-N/A}" >> "$GITHUB_OUTPUT" - echo "test-result=${test_result:-Tests failed}" >> "$GITHUB_OUTPUT" - + echo "test-result=${test_result:-Tests completed}" >> "$GITHUB_OUTPUT" + env: + CRAFT_DB_DSN: "pgsql:host=localhost;port=5432;dbname=postgres" + CRAFT_DB_USER: postgres + CRAFT_DB_PASSWORD: postgres + CRAFT_DB_SCHEMA: public + CRAFT_DB_TABLE_PREFIX: craft + CRAFT_SECURITY_KEY: test-security-key-for-github-actions + - name: Comment PR with coverage uses: marocchino/sticky-pull-request-comment@v2 if: github.event_name == 'pull_request' && matrix.php == '8.2' @@ -86,36 +112,36 @@ jobs: recreate: true message: | ## 📊 Test Coverage Report (PHP ${{ matrix.php }}) - + | Metric | Coverage | |--------|----------| | **Classes** | `${{ steps.coverage.outputs.classes }}` | | **Methods** | `${{ steps.coverage.outputs.methods }}` | | **Lines** | `${{ steps.coverage.outputs.lines }}` | - + **Test Results:** ${{ steps.coverage.outputs.test-result }} # Craft 4.x tests (v2 branch) - PHP 8.0+ craft4-tests: if: github.ref == 'refs/heads/v2' || github.base_ref == 'v2' runs-on: ubuntu-latest - + strategy: matrix: php: [8.0, 8.1, 8.2] - + name: Craft 4.x - PHP ${{ matrix.php }} Tests - + steps: - uses: actions/checkout@v4 - + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv coverage: xdebug - + - name: Cache Composer packages id: composer-cache uses: actions/cache@v3 @@ -124,16 +150,16 @@ jobs: key: craft4-${{ runner.os }}-php-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} restore-keys: | craft4-${{ runner.os }}-php-${{ matrix.php }}- - + - name: Install dependencies run: composer install --prefer-dist --no-progress --dev - + - name: Build Codeception (if exists) run: | if [ -f "vendor/bin/codecept" ]; then vendor/bin/codecept build fi - + - name: Run unit tests (if exists) run: | if [ -f "vendor/bin/codecept" ]; then @@ -145,18 +171,18 @@ jobs: code-quality: runs-on: ubuntu-latest name: Code Quality - + steps: - uses: actions/checkout@v4 - + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: 8.2 extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv - + - name: Install dependencies run: composer install --prefer-dist --no-progress --dev - + - name: Check PHP syntax - run: find src tests -name "*.php" -exec php -l {} \; \ No newline at end of file + run: find src tests -name "*.php" -exec php -l {} \; diff --git a/.gitignore b/.gitignore index a17970c..737f155 100755 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ # COMPOSER /vendor +composer.lock # BUILD FILES /bower_components/* @@ -30,3 +31,4 @@ !.vscode/extensions.json config.codekit3 prepros-6.config + diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..bed6c67 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,35 @@ +# Repository Guidelines + +## Project Structure & Module Organization +- `src/`: Plugin source code (controllers, models, asset bundles, templates, variables). +- `tests/`: Codeception suites (`unit/`, `functional/`) plus support data in `_support/` and `_data/`. +- `resources/`: Plugin resources and metadata assets. +- `vendor/`: Composer-managed dependencies (generated). + +## Build, Test, and Development Commands +- `composer install --dev`: Install runtime + dev dependencies for local development. +- `composer require wrav/simplesharing`: Install the plugin into a Craft project. +- `vendor/bin/codecept run`: Run all Codeception tests. +- `vendor/bin/codecept run unit`: Run unit tests only. +- `vendor/bin/codecept run functional`: Run functional tests only. +- `vendor/bin/codecept run --coverage`: Generate a coverage report. + +## Coding Style & Naming Conventions +- Language: PHP 8.2; Craft CMS plugin conventions. +- Autoloading: PSR-4 namespace `wrav\simplesharing\` mapped to `src/`. +- File naming: Class files match class names (e.g., `SimpleSharing.php`). +- Indentation: 4 spaces; keep files ASCII unless existing content requires Unicode. + +## Testing Guidelines +- Framework: Codeception (with PHPUnit under the hood). +- Suites: `unit` and `functional` are defined by `tests/*.suite.yml`. +- Naming: Place unit tests in `tests/unit` and functional tests in `tests/functional`; match Codeception naming conventions (e.g., `*Test.php`). +- Config: Set Craft test environment in `tests/_craft/config/test.php` before running functional tests. + +## Commit & Pull Request Guidelines +- Commits: Use short, imperative, sentence-case summaries (e.g., “Fix coverage summary extraction”); no prefix observed in recent history. +- PRs: Include a clear description, linked issue (if any), and test results. Add screenshots or recordings for Control Panel UI changes. + +## Security & Configuration Tips +- Do not commit secrets or `.env` files. Use local environment overrides only. +- Validate changes against Craft’s plugin requirements (`composer.json`) before release. diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a0c845..a97b13d 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,14 @@ # Simple Sharing Changelog -## 3.0.0 - 2024-XX-XX +## 3.0.0 - 2026-01-14 ### Updated - Craft5.x Support Added (^3.0.0 is not backward compatible with Craft4.x, use 2.x branch). - Fixed LinkedIn sharing URL to use correct endpoint - Updated Tumblr sharing URL format +# Added +- Added support for functional, integration and unit testing + ## 2.0.0 - 2022-11-17 ### Updated - Craft4.x Support Added (^2.0.0 is not backward compatible with Craft3.x, use 1.x branch). diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..c5cfa28 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,65 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Simple Sharing is a Craft CMS 5.x plugin that generates social media share links within the Control Panel, allowing quick sharing of entries to Facebook, Twitter, LinkedIn, Mix, Tumblr, and Reddit. + +## Commands + +```bash +# Install dependencies +composer install --dev + +# Build Codeception (regenerate actor classes) +vendor/bin/codecept build + +# Check PHP syntax +find src tests -name "*.php" -exec php -l {} \; +``` + +### Running Tests (requires Docker) + +Tests require a PostgreSQL database. Use Docker Compose: + +```bash +# Setup test environment +cp tests/.env.example tests/.env + +# Start Docker containers +docker compose up -d + +# Access app container and run tests +docker exec -it app sh +vendor/bin/codecept run # All tests +vendor/bin/codecept run unit # Unit tests only +vendor/bin/codecept run integration # Integration tests only +vendor/bin/codecept run --coverage # With coverage +``` + +## Architecture + +**Plugin Structure** (`src/`): +- `SimpleSharing.php` - Main plugin class, registers Twig variable and injects CP JavaScript +- `variables/SimpleSharingVariable.php` - Twig variable providing `craft.simpleSharing.link(url, service)` +- `models/Settings.php` - Plugin settings (allowedSections, allowedPlatforms) +- `controllers/DefaultController.php` - Controller for CP actions (`actionUrl`) +- `assetbundles/simplesharing/` - JavaScript for CP sidebar functionality +- `templates/settings.twig` - Settings page template + +**Key Integration Points**: +- Registers `simpleSharing` variable on `CraftVariable::EVENT_INIT` +- Injects JavaScript on `View::EVENT_END_PAGE` for CP requests +- Extends `craft\base\Plugin` with settings model + +**Testing** (`tests/`): +- Uses Codeception with `unit`, `integration`, and `functional` suites +- Unit tests: Core functionality without Craft bootstrap +- Integration tests: Full Craft CMS integration with plugin installed +- Test config in `codeception.yml` with `\craft\test\Craft` module +- Database setup: `dbSetup: { clean: true, setupCraft: true }` + +## Supported Platforms + +facebook, twitter, linkedin, mix, tumblr, reddit diff --git a/README.md b/README.md index 5b892ab..38461e3 100755 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Simple Sharing is a CraftCMS plugin that generates social media share links with the Craft CP page, allowing you to quickly and easily share entries. ## Requirements -Current Version: 3.0.0\ +Current Version: 3.0.0 This plugin requires Craft CMS ^5.0.0. If you are looking for CraftCMS 4.x support, use [Version 2.1.0](https://github.com/wrav/SimpleSharing/tree/master) @@ -61,6 +61,9 @@ vendor/bin/codecept run unit # Run only functional tests vendor/bin/codecept run functional +# Run integartion tests +vendor/bin/codecept run integration + # Run with coverage report vendor/bin/codecept run --coverage ``` diff --git a/codeception.yml b/codeception.yml index 056f82a..c8d4275 100644 --- a/codeception.yml +++ b/codeception.yml @@ -6,16 +6,29 @@ paths: data: tests/_data support: tests/_support envs: tests/_envs -actor_suffix: Tester -extensions: +bootstrap: _bootstrap.php +params: + - tests/.env +modules: enabled: - - Codeception\Extension\RunFailed + - \craft\test\Craft config: - Codeception\Extension\RunFailed: - file: tests/_output/failed + \craft\test\Craft: + configFile: "tests/_craft/config/test.php" + entryUrl: "https://localhost/index.php" + projectConfig: {} + migrations: [] + plugins: + simple-sharing: + class: '\wrav\simplesharing\SimpleSharing' + handle: simple-sharing + cleanup: true + transaction: true + dbSetup: { clean: true, setupCraft: true } coverage: enabled: true include: - src/* exclude: - - src/assetbundles/* \ No newline at end of file + - tests/* + - src/assetbundles/* diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7bf5b60 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,26 @@ +# Add postgres service for unit testing +services: + postgres: + image: postgres:13-alpine + container_name: postgres + ports: + - 5432:5432 + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + healthcheck: + test: ["CMD", "pg_isready", "-U", "postgres", "-d", "postgres"] + interval: 5s + retries: 3 + app: + image: craftcms/nginx:8.2-dev + container_name: app + environment: + XDEBUG_CONFIG: client_host=host.docker.internal + depends_on: + postgres: + condition: service_healthy + volumes: + - .:/app + # vendor/bin/codecept run \ No newline at end of file diff --git a/tests/.env.example b/tests/.env.example new file mode 100644 index 0000000..fb04154 --- /dev/null +++ b/tests/.env.example @@ -0,0 +1,7 @@ +CRAFT_DB_DSN="pgsql:host=postgres;port=5432;dbname=postgres" +CRAFT_DB_USER="postgres" +CRAFT_DB_PASSWORD="postgres" +CRAFT_DB_SCHEMA="public" +CRAFT_DB_TABLE_PREFIX="craft" + +CRAFT_SECURITY_KEY=test-security-key-change-in-production diff --git a/tests/_craft/config/db.php b/tests/_craft/config/db.php new file mode 100644 index 0000000..4647279 --- /dev/null +++ b/tests/_craft/config/db.php @@ -0,0 +1,9 @@ + getenv('CRAFT_DB_DSN'), + 'user' => getenv('CRAFT_DB_USER'), + 'password' => getenv('CRAFT_DB_PASSWORD'), + 'schema' => getenv('CRAFT_DB_SCHEMA'), + 'tablePrefix' => getenv('CRAFT_DB_TABLE_PREFIX'), +]; diff --git a/tests/_craft/config/test.php b/tests/_craft/config/test.php index 1d13758..a5b52b4 100644 --- a/tests/_craft/config/test.php +++ b/tests/_craft/config/test.php @@ -2,4 +2,4 @@ use craft\test\TestSetup; -return TestSetup::createTestCraftObjectConfig(); \ No newline at end of file +return TestSetup::createTestCraftObjectConfig(); diff --git a/tests/_support/IntegrationTester.php b/tests/_support/IntegrationTester.php new file mode 100644 index 0000000..12cf1c0 --- /dev/null +++ b/tests/_support/IntegrationTester.php @@ -0,0 +1,10 @@ +sendGet('/actions/simple-sharing/default/url', [ - 'id' => 1, - 'sectionId' => 1 - ]); - - // Should return 200 if entry exists and has URL - $I->seeResponseCodeIsSuccessful(); - } - - public function testControllerActionWithInvalidEntry(FunctionalTester $I): void - { - // Test with non-existent entry - $I->sendGet('/actions/simple-sharing/default/url', [ - 'id' => 99999, - 'sectionId' => 1 - ]); - - // Should return 404 for non-existent entry - $I->seeResponseCodeIs(404); - } - - public function testControllerActionWithMissingParameters(FunctionalTester $I): void - { - // Test without required parameters - $I->sendGet('/actions/simple-sharing/default/url'); - - // Should handle missing parameters gracefully - $I->seeResponseCodeIs(404); - } - - public function testControllerReturnsHtmlLinks(FunctionalTester $I): void - { - // Test that response contains expected HTML structure - $I->sendGet('/actions/simple-sharing/default/url', [ - 'id' => 1, - 'sectionId' => 1 - ]); - - if ($I->grabResponse() !== '') { - // If we get a response, check it contains sharing links - $I->seeInResponse('target="_blank"'); - $I->seeInResponse('href="https://'); - } - } -} \ No newline at end of file diff --git a/tests/integration.suite.yml b/tests/integration.suite.yml new file mode 100644 index 0000000..6f689bc --- /dev/null +++ b/tests/integration.suite.yml @@ -0,0 +1,11 @@ +# Codeception Test Suite Configuration +# +# Suite for integration tests with Craft CMS bootstrapped + +actor: IntegrationTester +bootstrap: _bootstrap.php +modules: + enabled: + - Asserts + - \tests\Helper\Unit + step_decorators: ~ diff --git a/tests/integration/PluginIntegrationTest.php b/tests/integration/PluginIntegrationTest.php new file mode 100644 index 0000000..6b7fc5b --- /dev/null +++ b/tests/integration/PluginIntegrationTest.php @@ -0,0 +1,64 @@ +plugins->getPlugin('simple-sharing'); + + $this->assertNotNull($plugin); + $this->assertInstanceOf(SimpleSharing::class, $plugin); + } + + public function testSettingsModelHasCorrectDefaults(): void + { + $plugin = SimpleSharing::getInstance(); + $settings = $plugin->getSettings(); + + $this->assertInstanceOf(Settings::class, $settings); + $this->assertIsArray($settings->allowedSections); + $this->assertIsArray($settings->allowedPlatforms); + } + + public function testSettingsHtmlRendersWithSections(): void + { + $plugin = SimpleSharing::getInstance(); + + $reflection = new \ReflectionMethod($plugin, 'settingsHtml'); + $reflection->setAccessible(true); + + $html = $reflection->invoke($plugin); + + $this->assertIsString($html); + $this->assertStringContainsString('allowedSections', $html); + $this->assertStringContainsString('allowedPlatforms', $html); + + // Verify platform options are rendered + $this->assertStringContainsString('Facebook', $html); + $this->assertStringContainsString('Twitter', $html); + $this->assertStringContainsString('LinkedIn', $html); + } + + public function testSettingsHtmlIncludesSectionsFromCraft(): void + { + $sections = Craft::$app->entries->getAllSections(); + $plugin = SimpleSharing::getInstance(); + + $reflection = new \ReflectionMethod($plugin, 'settingsHtml'); + $reflection->setAccessible(true); + + $html = $reflection->invoke($plugin); + + // If there are sections in the system, they should appear in the settings + foreach ($sections as $section) { + $this->assertStringContainsString($section->name, $html); + } + } +} diff --git a/tests/integration/_bootstrap.php b/tests/integration/_bootstrap.php new file mode 100644 index 0000000..cac8ad0 --- /dev/null +++ b/tests/integration/_bootstrap.php @@ -0,0 +1,4 @@ +assertTrue($reflection->isSubclassOf(\craft\base\Plugin::class)); } + + public function testSettingsHtmlMethodExists(): void + { + $reflection = new \ReflectionClass(SimpleSharing::class); + + $this->assertTrue($reflection->hasMethod('settingsHtml')); + + $method = $reflection->getMethod('settingsHtml'); + $this->assertTrue($method->isProtected()); + $this->assertEquals('string', $method->getReturnType()->getName()); + } + + public function testCreateSettingsModelMethodExists(): void + { + $reflection = new \ReflectionClass(SimpleSharing::class); + + $this->assertTrue($reflection->hasMethod('createSettingsModel')); + + $method = $reflection->getMethod('createSettingsModel'); + $this->assertTrue($method->isProtected()); + } + } From cdba0c6cf7a732bac0b7189d6f70f635cb67309f Mon Sep 17 00:00:00 2001 From: Regan Lawton Date: Wed, 14 Jan 2026 20:24:48 +1100 Subject: [PATCH 13/14] Update CI workflow: Add missing directories for Craft storage and output --- .github/workflows/tests.yml | 6 ++++++ tests/_craft/migrations/.gitkeep | 0 tests/_craft/translations/.gitkeep | 0 3 files changed, 6 insertions(+) create mode 100644 tests/_craft/migrations/.gitkeep create mode 100644 tests/_craft/translations/.gitkeep diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 317ef68..f14a2c2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -59,6 +59,12 @@ jobs: run: | cp tests/.env.example tests/.env sed -i 's/host=postgres/host=localhost/' tests/.env + mkdir -p tests/_craft/storage/runtime + mkdir -p tests/_craft/storage/logs + mkdir -p tests/_craft/storage/config-deltas + mkdir -p tests/_craft/migrations + mkdir -p tests/_craft/translations + mkdir -p tests/_output - name: Build Codeception run: vendor/bin/codecept build diff --git a/tests/_craft/migrations/.gitkeep b/tests/_craft/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/_craft/translations/.gitkeep b/tests/_craft/translations/.gitkeep new file mode 100644 index 0000000..e69de29 From e874a0850a77d6e38e0231b6f63380b7118f8693 Mon Sep 17 00:00:00 2001 From: Regan Lawton Date: Wed, 14 Jan 2026 20:34:54 +1100 Subject: [PATCH 14/14] Update README: Add version matrix, improve testing instructions, and refine test suite details --- README.md | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 38461e3..dcdfc8a 100755 --- a/README.md +++ b/README.md @@ -6,14 +6,16 @@ Simple Sharing is a CraftCMS plugin that generates social media share links with the Craft CP page, allowing you to quickly and easily share entries. ## Requirements -Current Version: 3.0.0 -This plugin requires Craft CMS ^5.0.0. -If you are looking for CraftCMS 4.x support, use [Version 2.1.0](https://github.com/wrav/SimpleSharing/tree/master) +| Version | Craft CMS | PHP | +|---------|-----------|-----| +| ^3.0.0 | ^5.0.0 | ^8.2 | +| ^2.0.0 | ^4.0.0 | ^8.0.2 | +| ^1.0.0 | ^3.0.0 | ^7.2.5 | -If you are looking for CraftCMS 3.x support, use [Version 1.0.8](https://github.com/wrav/SimpleSharing/tree/1.0.8) +If you are looking for CraftCMS 4.x support, use [Version 2.x](https://github.com/wrav/SimpleSharing/tree/v2) -If you are looking for CraftCMS 2.5 support, use [version 1.1.5](https://github.com/hut6/SimpleSharing/tree/1.1.5) +If you are looking for CraftCMS 3.x support, use [Version 1.0.8](https://github.com/wrav/SimpleSharing/tree/1.0.8) ## Installing @@ -44,25 +46,29 @@ Your able to generate share links on the fly in a template as followed. ## Testing -The plugin includes a comprehensive test suite using Codeception for both unit and functional testing. +The plugin includes a comprehensive test suite using Codeception with unit, integration, and functional tests. ### Running Tests +Tests require Docker with PostgreSQL: + ```bash -# Install dev dependencies -composer install --dev +# Setup test environment +cp tests/.env.example tests/.env + +# Start Docker containers +docker compose up -d + +# Access app container +docker exec -it app sh # Run all tests vendor/bin/codecept run -# Run only unit tests +# Run specific suites vendor/bin/codecept run unit - -# Run only functional tests -vendor/bin/codecept run functional - -# Run integartion tests vendor/bin/codecept run integration +vendor/bin/codecept run functional # Run with coverage report vendor/bin/codecept run --coverage @@ -71,17 +77,8 @@ vendor/bin/codecept run --coverage ### Test Coverage - **Unit Tests**: URL generation, input validation, platform support -- **Functional Tests**: Controller endpoints, Craft integration -- **Template Tests**: Twig variable availability and output - -### Development Setup - -For plugin development: - -1. Clone the repository -2. Run `composer install --dev` -3. Configure your test environment in `tests/_craft/config/test.php` -4. Run tests with `vendor/bin/codecept run` +- **Integration Tests**: Plugin installation, settings rendering, Craft integration +- **Functional Tests**: Template variable availability ## Credits