2018-11-03 23:25:08 +00:00
< ? php
namespace Tests\Integration\Services ;
use App\Models\Rule ;
use App\Models\User ;
use App\Services\SmartPlaylistService ;
use Carbon\Carbon ;
use Tests\TestCase ;
class SmartPlaylistServiceTest extends TestCase
{
/** @var SmartPlaylistService */
private $service ;
public function setUp () : void
{
parent :: setUp ();
$this -> service = $this -> app -> make ( SmartPlaylistService :: class );
Carbon :: setTestNow ( new Carbon ( '2018-07-15' ));
}
protected function tearDown () : void
{
Carbon :: setTestNow ();
parent :: tearDown ();
}
2018-11-18 21:50:03 +00:00
private function readFixtureFile ( string $fileName ) : array
{
2018-11-18 21:50:37 +00:00
return json_decode ( file_get_contents ( __DIR__ . '/../../blobs/rules/' . $fileName ), true );
2018-11-18 21:50:03 +00:00
}
2018-11-03 23:25:08 +00:00
public function provideRules () : array
{
return [
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'is.json' ),
'select * from "songs" where ("title" = ?)' ,
2018-11-03 23:25:08 +00:00
[ 'Foo' ],
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'isNot.json' ),
'select * from "songs" where ("title" <> ?)' ,
2018-11-03 23:25:08 +00:00
[ 'Foo' ],
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'contains.json' ),
'select * from "songs" where ("title" LIKE ?)' ,
2018-11-03 23:25:08 +00:00
[ '%Foo%' ],
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'doesNotContain.json' ),
'select * from "songs" where ("title" NOT LIKE ?)' ,
2018-11-03 23:25:08 +00:00
[ '%Foo%' ],
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'beginsWith.json' ),
'select * from "songs" where ("title" LIKE ?)' ,
[ 'Foo%' ],
2018-11-03 23:25:08 +00:00
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'endsWith.json' ),
'select * from "songs" where ("title" LIKE ?)' ,
[ '%Foo' ],
2018-11-03 23:25:08 +00:00
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'isBetween.json' ),
'select * from "songs" where ("bit_rate" between ? and ?)' ,
[ '192' , '256' ],
2018-11-03 23:25:08 +00:00
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'inLast.json' ),
'select * from "songs" where ("created_at" >= ?)' ,
2018-11-03 23:25:08 +00:00
[ '2018-07-08 00:00:00' ],
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'notInLast.json' ),
'select * from "songs" where ("created_at" < ?)' ,
2018-11-03 23:25:08 +00:00
[ '2018-07-08 00:00:00' ],
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'isLessThan.json' ),
'select * from "songs" where ("length" < ?)' ,
[ '300' ],
2018-11-03 23:25:08 +00:00
],
[
2018-11-18 21:50:03 +00:00
$this -> readFixtureFile ( 'is and isNot.json' ),
'select * from "songs" where ("title" = ? and exists (select * from "artists" where "songs"."artist_id" = "artists"."id" and "name" <> ?))' ,
[ 'Foo' , 'Bar' ],
],
[
$this -> readFixtureFile ( '(is and isNot) or (is and isGreaterThan).json' ),
'select * from "songs" where ("title" = ? and exists (select * from "albums" where "songs"."album_id" = "albums"."id" and "name" <> ?)) or ("genre" = ? and "bit_rate" > ?)' ,
[ 'Foo' , 'Bar' , 'Metal' , '128' ],
],
[
$this -> readFixtureFile ( 'is or is.json' ),
'select * from "songs" where ("title" = ?) or (exists (select * from "artists" where "songs"."artist_id" = "artists"."id" and "name" = ?))' ,
[ 'Foo' , 'Bar' ],
2018-11-03 23:25:08 +00:00
],
];
}
/**
* @ dataProvider provideRules
*
* @ param string [] $rules
* @ param mixed [] $bindings
*/
public function testBuildQueryForRules ( array $rules , string $sql , array $bindings ) : void
{
2018-11-18 21:50:03 +00:00
$query = $this -> service -> buildQueryFromRules ( $rules );
2020-09-06 18:21:39 +00:00
self :: assertSame ( $sql , $query -> toSql ());
2018-11-03 23:25:08 +00:00
$queryBinding = $query -> getBindings ();
for ( $i = 0 , $count = count ( $queryBinding ); $i < $count ; $i ++ ) {
2020-09-06 18:21:39 +00:00
self :: assertSame (
2018-11-03 23:25:08 +00:00
$bindings [ $i ],
is_object ( $queryBinding [ $i ]) ? ( string ) $queryBinding [ $i ] : $queryBinding [ $i ]
);
}
}
2018-11-18 21:50:03 +00:00
public function testAddRequiresUserRules () : void
2018-11-03 23:25:08 +00:00
{
2018-11-18 21:50:03 +00:00
$rules = $this -> readFixtureFile ( 'requiresUser.json' );
2018-11-03 23:25:08 +00:00
/** @var User $user */
$user = factory ( User :: class ) -> create ();
2020-09-06 18:21:39 +00:00
self :: assertEquals ([
2018-11-18 21:50:03 +00:00
'model' => 'interactions.user_id' ,
'operator' => 'is' ,
'value' => [ $user -> id ],
], $this -> service -> addRequiresUserRules ( $rules , $user )[ 0 ][ 'rules' ][ 1 ]);
2018-11-03 23:25:08 +00:00
}
2018-11-18 21:50:03 +00:00
public function testAllOperatorsAreCovered () : void
2018-11-03 23:25:08 +00:00
{
2018-11-18 21:50:03 +00:00
$rules = collect ( $this -> provideRules ()) -> map ( static function ( array $providedRule ) : array {
return $providedRule [ 0 ];
2018-11-03 23:25:08 +00:00
});
2018-11-18 21:50:03 +00:00
$operators = [];
2018-11-03 23:25:08 +00:00
2018-11-18 21:50:03 +00:00
foreach ( $rules as $rule ) {
foreach ( $rule as $ruleGroup ) {
foreach ( $ruleGroup [ 'rules' ] as $config ) {
$operators [] = $config [ 'operator' ];
}
}
}
2018-11-03 23:25:08 +00:00
2020-09-06 18:21:39 +00:00
self :: assertSame ( count ( Rule :: VALID_OPERATORS ), count ( array_unique ( $operators )));
2018-11-03 23:25:08 +00:00
}
}