Skip to content

Commit

Permalink
add feature is on middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
stevethomas committed Jun 13, 2022
1 parent cb6e552 commit 7b90bb2
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 26 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Its recommended that you seed the features to your database before a new deploym

### Check If A Feature Is Enabled
#### Blade View
Use the `@feature` blade directive anywhere in your view files.
```php
@feature('search-v2')
// new search goes here
Expand All @@ -67,6 +68,7 @@ Its recommended that you seed the features to your database before a new deploym
```

#### In Your Code
Use the `FeatureFlag` facade to conveniently check the state of a feature in your app code.
```php
use Codinglabs\FeatureFlags\Facades\FeatureFlag;

Expand All @@ -77,6 +79,19 @@ if (FeatureFlag::isOn('search-v2')) {
}
```

#### Middleware
Register `feature` as a route middleware in your HTTP Kernel to protect routes. A 404 response will be returned if the feature does not resolve to the on state.
```php
// app/Http/Kernel.php
protected $routeMiddleware = [
// ...
'feature' => \Codinglabs\FeatureFlags\Middleware\VerifyFeatureIsOn::class,
];

// routes/web.php
Route::get('search-v2', \App\Http\Controllers\SearchV2Controller::class)->middleware('feature:search-v2');
```

### Check If A Feature Is Disabled
#### Blade View
```php
Expand Down
17 changes: 17 additions & 0 deletions src/Middleware/VerifyFeatureIsOn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Codinglabs\FeatureFlags\Middleware;

use Closure;
use Illuminate\Http\Request;
use Codinglabs\FeatureFlags\Facades\FeatureFlag;

class VerifyFeatureIsOn
{
public function handle(Request $request, Closure $next, $feature)
{
abort_unless(FeatureFlag::isOn($feature), 404, __('Page not found.'));

return $next($request);
}
}
52 changes: 26 additions & 26 deletions tests/FeaturesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
// handling...
});

expect(FeatureFlag::isOn('some-feature'))->toBeFalse();
expect(FeatureFlag::isOff('some-feature'))->toBeTrue();
expect(cache()->store('array')->get('testing.some-feature'))->toBeNull();
expect(FeatureFlag::isOn('some-feature'))->toBeFalse()
->and(FeatureFlag::isOff('some-feature'))->toBeTrue()
->and(cache()->store('array')->get('testing.some-feature'))->toBeNull();
});

it('resolves isOn to false when the features state is "off"', function () {
Expand All @@ -54,9 +54,9 @@
'state' => FeatureState::off()
]);

expect(FeatureFlag::isOn('some-feature'))->toBeFalse();
expect(FeatureFlag::isOff('some-feature'))->toBeTrue();
expect(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::off()->value);
expect(FeatureFlag::isOn('some-feature'))->toBeFalse()
->and(FeatureFlag::isOff('some-feature'))->toBeTrue()
->and(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::off()->value);
});

it('resolves isOn to true when the features state is "on"', function () {
Expand All @@ -65,9 +65,9 @@
'state' => FeatureState::on()
]);

expect(FeatureFlag::isOn('some-feature'))->toBeTrue();
expect(FeatureFlag::isOff('some-feature'))->toBeFalse();
expect(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::on()->value);
expect(FeatureFlag::isOn('some-feature'))->toBeTrue()
->and(FeatureFlag::isOff('some-feature'))->toBeFalse()
->and(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::on()->value);
});

it('resolves isOn to true when feature state is "dynamic" and the closure returns true', function () {
Expand All @@ -80,9 +80,9 @@
return true;
});

expect(FeatureFlag::isOn('some-feature'))->toBeTrue();
expect(FeatureFlag::isOff('some-feature'))->toBeFalse();
expect(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::dynamic()->value);
expect(FeatureFlag::isOn('some-feature'))->toBeTrue()
->and(FeatureFlag::isOff('some-feature'))->toBeFalse()
->and(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::dynamic()->value);
});

it('resolves isOn to false when feature state is "dynamic" and the closure returns false', function () {
Expand All @@ -95,9 +95,9 @@
return false;
});

expect(FeatureFlag::isOn('some-feature'))->toBeFalse();
expect(FeatureFlag::isOff('some-feature'))->toBeTrue();
expect(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::dynamic()->value);
expect(FeatureFlag::isOn('some-feature'))->toBeFalse()
->and(FeatureFlag::isOff('some-feature'))->toBeTrue()
->and(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::dynamic()->value);
});

it('uses the default dynamic closure if no feature specific closure has been defined', function () {
Expand All @@ -110,9 +110,9 @@
return true;
});

expect(FeatureFlag::isOn('some-feature'))->toBeTrue();
expect(FeatureFlag::isOff('some-feature'))->toBeFalse();
expect(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::dynamic()->value);
expect(FeatureFlag::isOn('some-feature'))->toBeTrue()
->and(FeatureFlag::isOff('some-feature'))->toBeFalse()
->and(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::dynamic()->value);
});

it('resolves isOn to false when feature state is "dynamic" and no dynamic closure has been defined', function () {
Expand All @@ -121,8 +121,8 @@
'state' => FeatureState::dynamic(),
]);

expect(FeatureFlag::isOn('some-feature'))->toBeFalse();
expect(FeatureFlag::isOff('some-feature'))->toBeTrue();
expect(FeatureFlag::isOn('some-feature'))->toBeFalse()
->and(FeatureFlag::isOff('some-feature'))->toBeTrue();
});

it('resolves the current state', function () {
Expand All @@ -139,9 +139,9 @@
'state' => FeatureState::on()
]);

expect(FeatureFlag::getState('some-off-feature'))->toBe(FeatureState::off());
expect(FeatureFlag::getState('some-dynamic-feature'))->toBe(FeatureState::dynamic());
expect(FeatureFlag::getState('some-on-feature'))->toBe(FeatureState::on());
expect(FeatureFlag::getState('some-off-feature'))->toBe(FeatureState::off())
->and(FeatureFlag::getState('some-dynamic-feature'))->toBe(FeatureState::dynamic())
->and(FeatureFlag::getState('some-on-feature'))->toBe(FeatureState::on());
});

it('can update a features state', function () {
Expand All @@ -157,9 +157,9 @@
FeatureFlag::updateFeatureState('some-feature', FeatureState::on());

Event::assertDispatched(\Codinglabs\FeatureFlags\Events\FeatureUpdatedEvent::class);
expect(FeatureFlag::isOn('some-feature'))->toBeTrue();
expect(FeatureFlag::isOff('some-feature'))->toBeFalse();
expect(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::on()->value);
expect(FeatureFlag::isOn('some-feature'))->toBeTrue()
->and(FeatureFlag::isOff('some-feature'))->toBeFalse()
->and(cache()->store('array')->get('testing.some-feature'))->toBe(FeatureState::on()->value);
});

it('uses the default cache store when cache store has not been set', function () {
Expand Down

0 comments on commit 7b90bb2

Please sign in to comment.