diff --git a/.gitattributes b/.gitattributes index 88fa6e2..631f25b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13,4 +13,5 @@ /docker-compose.override.default.yml export-ignore /docker-compose.yml export-ignore /tmp export-ignore +/phpunit.xml export-ignore /README.developers.md export-ignore \ No newline at end of file diff --git a/.github/drupal/.editorconfig b/.github/drupal/.editorconfig new file mode 100644 index 0000000..686c443 --- /dev/null +++ b/.github/drupal/.editorconfig @@ -0,0 +1,17 @@ +# Drupal editor configuration normalization +# @see http://editorconfig.org/ + +# This is the top-most .editorconfig file; do not search in parent directories. +root = true + +# All files. +[*] +end_of_line = LF +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[composer.{json,lock}] +indent_size = 4 diff --git a/.github/drupal/.gitattributes b/.github/drupal/.gitattributes new file mode 100644 index 0000000..e7b792f --- /dev/null +++ b/.github/drupal/.gitattributes @@ -0,0 +1,64 @@ +# Drupal git normalization +# @see https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html +# @see https://www.drupal.org/node/1542048 + +# Normally these settings would be done with macro attributes for improved +# readability and easier maintenance. However macros can only be defined at the +# repository root directory. Drupal avoids making any assumptions about where it +# is installed. + +# Define text file attributes. +# - Treat them as text. +# - Ensure no CRLF line-endings, neither on checkout nor on checkin. +# - Detect whitespace errors. +# - Exposed by default in `git diff --color` on the CLI. +# - Validate with `git diff --check`. +# - Deny applying with `git apply --whitespace=error-all`. +# - Fix automatically with `git apply --whitespace=fix`. + +*.config text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.css text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.dist text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.engine text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php +*.html text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=html +*.inc text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php +*.install text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php +*.js text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.json text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.lock text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.map text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.md text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.module text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php +*.php text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php +*.po text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.profile text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php +*.script text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.sh text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php +*.sql text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.svg text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.theme text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php +*.twig text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.txt text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.xml text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.yml text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 + +# PHPStan's baseline uses tabs instead of spaces. +core/.phpstan-baseline.php text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tabwidth=2 diff=php linguist-language=php + +# Define binary file attributes. +# - Do not treat them as text. +# - Include binary diff in patches instead of "binary files differ." +*.eot -text diff +*.exe -text diff +*.gif -text diff +*.gz -text diff +*.ico -text diff +*.jpeg -text diff +*.jpg -text diff +*.otf -text diff +*.phar -text diff +*.png -text diff +*.svgz -text diff +*.ttf -text diff +*.woff -text diff +*.woff2 -text diff diff --git a/.github/drupal/Dockerfile b/.github/drupal/Dockerfile new file mode 100644 index 0000000..88d0570 --- /dev/null +++ b/.github/drupal/Dockerfile @@ -0,0 +1,22 @@ +FROM php:8.3-cli + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + git \ + unzip \ + libzip-dev \ + && docker-php-ext-install zip + +# Install Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Configure environment +ENV COMPOSER_ALLOW_SUPERUSER=1 +WORKDIR /app + +# Copy only required files for dependency installation +COPY composer.json composer.lock ./ +RUN composer install --no-interaction --prefer-dist --no-scripts + +# Copy remaining source files +COPY . . diff --git a/.github/drupal/composer.json b/.github/drupal/composer.json new file mode 100644 index 0000000..e47636f --- /dev/null +++ b/.github/drupal/composer.json @@ -0,0 +1,100 @@ +{ + "name": "drupal/recommended-project", + "description": "Project template for Drupal projects with a relocated document root", + "type": "project", + "license": "GPL-2.0-or-later", + "homepage": "https://www.drupal.org/project/drupal", + "support": { + "docs": "https://www.drupal.org/docs/user_guide/en/index.html", + "chat": "https://www.drupal.org/node/314178" + }, + "repositories": [ + { + "type": "path", + "url": "/var/www/html", + "options": { + "symlink": true + } + }, + { + "type": "composer", + "url": "https://packages.drupal.org/8" + } + ], + "require": { + "composer/installers": "^2.0", + "drupal/core-composer-scaffold": "^10.1", + "drupal/core-project-message": "^10.1", + "drupal/core-recommended": "^10.1", + "drush/drush": "^12.4", + "salsadigitalauorg/scaffold-testing": "*" + }, + "require-dev": { + "drevops/behat-format-progress-fail": "^1", + "drevops/behat-screenshot": "1.5.0", + "drevops/behat-steps": "^2", + "drupal/core-dev": "^10.1", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/phpunit-bridge": "^6.4" + }, + "conflict": { + "drupal/drupal": "*" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "config": { + "allow-plugins": { + "composer/installers": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "drupal/core-composer-scaffold": true, + "drupal/core-project-message": true, + "php-http/discovery": true, + "phpstan/extension-installer": true, + "tbachert/spi": true + }, + "sort-packages": true + }, + "autoload-dev": { + "psr-4": { + "Salsadigitalauorg\\ScaffoldTesting\\Tests\\": "vendor/salsadigitalauorg/scaffold-testing/tests/", + "Salsadigitalauorg\\ScaffoldTesting\\Tests\\Behat\\": "vendor/salsadigitalauorg/scaffold-testing/tests/behat/bootstrap/" + } + }, + "extra": { + "drupal-scaffold": { + "locations": { + "web-root": "web/" + } + }, + "installer-paths": { + "web/core": ["type:drupal-core"], + "web/libraries/{$name}": ["type:drupal-library"], + "web/modules/contrib/{$name}": ["type:drupal-module"], + "web/profiles/contrib/{$name}": ["type:drupal-profile"], + "web/themes/contrib/{$name}": ["type:drupal-theme"], + "drush/Commands/contrib/{$name}": ["type:drupal-drush"], + "web/modules/custom/{$name}": ["type:drupal-custom-module"], + "web/profiles/custom/{$name}": ["type:drupal-custom-profile"], + "web/themes/custom/{$name}": ["type:drupal-custom-theme"] + }, + "drupal-core-project-message": { + "include-keys": ["homepage", "support"], + "post-create-project-cmd-message": [ + " ", + " Congratulations, you've installed the Drupal codebase ", + " from the drupal/recommended-project template! ", + " ", + "", + "Next steps:", + " * Install the site: https://www.drupal.org/docs/installing-drupal", + " * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html", + " * Get support: https://www.drupal.org/support", + " * Get involved with the Drupal community:", + " https://www.drupal.org/getting-involved", + " * Remove the plugin that prints this message:", + " composer remove drupal/core-project-message" + ] + } + } +} diff --git a/.github/drupal/phpunit.xml b/.github/drupal/phpunit.xml new file mode 100644 index 0000000..fc9fa3e --- /dev/null +++ b/.github/drupal/phpunit.xml @@ -0,0 +1,15 @@ + + + + + .github/drupal/tests/Unit/Installer + + + + + + + diff --git a/.github/drupal/tests/Unit/Installer/InstallerTest.php b/.github/drupal/tests/Unit/Installer/InstallerTest.php new file mode 100644 index 0000000..988a957 --- /dev/null +++ b/.github/drupal/tests/Unit/Installer/InstallerTest.php @@ -0,0 +1,17 @@ +assertTrue(class_exists(Installer::class), + 'Installer class should be available in GHA environment'); + } +} diff --git a/.github/drupal/tests/Unit/InstallerTest.php b/.github/drupal/tests/Unit/InstallerTest.php new file mode 100644 index 0000000..ad91ade --- /dev/null +++ b/.github/drupal/tests/Unit/InstallerTest.php @@ -0,0 +1,71 @@ +io = $this->createMock(IOInterface::class); + $this->package = $this->createMock(RootPackage::class); + $this->config = $this->createMock(Config::class); + $this->composer = $this->createMock(Composer::class); + + $this->composer->method('getConfig') + ->willReturn($this->config); + + $this->config->method('get') + ->with('vendor-dir') + ->willReturn('/var/www/html/vendor'); + + $this->package->method('getExtra') + ->willReturn([ + 'scaffold-testing' => [ + 'target-dir' => 'tests/behat/', + 'override' => false + ] + ]); + + $this->composer->method('getPackage') + ->willReturn($this->package); + + $this->event = $this->createMock(Event::class); + $this->event->method('getIO') + ->willReturn($this->io); + $this->event->method('getComposer') + ->willReturn($this->composer); + } + + public function testFeatures(): void + { + $this->io->expects(self::atLeastOnce()) + ->method('write') + ->with('[scaffold-testing] Installer::features method called'); + + Installer::features($this->event); + } + + protected function tearDown(): void + { + // Cleanup test files using absolute paths + @unlink('/var/www/html/tests/behat/features/login.feature'); + @unlink('/var/www/html/tests/behat/features/search.feature'); + } +} diff --git a/.github/drupal/tests/bootstrap.php b/.github/drupal/tests/bootstrap.php new file mode 100644 index 0000000..af32a54 --- /dev/null +++ b/.github/drupal/tests/bootstrap.php @@ -0,0 +1,2 @@ +' - RENOVATE_DEPENDENCY_DASHBOARD_TITLE: 'Renovate Dependency Dashboard (self-hosted) by GitHub Actions' + RENOVATE_GIT_AUTHOR: 'salsadeploy ' + RENOVATE_DEPENDENCY_DASHBOARD_TITLE: 'Renovate Dependency Dashboard' RENOVATE_DEPENDENCY_DASHBOARD: true RENOVATE_REPOSITORIES: ${{ github.repository }} RENOVATE_PLATFORM: 'github' RENOVATE_AUTODISCOVER: false - RENOVATE_DRY_RUN: true + LOG_LEVEL: debug with: configurationFile: renovate-gh.json token: ${{ secrets.RENOVATE_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..4896bc2 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,74 @@ +name: Test Scaffold Testing Package + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + test: + runs-on: ubuntu-latest + container: + image: php:8.3-cli + + steps: + - uses: actions/checkout@v2 + + - name: Install system dependencies + run: | + apt-get update && apt-get install -y \ + git \ + unzip \ + libzip-dev \ + tree \ + && docker-php-ext-install zip + + - name: Install Composer + run: | + curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + + - name: Run tests + working-directory: /var/www/html + run: | + echo "Debug workspace paths:" + echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE" + echo "Current directory: $(pwd)" + echo "Workspace contents:" + ls -la $GITHUB_WORKSPACE + + # Copy project files to working directory + cp -r $GITHUB_WORKSPACE/. . + + echo "Current directory structure after copy:" + pwd + ls -la + + # Create phpunit.xml + echo ' + + + + tests/Unit + + + ' > phpunit.xml + + echo "PHPUnit config contents:" + cat phpunit.xml + + # Install dependencies + composer install --no-interaction --no-progress + + echo "Directory structure after composer install:" + tree -L 3 + + # Run PHPUnit tests with debug + ./vendor/bin/phpunit \ + -v \ + --debug \ + --configuration phpunit.xml \ + tests/Unit/ \ No newline at end of file diff --git a/README.developers.md b/README.developers.md index 6d0e835..39745d1 100644 --- a/README.developers.md +++ b/README.developers.md @@ -1,31 +1,111 @@ -#### Overview - -The **Scaffold Testing Library** provides a set of default Behat tests tailored for Drupal projects, aiming to ensure consistent testing across different deployments. This library helps streamline the testing process by providing ready-to-use Behat test scenarios that cover common functionalities within Drupal sites. - -#### Installation for developers. - -1. **Add the Library to Your Project**: You can include this library in your Drupal project by adding it to your `composer.json` file. Ensure you have access to the library path if it's hosted locally or available on a VCS. For local development, you can use: - - ```json - { - "repositories": [ - { - "type": "path", - "url": "/path/to/scaffold-testing", - "options": { - "symlink": false - } - } - ], - "require-dev": { - "salsadigitalauorg/scaffold-testing": "*" - } - } - ``` - -2. **Install the Library**: Run the following command to install the library: - - ```bash - composer require --dev salsadigitalauorg/scaffold-testing - ``` -Refer to the [README.md](README.md) for more information. \ No newline at end of file +# Developer Documentation + +## Testing + +### Unit Tests + +The package includes comprehensive unit tests for all configuration options. Tests are run in a Docker container via GitHub Actions. + +#### Test Cases + +1. Default Configuration: + - Tests default target directory + - Default override settings + +2. Custom Target Directory: + - Tests custom directory path + - Verifies file creation in custom location + +3. Specific Feature Files: + - Tests selective feature file installation + - Individual override settings per file + +4. Override Features: + - Tests global override setting + - Tests per-file override settings + +5. Feature Context: + - Tests FeatureContext.php installation + - Tests override behavior + +### Running Tests Locally + +```bash +# Run PHPUnit tests +composer phpunit-test + +# Run tests in Docker (same as GHA) +act push -W .github/workflows/test.yml --container-architecture linux/amd64 -v +``` + +### GitHub Actions Local Development + +#### Prerequisites +1. Install `act` tool: + ```bash + brew install act # macOS + ``` + +2. Ensure Docker is running on your machine. + +#### Running GHA Locally + +Basic usage: +```bash +act push -W .github/workflows/test.yml --container-architecture linux/amd64 -v +``` + +Reset environment and re-run tests: +```bash +# Stop and remove all act containers, then run tests +docker stop $(docker ps -a | grep act | awk '{print $1}') && \ +docker rm --volumes $(docker ps -a | grep act | awk '{print $1}') && \ +act push -W .github/workflows/test.yml --container-architecture linux/amd64 -v +``` + +Common issues: +- If tests fail, always clean up containers before re-running +- Use `-v` flag for verbose output to debug issues +- Check Docker logs if containers fail to start + +### Test Environment + +Tests are executed in a Docker container with the following setup: +- PHP 8.3 +- Composer 2.x +- PHPUnit 9.6 + +### Adding New Tests + +When adding new test cases: +1. Create test method in `tests/Unit/Installer/InstallerTest.php` +2. Mock necessary Composer components +3. Add cleanup in tearDown() if creating files +4. Update test documentation + +## Configuration Options + +### Target Directory +- Default: `tests/behat/` +- Can be customized to any valid path +- Must be writable by the process + +### Feature Files +- Located in `tests/behat/features/` +- Default files: + - homepage.feature + - login.feature + - search.feature + - contenttypes.feature + +### Override Settings +- Global override: `override_feature` +- Per-file override in `files` array +- FeatureContext override: `override_feature_context` + +## Development Guidelines + +1. Follow PSR-12 coding standards +2. Add unit tests for new features +3. Update documentation for configuration changes +4. Test in Docker environment before committing \ No newline at end of file diff --git a/README.md b/README.md index 784b5fa..307bf95 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,91 @@ +# Scaffold Testing + +A testing framework for Vortex scaffold that provides automated test setup and configuration. + +## Installation + +```bash +composer require salsadigitalauorg/scaffold-testing --dev +``` + +## Configuration + +Add the following configuration to your project's `composer.json`: + +```json +{ + "extra": { + "scaffold-testing": { + "target-dir": "tests/behat/", + "files": { + "homepage.feature": false, + "login.feature": false, + "search.feature": false, + "contenttypes.feature": false + }, + "override_feature": false, + "override_feature_context": false + } + } +} +``` + +### Configuration Options + +- `target-dir`: The directory where test files will be installed (default: `tests/behat/`) +- `files`: Specific feature files to install and their override settings + - Key: Feature file name + - Value: Boolean indicating whether to override if file exists +- `override_feature`: Global override setting for all feature files (default: `false`) +- `override_feature_context`: Whether to override the FeatureContext.php file (default: `false`) + +### Examples + +1. Default Setup: +```json +{ + "scaffold-testing": { + "target-dir": "tests/behat/" + } +} +``` + +2. Custom Directory: +```json +{ + "scaffold-testing": { + "target-dir": "custom/path/behat/" + } +} +``` + +3. Specific Features with Override: +```json +{ + "scaffold-testing": { + "target-dir": "tests/behat/", + "files": { + "homepage.feature": true, + "login.feature": false + } + } +} +``` + +4. Override All Features: +```json +{ + "scaffold-testing": { + "target-dir": "tests/behat/", + "override_feature": true + } +} +``` + +## Development + +See [README.developers.md](README.developers.md) for development setup and guidelines. + #### Overview The **Scaffold Testing Library** provides a set of default Behat tests tailored for Drupal projects, aiming to ensure consistent testing across different deployments. This library helps streamline the testing process by providing ready-to-use Behat test scenarios that cover common functionalities within Drupal sites. @@ -10,14 +98,6 @@ The **Scaffold Testing Library** provides a set of default Behat tests tailored - **Search Functionality Test**: Verifies that search indexing works and returns expected results. - **Content Types Test**: Verifies that content types can be created. -#### Installation - -1. **Install the Library**: Run the following command to install the library: - - ```bash - composer require --dev salsadigitalauorg/scaffold-testing - ``` - #### Usage After installation, the Behat test files are placed in the `tests/behat/features/` directory of your Drupal project. You can run these tests using Behat with a command similar to: diff --git a/composer.json b/composer.json index 23afaf0..efb3f1e 100644 --- a/composer.json +++ b/composer.json @@ -1,57 +1,49 @@ { "name": "salsadigitalauorg/scaffold-testing", - "description": "Provides a set of default Behat tests for Drupal projects, ensuring consistent testing across deployments.", - "version": "0.4.2", + "description": "Testing framework for Vortex scaffold", + "version": "0.4.4", "type": "library", + "license": "GPL-2.0-or-later", + "autoload": { + "psr-4": { + "Salsadigitalauorg\\ScaffoldTesting\\": "src/" + } + }, +"autoload-dev": { + "psr-4": { + "Salsadigitalauorg\\ScaffoldTesting\\Tests\\": ["tests/", ".github/drupal/tests/"], + "Salsadigitalauorg\\ScaffoldTesting\\Tests\\Behat\\": "tests/behat/bootstrap/" + } +}, "require": { "php": ">=8.3", + "composer/installers": "^2.0", + "phpunit/phpunit": "^9.6", "behat/behat": "^3.13", - "composer/composer": "^2.6", - "symfony/process": "^6.0|^7.0", - "phpunit/phpunit": "^9.6.13" + "drupal/drupal-extension": "^5.0", + "symfony/process": "^6.0|^7.0" }, "require-dev": { - "drupal/drupal-extension": "^5.0", + "drupal/core-dev": "^10.1", + "symfony/phpunit-bridge": "^6.4", + "phpspec/prophecy-phpunit": "^2.0", "drevops/behat-format-progress-fail": "^1", "drevops/behat-screenshot": "^1.5.0", "drevops/behat-steps": "^2" }, - "autoload": { - "psr-4": { - "Salsadigitalauorg\\ScaffoldTesting\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Salsadigitalauorg\\ScaffoldTesting\\Tests\\": "tests/" + "config": { + "sort-packages": true, + "allow-plugins": { + "composer/installers": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true, + "php-http/discovery": true } }, + "minimum-stability": "dev", + "prefer-stable": true, "scripts": { "phpunit-test": "phpunit --configuration phpunit.xml", - "install-features": "Salsadigitalauorg\\ScaffoldTesting\\Installer\\Installer::features", - "post-install-cmd": [ ], - "post-update-cmd": [ ] - }, - "extra": { - "scaffold-testing": { - "target-dir": "tmp/tests/behat/", - "files": [ - "homepage.feature", - "login.feature", - "search.feature", - "permissions.feature", - "contenttypes.feature" - ], - "override_feature_context": true - } - }, - "license": "MIT", - "authors": [ - { - "name": "Your Name", - "email": "your.email@example.com" - } - ], - "minimum-stability": "dev", - "prefer-stable": true + "install-features": "Salsadigitalauorg\\ScaffoldTesting\\Installer\\Installer::features" + } } diff --git a/composer.lock b/composer.lock index 0b5a67b..75b1a4c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b9ffe79d51bfeb032d7e8f7377bb331e", + "content-hash": "4097e6155eb199dbe6f4270b647996ef", "packages": [ { "name": "behat/behat", @@ -5999,12 +5999,12 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": ">=8.3" }, - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/renovate-gh.json b/renovate-gh.json new file mode 100644 index 0000000..5882613 --- /dev/null +++ b/renovate-gh.json @@ -0,0 +1,62 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base", + ":semanticCommits", + ":semanticPrefixFix", + ":ignoreUnstable", + ":enableVulnerabilityAlerts", + ":separateMajorReleases", + ":combinePatchMinorReleases", + "group:recommended", + "workarounds:all" + ], + "labels": ["dependencies"], + "assignees": ["ivangrynenko"], + "reviewers": ["ivangrynenko"], + "packageRules": [ + { + "matchManagers": ["composer"], + "matchDepTypes": ["require"], + "groupName": "PHP production dependencies", + "labels": ["php-prod-deps"] + }, + { + "matchManagers": ["composer"], + "matchDepTypes": ["require-dev"], + "groupName": "PHP development dependencies", + "labels": ["php-dev-deps"] + }, + { + "matchPackagePatterns": ["^drupal/"], + "groupName": "Drupal dependencies", + "labels": ["drupal-deps"] + }, + { + "matchPackagePatterns": ["^symfony/"], + "groupName": "Symfony dependencies", + "labels": ["symfony-deps"] + } + ], + "composerIgnorePlatformReqs": ["ext-*", "lib-*"], + "rangeStrategy": "bump", + "schedule": ["after 10pm and before 5am every weekday", "every weekend"], + "timezone": "Australia/Sydney", + "prConcurrentLimit": 5, + "prHourlyLimit": 2, + "stabilityDays": 3, + "dependencyDashboard": true, + "dependencyDashboardTitle": "Renovate Dependency Dashboard", + "commitMessagePrefix": "chore(deps):", + "commitBody": "Signed-off-by: salsadeploy ", + "ignorePaths": [ + "**/node_modules/**", + "**/bower_components/**", + ".github/drupal/**" + ], + "automerge": false, + "platformAutomerge": false, + "rebaseWhen": "behind-base-branch", + "recreateClosed": true, + "suppressNotifications": ["prIgnoreNotification"] +} \ No newline at end of file diff --git a/src/Installer/Installer.php b/src/Installer/Installer.php index 7e03486..5189523 100644 --- a/src/Installer/Installer.php +++ b/src/Installer/Installer.php @@ -40,9 +40,14 @@ public static function features(Event $event): void $config = $extras['scaffold-testing']; $targetDir = rtrim($config['target-dir'] ?? 'tests/behat/', '/') . '/'; + $override_feature = $config['override_feature'] ?? false; $override_feature_context = $config['override_feature_context'] ?? false; - $targetPath = getcwd() . '/' . $targetDir; + // Use absolute path from composer's vendor dir + $vendorDir = $composer->getConfig()->get('vendor-dir'); + $projectRoot = dirname($vendorDir); + $targetPath = $projectRoot . '/' . $targetDir; + $featurePath = $targetPath . 'features/'; $bootstrapPath = $targetPath . 'bootstrap/'; @@ -54,10 +59,10 @@ public static function features(Event $event): void if (!isset($config['files']) || empty($config['files'])) { // If 'files' is not set or empty, get all .feature files from the source directory $files = array_map('basename', glob($sourceDir . '*.feature')); - $files = array_fill_keys($files, false); // Set override to false for all files + $files = array_fill_keys($files, $override_feature); // Use the override_feature setting } else { - // Convert the list of files to an associative array with override set to false - $files = array_fill_keys($config['files'], false); + // Convert the list of files to an associative array with override from config + $files = array_fill_keys($config['files'], $override_feature); } foreach ($files as $file => $override) { @@ -67,21 +72,21 @@ public static function features(Event $event): void if (file_exists($sourcePath)) { if (!file_exists($destPath)) { if (copy($sourcePath, $destPath)) { - $io->write("Installed $file file to " . dirname($destPath)); + $io->write("[scaffold-testing] Installed $file file to " . dirname($destPath)); } else { - $io->writeError("Failed to install $file file to " . dirname($destPath)); + $io->writeError("[scaffold-testing] Failed to install $file file to " . dirname($destPath)); } } else if ($override) { if (copy($sourcePath, $destPath)) { - $io->write("Updated $file file in " . dirname($destPath)); + $io->write("[scaffold-testing] Updated $file file in " . dirname($destPath)); } else { - $io->writeError("Failed to update $file file in " . dirname($destPath)); + $io->writeError("[scaffold-testing] Failed to update $file file in " . dirname($destPath)); } } else { $io->write("[scaffold-testing] Skipped $file file as it already exists and override is set to false."); } } else { - $io->writeError("Source file not found: $file"); + $io->writeError("[scaffold-testing] Source file not found: $file"); } } @@ -120,9 +125,9 @@ private static function createDirectory(IOInterface $io, string $path): void /** * Updates or creates the FeatureContext file. */ - private static function updateFeatureContext(string $projectRoot, IOInterface $io): void + private static function updateFeatureContext(string $targetPath, IOInterface $io): void { - $featureContextPath = $projectRoot . '/tests/behat/features/bootstrap/FeatureContext.php'; + $featureContextPath = rtrim($targetPath, '/') . '/bootstrap/FeatureContext.php'; $useStatements = [ 'use Behat\Behat\Context\Context;', 'use Behat\Behat\Hook\Scope\AfterScenarioScope;', diff --git a/tests/Unit/Installer/InstallerTest.php b/tests/Unit/Installer/InstallerTest.php new file mode 100644 index 0000000..c4ab9e8 --- /dev/null +++ b/tests/Unit/Installer/InstallerTest.php @@ -0,0 +1,16 @@ +assertTrue(class_exists(Installer::class)); + } +} diff --git a/tests/Unit/InstallerTest.php b/tests/Unit/InstallerTest.php deleted file mode 100644 index 6c254b7..0000000 --- a/tests/Unit/InstallerTest.php +++ /dev/null @@ -1,112 +0,0 @@ -testDir = sys_get_temp_dir() . '/scaffold-testing-test-' . uniqid(); - $this->vendorDir = $this->testDir . '/vendor/salsadigitalauorg/scaffold-testing'; - if (is_dir($this->testDir)) { - $this->removeDirectory($this->testDir); - } - mkdir($this->vendorDir, 0777, true); - chdir($this->testDir); - } - - protected function tearDown(): void - { - if (is_dir($this->testDir)) { - $this->removeDirectory($this->testDir); - } - parent::tearDown(); - } - - public function testFeatureInstallation() - { - // Create a mock Composer setup - $composer = new Composer(); - $config = new Config(); - $config->merge(['config' => ['vendor-dir' => $this->testDir . '/vendor']]); - $composer->setConfig($config); - - $package = new RootPackage('test/test', '1.0.0.0', '1.0.0'); - $package->setExtra([ - 'scaffold-testing' => [ - 'target-dir' => 'tests/behat/', - 'files' => ['homepage.feature', 'login.feature', 'search.feature'], - 'override_feature' => false, - 'override_feature_context' => false - ] - ]); - $composer->setPackage($package); - - $io = new NullIO(); - $event = new Event('post-install-cmd', $composer, $io); - - // Create source files in the simulated vendor directory - mkdir($this->vendorDir . '/features', 0777, true); - file_put_contents($this->vendorDir . '/features/homepage.feature', 'Feature: Homepage'); - file_put_contents($this->vendorDir . '/features/login.feature', 'Feature: Login'); - file_put_contents($this->vendorDir . '/features/search.feature', 'Feature: Search'); - mkdir($this->vendorDir . '/bootstrap', 0777, true); - file_put_contents($this->vendorDir . '/bootstrap/Salsadigitalauorg\ScaffoldTesting\Tests\behat\bootstrap\FeatureContext.php', 'assertFileExists($this->testDir . '/tests/behat/features/homepage.feature'); - $this->assertFileExists($this->testDir . '/tests/behat/features/login.feature'); - $this->assertFileExists($this->testDir . '/tests/behat/features/search.feature'); - - // Assert Salsadigitalauorg\ScaffoldTesting\Tests\behat\bootstrap\FeatureContext was copied - $this->assertFileExists($this->testDir . '/tests/behat/bootstrap/Salsadigitalauorg\ScaffoldTesting\Tests\behat\bootstrap\FeatureContext.php'); - - // Test skipping (not overwriting) - file_put_contents($this->testDir . '/tests/behat/features/homepage.feature', 'Modified: Homepage'); - Installer::features($event); - $this->assertEquals('Modified: Homepage', file_get_contents($this->testDir . '/tests/behat/features/homepage.feature')); - - // Test overwriting - $package->setExtra([ - 'scaffold-testing' => [ - 'target-dir' => 'tests/behat/', - 'files' => ['homepage.feature', 'login.feature', 'search.feature'], - 'override_feature' => true, - 'override_feature_context' => true - ] - ]); - Installer::features($event); - $this->assertEquals('Feature: Homepage', file_get_contents($this->testDir . '/tests/behat/features/homepage.feature')); - } - - private function removeDirectory($dir) - { - if (is_dir($dir)) { - $objects = scandir($dir); - foreach ($objects as $object) { - if ($object != "." && $object != "..") { - if (is_dir($dir . "/" . $object)) - $this->removeDirectory($dir . "/" . $object); - else - unlink($dir . "/" . $object); - } - } - rmdir($dir); - } - } -} diff --git a/tests/behat/behat.yml b/tests/behat/behat.yml index ef32a8b..cfb4948 100644 --- a/tests/behat/behat.yml +++ b/tests/behat/behat.yml @@ -10,11 +10,13 @@ default: default: paths: ['%paths.base%/tests/behat/features'] contexts: - - Salsadigitalauorg\ScaffoldTesting\Tests\behat\bootstrap\FeatureContext + - FeatureContext + - Drupal\DrupalExtension\Context\DrupalContext - Drupal\DrupalExtension\Context\MinkContext - Drupal\DrupalExtension\Context\MarkupContext - Drupal\DrupalExtension\Context\MessageContext - DrevOps\BehatScreenshotExtension\Context\ScreenshotContext + - Drupal\DrupalExtension\Context\DrushContext formatters: progress_fail: true # Disable JUnit formatter if memory leaks start to occur. @@ -23,34 +25,36 @@ default: output_path: '%paths.base%/.logs/test_results/behat' extensions: - Drupal\MinkExtension: - browserkit_http: ~ - base_url: http://nginx:8080 - files_path: '%paths.base%/tests/behat/fixtures' - browser_name: chrome - selenium2: - wd_host: "http://chrome:4444/wd/hub" - javascript_session: selenium2 - # Provides integration with Drupal APIs. + DrevOps\BehatFormatProgressFail\FormatExtension: ~ + DrevOps\BehatScreenshotExtension: + dir: '%paths.base%/screenshots' + fail: true + fail_prefix: 'failed_' + purge: false Drupal\DrupalExtension: blackbox: ~ - api_driver: drupal - drush_driver: drush + api_driver: 'drupal' drupal: - drupal_root: web - drush: - root: web + drupal_root: '%paths.base%/../../web' + region_map: + content: '.region-content' + footer: '.site-footer' + header: '.region-header' + page: '#page' selectors: message_selector: '.messages' - error_message_selector: '.messages.error' - success_message_selector: '.messages.status' - warning_message_selector: '.messages.warning' - # Capture HTML and JPG screenshots on demand and on failure. - DrevOps\BehatScreenshotExtension: - dir: '%paths.base%/.logs/screenshots' - purge: false # Change to 'true' (no quotes) to purge screenshots on each run. - # Show explicit fail information and continue the test run. - DrevOps\BehatFormatProgressFail\FormatExtension: ~ + error_message_selector: '.messages.messages--error' + success_message_selector: '.messages.messages--status' + warning_message_selector: '.messages.messages--warning' + Behat\MinkExtension: + base_url: 'http://localhost:8080' + browser_name: chrome + sessions: + default: + goutte: ~ + javascript: + chrome: + api_url: "http://localhost:9222" # Profile for parallel testing. # Runs all tests not tagged with "smoke" or "@p1" and not tagged with "@skipped". diff --git a/tests/behat/bootstrap/FeatureContext.php b/tests/behat/bootstrap/FeatureContext.php index ff4bb28..4f5e3df 100644 --- a/tests/behat/bootstrap/FeatureContext.php +++ b/tests/behat/bootstrap/FeatureContext.php @@ -5,8 +5,7 @@ * Defines application features for Behat testing within a Drupal context. */ -namespace Salsadigitalauorg\ScaffoldTesting\Tests\behat\bootstrap; - +use Behat\Behat\Context\Context; use Behat\Gherkin\Node\TableNode; use DrevOps\BehatSteps\ContentTrait; use DrevOps\BehatSteps\FieldTrait; @@ -17,9 +16,11 @@ use DrevOps\BehatSteps\WaitTrait; use DrevOps\BehatSteps\WatchdogTrait; use Drupal\DrupalExtension\Context\DrupalContext; +use Drupal\user\Entity\User; use Drupal\group\Entity\Group; use Drupal\group\Entity\GroupType; -use Drupal\user\Entity\User; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Salsadigitalauorg\ScaffoldTesting\Traits\ScaffoldTestingTrait; // Ensure TableNode is included for handling table data @@ -30,6 +31,7 @@ class FeatureContext extends DrupalContext { use ContentTrait, FieldTrait, FileTrait, PathTrait, TaxonomyTrait, SearchApiTrait, WaitTrait, WatchdogTrait; + use ScaffoldTestingTrait; /** * Creates a new user with specified details. @@ -123,4 +125,3 @@ public function iSelectTheFollowingFieldsWithValues(TableNode $table) { } } - diff --git a/tests/behat/features/contenttypes.feature b/tests/behat/features/contenttypes.feature index 7e3bfe2..1ea25f0 100644 --- a/tests/behat/features/contenttypes.feature +++ b/tests/behat/features/contenttypes.feature @@ -2,44 +2,6 @@ Feature: Every content type and testing every roles available permissions Ensure that each created content type has the expected message shortly after pressing 'Save' - @api @p0 - Scenario: Administrator creates news content - Given I am logged in as a user with the "Administrator" role - And I visit "node/add/article" - And I fill in "Title" with "News Test 1" - And I fill in "Date" with "2024-01-25" - And I fill in "Meta Title" with "meta test 1" - And I fill in "Meta Description" with "meta description test 1" - And I press "Save" - Then the response status code should be 200 - And save screenshot - And I should see the text "News News Test 1 has been created." - - @api @p0 - Scenario: Administrator creates Events content - Given I am logged in as a user with the "Administrator" role - And I visit "node/add/events" - And I fill in "Title" with "Events Test 1" - And I fill in "Date" with "2024-01-25" - And I fill in "Meta Title" with "meta test 3" - And I fill in "Meta Description" with "meta description test 3" - And I press "Save" - Then the response status code should be 200 - And save screenshot - And I should see the text "Events Events Test 1 has been created." - - @api @p0 - Scenario: Administrator creates Landing Page Content - Given I am logged in as a user with the "Administrator" role - And I visit "node/add/landing_pages" - And I fill in "Title" with "LandingPage Test 1" - And I fill in "Meta Title" with "meta test 7" - And I fill in "Meta Description" with "meta description test 7" - And I press "Save" - Then the response status code should be 200 - And save screenshot - And I should see the text "Basic Pages without sidebar LandingPage Test 1 has been created." - @api @p0 Scenario: Administrator creates Basic Page Content Given I am logged in as a user with the "Administrator" role diff --git a/tests/behat/features/permissions.feature b/tests/behat/features/permissions.feature index 42c419b..109432e 100644 --- a/tests/behat/features/permissions.feature +++ b/tests/behat/features/permissions.feature @@ -10,41 +10,8 @@ Feature: Access to every content type for every role Then I should get a 404 HTTP response Examples: - | card | - | forum | - | news | | page | - @api - Scenario Outline: Users have access to create Forum content - Given I am logged in as a user with the "" role - When I go to "node/add/forum" - And save screenshot - Then I should get a "" HTTP response - - Examples: - | role | access_code | - | Authenticated user | 200 | - | Group Member Admin | 200 | - | Editor | 200 | - | Admin | 200 | - | System Admin | 200 | - - @api - Scenario Outline: Users have access to create News content - Given I am logged in as a user with the "" role - When I go to "node/add/news" - And save screenshot - Then I should get a "" HTTP response - - Examples: - | role | access_code | - | Authenticated user | 403 | - | Group Member Admin | 403 | - | Editor | 200 | - | Admin | 200 | - | System Admin | 200 | - @api Scenario Outline: Users have access to create Page content Given I am logged in as a user with the "" role @@ -55,7 +22,4 @@ Feature: Access to every content type for every role Examples: | role | access_code | | Authenticated user | 403 | - | Group Member Admin | 200 | - | Editor | 200 | | Admin | 200 | - | System Admin | 200 | diff --git a/tests/behat/fixtures/eicar.com.txt b/tests/behat/fixtures/eicar.com.txt new file mode 100644 index 0000000..a2463df --- /dev/null +++ b/tests/behat/fixtures/eicar.com.txt @@ -0,0 +1 @@ +X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* \ No newline at end of file