From d81a0ebba4dbd7f9564f3265e3771433df3d9e1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 03:46:01 +0000 Subject: [PATCH 1/4] chore(deps-dev): bump vite from 4.4.11 to 4.5.0 Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.4.11 to 4.5.0. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v4.5.0/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v4.5.0/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index e1b180dcab..6ae971cbc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "axios": "^1.5.1", "laravel-vite-plugin": "^0.8.1", "sass": "^1.69.0", - "vite": "^4.4.11", + "vite": "^4.5.0", "vite-plugin-manifest-sri": "^0.1.0" } }, @@ -978,9 +978,9 @@ } }, "node_modules/vite": { - "version": "4.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.11.tgz", - "integrity": "sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", + "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", "dev": true, "dependencies": { "esbuild": "^0.18.10", diff --git a/package.json b/package.json index f58614c426..bd60a70430 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "axios": "^1.5.1", "laravel-vite-plugin": "^0.8.1", "sass": "^1.69.0", - "vite": "^4.4.11", + "vite": "^4.5.0", "vite-plugin-manifest-sri": "^0.1.0" }, "dependencies": { From ea7d1f481a593000ee20d0199bc28be486801ddc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 03:46:29 +0000 Subject: [PATCH 2/4] chore(deps): bump alpinejs from 3.13.1 to 3.13.2 Bumps [alpinejs](https://github.com/alpinejs/alpine/tree/HEAD/packages/alpinejs) from 3.13.1 to 3.13.2. - [Release notes](https://github.com/alpinejs/alpine/releases) - [Commits](https://github.com/alpinejs/alpine/commits/v3.13.2/packages/alpinejs) --- updated-dependencies: - dependency-name: alpinejs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index e1b180dcab..b7709b54b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.4.0", "@popperjs/core": "^2.11.8", - "alpinejs": "^3.13.1", + "alpinejs": "^3.13.2", "bootstrap": "^5.3.0", "bootstrap5-autocomplete": "^1.1.22", "chart.js": "^4.4.0", @@ -425,9 +425,9 @@ "integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==" }, "node_modules/alpinejs": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.1.tgz", - "integrity": "sha512-/LZ7mumW02V7AV5xTTftJFHS0I3KOXLl7tHm4xpxXAV+HJ/zjTT0n8MU7RZ6UoGPhmO/i+KEhQojaH/0RsH5tg==", + "version": "3.13.2", + "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.2.tgz", + "integrity": "sha512-WzojeeN082kLZznGI1HAuP8yFJSWqJ1fGdz2mUjj45H4y0XwToE7fFqtI3mCPRR+BpcSbxT/NL+FyPnYAWSltw==", "dependencies": { "@vue/reactivity": "~3.1.1" } diff --git a/package.json b/package.json index f58614c426..245e837879 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.4.0", "@popperjs/core": "^2.11.8", - "alpinejs": "^3.13.1", + "alpinejs": "^3.13.2", "bootstrap": "^5.3.0", "bootstrap5-autocomplete": "^1.1.22", "chart.js": "^4.4.0", From 73b912ee8bebf4cea58389d4392efa239981beab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 03:48:18 +0000 Subject: [PATCH 3/4] chore(deps-dev): bump sass from 1.69.3 to 1.69.4 Bumps [sass](https://github.com/sass/dart-sass) from 1.69.3 to 1.69.4. - [Release notes](https://github.com/sass/dart-sass/releases) - [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md) - [Commits](https://github.com/sass/dart-sass/compare/1.69.3...1.69.4) --- updated-dependencies: - dependency-name: sass dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6ae971cbc4..fa948aa338 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "devDependencies": { "axios": "^1.5.1", "laravel-vite-plugin": "^0.8.1", - "sass": "^1.69.0", + "sass": "^1.69.4", "vite": "^4.5.0", "vite-plugin-manifest-sri": "^0.1.0" } @@ -932,9 +932,9 @@ } }, "node_modules/sass": { - "version": "1.69.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.3.tgz", - "integrity": "sha512-X99+a2iGdXkdWn1akFPs0ZmelUzyAQfvqYc2P/MPTrJRuIRoTffGzT9W9nFqG00S+c8hXzVmgxhUuHFdrwxkhQ==", + "version": "1.69.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.4.tgz", + "integrity": "sha512-+qEreVhqAy8o++aQfCJwp0sklr2xyEzkm9Pp/Igu9wNPoe7EZEQ8X/MBvvXggI2ql607cxKg/RKOwDj6pp2XDA==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", diff --git a/package.json b/package.json index bd60a70430..616b208039 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "devDependencies": { "axios": "^1.5.1", "laravel-vite-plugin": "^0.8.1", - "sass": "^1.69.0", + "sass": "^1.69.4", "vite": "^4.5.0", "vite-plugin-manifest-sri": "^0.1.0" }, From dd2f8d4404e1ebc8376afb5542140bea7f540959 Mon Sep 17 00:00:00 2001 From: Antonio Spinelli Date: Fri, 20 Oct 2023 19:00:45 -0300 Subject: [PATCH 4/4] Cover endOfPeriod method of the Navigation class The custom frequency requires a timezone configuration, forcing it to run in the integration test scope. Running the integration tests requires a database connection in the build process. It enables other case tests. The API Tests cause interference in other tests, requiring isolating them. --- .github/workflows/sonarcloud.yml | 60 +++++++++- .../Commands/System/CreateDatabase.php | 1 + composer.json | 2 +- phpunit.xml | 1 + .../Autocomplete/AccountControllerTest.php | 27 +---- .../NavigationCustomEndOfPeriodTest.php | 25 ++++ .../Support/NavigationEndOfPeriodTest.php | 107 ++++++++++++++++++ 7 files changed, 197 insertions(+), 26 deletions(-) create mode 100644 tests/integration/Support/NavigationCustomEndOfPeriodTest.php create mode 100644 tests/unit/Support/NavigationEndOfPeriodTest.php diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index e9ba1b9b27..1a62d846f7 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -1,14 +1,37 @@ name: Sonarcloud on: - pull_request: + pull_request: push: branches: - main - develop +env: + DB_CONNECTION: mysql + DB_HOST: "127.0.0.1" + DB_DATABASE: firefly + DB_USER: firefly + DB_PASSWORD: secret_firefly_password + jobs: sonarcloud: name: SonarCloud runs-on: ubuntu-latest + services: + mariadb: + image: mariadb:latest + ports: + - 3306:3306 + env: + MYSQL_ROOT_PASSWORD: yes + MYSQL_USER: ${{ env.DB_USER }} + MYSQL_PASSWORD: ${{ env.DB_PASSWORD }} + MYSQL_DATABASE: ${{ env.DB_DATABASE }} + options: >- + --health-cmd="healthcheck.sh --connect --innodb_initialized" + --health-interval=10s + --health-timeout=5s + --health-retries=3 + steps: - uses: actions/checkout@v3 with: @@ -24,16 +47,49 @@ jobs: with: php-version: '8.2' coverage: xdebug + extensions: >- + bcmath + curl + fileinfo + iconv + intl + json + mbstring + openssl + pdo + session + simplexml + sodium + tokenizer + xml + xmlwriter - name: Install Composer dependencies run: composer install --prefer-dist --no-interaction --no-progress --no-scripts + - name: Verify Database connection + env: + PORT: ${{ job.services.mariadb.ports[3306] }} + run: | + while ! mysqladmin ping -h"${{env.DB_HOST}}" -P"${PORT}" --silent; do + sleep 1 + done + - name: Copy environment file - run: cp .env.example .env + run: sed 's@DB_HOST=.*@DB_HOST=${{env.DB_HOST}}@g' .env.example > .env - name: Generate app key run: php artisan key:generate + - name: "Create the database" + run: php artisan firefly-iii:create-database + + - name: "Upgrades the database to the latest version" + run: php artisan firefly-iii:upgrade-database + + - name: "Integrity Database Report" + run: php artisan firefly-iii:report-integrity + - name: "Run tests with coverage" run: composer coverage diff --git a/app/Console/Commands/System/CreateDatabase.php b/app/Console/Commands/System/CreateDatabase.php index b34914e310..5960f59144 100644 --- a/app/Console/Commands/System/CreateDatabase.php +++ b/app/Console/Commands/System/CreateDatabase.php @@ -83,6 +83,7 @@ class CreateDatabase extends Command $pdo = new PDO($dsn, env('DB_USERNAME'), env('DB_PASSWORD'), $options); } catch (PDOException $e) { $this->friendlyError(sprintf('Error when connecting to DB: %s', $e->getMessage())); + return 1; } // only continue when no error. diff --git a/composer.json b/composer.json index f0143e13a5..7819851728 100644 --- a/composer.json +++ b/composer.json @@ -176,7 +176,7 @@ "@php vendor/bin/phpunit -c phpunit.xml --testsuite integration --no-coverage" ], "coverage": [ - "@php vendor/bin/phpunit -c phpunit.xml --testsuite unit" + "@php vendor/bin/phpunit -c phpunit.xml" ] }, "config": { diff --git a/phpunit.xml b/phpunit.xml index aa51a02e21..d5008da502 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -33,6 +33,7 @@ stopOnFailure="true"> + diff --git a/tests/integration/Api/Autocomplete/AccountControllerTest.php b/tests/integration/Api/Autocomplete/AccountControllerTest.php index 5eb0ec0ca7..c268f9fb2e 100644 --- a/tests/integration/Api/Autocomplete/AccountControllerTest.php +++ b/tests/integration/Api/Autocomplete/AccountControllerTest.php @@ -23,8 +23,6 @@ declare(strict_types=1); namespace Tests\integration\Api\Autocomplete; -use Laravel\Passport\Passport; -use Log; use Tests\integration\TestCase; /** @@ -32,33 +30,16 @@ use Tests\integration\TestCase; */ class AccountControllerTest extends TestCase { - /** - * - */ - public function setUp(): void - { - parent::setUp(); - Passport::actingAs($this->user()); - Log::info(sprintf('Now in %s.', get_class($this))); - } - /** * @covers \FireflyIII\Api\V1\Controllers\Autocomplete\AccountController + * @runInSeparateProcess */ - public function testAccounts(): void + public function testGivenAnUnauthenticatedRequestWhenCallingTheAccountsEndpointThenReturns401HttpCode(): void { // test API $response = $this->get(route('api.v1.autocomplete.accounts'), ['Accept' => 'application/json']); - $response->assertStatus(200); + $response->assertStatus(401); $response->assertHeader('Content-Type', 'application/json'); - $response->assertSee('Checking Account'); - } - - /** - * - */ - public function testBasic(): void - { - $this->assertTrue(true); + $response->assertContent('{"message":"Unauthenticated","exception":"AuthenticationException"}'); } } diff --git a/tests/integration/Support/NavigationCustomEndOfPeriodTest.php b/tests/integration/Support/NavigationCustomEndOfPeriodTest.php new file mode 100644 index 0000000000..a7bd3c1652 --- /dev/null +++ b/tests/integration/Support/NavigationCustomEndOfPeriodTest.php @@ -0,0 +1,25 @@ +endOfPeriod($from, 'custom'); + $this->assertEquals($expected->toDateString(), $period->toDateString()); + } +} diff --git a/tests/unit/Support/NavigationEndOfPeriodTest.php b/tests/unit/Support/NavigationEndOfPeriodTest.php new file mode 100644 index 0000000000..af86ed7f03 --- /dev/null +++ b/tests/unit/Support/NavigationEndOfPeriodTest.php @@ -0,0 +1,107 @@ + + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +declare(strict_types=1); + +namespace Tests\unit\Support; + +use Carbon\Carbon; +use FireflyIII\Support\Navigation; +use Illuminate\Support\Facades\Log; +use PHPUnit\Framework\TestCase; + +/** + * @group unit-test + * @group support + * @group navigation + */ +class NavigationEndOfPeriodTest extends TestCase +{ + private Navigation $navigation; + + public function __construct(string $name) + { + parent::__construct($name); + $this->navigation = new Navigation(); + } + + public static function provideDates(): array + { + return [ + '1D' => ['frequency' => '1D', 'from' => Carbon::now(), 'expected' => Carbon::now()->endOfDay()], + 'daily' => ['frequency' => 'daily', 'from' => Carbon::now(), 'expected' => Carbon::now()->endOfDay()], + '1W' => ['frequency' => '1W', 'from' => Carbon::now(), 'expected' => Carbon::now()->addWeek()->subDay()->endOfDay()], + 'week' => ['frequency' => 'week', 'from' => Carbon::now(), 'expected' => Carbon::now()->addWeek()->subDay()->endOfDay()], + 'weekly' => ['frequency' => 'weekly', 'from' => Carbon::now(), 'expected' => Carbon::now()->addWeek()->subDay()->endOfDay()], + 'month' => ['frequency' => 'month', 'from' => Carbon::now(), 'expected' => Carbon::now()->addMonth()->subDay()->endOfDay()], + '1M' => ['frequency' => '1M', 'from' => Carbon::now(), 'expected' => Carbon::now()->addMonth()->subDay()->endOfDay()], + 'monthly' => ['frequency' => 'monthly', 'from' => Carbon::now(), 'expected' => Carbon::now()->addMonth()->subDay()->endOfDay()], + '3M' => ['frequency' => '3M', 'from' => Carbon::now(), 'expected' => Carbon::now()->addQuarterNoOverflow()->subDay()->endOfDay()], + 'quarter' => ['frequency' => 'quarter', 'from' => Carbon::now(), 'expected' => Carbon::now()->addQuarterNoOverflow()->subDay()->endOfDay()], + 'quarterly' => ['frequency' => 'quarterly', 'from' => Carbon::now(), 'expected' => Carbon::now()->addQuarterNoOverflow()->subDay()->endOfDay()], + 'year' => ['frequency' => 'year', 'from' => Carbon::now(), 'expected' => Carbon::now()->addYearNoOverflow()->subDay()->endOfDay()], + 'yearly' => ['frequency' => 'yearly', 'from' => Carbon::now(), 'expected' => Carbon::now()->addYearNoOverflow()->subDay()->endOfDay()], + '1Y' => ['frequency' => '1Y', 'from' => Carbon::now(), 'expected' => Carbon::now()->addYearNoOverflow()->subDay()->endOfDay()], + 'half-year' => ['frequency' => 'half-year', 'from' => Carbon::parse('2023-05-20'), 'expected' => Carbon::parse('2023-11-19')->endOfDay()], + '6M' => ['frequency' => '6M', 'from' => Carbon::parse('2023-08-20'), 'expected' => Carbon::parse('2024-02-19')], + 'last7' => ['frequency' => 'last7', 'from' => Carbon::now(), 'expected' => Carbon::now()->addDays(7)->endOfDay()], + 'last30' => ['frequency' => 'last30', 'from' => Carbon::now(), 'expected' => Carbon::now()->addDays(30)->endOfDay()], + 'last90' => ['frequency' => 'last90', 'from' => Carbon::now(), 'expected' => Carbon::now()->addDays(90)->endOfDay()], + 'last365' => ['frequency' => 'last365', 'from' => Carbon::now(), 'expected' => Carbon::now()->addDays(365)->endOfDay()], + 'MTD' => ['frequency' => 'MTD', 'from' => Carbon::now(), 'expected' => Carbon::now()->startOfMonth()->startOfDay()], + 'QTD' => ['frequency' => 'QTD', 'from' => Carbon::now(), 'expected' => Carbon::now()->firstOfQuarter()->startOfDay()], + 'YTD' => ['frequency' => 'YTD', 'from' => Carbon::now(), 'expected' => Carbon::now()->startOfYear()->startOfDay()], + 'week 2023-08-05 to 2023-08-11' => ['frequency' => '1W', 'from' => Carbon::parse('2023-08-05'), 'expected' => Carbon::parse('2023-08-11')->endOfDay()], + ]; + } + + /** + * @dataProvider provideDates + */ + public function testGivenADateAndFrequencyWhenCalculateTheDateThenReturnsTheExpectedDateSuccessful(string $frequency, Carbon $from, Carbon $expected) + { + $period = $this->navigation->endOfPeriod($from, $frequency); + $this->assertEquals($expected->toDateString(), $period->toDateString()); + } + + public static function provideUnknownFrequencies(): array + { + return [ + '1day' => ['frequency' => '1day', 'from' => Carbon::now(), 'expected' => Carbon::now()], + 'unknown' => ['frequency' => 'unknown', 'from' => Carbon::now(), 'expected' => Carbon::now()->startOfDay()], + 'empty' => ['frequency' => '', 'from' => Carbon::now(), 'expected' => Carbon::now()->startOfDay()], + ]; + } + + /** + * @dataProvider provideUnknownFrequencies + */ + public function testGivenADateAndUnknownFrequencyWhenCalculateTheDateThenReturnsTheSameDateSuccessful(string $frequency, Carbon $from, Carbon $expected) + { + Log::spy(); + + $period = $this->navigation->endOfPeriod($from, $frequency); + $this->assertEquals($expected->toDateString(), $period->toDateString()); + $expectedMessage = sprintf('Cannot do endOfPeriod for $repeat_freq "%s"', $frequency); + + Log::shouldHaveReceived('error', [$expectedMessage]); + } +}