From f2133388a4d19933a1c2eeb83da8cd7fd977d284 Mon Sep 17 00:00:00 2001 From: Alexander Lentner Date: Thu, 23 Feb 2023 11:55:38 +0100 Subject: [PATCH] Add PHP 8.2. Support --- .github/workflows/ci.yml | 40 ++++++ .github/workflows/lint.yml | 34 ----- .github/workflows/test.yml | 34 ----- .gitignore | 4 +- .php_cs | 28 ---- CHANGELOG.md | 19 ++- README.md | 3 +- UPGRADE.md | 92 ++++++++++++++ composer.json | 37 ++++-- phpstan.neon | 7 + phpunit.xml | 23 ++++ phpunit.xml.dist | 13 -- pint.json | 8 ++ src/Factories/StateFactory.php | 9 +- src/State.php | 63 ++------- src/StateServiceProvider.php | 32 ++--- src/Stores/CacheStore.php | 23 ++-- src/Stores/SessionStore.php | 16 +-- src/Stores/Store.php | 28 +--- tests/Factories/StateFactoryTest.php | 56 +++----- tests/StateTest.php | 82 +++++------- tests/Stores/CacheStoreTest.php | 183 ++++++++++++++++----------- tests/Stores/SessionStoreTest.php | 93 +++++++------- 23 files changed, 467 insertions(+), 460 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/lint.yml delete mode 100644 .github/workflows/test.yml delete mode 100644 .php_cs create mode 100644 UPGRADE.md create mode 100644 phpstan.neon create mode 100644 phpunit.xml delete mode 100644 phpunit.xml.dist create mode 100644 pint.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0dd2959 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + strategy: + fail-fast: true + matrix: + php: [ "8.0", "8.1", "8.2" ] + + runs-on: ubuntu-latest + name: PHP@${{ matrix.php }} + + steps: + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + + - uses: actions/checkout@v3 + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Install dependencies + run: composer install --prefer-dist --no-progress --no-suggest + + - name: Lint code + run: composer run-script lint + + - name: Analyse code + run: composer run-script analyse + + - name: Test code + run: composer run-script test diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index ff1175c..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: lint - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - - strategy: - fail-fast: true - matrix: - php: [7.4, 8.0] - - runs-on: ubuntu-latest - name: PHP@${{ matrix.php }} - - steps: - - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - - - uses: actions/checkout@v2 - - - name: Validate composer.json and composer.lock - run: composer validate - - - name: Install dependencies - run: composer install --prefer-dist --no-progress --no-suggest - - - name: Lint code - run: composer run-script lint \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 79dde74..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: test - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - - strategy: - fail-fast: true - matrix: - php: [7.4, 8.0] - - runs-on: ubuntu-latest - name: PHP@${{ matrix.php }} - - steps: - - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - - - uses: actions/checkout@v2 - - - name: Validate composer.json and composer.lock - run: composer validate - - - name: Install dependencies - run: composer install --prefer-dist --no-progress --no-suggest - - - name: Run test suite - run: composer test \ No newline at end of file diff --git a/.gitignore b/.gitignore index 258498b..cddfbd5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,5 @@ build/ coverage/ coverage.xml composer.lock -.php_cs.cache -.phpunit.result.cache \ No newline at end of file +.phpunit.result.cache +junit.xml \ No newline at end of file diff --git a/.php_cs b/.php_cs deleted file mode 100644 index 4277bb1..0000000 --- a/.php_cs +++ /dev/null @@ -1,28 +0,0 @@ -in(__DIR__ . DIRECTORY_SEPARATOR . 'tests') - ->in(__DIR__ . DIRECTORY_SEPARATOR . 'src') - ->append(['.php_cs']); - -$rules = [ - '@Symfony' => true, - 'phpdoc_no_empty_return' => false, - 'array_syntax' => ['syntax' => 'short'], - 'yoda_style' => false, - 'binary_operator_spaces' => [ - 'operators' => [ - '=>' => 'align', - '=' => 'align', - ], - ], - 'concat_space' => ['spacing' => 'one'], - 'not_operator_with_space' => false, -]; - -$rules['increment_style'] = ['style' => 'post']; - -return PhpCsFixer\Config::create() - ->setUsingCache(true) - ->setRules($rules) - ->setFinder($finder); diff --git a/CHANGELOG.md b/CHANGELOG.md index ab8e599..6f52782 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.0.0] - 2023-03-01 +### Added +- Support for PHP 8.2. +- Support for `illuminate/support` and `illuminate/session` version `^10.0` +- Static analysis +- [BREAKING] Return types and type hint + +### Changed +- Linting to `pint` +- Unit tests to `pest` + +### Removed +- Support for PHP 7.4. +- Support for `illuminate/support` and `illuminate/session` version < `^9.0` + ## [2.2.0] - 2022-03-24 -## Added +### Added - Support for `illuminate/support` and `illuminate/session` version `^9.0` ## [2.1.0] - 2021-10-20 -## Added +### Added - Support for PHP 8 ## [2.0.0] - 2020-10-06 diff --git a/README.md b/README.md index f8ac983..258ae98 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@     -![](https://github.com/karriereat/state/workflows/test/badge.svg) -![](https://github.com/karriereat/state/workflows/lint/badge.svg) +![](https://github.com/karriereat/state/workflows/CI/badge.svg) [![Packagist Downloads](https://img.shields.io/packagist/dt/karriere/state.svg?style=flat-square)](https://packagist.org/packages/karriere/state) # State package for Laravel diff --git a/UPGRADE.md b/UPGRADE.md new file mode 100644 index 0000000..d2d922f --- /dev/null +++ b/UPGRADE.md @@ -0,0 +1,92 @@ +# Upgrade Guide + +## v2 to v3 +Most likely this new major version does not contain any breaking changes. Only potential for breaking changes +are return types and type hints. + +### Constructor signature changes + +#### State.php +```php +// Before +public function __construct($identifier, $name, $data) {} + +// After +public function __construct(private string $identifier, private string $name, private array $data) {} +``` + +#### Stores/CacheStore.php +```php +// Before +public function __construct($statePrefix, CacheItemPoolInterface $cacheItemPool, $expiresAfter = 300) {} + +// After +public function __construct( + string $statePrefix, + private CacheItemPoolInterface $cacheItemPool, + private int $expiresAfter = 300, +) {} +``` + +#### Stores/SessionStore.php +```php +// Before +public function __construct($statePrefix, Session $session) {} + +// After +public function __construct(string $statePrefix, private Session $session) {} +``` + +#### Stores/Store.php +```php +// Before +public function __construct($statePrefix) {} + +// After +public function __construct(protected string $statePrefix) {} +``` + +### Signature changes of public methods + +#### Factories/StateFactory.php +```php +// Before +public function build($name, $data) {} + +// After +public function build(string $name, array $data): State {} +``` + +#### State.php +```php +// Before +public function identifier() {} +public function name() {} +public function hasName($name) {} +public function set($data) {} +public function isEmpty() {} +public function raw() {} +public function collection() {} + +// After +public function identifier(): string {} +public function name(): string {} +public function hasName(string $name): bool {} +public function set(array $data): void {} +public function isEmpty(): bool {} +public function raw(): array {} +public function collection(): Collection {} +``` + +#### All "Store classes" (`Stores/*Store.php`) +```php +// Before +public function put(State $state) {} +public function get($identifier, $keepState = false) {} +protected function getStoreKey($identifier) {} + +// After +public function put(State $state): void {} +public function get(string $identifier, bool $keepState = false): State {} +protected function getStoreKey(string $identifier): string {} +``` \ No newline at end of file diff --git a/composer.json b/composer.json index 183cc1f..3a6d851 100644 --- a/composer.json +++ b/composer.json @@ -4,8 +4,8 @@ "homepage": "https://github.com/karriereat/state", "authors": [ { - "name": "Johannes Pichler", - "email": "johannes.pichler@karriere.at" + "name": "Alexander Lentner", + "email": "alexander.lentner@karriere.at" } ], "keywords": [ @@ -19,15 +19,16 @@ ], "license": "Apache-2.0", "require": { - "php": "^7.4 | ^8.0", - "illuminate/support": "^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0", - "illuminate/session": "^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0", + "php": "8.0.* | 8.1.* | 8.2.*", + "illuminate/support": "^9.0 || ^10.0", + "illuminate/session": "^9.0 || ^10.0", "psr/cache": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", - "friendsofphp/php-cs-fixer": "^2.0", - "mockery/mockery": "^1.0" + "mockery/mockery": "^1.0", + "pestphp/pest": "^1.22", + "laravel/pint": "^1.5 | ^1.6", + "phpstan/phpstan": "^1.10" }, "extra": { "laravel": { @@ -49,11 +50,21 @@ "Karriere\\State\\Tests\\": "tests/" } }, - "minimum-stability": "stable", "scripts": { - "test": "phpunit", - "coverage": "phpunit --coverage-clover coverage.xml", - "lint": "php-cs-fixer fix -v --dry-run", - "fix": "php-cs-fixer fix -v" + "analyse": "phpstan analyse --memory-limit 512M", + "lint": "pint --test", + "lint:verbose": "pint -v --test", + "fix": "pint", + "test": "vendor/bin/pest", + "coverage": "vendor/bin/pest --coverage --ci --coverage-html coverage --coverage-clover coverage.xml --log-junit junit.xml", + "report": "vendor/bin/pest --coverage", + "report:html": "vendor/bin/pest --coverage --coverage-html coverage" + }, + "minimum-stability": "stable", + "config": { + "allow-plugins": { + "pestphp/pest-plugin": true + }, + "sort-packages": true } } diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..8f0433d --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,7 @@ +parameters: + paths: + - src + level: max + checkGenericClassInNonGenericObjectType: false + excludePaths: + - src/StateServiceProvider.php diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..74ed317 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,23 @@ + + + + + ./tests + + + + + ./src + + + ./src/StateServiceProvider.php + ./src/StoreFacade.php + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 1a2e079..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,13 +0,0 @@ - - - - - src/ - - - - - tests - - - \ No newline at end of file diff --git a/pint.json b/pint.json new file mode 100644 index 0000000..e071280 --- /dev/null +++ b/pint.json @@ -0,0 +1,8 @@ +{ + "preset": "psr12", + "rules": { + "concat_space": { + "spacing": "one" + } + } +} diff --git a/src/Factories/StateFactory.php b/src/Factories/StateFactory.php index 4b64fd4..76ae150 100644 --- a/src/Factories/StateFactory.php +++ b/src/Factories/StateFactory.php @@ -6,10 +6,11 @@ class StateFactory { - public function build($name, $data) + /** + * @param array $data + */ + public function build(string $name, array $data): State { - $identifier = md5(uniqid('')); - - return new State($identifier, $name, $data); + return new State(md5(uniqid()), $name, $data); } } diff --git a/src/State.php b/src/State.php index cf840ac..7bc21ba 100644 --- a/src/State.php +++ b/src/State.php @@ -6,91 +6,50 @@ class State { - /** @var string */ - private $identifier; - - /** @var string */ - private $name; - - /** @var array */ - private $data; - /** - * State constructor. - * - * @param $identifier string the state's unique identifier - * @param $name string the state name - * @param $data array the state data + * @param array $data */ - public function __construct($identifier, $name, $data) + public function __construct(private string $identifier, private string $name, private array $data) { - $this->identifier = $identifier; - $this->name = $name; - $this->data = $data; } - /** - * @return string gets the unique identifier of the state - */ - public function identifier() + public function identifier(): string { return $this->identifier; } - /** - * @return string the state name - */ - public function name() + public function name(): string { return $this->name; } - /** - * checks if the state has the given name. - * - * @param $name string the name to check - * - * @return bool true if the state has the name - */ - public function hasName($name) + public function hasName(string $name): bool { return strcmp($this->name, $name) == 0; } /** - * @param $data array the state data + * @param array $data */ - public function set($data) + public function set(array $data): void { $this->data = $data; } - /** - * check if the state is empty. - * - * @return bool - */ - public function isEmpty() + public function isEmpty(): bool { return empty($this->data); } /** - * retrieve the state's raw array data. - * - * @return array + * @return array */ - public function raw() + public function raw(): array { return $this->data; } - /** - * retrieve the state data in a collection. - * - * @return Collection - */ - public function collection() + public function collection(): Collection { return new Collection($this->data); } diff --git a/src/StateServiceProvider.php b/src/StateServiceProvider.php index 73a490f..1ebfa1f 100644 --- a/src/StateServiceProvider.php +++ b/src/StateServiceProvider.php @@ -25,27 +25,17 @@ public function register() $this->mergeConfigFrom(__DIR__ . '/../config/state.php', 'state'); $this->app->bind(Store::class, function () { - $stateStoreType = config('state.storage'); - - $store = null; - - switch ($stateStoreType) { - case 'cache': - $store = new CacheStore( - config('state.storage-prefix'), - $this->app->make(CacheItemPoolInterface::class), - config('state.expires-after') - ); - break; - default: - $store = new SessionStore( - config('state.storage-prefix'), - $this->app->make(\Illuminate\Session\Store::class) - ); - break; - } - - return $store; + return match (config('state.storage')) { + 'cache' => new CacheStore( + config('state.storage-prefix'), + $this->app->make(CacheItemPoolInterface::class), + config('state.expires-after') + ), + default => new SessionStore( + config('state.storage-prefix'), + $this->app->make(\Illuminate\Session\Store::class) + ), + }; }); $this->app->alias(Store::class, 'store'); diff --git a/src/Stores/CacheStore.php b/src/Stores/CacheStore.php index d45d45b..1617b25 100644 --- a/src/Stores/CacheStore.php +++ b/src/Stores/CacheStore.php @@ -7,21 +7,18 @@ class CacheStore extends Store { - /** @var CacheItemPoolInterface */ - private $cacheItemPool; - - /** @var int */ - private $expiresAfter; - - public function __construct($statePrefix, CacheItemPoolInterface $cacheItemPool, $expiresAfter = 300) - { + public function __construct( + string $statePrefix, + private CacheItemPoolInterface $cacheItemPool, + private int $expiresAfter = 300 + ) { parent::__construct($statePrefix); $this->cacheItemPool = $cacheItemPool; $this->expiresAfter = $expiresAfter; } - public function put(State $state) + public function put(State $state): void { $cacheItem = $this->cacheItemPool->getItem($this->getStoreKey($state->identifier())); @@ -35,7 +32,7 @@ public function put(State $state) $this->cacheItemPool->commit(); } - public function get($identifier, $keepState = false) + public function get(string $identifier, bool $keepState = false): State { $key = $this->getStoreKey($identifier); @@ -45,7 +42,11 @@ public function get($identifier, $keepState = false) $cacheItem = $this->cacheItemPool->getItem($key); if ($cacheItem->isHit()) { - extract($cacheItem->get()); + $cacheItemData = $cacheItem->get(); + + if (is_array($cacheItemData)) { + extract($cacheItemData); + } if (!$keepState) { $this->cacheItemPool->deleteItem($key); diff --git a/src/Stores/SessionStore.php b/src/Stores/SessionStore.php index 62e74f8..931f1c5 100644 --- a/src/Stores/SessionStore.php +++ b/src/Stores/SessionStore.php @@ -7,16 +7,12 @@ class SessionStore extends Store { - /** @var Session */ - private $session; - - public function __construct($statePrefix, Session $session) + public function __construct(string $statePrefix, private Session $session) { - $this->session = $session; parent::__construct($statePrefix); } - public function put(State $state) + public function put(State $state): void { $this->session->put( $this->getStoreKey($state->identifier()), @@ -27,7 +23,7 @@ public function put(State $state) ); } - public function get($identifier, $keepState = false) + public function get(string $identifier, bool $keepState = false): State { $key = $this->getStoreKey($identifier); @@ -35,7 +31,11 @@ public function get($identifier, $keepState = false) $data = []; if ($this->session->has($key)) { - extract($this->session->get($key)); + $sessionData = $this->session->get($key); + + if (is_array($sessionData)) { + extract($sessionData); + } if (!$keepState) { $this->session->forget($key); diff --git a/src/Stores/Store.php b/src/Stores/Store.php index 596a693..abd8d64 100644 --- a/src/Stores/Store.php +++ b/src/Stores/Store.php @@ -6,44 +6,24 @@ abstract class Store { - /** @var string */ - protected $statePrefix; - - /** - * Store constructor. - * - * @param $statePrefix string - */ - public function __construct($statePrefix) + public function __construct(protected string $statePrefix) { - $this->statePrefix = $statePrefix; } /** * store the given state in the store. - * - * @param State $state the state to store */ - abstract public function put(State $state); + abstract public function put(State $state): void; /** * get the stored state by its unique identifier. - * - * @param $identifier string - * @param $keepState bool indicates if the stored state should be kept in store - * - * @return State */ - abstract public function get($identifier, $keepState = false); + abstract public function get(string $identifier, bool $keepState = false): State; /** * create store key for identifier. - * - * @param $identifier string - * - * @return string */ - protected function getStoreKey($identifier) + protected function getStoreKey(string $identifier): string { return sprintf('%s/%s', $this->statePrefix, $identifier); } diff --git a/tests/Factories/StateFactoryTest.php b/tests/Factories/StateFactoryTest.php index 270e09d..3539b58 100644 --- a/tests/Factories/StateFactoryTest.php +++ b/tests/Factories/StateFactoryTest.php @@ -1,41 +1,23 @@ stateFactory = new StateFactory(); - } - - public function testFactoryShouldCreateUniqueIdentifier() - { - $state = $this->stateFactory->build('name', []); - - $this->assertNotEmpty($state->identifier()); - $this->assertIsString($state->identifier()); - } - - public function testFactoryAssignsName() - { - $state = $this->stateFactory->build('name', []); - - $this->assertEquals('name', $state->name()); - } - - public function testFactoryAssignsData() - { - $state = $this->stateFactory->build('name', [1, 2, 3]); - $this->assertEquals([1, 2, 3], $state->raw()); - } -} +beforeEach(function () { + $this->stateFactory = new StateFactory(); +}); + +it('creates unique identifier', function () { + expect($this->stateFactory->build('name', [])) + ->identifier()->not->toBeEmpty() + ->identifier()->toBeString(); +}); + +it('assigns name', function () { + expect($this->stateFactory->build('name', [])) + ->name()->toEqual('name'); +}); + +it('assigns data', function () { + expect($this->stateFactory->build('name', [1, 2, 3])) + ->raw()->toEqual([1, 2, 3]); +}); diff --git a/tests/StateTest.php b/tests/StateTest.php index 591c856..2c26e69 100644 --- a/tests/StateTest.php +++ b/tests/StateTest.php @@ -1,53 +1,37 @@ state = new State('id', 'name', []); - } - - public function testStateReturnsIdentifier() - { - $this->assertEquals('id', $this->state->identifier()); - } - - public function testStateReturnsName() - { - $this->assertEquals('name', $this->state->name()); - } - - public function testStateChecksName() - { - $this->assertTrue($this->state->hasName('name')); - $this->assertFalse($this->state->hasName('foo')); - } - - public function testStateSetData() - { - $this->assertTrue($this->state->isEmpty()); - $this->state->set(['key' => 'value']); - $this->assertFalse($this->state->isEmpty()); - } - - public function testStateGetRawData() - { - $this->assertIsArray($this->state->raw()); - } - - public function testStateGetCollection() - { - $this->assertInstanceOf(Collection::class, $this->state->collection()); - } -} + +beforeEach(function () { + $this->state = new State('id', 'name', []); +}); + +test('getters', function () { + expect($this->state) + ->identifier()->toEqual('id') + ->name()->toEqual('name') + ->raw()->toBeArray() + ->collection()->toBeInstanceOf(Collection::class); +}); + +it('sets data', function () { + expect($this->state)->isEmpty()->toBeTrue(); + + $this->state->set(['key' => 'value']); + + expect($this->state)->isEmpty()->toBeFalse(); +}); + +it('sets data2', function () { + expect($this->state)->identifier()->toEqual('id'); + + $this->state->set(['key' => 'value']); + + expect($this->state)->isEmpty()->toBeFalse(); +}); + +it('checks for name', function () { + expect($this->state)->hasName('name')->toBeTrue(); + expect($this->state)->hasName('foo')->toBeFalse(); +}); diff --git a/tests/Stores/CacheStoreTest.php b/tests/Stores/CacheStoreTest.php index df6e796..09949bb 100644 --- a/tests/Stores/CacheStoreTest.php +++ b/tests/Stores/CacheStoreTest.php @@ -1,83 +1,114 @@ cacheItemPool = Mockery::mock(CacheItemPoolInterface::class); - $this->cacheStore = new CacheStore('prefix', $this->cacheItemPool, 100); - } - - public function testEmptyCache() - { - $cacheItem = Mockery::mock(CacheItemInterface::class); - $cacheItem->shouldReceive('isHit')->andReturn(false); - $this->cacheItemPool->shouldReceive('getItem')->andReturn($cacheItem); - - $state = $this->cacheStore->get('id'); - - $this->assertTrue($state->isEmpty()); - } - - public function testCacheHit() - { - $cacheItem = Mockery::mock(CacheItemInterface::class); - $cacheItem->shouldReceive('isHit')->andReturn(true); - $cacheItem->shouldReceive('get')->andReturn(['name' => 'name', 'data' => [1, 2, 3]]); - - $this->cacheItemPool->shouldReceive('getItem')->andReturn($cacheItem); - $this->cacheItemPool->shouldReceive('deleteItem')->with('prefix/id'); - - $state = $this->cacheStore->get('id'); - - $this->assertFalse($state->isEmpty()); - $this->assertEquals('name', $state->name()); - } - - public function testCacheHitWithoutDelete() - { - $cacheItem = Mockery::mock(CacheItemInterface::class); - $cacheItem->shouldReceive('isHit')->andReturn(true); - $cacheItem->shouldReceive('get')->andReturn(['name' => 'name', 'data' => [1, 2, 3]]); - - $this->cacheItemPool->shouldReceive('getItem')->andReturn($cacheItem); - $this->cacheItemPool->shouldNotReceive('deleteItem'); - - $state = $this->cacheStore->get('id'); - - $this->assertFalse($state->isEmpty()); - $this->assertEquals('name', $state->name()); - } - - public function testCacheStoresState() - { - $this->expectNotToPerformAssertions(); - $state = new State('id', 'name', [1, 2, 3]); - - $cacheItem = Mockery::mock(CacheItemInterface::class); - $cacheItem->shouldReceive('set'); - $cacheItem->shouldReceive('expiresAfter')->with(100); - - $this->cacheItemPool->shouldReceive('getItem')->with('prefix/id')->andReturn($cacheItem); - $this->cacheItemPool->shouldReceive('save')->with($cacheItem); - $this->cacheItemPool->shouldReceive('commit'); - - $this->cacheStore->put($state); - } -} +beforeEach(function () { + $this->cacheItemPool = Mockery::mock(CacheItemPoolInterface::class); + $this->cacheStore = new CacheStore('prefix', $this->cacheItemPool, 100); +}); + +test('cache is empty', function () { + $cacheItem = Mockery::mock(CacheItemInterface::class); + + $cacheItem + ->shouldReceive('isHit') + ->once() + ->andReturn(false); + + $this->cacheItemPool + ->shouldReceive('getItem') + ->once() + ->andReturn($cacheItem); + + expect($this->cacheStore->get('id')) + ->isEmpty()->toBeTrue(); +}); + +it('hits cache', function () { + $cacheItem = Mockery::mock(CacheItemInterface::class); + + $cacheItem + ->shouldReceive('isHit') + ->once() + ->andReturn(true); + + $cacheItem + ->shouldReceive('get') + ->once() + ->andReturn(['name' => 'name', 'data' => [1, 2, 3]]); + + $this->cacheItemPool + ->shouldReceive('getItem') + ->once() + ->andReturn($cacheItem); + + $this->cacheItemPool + ->shouldReceive('deleteItem') + ->once() + ->with('prefix/id'); + + expect($this->cacheStore->get('id')) + ->isEmpty()->toBeFalse() + ->name()->toEqual('name'); +}); + +it('hits cache without deleting it', function () { + $cacheItem = Mockery::mock(CacheItemInterface::class); + + $cacheItem + ->shouldReceive('isHit') + ->once() + ->andReturn(true); + + $cacheItem + ->shouldReceive('get') + ->once() + ->andReturn(['name' => 'name', 'data' => [1, 2, 3]]); + + $this->cacheItemPool + ->shouldReceive('getItem') + ->once() + ->andReturn($cacheItem); + + $this->cacheItemPool + ->shouldReceive('deleteItem') + ->never(); + + expect($this->cacheStore->get('id', true)) + ->isEmpty()->toBeFalse() + ->name()->toEqual('name'); +}); + +it('stores state', function () { + $state = new State('id', 'name', [1, 2, 3]); + $cacheItem = Mockery::mock(CacheItemInterface::class); + + $cacheItem + ->shouldReceive('set') + ->once(); + + $cacheItem + ->shouldReceive('expiresAfter') + ->once() + ->with(100); + + $this->cacheItemPool + ->shouldReceive('getItem') + ->with('prefix/id') + ->once() + ->andReturn($cacheItem); + + $this->cacheItemPool + ->shouldReceive('save') + ->with($cacheItem) + ->once(); + + $this->cacheItemPool + ->shouldReceive('commit') + ->once(); + + $this->cacheStore->put($state); +}); diff --git a/tests/Stores/SessionStoreTest.php b/tests/Stores/SessionStoreTest.php index adf1e09..e9401c1 100644 --- a/tests/Stores/SessionStoreTest.php +++ b/tests/Stores/SessionStoreTest.php @@ -1,55 +1,48 @@ store = Mockery::mock(Store::class); - $this->sessionStore = new SessionStore('prefix', $this->store); - } - - public function testSessionNotFound() - { - $this->store->shouldReceive('has')->andReturn(false); - $state = $this->sessionStore->get('id'); - - $this->assertTrue($state->isEmpty()); - } - - public function testStateFoundInSession() - { - $this->store->shouldReceive('has')->andReturn(true); - $this->store->shouldReceive('get')->andReturn(['name' => 'name', 'data' => [1, 2, 3]]); - $this->store->shouldReceive('forget'); - - $state = $this->sessionStore->get('id'); - - $this->assertFalse($state->isEmpty()); - $this->assertEquals('name', $state->name()); - } - - public function testStoresStateInSession() - { - $this->expectNotToPerformAssertions(); - - $this->store->shouldReceive('put')->with('prefix/id', ['name' => 'name', 'data' => [1, 2, 3]]); - - $state = new State('id', 'name', [1, 2, 3]); - $this->sessionStore->put($state); - } -} + +beforeEach(function () { + $this->store = Mockery::mock(Store::class); + $this->sessionStore = new SessionStore('prefix', $this->store); +}); + +it('does not find session', function () { + $this->store + ->shouldReceive('has') + ->once() + ->andReturn(false); + + expect($this->sessionStore->get('id'))->isEmpty()->toBeTrue(); +}); + +it('finds state in session', function () { + $this->store + ->shouldReceive('has') + ->once() + ->andReturn(true); + + $this->store + ->shouldReceive('get') + ->once() + ->andReturn(['name' => 'name', 'data' => [1, 2, 3]]); + + $this->store + ->shouldReceive('forget') + ->once(); + + expect($this->sessionStore->get('id')) + ->isEmpty()->toBeFalse() + ->name()->toEqual('name'); +}); + +it('stores state in session', function () { + $this->store + ->shouldReceive('put') + ->with('prefix/id', ['name' => 'name', 'data' => [1, 2, 3]]) + ->once(); + + $this->sessionStore->put(new State('id', 'name', [1, 2, 3])); +});