diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ef4466c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 4 + +[Makefile] +indent_style = tab +indent_size = 8 + +[{*.yml,*.yaml}] +indent_style = space +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..500a7cf --- /dev/null +++ b/.gitattributes @@ -0,0 +1,19 @@ +# Ignore all test and documentation for archive +/.github export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.travis.yml export-ignore +/.editorconfig export-ignore +/codecov.yml export-ignore +/.remarkrc export-ignore +/.remarkignore export-ignore +/behat.yml export-ignore +/phpunit.xml.dist export-ignore +/phpcs.xml.dist export-ignore +/CODE_OF_CONDUCT.md export-ignore +/CONTRIBUTING.md export-ignore +/Makefile export-ignore +/tests export-ignore +/features export-ignore +/docs export-ignore diff --git a/.github/.editorconfig b/.github/.editorconfig new file mode 100644 index 0000000..e3ed7d1 --- /dev/null +++ b/.github/.editorconfig @@ -0,0 +1,3 @@ +[*.yml] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..3f2b8b5 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,261 @@ +name: 'CI' +on: # Build any PRs and main branch changes + workflow_dispatch: # Allows to run the workflow manually from the Actions tab + pull_request: + types: + - opened + - edited + - synchronize + push: + branches: [ master ] + schedule: + - cron: '0 0 1 * *' # Every month + +concurrency: + group: "${{ github.workflow }}-${{ github.head_ref || github.ref }}" + cancel-in-progress: true + +env: + TEST_OUTPUT_STYLE: pretty + COMPOSER_OPTIONS: --optimize-autoloader + CODACY_CACHE_PATH: ~/.cache/codacy + CODACY_BIN: ~/.cache/codacy/codacy.sh + +jobs: + tests: + name: UTs & FTs - Symfony ${{ matrix.symfony-version }} + runs-on: ubuntu-latest + env: + COVERAGE_TYPE: none + strategy: + fail-fast: true + max-parallel: 4 + matrix: + include: + # Bare minimum => Lowest versions allowed by composer config + - symfony-version: '4.4' + php-version: '8.0' + composer-flag: --prefer-lowest + # Up to date versions => Latest versions allowed by composer config + - symfony-version: '5.4' + php-version: '8.2' + # Late symfony migration => Lowest symfony version with latest minor php version allowed by composer config + - symfony-version: '4.4' + php-version: '8.2' + composer-flag: --prefer-lowest + # Late php migration => Latest symfony version with lowest minor php version allowed by composer config + - symfony-version: '5.4' + php-version: '8.0' + # Symfony 6.0 latest + - symfony-version: '6.0' + php-version: '8.2' + # Symfony 6.0 lowest + - symfony-version: '6.0' + php-version: '8.0' + composer-flag: --prefer-lowest + steps: + - name: Check out code + uses: actions/checkout@v3 + + - name: Enable coverage + if: ${{ matrix.php-version == '8.2' }} + run: | + echo "COVERAGE_OUTPUT_STYLE=clover" >> $GITHUB_ENV + echo "COVERAGE_TYPE=xdebug" >> $GITHUB_ENV + + - name: Setup PHP ${{ matrix.php-version }} + uses: shivammathur/setup-php@v2 + with: + php-version: '${{ matrix.php-version }}' + tools: composer + coverage: ${{ env.COVERAGE_TYPE }} + env: + # Always use latest available patch for the version + update: true + + - name: Setup cache + id: cache + uses: actions/cache@v3 + with: + path: | + ~/.composer + ./vendor + ${{ env.CODACY_CACHE_PATH }} + # Clear the cache if composer json (as composer.lock is in the repo) has been updated + key: tests-${{ matrix.php-version }}-${{ matrix.symfony-version }}-${{ matrix.composer-flag }}-${{ hashFiles('composer.json') }} + + - name: Download codacy binary + if: steps.cache.outputs.cache-hit != 'true' + run: | + mkdir -p ${{ env.CODACY_CACHE_PATH }} \ + && curl -LN https://coverage.codacy.com/get.sh -o ${{ env.CODACY_BIN }} \ + && chmod +x ${{ env.CODACY_BIN }} \ + && ${{ env.CODACY_BIN }} download + + - name: Build + run: | + SF_VERSION=${{ matrix.symfony-version }} + # Issue with ParamterBag below 4.4.30 => https://github.com/symfony/symfony/commit/3eca446b21607ea1c7a865ece2dd8254c33679cc + test '${{ matrix.symfony-version }}' = '4.4' && test '${{ matrix.php-version }}' = '8.2' && SF_VERSION=4.4.30 + composer require -W ${{ env.COMPOSER_OPTIONS }} ${{ matrix.composer-flag }} \ + symfony/http-foundation:^$SF_VERSION \ + symfony/http-kernel:^$SF_VERSION \ + symfony/config:^$SF_VERSION \ + symfony/dependency-injection:^$SF_VERSION \ + symfony/framework-bundle:^$SF_VERSION \ + symfony/routing:^$SF_VERSION \ + && composer update ${{ env.COMPOSER_OPTIONS }} ${{ matrix.composer-flag }} \ + && make build + + - name: Tests + run: make test-unit && make test-functional + + # Upload to codacy first as codecov action always remove coverage files despite move_coverage_to_trash at false + # And only if it's not a PR from a fork => Can't work as codacy secret is not accessible in that context + - name: Upload coverages to Codacy + if: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'yoanm/symfony-jsonrpc-http-server-doc') && env.COVERAGE_TYPE == 'xdebug' }} + run: ${{ env.CODACY_BIN }} report -r build/coverage-phpunit/unit.clover -r build/coverage-behat/clover.xml -r build/coverage-phpunit/functional.clover -t ${{ secrets.CODACY_PROJECT_TOKEN }} --partial + + # See the reports at https://codecov.io/gh/yoanm/symfony-jsonrpc-http-server-doc + - name: Upload unit tests coverage to codecov + if: ${{ env.COVERAGE_TYPE == 'xdebug' }} + uses: codecov/codecov-action@v3 + with: + file: "build/coverage-phpunit/unit.clover" + name: "unit-tests-${{ matrix.php-version }}-${{ matrix.symfony-version }}" + flags: "unit-tests,php-${{ matrix.php-version }},sf-${{ matrix.symfony-version }}" + fail_ci_if_error: true + move_coverage_to_trash: false + verbose: ${{ runner.debug == '1' }} + + - name: Upload functional tests coverage to codecov + if: ${{ env.COVERAGE_TYPE == 'xdebug' }} + uses: codecov/codecov-action@v3 + with: + files: "build/coverage-behat/clover.xml,build/coverage-phpunit/functional.clover" + name: "functional-tests-${{ matrix.php-version }}-${{ matrix.symfony-version }}" + flags: "functional-tests,php-${{ matrix.php-version }},sf-${{ matrix.symfony-version }}" + fail_ci_if_error: true + move_coverage_to_trash: false + verbose: ${{ runner.debug == '1' }} + + static-checks: + name: Static checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP 8.2 + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 # Latest supported + tools: composer + coverage: none + env: + # Always use latest available patch for the version + update: true + + - name: Setup cache + id: cache + uses: actions/cache@v3 + with: + path: | + ~/.composer + # Clear the cache if composer json (as composer.lock is in the repo) has been updated + key: tests-${{ env.PHP_VERSION }}-${{ hashFiles('composer.json') }} + + - name: Build + run: make build + + - name: ComposerRequireChecker + uses: docker://webfactory/composer-require-checker:4.5.0 + + - name: Dependencies check + if: ${{ github.event_name == 'pull_request' }} + uses: actions/dependency-review-action@v1 + + finalize-codacy-coverage-report: + runs-on: ubuntu-latest + name: Finalize Codacy coverage report + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'yoanm/symfony-jsonrpc-http-server-doc' }} + needs: [ tests ] + steps: + - name: Setup cache + id: cache + uses: actions/cache@v3 + with: + path: | + ${{ env.CODACY_CACHE_PATH }} + key: codacy-final + + - name: Download codacy binary + if: steps.cache.outputs.cache-hit != 'true' + run: | + mkdir -p ${{ env.CODACY_CACHE_PATH }} \ + && curl -LN https://coverage.codacy.com/get.sh -o ${{ env.CODACY_BIN }} \ + && chmod +x ${{ env.CODACY_BIN }} \ + && ${{ env.CODACY_BIN }} download + + - name: Finalize reporting + run: ${{ env.CODACY_BIN }} final -t ${{ secrets.CODACY_PROJECT_TOKEN }} + + nightly-tests: + name: Nightly - Symfony ${{ matrix.symfony-version }} + runs-on: ubuntu-latest + env: + COMPOSER_OPTIONS: '--optimize-autoloader --ignore-platform-req=php+' + continue-on-error: true + needs: [ static-checks, tests ] + strategy: + fail-fast: false + max-parallel: 4 + matrix: + php-version: + - '8.3' # Current php dev version + symfony-version: + - '4.4' # Lowest LTS + - '5.4' # Latest LTS + - '6.0' # Current major version + include: + - symfony-version: '6.3' # Next symfony minor version to manage with latest supported PHP version + php-version: '8.2' + + steps: + - name: Check out code + uses: actions/checkout@v3 + + - name: Setup PHP ${{ matrix.php-version }} + uses: shivammathur/setup-php@v2 + with: + php-version: '${{ matrix.php-version }}' + tools: composer + coverage: none + env: + # Always use latest available patch for the version + update: true + + - name: Setup cache + id: cache + uses: actions/cache@v3 + with: + path: | + ~/.composer + ./vendor + # Clear the cache if composer json (as composer.lock is in the repo) has been updated + key: tests-${{ matrix.php-version }}-${{ matrix.symfony-version }}-${{ hashFiles('composer.json') }} + + - name: Build + run: | + composer config minimum-stability dev \ + && composer require -W ${{ env.COMPOSER_OPTIONS }} \ + symfony/http-foundation:^${{ matrix.symfony-version }} \ + symfony/http-kernel:^${{ matrix.symfony-version }} \ + symfony/config:^${{ matrix.symfony-version }} \ + symfony/dependency-injection:^${{ matrix.symfony-version }} \ + symfony/framework-bundle:^${{ matrix.symfony-version }} \ + symfony/routing:^${{ matrix.symfony-version }} \ + && composer update ${{ env.COMPOSER_OPTIONS }} \ + && make build + + - name: Test + run: make test-unit && make test-functional diff --git a/.remarkignore b/.remarkignore new file mode 100644 index 0000000..22d0d82 --- /dev/null +++ b/.remarkignore @@ -0,0 +1 @@ +vendor diff --git a/.remarkrc b/.remarkrc new file mode 100644 index 0000000..0527df5 --- /dev/null +++ b/.remarkrc @@ -0,0 +1,6 @@ +{ + "plugins": [ + "remark-preset-lint-consistent", + "remark-preset-lint-recommended" + ] +} diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 156f560..b579dd2 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,96 +1,98 @@ build_failure_conditions: - - 'project.metric_change("scrutinizer.quality", < -0.30)' - - 'elements.rating(<= D).exists' # No classes/methods with a rating of D or worse - - 'issues.severity(>= MAJOR).exists' # New major or higher severity issues - - 'project.metric("scrutinizer.quality", < 9)' # Code Quality Rating drops below 9 - - 'project.metric("scrutinizer.test_coverage", < 1)' # Code Coverage must alway be 100% - - 'patches.label("Doc Comments").exists' # No doc comments patches allowed - - 'patches.label("Spacing").exists' # No spacing patches allowed - - 'patches.label("Bug").exists' # No bug patches allowed - - 'issues.label("coding-style").exists' # No coding style issues allowed + - 'project.metric_change("scrutinizer.quality", < -0.30)' + - 'elements.rating(<= D).exists' # No classes/methods with a rating of D or worse + - 'issues.severity(>= MAJOR).exists' # New major or higher severity issues + - 'project.metric("scrutinizer.quality", < 9)' # Code Quality Rating drops below 9 + - 'project.metric("scrutinizer.test_coverage", < 1)' # Code Coverage must alway be 100% + - 'patches.label("Doc Comments").exists' # No doc comments patches allowed + - 'patches.label("Spacing").exists' # No spacing patches allowed + - 'patches.label("Bug").exists' # No bug patches allowed + - 'issues.label("coding-style").exists' # No coding style issues allowed build: - dependencies: - override: - - - command: make build - title: Build deps - tests: - stop_on_failure: true - override: - - - command: make coverage - title: Coverage - idle_timeout: 1200 - coverage: - file: 'build/coverage/clover.xml' - format: 'php-clover' - - - command: make codestyle - title: Code style - - - command: composer global require maglnet/composer-require-checker && composer-require-checker check composer.json - title: Composer-require-checker - - - command: php-scrutinizer-run --enable-security-analysis - title: Scrutinizer checks - cache: - directories: - - ~/.composer - - vendor + dependencies: + override: + - command: make build + title: Build deps + idle_timeout: 240 + tests: + stop_on_failure: true + override: + - command: make codestyle + title: Code style + - command: make scrutinizer-phpunit + idle_timeout: 1200 + coverage: + file: 'build/coverage-phpunit/scrutinizer.xml' + format: 'php-clover' + - command: make scrutinizer-behat + idle_timeout: 1200 + coverage: + file: 'build/coverage-behat/clover.xml' + format: 'php-clover' + - command: php-scrutinizer-run --enable-security-analysis + title: Scrutinizer checks - environment: - variables: - CI: 'true' - TEST_OUTPUT_STYLE: 'pretty' - COMPOSER_OPTIONS: '--optimize-autoloader' - COVERAGE_OUTPUT_STYLE: 'clover' - COVERAGE_CLOVER_FILE_PATH: 'build/coverage/clover.xml' - php: - version: "7.3" - timezone: UTC - postgresql: false - redis: false + cache: + directories: + - ~/.composer + - vendor + + environment: + variables: + CI: 'true' + TEST_OUTPUT_STYLE: 'pretty' + COMPOSER_OPTIONS: '--optimize-autoloader' + COVERAGE_OUTPUT_STYLE: 'clover' + COVERAGE_CLOVER_FILE_PATH: 'build/coverage/clover.xml' + PHPCS_DISABLE_WARNING: 'true' + php: + version: "8.2" + ini: + memory_limit: "-1" + timezone: UTC + postgresql: false + redis: false filter: - paths: - - src/* + paths: + - src/* checks: - php: - code_rating: true - duplication: true - no_debug_code: true - check_method_contracts: - verify_interface_like_constraints: true - verify_documented_constraints: true - verify_parent_constraints: true - simplify_boolean_return: true - return_doc_comments: true - return_doc_comment_if_not_inferrable: true - remove_extra_empty_lines: true - properties_in_camelcaps: true - phpunit_assertions: true - parameters_in_camelcaps: true - parameter_doc_comments: true - param_doc_comment_if_not_inferrable: true - overriding_parameter: true - no_trailing_whitespace: true - no_short_variable_names: - minimum: '3' - no_short_method_names: - minimum: '3' - no_long_variable_names: - maximum: '20' - no_goto: true - naming_conventions: - local_variable: '^[a-z][a-zA-Z0-9]*$' - abstract_class_name: ^Abstract|Factory$ - utility_class_name: 'Utils?$' - constant_name: '^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$' - property_name: '^[a-z][a-zA-Z0-9]*$' - method_name: '^(?:[a-z]|__)[a-zA-Z0-9]*$' - parameter_name: '^[a-z][a-zA-Z0-9]*$' - interface_name: '^[A-Z][a-zA-Z0-9]*Interface$' - type_name: '^[A-Z][a-zA-Z0-9]*$' - exception_name: '^[A-Z][a-zA-Z0-9]*Exception$' - isser_method_name: '^(?:is|has|should|may|supports)' - more_specific_types_in_doc_comments: true - fix_doc_comments: false + php: + code_rating: true + duplication: true + no_debug_code: true + check_method_contracts: + verify_interface_like_constraints: true + verify_documented_constraints: true + verify_parent_constraints: true + simplify_boolean_return: true + return_doc_comments: true + return_doc_comment_if_not_inferrable: true + remove_extra_empty_lines: true + properties_in_camelcaps: true + phpunit_assertions: true + parameters_in_camelcaps: true + parameter_doc_comments: true + param_doc_comment_if_not_inferrable: true + overriding_parameter: true + no_trailing_whitespace: true + no_short_variable_names: + minimum: '3' + no_short_method_names: + minimum: '3' + no_long_variable_names: + maximum: '20' + no_goto: true + naming_conventions: + local_variable: '^[a-z][a-zA-Z0-9]*$' + abstract_class_name: ^Abstract|Factory$ + utility_class_name: 'Utils?$' + constant_name: '^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$' + property_name: '^[a-z][a-zA-Z0-9]*$' + method_name: '^(?:[a-z]|__)[a-zA-Z0-9]*$' + parameter_name: '^[a-z][a-zA-Z0-9]*$' + interface_name: '^[A-Z][a-zA-Z0-9]*Interface$' + type_name: '^[A-Z][a-zA-Z0-9]*$' + exception_name: '^[A-Z][a-zA-Z0-9]*Exception$' + isser_method_name: '^(?:is|has|should|may|supports)' + more_specific_types_in_doc_comments: true + fix_doc_comments: false diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5b81dc1..0000000 --- a/.travis.yml +++ /dev/null @@ -1,41 +0,0 @@ -language: php - -php: - - '7.2' - - '7.3' - - '7.4' - -env: - global: - - CI: 'true' - - TEST_OUTPUT_STYLE: 'pretty' - - PHPCS_REPORT_STYLE: 'full' - - COMPOSER_OPTIONS: '--optimize-autoloader' - jobs: - - SYMFONY_VERSION: '~4.0' - - SYMFONY_VERSION: '~5.0' - -jobs: - fast_finish: true - -before_install: - # remove xdebug to speed up build - - phpenv config-rm xdebug.ini || true - -install: - - composer require symfony/http-kernel:$SYMFONY_VERSION symfony/config:$SYMFONY_VERSION symfony/dependency-injection:$SYMFONY_VERSION symfony/routing:$SYMFONY_VERSION - - make build -script: - - make test-technical - - make test-functional - -cache: - directories: - - $HOME/.composer - - vendor - -branches: - except: - - /.*\-dev$/ - - /.*\-patch(\-\d+)?$/ - - /^dev-.*/ diff --git a/Makefile b/Makefile index 24c8bd3..fdbc8a1 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ COLOR_ENABLED ?= true TEST_OUTPUT_STYLE ?= dot -COVERAGE_OUTPUT_STYLE ?= html ## DIRECTORY AND FILE BUILD_DIRECTORY ?= build -REPORTS_DIRECTORY ?= ${BUILD_DIRECTORY}/reports -COVERAGE_DIRECTORY ?= ${BUILD_DIRECTORY}/coverage -BEHAT_COVERAGE_DIRECTORY ?= ${BUILD_DIRECTORY}/behat-coverage -COVERAGE_CLOVER_FILE_PATH ?= ${COVERAGE_DIRECTORY}/clover.xml +REPORTS_DIRECTORY ?= ${BUILD_DIRECTORY}/reports # Codestyle +BEHAT_COVERAGE_DIRECTORY ?= ${BUILD_DIRECTORY}/coverage-behat +PHPUNIT_COVERAGE_DIRECTORY ?= ${BUILD_DIRECTORY}/coverage-phpunit +PHPUNIT_UNIT_COVERAGE_FILE_PATH ?= ${PHPUNIT_COVERAGE_DIRECTORY}/unit.clover +PHPUNIT_FUNCTIONAL_COVERAGE_FILE_PATH ?= ${PHPUNIT_COVERAGE_DIRECTORY}/functional.clover ## Commands options ### Composer @@ -39,14 +39,21 @@ else BEHAT_OUTPUT_STYLE_OPTION ?= --format progress endif -ifeq ("${COVERAGE_OUTPUT_STYLE}","clover") - PHPUNIT_COVERAGE_OPTION ?= --coverage-clover ${COVERAGE_CLOVER_FILE_PATH} -else +ifdef COVERAGE_OUTPUT_STYLE + export XDEBUG_MODE=coverage ifeq ("${COVERAGE_OUTPUT_STYLE}","html") - PHPUNIT_COVERAGE_OPTION ?= --coverage-html ${COVERAGE_DIRECTORY} - else - PHPUNIT_COVERAGE_OPTION ?= --coverage-text - endif + PHPUNIT_COVERAGE_OPTION ?= --coverage-html ${PHPUNIT_COVERAGE_DIRECTORY} + PHPUNIT_FUNCTIONAL_COVERAGE_OPTION ?= --coverage-html ${PHPUNIT_COVERAGE_DIRECTORY} + BEHAT_COVERAGE_OPTION ?= --profile coverage-html + else ifeq ("${COVERAGE_OUTPUT_STYLE}","clover") + PHPUNIT_COVERAGE_OPTION ?= --coverage-clover ${PHPUNIT_UNIT_COVERAGE_FILE_PATH} + PHPUNIT_FUNCTIONAL_COVERAGE_OPTION ?= --coverage-clover ${PHPUNIT_FUNCTIONAL_COVERAGE_FILE_PATH} + BEHAT_COVERAGE_OPTION ?= --profile coverage-clover + else + PHPUNIT_COVERAGE_OPTION ?= --coverage-text + PHPUNIT_FUNCTIONAL_COVERAGE_OPTION ?= --coverage-text + BEHAT_COVERAGE_OPTION ?= --profile coverage + endif endif ifneq ("${PHPCS_REPORT_FILE}","") @@ -71,39 +78,36 @@ install: configure: # Project tests -test: - make test-functional - make test-technical - make codestyle +test: test-functional test-unit codestyle -test-technical: - ./vendor/bin/phpunit ${PHPUNIT_COLOR_OPTION} ${PHPUNIT_OUTPUT_STYLE_OPTION} --testsuite technical +ifdef PHPUNIT_COVERAGE_OPTION +test-unit: create-build-directories +endif +test-unit: + ./vendor/bin/phpunit ${PHPUNIT_COLOR_OPTION} ${PHPUNIT_OUTPUT_STYLE_OPTION} ${PHPUNIT_COVERAGE_OPTION} --testsuite technical +ifdef BEHAT_COVERAGE_OPTION +test-functional: create-build-directories +else ifdef PHPUNIT_FUNCTIONAL_COVERAGE_OPTION +test-functional: create-build-directories +endif test-functional: - ./vendor/bin/phpunit ${PHPUNIT_COLOR_OPTION} ${PHPUNIT_OUTPUT_STYLE_OPTION} --testsuite functional - ./vendor/bin/behat ${BEHAT_COLOR_OPTION} ${BEHAT_OUTPUT_STYLE_OPTION} --no-snippets + ./vendor/bin/phpunit ${PHPUNIT_COLOR_OPTION} ${PHPUNIT_OUTPUT_STYLE_OPTION} ${PHPUNIT_FUNCTIONAL_COVERAGE_OPTION} --testsuite functional + ./vendor/bin/behat ${BEHAT_COLOR_OPTION} ${BEHAT_OUTPUT_STYLE_OPTION} ${BEHAT_COVERAGE_OPTION} --no-snippets -codestyle: create-reports-directory +codestyle: create-build-directories ./vendor/bin/phpcs ${PHPCS_DISABLE_WARNING_OPTION} --standard=phpcs.xml.dist ${PHPCS_COLOR_OPTION} ${PHPCS_REPORT_FILE_OPTION} --report=${PHPCS_REPORT_STYLE} -coverage: create-coverage-directory - ./vendor/bin/phpunit ${PHPUNIT_COLOR_OPTION} ${PHPUNIT_OUTPUT_STYLE_OPTION} ${PHPUNIT_COVERAGE_OPTION} +scrutinizer-phpunit: + XDEBUG_MODE=coverage ./vendor/bin/phpunit ${PHPUNIT_COLOR_OPTION} ${PHPUNIT_OUTPUT_STYLE_OPTION} --coverage-clover build/coverage-phpunit/scrutinizer.xml -behat-coverage: create-behat-coverage-directory - composer required leanphp/behat-code-coverage - ./vendor/bin/behat ${BEHAT_COLOR_OPTION} ${BEHAT_OUTPUT_STYLE_OPTION} --no-snippets --profile coverage +scrutinizer-behat: + XDEBUG_MODE=coverage ./vendor/bin/behat ${BEHAT_COLOR_OPTION} ${BEHAT_OUTPUT_STYLE_OPTION} --profile coverage-clover --no-snippets # Internal commands -create-coverage-directory: - mkdir -p ${COVERAGE_DIRECTORY} - -create-behat-coverage-directory: - mkdir -p ${BEHAT_COVERAGE_DIRECTORY} - -create-reports-directory: - mkdir -p ${REPORTS_DIRECTORY} - +create-build-directories: + mkdir -p ${PHPUNIT_COVERAGE_DIRECTORY} ${BEHAT_COVERAGE_DIRECTORY} ${REPORTS_DIRECTORY} -.PHONY: build install configure test test-technical test-functional codestyle coverage behat-coverage create-coverage-directory create-behat-coverage-directory create-reports-directory +.PHONY: build install configure test test-unit test-functional codestyle create-build-directories scrutinizer-behat scrutinizer-phpunit .DEFAULT: build diff --git a/README.md b/README.md index 3b72bf1..b55987d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,19 @@ # Symfony JSON-RPC server documentation -[![License](https://img.shields.io/github/license/yoanm/symfony-jsonrpc-http-server-doc.svg)](https://github.com/yoanm/symfony-jsonrpc-http-server-doc) [![Code size](https://img.shields.io/github/languages/code-size/yoanm/symfony-jsonrpc-http-server-doc.svg)](https://github.com/yoanm/symfony-jsonrpc-http-server-doc) [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=yoanm/symfony-jsonrpc-http-server-doc)](https://dependabot.com) -[![Scrutinizer Build Status](https://img.shields.io/scrutinizer/build/g/yoanm/symfony-jsonrpc-http-server-doc.svg?label=Scrutinizer&logo=scrutinizer)](https://scrutinizer-ci.com/g/yoanm/symfony-jsonrpc-http-server-doc/build-status/master) [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/yoanm/symfony-jsonrpc-http-server-doc/master.svg?logo=scrutinizer)](https://scrutinizer-ci.com/g/yoanm/symfony-jsonrpc-http-server-doc/?branch=master) [![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/yoanm/symfony-jsonrpc-http-server-doc/master.svg?logo=scrutinizer)](https://scrutinizer-ci.com/g/yoanm/symfony-jsonrpc-http-server-doc/?branch=master) +[![License](https://img.shields.io/github/license/yoanm/symfony-jsonrpc-http-server-doc.svg)](https://github.com/yoanm/symfony-jsonrpc-http-server-doc) +[![Code size](https://img.shields.io/github/languages/code-size/yoanm/symfony-jsonrpc-http-server-doc.svg)](https://github.com/yoanm/symfony-jsonrpc-http-server-doc) +[![Dependabot Status](https://api.dependabot.com/badges/status?host=github\&repo=yoanm/symfony-jsonrpc-http-server-doc)](https://dependabot.com) -[![Travis Build Status](https://img.shields.io/travis/com/yoanm/symfony-jsonrpc-http-server-doc/master.svg?label=Travis&logo=travis)](https://travis-ci.com/yoanm/symfony-jsonrpc-http-server-doc) [![Travis Symfony Versions](https://img.shields.io/badge/Symfony-v4%20%2F%20v5-8892BF.svg?logo=travis)](https://symfony.com/) +[![Scrutinizer Build Status](https://img.shields.io/scrutinizer/build/g/yoanm/symfony-jsonrpc-http-server-doc.svg?label=Scrutinizer\&logo=scrutinizer)](https://scrutinizer-ci.com/g/yoanm/symfony-jsonrpc-http-server-doc/build-status/master) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/yoanm/symfony-jsonrpc-http-server-doc/master.svg?logo=scrutinizer)](https://scrutinizer-ci.com/g/yoanm/symfony-jsonrpc-http-server-doc/?branch=master) +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/8f39424add044b43a70bdb238e2f48db)](https://www.codacy.com/gh/yoanm/symfony-jsonrpc-http-server-doc/dashboard?utm_source=github.com\&utm_medium=referral\&utm_content=yoanm/symfony-jsonrpc-http-server-doc\&utm_campaign=Badge_Grade) -[![Latest Stable Version](https://img.shields.io/packagist/v/yoanm/symfony-jsonrpc-http-server-doc.svg)](https://packagist.org/packages/yoanm/symfony-jsonrpc-http-server-doc) [![Packagist PHP version](https://img.shields.io/packagist/php-v/yoanm/symfony-jsonrpc-http-server-doc.svg)](https://packagist.org/packages/yoanm/symfony-jsonrpc-http-server-doc) +[![CI](https://github.com/yoanm/symfony-jsonrpc-http-server-doc/actions/workflows/CI.yml/badge.svg?branch=master)](https://github.com/yoanm/symfony-jsonrpc-http-server-doc/actions/workflows/CI.yml) +[![codecov](https://codecov.io/gh/yoanm/symfony-jsonrpc-http-server-doc/branch/master/graph/badge.svg?token=NHdwEBUFK5)](https://codecov.io/gh/yoanm/symfony-jsonrpc-http-server-doc) +[![Symfony Versions](https://img.shields.io/badge/Symfony-v4.4%20%2F%20v5.4%2F%20v6.x-8892BF.svg?logo=github)](https://symfony.com/) + +[![Latest Stable Version](https://img.shields.io/packagist/v/yoanm/symfony-jsonrpc-http-server-doc.svg)](https://packagist.org/packages/yoanm/symfony-jsonrpc-http-server-doc) +[![Packagist PHP version](https://img.shields.io/packagist/php-v/yoanm/symfony-jsonrpc-http-server-doc.svg)](https://packagist.org/packages/yoanm/symfony-jsonrpc-http-server-doc) Symfony bundle for easy JSON-RPC server documentation @@ -15,9 +23,9 @@ See [yoanm/symfony-jsonrpc-params-sf-constraints-doc](https://github.com/yoanm/s ## Availble formats - - Raw : Built-in `json` format at `/doc` or `/doc/raw.json` - - Swagger : [yoanm/symfony-jsonrpc-http-server-swagger-doc](https://github.com/yoanm/symfony-jsonrpc-http-server-swagger-doc) - - OpenApi : [yoanm/symfony-jsonrpc-http-server-openapi-doc](https://github.com/yoanm/symfony-jsonrpc-http-server-openapi-doc) +* Raw : Built-in `json` format at `/doc` or `/doc/raw.json` +* Swagger : [yoanm/symfony-jsonrpc-http-server-swagger-doc](https://github.com/yoanm/symfony-jsonrpc-http-server-swagger-doc) +* OpenApi : [yoanm/symfony-jsonrpc-http-server-openapi-doc](https://github.com/yoanm/symfony-jsonrpc-http-server-openapi-doc) ## How to use @@ -29,45 +37,46 @@ See below how to configure it. *[Behat demo app configuration folders](./features/demo_app/) can be used as examples.* - - Add the bundles in your `config/bundles.php` file: - ```php - // config/bundles.php - return [ - ... - Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], - Yoanm\SymfonyJsonRpcHttpServer\JsonRpcHttpServerBundle::class => ['all' => true], - Yoanm\SymfonyJsonRpcHttpServerDoc\JsonRpcHttpServerDocBundle::class => ['all' => true], - ... - ]; - ``` - - - Add the following in your routing configuration : - ```yaml - # config/routes.yaml - json-rpc-endpoint: - resource: '@JsonRpcHttpServerBundle/Resources/config/routing/endpoint.xml' - - json-rpc-endpoint-doc: - resource: '@JsonRpcHttpServerDocBundle/Resources/config/routing/endpoint.xml' - ``` - - - Add the following in your configuration : - ```yaml - # config/config.yaml - framework: - secret: '%env(APP_SECRET)%' - - json_rpc_http_server: ~ - - json_rpc_http_server_doc: ~ - # Or the following in case you want to customize endpoint path - #json_rpc_http_server_doc: - # endpoint: '/my-custom-doc-endpoint' # Default to '/doc' - ``` - - - Register JSON-RPC methods as described on [yoanm/symfony-jsonrpc-http-server](https://github.com/yoanm/symfony-jsonrpc-http-server) documentation. - - - Query your project at `/doc` endpoint and you will have a `json` documentation of your server. +* Add the bundles in your `config/bundles.php` file: + ```php + // config/bundles.php + return [ + ... + Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], + Yoanm\SymfonyJsonRpcHttpServer\JsonRpcHttpServerBundle::class => ['all' => true], + Yoanm\SymfonyJsonRpcHttpServerDoc\JsonRpcHttpServerDocBundle::class => ['all' => true], + ... + ]; + ``` + +* Add the following in your routing configuration : + ```yaml + # config/routes.yaml + json-rpc-endpoint: + resource: '@JsonRpcHttpServerBundle/Resources/config/routing/endpoint.xml' + + json-rpc-endpoint-doc: + resource: '@JsonRpcHttpServerDocBundle/Resources/config/routing/endpoint.xml' + ``` + +* Add the following in your configuration : + ```yaml + # config/config.yaml + framework: + secret: '%env(APP_SECRET)%' + + json_rpc_http_server: ~ + + json_rpc_http_server_doc: ~ + # Or the following in case you want to customize endpoint path + #json_rpc_http_server_doc: + # endpoint: '/my-custom-doc-endpoint' # Default to '/doc' + ``` + +* Register JSON-RPC methods as described on [yoanm/symfony-jsonrpc-http-server](https://github.com/yoanm/symfony-jsonrpc-http-server) documentation. + +* Query your project at `/doc` endpoint and you will have a `json` documentation of your server. ## Contributing + See [contributing note](./CONTRIBUTING.md) diff --git a/behat.yml b/behat.yml index 7fae20b..4244bfa 100644 --- a/behat.yml +++ b/behat.yml @@ -1,19 +1,30 @@ default: + extensions: + DVDoug\Behat\CodeCoverage\Extension: + filter: + include: + directories: + 'src': ~ + reports: [] # No reports suites: default: contexts: - Tests\Functional\BehatContext\DemoAppContext: ~ coverage: extensions: - LeanPHP\Behat\CodeCoverage\Extension: - drivers: - - local - filter: - whitelist: - include: - directories: - 'src': ~ - report: - format: html - options: - target: build/behat-coverage + DVDoug\Behat\CodeCoverage\Extension: + reports: + text: + showColors: true +coverage-html: + extensions: + DVDoug\Behat\CodeCoverage\Extension: + reports: + html: + target: build/coverage-behat +coverage-clover: + extensions: + DVDoug\Behat\CodeCoverage\Extension: + reports: + clover: + target: build/coverage-behat/clover.xml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..ad6143e --- /dev/null +++ b/codecov.yml @@ -0,0 +1,12 @@ +coverage: + range: "80...100" + +flags: + nightly: + joined: false + +comment: + show_carryforward_flags: true + +github_checks: + annotations: true diff --git a/composer.json b/composer.json index e920de9..0ec9488 100644 --- a/composer.json +++ b/composer.json @@ -32,25 +32,32 @@ "yoanm/symfony-jsonrpc-http-server-swagger-doc": "Symfony bundle for easy JSON-RPC server Swagger 2.0 documentation" }, "require": { + "php": "^8.0", "ext-json": "*", - "php": ">=7.2", - "yoanm/jsonrpc-server-sdk": "^3.0", - "yoanm/jsonrpc-server-doc-sdk": "^0.2", - "yoanm/symfony-jsonrpc-http-server": "^3.0", - "symfony/http-foundation": "^4.0 || ^5.0", - "symfony/http-kernel": "^4.0 || ^5.0", - "symfony/config": "^4.0 || ^5.0", - "symfony/dependency-injection": "^4.0 || ^5.0", - "symfony/event-dispatcher-contracts": "^1.0 || ^2.0" + "symfony/config": "^4.4 || ^5.4 || ^6.0", + "symfony/dependency-injection": "^4.4 || ^5.4 || ^6.0", + "symfony/event-dispatcher-contracts": "^1.0 || ^2.0", + "symfony/http-foundation": "^4.4 || ^5.4 || ^6.0", + "symfony/http-kernel": "^4.4 || ^5.4 || ^6.0", + "yoanm/jsonrpc-server-doc-sdk": "^0.3 || ^1.0", + "yoanm/jsonrpc-server-sdk": "^3.3", + "yoanm/symfony-jsonrpc-http-server": "^3.3" }, "require-dev": { - "behat/behat": "~3.0", - "squizlabs/php_codesniffer": "3.*", - "phpunit/phpunit": "^7.0 || ^8.0", - "matthiasnoback/symfony-dependency-injection-test": "^3.0 || ^4.0", - "matthiasnoback/symfony-config-test": "^3.0 || ^4.0", - "symfony/framework-bundle": "^4.0 || ^5.0", - "symfony/routing": "^4.0 || ^5.0", - "yoanm/php-unit-extended": "~1.0" + "behat/behat": "^3.9.0", + "dvdoug/behat-code-coverage": "^5.0", + "matthiasnoback/symfony-config-test": "^4.0", + "matthiasnoback/symfony-dependency-injection-test": "^4.0", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/php-code-coverage": "^9.2.4", + "phpunit/phpunit": "^9.0", + "squizlabs/php_codesniffer": "^3.5", + "symfony/framework-bundle": "^4.4 || ^5.4 || ^6.0", + "symfony/routing": "^4.4 || ^5.4 || ^6.0", + "yoanm/php-unit-extended": "^2.0.2" + }, + "config": { + "sort-packages": true } } diff --git a/features/bundle.feature b/features/bundle.feature index 2fc22ab..e4e14e9 100644 --- a/features/bundle.feature +++ b/features/bundle.feature @@ -1,7 +1,7 @@ Feature: demo symfony application Scenario: Check that all methods are available - # Ensure methods with tag have been succesfully loaded + # Ensure methods with tag have been successfully loaded When I send a "GET" request on "/my-custom-doc-endpoint" demoApp kernel endpoint Then I should have a "200" response from demoApp with following content: """ @@ -84,13 +84,12 @@ Feature: demo symfony application "nullable": true, "required": false, "siblings": { - "previous": { - "type": "string", - "nullable": true, - "required": false, - "description": "Previous error message" - } - } + "_class": {"type": "string", "nullable": true, "required": false, "description": "Exception class"}, + "_code": {"type": "integer", "nullable": true, "required": false, "description": "Exception code"}, + "_message": {"type": "string", "nullable": true, "required": false, "description": "Exception message"}, + "_trace": {"type": "array", "nullable": true, "required": false, "description": "PHP stack trace"} + }, + "allowMissing": true } } } @@ -179,13 +178,12 @@ Feature: demo symfony application "nullable": true, "required": false, "siblings": { - "previous": { - "type": "string", - "nullable": true, - "required": false, - "description": "Previous error message" - } - } + "_class": {"type": "string", "nullable": true, "required": false, "description": "Exception class"}, + "_code": {"type": "integer", "nullable": true, "required": false, "description": "Exception code"}, + "_message": {"type": "string", "nullable": true, "required": false, "description": "Exception message"}, + "_trace": {"type": "array", "nullable": true, "required": false, "description": "PHP stack trace"} + }, + "allowMissing": true } } } @@ -264,13 +262,12 @@ Feature: demo symfony application "nullable": true, "required": false, "siblings": { - "previous": { - "type": "string", - "nullable": true, - "required": false, - "description": "Previous error message" - } - } + "_class": {"type": "string", "nullable": true, "required": false, "description": "Exception class"}, + "_code": {"type": "integer", "nullable": true, "required": false, "description": "Exception code"}, + "_message": {"type": "string", "nullable": true, "required": false, "description": "Exception message"}, + "_trace": {"type": "array", "nullable": true, "required": false, "description": "PHP stack trace"} + }, + "allowMissing": true } } } diff --git a/features/demo_app/src/AbstractKernel.php b/features/demo_app/src/AbstractKernel.php index 5848183..d874983 100644 --- a/features/demo_app/src/AbstractKernel.php +++ b/features/demo_app/src/AbstractKernel.php @@ -2,8 +2,12 @@ namespace DemoApp; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; +use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Kernel as BaseHttpKernel; +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; +use Symfony\Component\Routing\RouteCollectionBuilder; abstract class AbstractKernel extends BaseHttpKernel { @@ -13,14 +17,25 @@ abstract class AbstractKernel extends BaseHttpKernel /** @var string|null */ private $customCacheDir = null; + public function registerBundles(): iterable + { + /** @noinspection PhpIncludeInspection */ + $contents = require $this->getConfigDir().'/bundles.php'; + foreach ($contents as $class => $envs) { + if (isset($envs['all']) || isset($envs[$this->environment])) { + yield new $class(); + } + } + } + /** * {@inheritdoc} */ - public function getCacheDir() + public function getCacheDir(): string { // Use a specific cache for each kernels if (null === $this->customCacheDir) { - $this->customCacheDir = $this->getProjectDir().'/var/cache/'.$this->environment.'/'.$this->getConfigDirectory(); + $this->customCacheDir = $this->getProjectDir().'/var/cache/'.$this->environment.'/'.$this->getConfigDirectoryName(); } return $this->customCacheDir; @@ -29,7 +44,7 @@ public function getCacheDir() /** * {@inheritdoc} */ - public function getLogDir() + public function getLogDir(): string { return $this->getProjectDir().'/var/log'; } @@ -37,21 +52,50 @@ public function getLogDir() /** * {@inheritdoc} */ - public function getProjectDir() + public function getProjectDir(): string { return realpath(__DIR__.'/../'); } + public function getConfigDir(): string + { + return $this->getProjectDir().'/'.$this->getConfigDirectoryName(); + } + + /** + * @param RouteCollectionBuilder|RoutingConfigurator $routes + */ + protected function configureRoutes($routes) + { + $confDir = $this->getConfigDir(); + if ($routes instanceof RoutingConfigurator) { + $routes->import($confDir . '/routes' . self::CONFIG_EXTS, 'glob'); + } else { + $routes->import($confDir . '/routes' . self::CONFIG_EXTS, '/', 'glob'); + } + } + + /** + * {@inheritdoc} + */ + protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader) + { + $container->setParameter('container.dumper.inline_class_loader', true); + $confDir = $this->getConfigDir(); + $loader->load($confDir.'/config'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/services'.self::CONFIG_EXTS, 'glob'); + } + /** * Gets the container class. * * @return string The container class */ - protected function getContainerClass() + protected function getContainerClass(): string { // In order to avoid collisions between kernels use a dedicated name - return parent::getContainerClass().Container::camelize($this->getConfigDirectory()); + return parent::getContainerClass().Container::camelize($this->getConfigDirectoryName()); } - abstract public function getConfigDirectory() : string; + abstract public function getConfigDirectoryName() : string; } diff --git a/features/demo_app/src/DefaultKernel.php b/features/demo_app/src/DefaultKernel.php index e93b143..1f93962 100644 --- a/features/demo_app/src/DefaultKernel.php +++ b/features/demo_app/src/DefaultKernel.php @@ -1,46 +1,11 @@ getProjectDir().'/'.$this->getConfigDirectory().'/bundles.php'; - foreach ($contents as $class => $envs) { - if (isset($envs['all']) || isset($envs[$this->environment])) { - yield new $class(); - } - } - } - - /** - * {@inheritdoc} - */ - protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader) - { - $container->setParameter('container.dumper.inline_class_loader', true); - $confDir = $this->getProjectDir().'/'.$this->getConfigDirectory(); - $loader->load($confDir.'/config'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/services'.self::CONFIG_EXTS, 'glob'); - } - - /** - * {@inheritdoc} - */ - protected function configureRoutes(RouteCollectionBuilder $routes) - { - $confDir = $this->getProjectDir().'/'.$this->getConfigDirectory(); - $routes->import($confDir.'/routes'.self::CONFIG_EXTS, '/', 'glob'); - } - - /** - * {@inheritdoc} - */ - public function getConfigDirectory() : string + public function getConfigDirectoryName() : string { return 'default_config'; } diff --git a/features/demo_app/src/KernelWithMethodDocCreatedListener.php b/features/demo_app/src/KernelWithMethodDocCreatedListener.php index a54cff9..2534315 100644 --- a/features/demo_app/src/KernelWithMethodDocCreatedListener.php +++ b/features/demo_app/src/KernelWithMethodDocCreatedListener.php @@ -1,46 +1,14 @@ getProjectDir().'/'.$this->getConfigDirectory().'/bundles.php'; - foreach ($contents as $class => $envs) { - if (isset($envs['all']) || isset($envs[$this->environment])) { - yield new $class(); - } - } - } - - /** - * {@inheritdoc} - */ - protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader) - { - $container->setParameter('container.dumper.inline_class_loader', true); - $confDir = $this->getProjectDir().'/'.$this->getConfigDirectory(); - $loader->load($confDir.'/config'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/services'.self::CONFIG_EXTS, 'glob'); - } - - /** - * {@inheritdoc} - */ - protected function configureRoutes(RouteCollectionBuilder $routes) - { - $confDir = $this->getProjectDir().'/'.$this->getConfigDirectory(); - $routes->import($confDir.'/routes'.self::CONFIG_EXTS, '/', 'glob'); - } - /** * {@inheritdoc} */ - public function getConfigDirectory() : string + public function getConfigDirectoryName() : string { return 'config_with_method_doc_created_listener'; } diff --git a/features/demo_app/src/KernelWithServerDocCreatedListener.php b/features/demo_app/src/KernelWithServerDocCreatedListener.php index 2e960a9..7754373 100644 --- a/features/demo_app/src/KernelWithServerDocCreatedListener.php +++ b/features/demo_app/src/KernelWithServerDocCreatedListener.php @@ -7,40 +7,7 @@ class KernelWithServerDocCreatedListener extends AbstractKernel { - public function registerBundles(): iterable - { - $contents = require $this->getProjectDir().'/'.$this->getConfigDirectory().'/bundles.php'; - foreach ($contents as $class => $envs) { - if (isset($envs['all']) || isset($envs[$this->environment])) { - yield new $class(); - } - } - } - - /** - * {@inheritdoc} - */ - protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader) - { - $container->setParameter('container.dumper.inline_class_loader', true); - $confDir = $this->getProjectDir().'/'.$this->getConfigDirectory(); - $loader->load($confDir.'/config'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/services'.self::CONFIG_EXTS, 'glob'); - } - - /** - * {@inheritdoc} - */ - protected function configureRoutes(RouteCollectionBuilder $routes) - { - $confDir = $this->getProjectDir().'/'.$this->getConfigDirectory(); - $routes->import($confDir.'/routes'.self::CONFIG_EXTS, '/', 'glob'); - } - - /** - * {@inheritdoc} - */ - public function getConfigDirectory() : string + public function getConfigDirectoryName() : string { return 'config_with_server_doc_created_listener'; } diff --git a/src/Listener/ServerDocCreatedListener.php b/src/Listener/ServerDocCreatedListener.php index cf8dc39..2cb18e3 100644 --- a/src/Listener/ServerDocCreatedListener.php +++ b/src/Listener/ServerDocCreatedListener.php @@ -8,6 +8,7 @@ use Yoanm\JsonRpcServer\Domain\Exception\JsonRpcParseErrorException; use Yoanm\JsonRpcServerDoc\Domain\Model\ErrorDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ArrayDoc; +use Yoanm\JsonRpcServerDoc\Domain\Model\Type\IntegerDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ObjectDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\StringDoc; use Yoanm\SymfonyJsonRpcHttpServerDoc\Event\ServerDocCreatedEvent; @@ -64,14 +65,25 @@ public function appendJsonRpcServerErrorsDoc(ServerDocCreatedEvent $event) : voi (new ErrorDoc('Internal error', JsonRpcInternalErrorException::CODE)) ->setDataDoc( (new ObjectDoc()) - ->setAllowMissingSibling(false) + ->setAllowMissingSibling(true) ->setAllowExtraSibling(false) ->setRequired(false) - ->addSibling( - (new StringDoc()) - ->setName(JsonRpcInternalErrorException::DATA_PREVIOUS_KEY) - ->setDescription('Previous error message') - ) + ->addSibling(( + new StringDoc()) + ->setName('_class') + ->setDescription('Exception class')) + ->addSibling(( + new IntegerDoc()) + ->setName('_code') + ->setDescription('Exception code')) + ->addSibling(( + new StringDoc()) + ->setName('_message') + ->setDescription('Exception message')) + ->addSibling(( + new ArrayDoc()) + ->setName('_trace') + ->setDescription('PHP stack trace')) ) ); } diff --git a/src/Resources/config/routing/endpoint.xml b/src/Resources/config/routing/endpoint.xml index 89f3e7a..c609b0b 100644 --- a/src/Resources/config/routing/endpoint.xml +++ b/src/Resources/config/routing/endpoint.xml @@ -9,7 +9,7 @@ path="%json_rpc_http_server_doc.http_endpoint_path%/{filename}" methods="GET" > - json_rpc_http_server_doc.endpoint:httpGet + json_rpc_http_server_doc.endpoint::httpGet raw.json - json_rpc_http_server_doc.endpoint:httpOptions + json_rpc_http_server_doc.endpoint::httpOptions raw.json diff --git a/tests/Functional/Creator/HttpServerDocCreatorTest.php b/tests/Functional/Creator/HttpServerDocCreatorTest.php index c14897e..980c8a0 100644 --- a/tests/Functional/Creator/HttpServerDocCreatorTest.php +++ b/tests/Functional/Creator/HttpServerDocCreatorTest.php @@ -3,6 +3,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; @@ -16,6 +17,8 @@ */ class HttpServerDocCreatorTest extends TestCase { + use ProphecyTrait; + /** @var HttpServerDocCreator */ private $creator; diff --git a/tests/Functional/DependencyInjection/ConfigFilesTest.php b/tests/Functional/DependencyInjection/ConfigFilesTest.php index b8eb340..750e93a 100644 --- a/tests/Functional/DependencyInjection/ConfigFilesTest.php +++ b/tests/Functional/DependencyInjection/ConfigFilesTest.php @@ -1,6 +1,7 @@ So no [at]covers tag ! + * => So no [at]covers tag ! (but @coversNothing is mandatory to avoid failure) + * @coversNothing */ class ConfigFilesTest extends AbstractTestClass { + use ProphecyTrait; + /** * @dataProvider provideSDKInfraServiceIdAndClass * @dataProvider provideBundlePublicServiceIdAndClass diff --git a/tests/Functional/DependencyInjection/ConfigurationTest.php b/tests/Functional/DependencyInjection/ConfigurationTest.php index af29d36..152d971 100644 --- a/tests/Functional/DependencyInjection/ConfigurationTest.php +++ b/tests/Functional/DependencyInjection/ConfigurationTest.php @@ -3,6 +3,7 @@ use Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Yoanm\SymfonyJsonRpcHttpServerDoc\DependencyInjection\Configuration; /** @@ -10,6 +11,7 @@ */ class ConfigurationTest extends TestCase { + use ProphecyTrait; use ConfigurationTestCaseTrait; protected function getConfiguration() diff --git a/tests/Functional/DependencyInjection/JsonRpcHttpServerDocExtensionTest.php b/tests/Functional/DependencyInjection/JsonRpcHttpServerDocExtensionTest.php index 5aef988..4bba889 100644 --- a/tests/Functional/DependencyInjection/JsonRpcHttpServerDocExtensionTest.php +++ b/tests/Functional/DependencyInjection/JsonRpcHttpServerDocExtensionTest.php @@ -1,6 +1,7 @@ loadContainer(); diff --git a/tests/Functional/Endpoint/DocumentationEndpointTest.php b/tests/Functional/Endpoint/DocumentationEndpointTest.php index 753d63b..6e851e5 100644 --- a/tests/Functional/Endpoint/DocumentationEndpointTest.php +++ b/tests/Functional/Endpoint/DocumentationEndpointTest.php @@ -2,6 +2,7 @@ namespace Tests\Functional\Endpoint; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -14,6 +15,8 @@ */ class DocumentationEndpointTest extends TestCase { + use ProphecyTrait; + /** @var DocumentationEndpoint */ private $endpoint; @@ -97,10 +100,10 @@ public function testHttOptionsShouldReturnAllowedMethodsAndContentType() $this->assertSame('application/json', $response->headers->get('Content-Type')); // Check allowed methods - $this->assertSame($expectedAllowedMethodList, $response->headers->get('Allow', null, false)); + $this->assertSame($expectedAllowedMethodList, $response->headers->get('Allow', null)); $this->assertSame( $expectedAllowedMethodList, - $response->headers->get('Access-Control-Request-Method', null, false) + $response->headers->get('Access-Control-Request-Method', null) ); // Check allowed content types diff --git a/tests/Functional/Event/MethodDocCreatedEventTest.php b/tests/Functional/Event/MethodDocCreatedEventTest.php index 35a0d7c..24f39f2 100644 --- a/tests/Functional/Event/MethodDocCreatedEventTest.php +++ b/tests/Functional/Event/MethodDocCreatedEventTest.php @@ -2,6 +2,7 @@ namespace Tests\Functional\Event; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; use Yoanm\JsonRpcServerDoc\Domain\Model\MethodDoc; @@ -12,6 +13,8 @@ */ class MethodDocCreatedEventTest extends TestCase { + use ProphecyTrait; + /** @var MethodDocCreatedEvent */ private $event; diff --git a/tests/Functional/Event/ServerDocCreatedEventTest.php b/tests/Functional/Event/ServerDocCreatedEventTest.php index f4c42a2..850114c 100644 --- a/tests/Functional/Event/ServerDocCreatedEventTest.php +++ b/tests/Functional/Event/ServerDocCreatedEventTest.php @@ -2,6 +2,7 @@ namespace Tests\Functional\Event; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use Yoanm\JsonRpcServerDoc\Domain\Model\ServerDoc; use Yoanm\SymfonyJsonRpcHttpServerDoc\Event\ServerDocCreatedEvent; @@ -11,6 +12,8 @@ */ class ServerDocCreatedEventTest extends TestCase { + use ProphecyTrait; + /** @var ServerDocCreatedEvent */ private $event; diff --git a/tests/Functional/Finder/NormalizedDocFinderTest.php b/tests/Functional/Finder/NormalizedDocFinderTest.php index 6d1cb42..13fc7e2 100644 --- a/tests/Functional/Finder/NormalizedDocFinderTest.php +++ b/tests/Functional/Finder/NormalizedDocFinderTest.php @@ -2,6 +2,7 @@ namespace Tests\Functional\Finder; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use Yoanm\SymfonyJsonRpcHttpServerDoc\Finder\NormalizedDocFinder; use Yoanm\SymfonyJsonRpcHttpServerDoc\Provider\DocProviderInterface; @@ -11,6 +12,8 @@ */ class NormalizedDocFinderTest extends TestCase { + use ProphecyTrait; + /** @var NormalizedDocFinder */ private $finder; diff --git a/tests/Functional/Listener/ServerDocCreatedListenerTest.php b/tests/Functional/Listener/ServerDocCreatedListenerTest.php index 2e2f717..516c28d 100644 --- a/tests/Functional/Listener/ServerDocCreatedListenerTest.php +++ b/tests/Functional/Listener/ServerDocCreatedListenerTest.php @@ -10,6 +10,7 @@ use Yoanm\JsonRpcServerDoc\Domain\Model\ErrorDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\ServerDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ArrayDoc; +use Yoanm\JsonRpcServerDoc\Domain\Model\Type\IntegerDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ObjectDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\StringDoc; use Yoanm\SymfonyJsonRpcHttpServerDoc\Event\ServerDocCreatedEvent; @@ -98,14 +99,25 @@ public function testInternalErrorShouldHaveRightDataDoc() $this->assertNotNull($internalError->getDataDoc()); $this->assertEquals( (new ObjectDoc()) - ->setAllowMissingSibling(false) + ->setAllowMissingSibling(true) ->setAllowExtraSibling(false) ->setRequired(false) - ->addSibling( - (new StringDoc()) - ->setName(JsonRpcInternalErrorException::DATA_PREVIOUS_KEY) - ->setDescription('Previous error message') - ), + ->addSibling(( + new StringDoc()) + ->setName('_class') + ->setDescription('Exception class')) + ->addSibling(( + new IntegerDoc()) + ->setName('_code') + ->setDescription('Exception code')) + ->addSibling(( + new StringDoc()) + ->setName('_message') + ->setDescription('Exception message')) + ->addSibling(( + new ArrayDoc()) + ->setName('_trace') + ->setDescription('PHP stack trace')), $internalError->getDataDoc() ); } diff --git a/tests/Functional/Provider/RawDocProviderTest.php b/tests/Functional/Provider/RawDocProviderTest.php index 85deea2..f8862e9 100644 --- a/tests/Functional/Provider/RawDocProviderTest.php +++ b/tests/Functional/Provider/RawDocProviderTest.php @@ -2,6 +2,7 @@ namespace Tests\Functional\Provider; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use Yoanm\JsonRpcServerDoc\Domain\Model\HttpServerDoc; use Yoanm\JsonRpcServerDoc\Infra\Normalizer\HttpServerDocNormalizer; @@ -13,6 +14,8 @@ */ class RawDocProviderTest extends TestCase { + use ProphecyTrait; + /** @var RawDocProvider */ private $provider;