[Scope::PRODUCTS, 'products'], 'products:read' => [Scope::PRODUCTS_READ, 'products:read'], 'reseller-customers' => [Scope::RESELLER_CUSTOMERS, 'reseller-customers'], 'reseller-customers:read' => [Scope::RESELLER_CUSTOMERS_READ, 'reseller-customers:read'], 'reseller-grants' => [Scope::RESELLER_GRANTS, 'reseller-grants'], 'reseller-orders' => [Scope::RESELLER_ORDERS, 'reseller-orders'], ]; } #[DataProvider('newScopes')] public function test_the_product_and_reseller_scopes_have_their_names(string $constant, string $expected): void { $this->assertSame($expected, $constant); } public function test_every_scope_follows_the_resource_and_level_schema(): void { $scopes = array_values((new ReflectionClass(Scope::class))->getConstants()); $this->assertSame($scopes, array_values(array_unique($scopes)), 'scope values must be unique'); foreach ($scopes as $scope) { // "resource" (full access), "resource:read" or "resource:client"; Anikeen ID groups by resource $this->assertMatchesRegularExpression('/^[a-z]+(-[a-z]+)*(:(read|client))?$/', $scope); } } public function test_each_reseller_resource_is_its_own_group(): void { $groups = collect((new ReflectionClass(Scope::class))->getConstants()) ->filter(fn (string $scope) => str_starts_with($scope, 'reseller-')) ->groupBy(fn (string $scope) => explode(':', $scope)[0]) ->map(fn ($scopes) => $scopes->sort()->values()->all()) ->all(); $this->assertSame([ 'reseller-customers' => ['reseller-customers', 'reseller-customers:read'], 'reseller-grants' => ['reseller-grants'], 'reseller-orders' => ['reseller-orders'], ], $groups); } }