From afffa84c99d0604bb41b1532cdfb40f09bc76b16 Mon Sep 17 00:00:00 2001 From: Aenimus Date: Wed, 14 Jan 2026 15:47:44 +0000 Subject: [PATCH 1/3] chore: add more authorization directive tests --- .../authorization-directives.test.ts | 726 ++++++++++++++++-- 1 file changed, 650 insertions(+), 76 deletions(-) diff --git a/composition/tests/v1/directives/authorization-directives.test.ts b/composition/tests/v1/directives/authorization-directives.test.ts index 00c02ad11a..0399c4bb68 100644 --- a/composition/tests/v1/directives/authorization-directives.test.ts +++ b/composition/tests/v1/directives/authorization-directives.test.ts @@ -2,7 +2,9 @@ import { describe, expect, test } from 'vitest'; import { AuthorizationData, FieldAuthorizationData, + INTERFACE, MAX_OR_SCOPES, + OBJECT, orScopesLimitError, parse, QUERY, @@ -507,26 +509,27 @@ describe('Authorization directives tests', () => { }); describe('Federation tests', () => { - test('that @authenticated is persisted in the federated schema', () => { - const { fieldConfigurations, federatedGraphClientSchema, federatedGraphSchema } = federateSubgraphsSuccess( - [faa, fab], - ROUTER_COMPATIBILITY_VERSION_ONE, - ); - expect(fieldConfigurations).toStrictEqual([ - { - argumentNames: [], - fieldName: 'object', - typeName: QUERY, - requiresAuthentication: true, - requiredScopes: [], - requiredScopesByOR: [], - }, - ]); - expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( - normalizeString( - SCHEMA_QUERY_DEFINITION + - AUTHENTICATED_DIRECTIVE + - ` + describe('@authenticated tests', () => { + test('that @authenticated is persisted in the federated schema', () => { + const { fieldConfigurations, federatedGraphClientSchema, federatedGraphSchema } = federateSubgraphsSuccess( + [faa, fab], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'object', + typeName: QUERY, + requiresAuthentication: true, + requiredScopes: [], + requiredScopesByOR: [], + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + AUTHENTICATED_DIRECTIVE + + ` type Object @authenticated { age: Int! id: ID! @@ -537,12 +540,12 @@ describe('Authorization directives tests', () => { object: Object! } `, - ), - ); - expect(schemaToSortedNormalizedString(federatedGraphClientSchema)).toBe( - normalizeString( - SCHEMA_QUERY_DEFINITION + - ` + ), + ); + expect(schemaToSortedNormalizedString(federatedGraphClientSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + ` type Object { age: Int! id: ID! @@ -553,30 +556,344 @@ describe('Authorization directives tests', () => { object: Object! } `, - ), - ); + ), + ); + }); + + test('that @authenticated on an Enum type generates the correct router configuration', () => { + const { fieldConfigurations, federatedGraphSchema } = federateSubgraphsSuccess( + [fiaa, fiab], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'a', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + { + argumentNames: [], + fieldName: 'b', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + { + argumentNames: [], + fieldName: 'c', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + AUTHENTICATED_DIRECTIVE + + ` + enum Enum @authenticated { + A + } + + type Query { + a: Enum! + b: Enum! + c: Enum! + } + `, + ), + ); + }); + + test('that @authenticated on an Interface type generates the correct router configuration', () => { + const { fieldConfigurations, federatedGraphSchema } = federateSubgraphsSuccess( + [fjaa, fjab], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'a', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + { + argumentNames: [], + fieldName: 'b', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + { + argumentNames: [], + fieldName: 'd', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + AUTHENTICATED_DIRECTIVE + + ` + interface Interface @authenticated { + a: ID + } + + type Object implements Interface { + a: ID + } + + type Query { + a: Interface! + b: Interface! + c: Object! + d: Interface! + e: Object! + } + `, + ), + ); + }); + + test('that @authenticated on an Object type generates the correct router configuration', () => { + const { fieldConfigurations, federatedGraphSchema } = federateSubgraphsSuccess( + [fkaa, fkab], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'a', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + { + argumentNames: [], + fieldName: 'b', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + { + argumentNames: [], + fieldName: 'c', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + AUTHENTICATED_DIRECTIVE + + ` + type Object @authenticated { + a: ID + } + + type Query { + a: Object! + b: Object! + c: Object! + } + `, + ), + ); + }); + + test('that @authenticated on a Scalar type generates the correct router configuration', () => { + const { fieldConfigurations, federatedGraphSchema } = federateSubgraphsSuccess( + [flaa, flab], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'a', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + { + argumentNames: [], + fieldName: 'b', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + { + argumentNames: [], + fieldName: 'c', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: QUERY, + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + AUTHENTICATED_DIRECTIVE + + ` + type Query { + a: Scalar! + b: Scalar! + c: Scalar! + } + + scalar Scalar @authenticated + `, + ), + ); + }); + + test('that @authenticated on an Interface field generates the correct router configuration', () => { + const { fieldConfigurations, federatedGraphSchema } = federateSubgraphsSuccess( + [fmaa, fmab], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'a', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: INTERFACE, + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + AUTHENTICATED_DIRECTIVE + + ` + interface Interface { + a: ID @authenticated + } + + type Object implements Interface { + a: ID + } + + type Query { + a: Interface! + b: Interface! + c: Object! + d: Interface! + e: Object! + } + `, + ), + ); + }); + + test('that @authenticated on an Object field generates the correct router configuration', () => { + const { fieldConfigurations, federatedGraphSchema } = federateSubgraphsSuccess( + [fnaa, fnab], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'a', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: OBJECT, + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + AUTHENTICATED_DIRECTIVE + + ` + type Object { + a: ID @authenticated + } + + type Query { + a: Object! + b: Object! + c: Object! + } + `, + ), + ); + }); + + test('that @authenticated on an Object field generates the correct router configuration', () => { + const { fieldConfigurations, federatedGraphSchema } = federateSubgraphsSuccess( + [fnaa, fnab], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'a', + requiredScopes: [], + requiredScopesByOR: [], + requiresAuthentication: true, + typeName: OBJECT, + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + AUTHENTICATED_DIRECTIVE + + ` + type Object { + a: ID @authenticated + } + + type Query { + a: Object! + b: Object! + c: Object! + } + `, + ), + ); + }); }); - test('that @requiresScopes is persisted in the federated schema', () => { - const { fieldConfigurations, federatedGraphClientSchema, federatedGraphSchema } = federateSubgraphsSuccess( - [fab, fac], - ROUTER_COMPATIBILITY_VERSION_ONE, - ); - expect(fieldConfigurations).toStrictEqual([ - { - argumentNames: [], - fieldName: 'object', - typeName: QUERY, - requiresAuthentication: false, - requiredScopes: [['b']], - requiredScopesByOR: [['b']], - }, - ]); - expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( - normalizeString( - SCHEMA_QUERY_DEFINITION + - REQUIRES_SCOPES_DIRECTIVE + - ` + describe('@requiresScopes tests', () => { + test('that @requiresScopes is persisted in the federated schema', () => { + const { fieldConfigurations, federatedGraphClientSchema, federatedGraphSchema } = federateSubgraphsSuccess( + [fab, fac], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'object', + typeName: QUERY, + requiresAuthentication: false, + requiredScopes: [['b']], + requiredScopesByOR: [['b']], + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + REQUIRES_SCOPES_DIRECTIVE + + ` type Object @requiresScopes(scopes: [["b"]]) { age: Int! id: ID! @@ -587,13 +904,13 @@ describe('Authorization directives tests', () => { object: Object! } ` + - OPENFED_SCOPE, - ), - ); - expect(schemaToSortedNormalizedString(federatedGraphClientSchema)).toBe( - normalizeString( - SCHEMA_QUERY_DEFINITION + - ` + OPENFED_SCOPE, + ), + ); + expect(schemaToSortedNormalizedString(federatedGraphClientSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + ` type Object { age: Int! id: ID! @@ -604,8 +921,82 @@ describe('Authorization directives tests', () => { object: Object! } `, - ), - ); + ), + ); + }); + + test('that @requiresScopes defined on an Interface field does not affect its implementations', () => { + const { fieldConfigurations, federatedGraphClientSchema, federatedGraphSchema } = federateSubgraphsSuccess( + [foaa], + ROUTER_COMPATIBILITY_VERSION_ONE, + ); + expect(fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'id', + typeName: INTERFACE, + requiresAuthentication: false, + requiredScopes: [['read:id']], + requiredScopesByOR: [['read:id']], + }, + ]); + expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + REQUIRES_SCOPES_DIRECTIVE + + ` + interface Interface { + id: ID! @requiresScopes(scopes: [["read:id"]]) + name: String! + } + + type Object implements Interface { + id: ID! + name: String! + } + + type Query { + interfaces: [Interface!]! + objects: [Object!]! + } + ` + + OPENFED_SCOPE, + ), + ); + expect(schemaToSortedNormalizedString(federatedGraphClientSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + ` + interface Interface { + id: ID! + name: String! + } + + type Object implements Interface { + id: ID! + name: String! + } + + type Query { + interfaces: [Interface!]! + objects: [Object!]! + } + `, + ), + ); + }); + + test('that an error is returned if the limit of @requiresScopes scopes is exceeded after federation #1.1', () => { + const result = federateSubgraphsFailure([fba, fbb], ROUTER_COMPATIBILITY_VERSION_ONE); + expect(result.errors).toHaveLength(1); + expect(result.errors[0]).toStrictEqual(orScopesLimitError(MAX_OR_SCOPES, ['Query.entity', 'Interface.enum'])); + }); + + test('that an error is returned if the limit of @requiresScopes scopes is exceeded after federation #1.2', () => { + const result = federateSubgraphsFailure([fbb, fba], ROUTER_COMPATIBILITY_VERSION_ONE); + expect(result.errors).toHaveLength(1); + expect(result.errors[0]).toStrictEqual(orScopesLimitError(MAX_OR_SCOPES, ['Query.entity', 'Interface.enum'])); + }); }); test('that authorization directives generate the correct router configuration', () => { @@ -649,18 +1040,6 @@ describe('Authorization directives tests', () => { ); }); - test('that an error is returned if the limit of @requiresScopes scopes is exceeded after federation #1.1', () => { - const result = federateSubgraphsFailure([fba, fbb], ROUTER_COMPATIBILITY_VERSION_ONE); - expect(result.errors).toHaveLength(1); - expect(result.errors[0]).toStrictEqual(orScopesLimitError(MAX_OR_SCOPES, ['Query.entity', 'Interface.enum'])); - }); - - test('that an error is returned if the limit of @requiresScopes scopes is exceeded after federation #1.2', () => { - const result = federateSubgraphsFailure([fbb, fba], ROUTER_COMPATIBILITY_VERSION_ONE); - expect(result.errors).toHaveLength(1); - expect(result.errors[0]).toStrictEqual(orScopesLimitError(MAX_OR_SCOPES, ['Query.entity', 'Interface.enum'])); - }); - test('that the federated graph and its router configuration are generated correctly', () => { const result = federateSubgraphsSuccess([fca, fcb], ROUTER_COMPATIBILITY_VERSION_ONE); expect(result.fieldConfigurations).toStrictEqual([ @@ -1894,18 +2273,213 @@ const fhb: Subgraph = { `), }; -const subgraphQ: Subgraph = { - name: 'subgraph-q', +const fiaa: Subgraph = { + name: 'fiaa', url: '', definitions: parse(` + enum Enum @authenticated { + A + } + type Query { - object: Object @authenticated @requiresScopes(scopes: [["a"], ["b"]]) + a: Enum! + b: Enum! } - type Object @authenticated @requiresScopes(scopes: [["b", "c"], ["d"]]) { - b: Boolean! @authenticated @requiresScopes(scopes: [["f"], ["c"]]) - s: Scalar! + `), +}; + +const fiab: Subgraph = { + name: 'fiab', + url: '', + definitions: parse(` + enum Enum { + A + } + + type Query { + c: Enum! } + `), +}; - scalar Scalar @authenticated @requiresScopes(scopes: [["c", "e"], ["d"]]) +const fjaa: Subgraph = { + name: 'fjaa', + url: '', + definitions: parse(` + interface Interface @authenticated { + a: ID + } + + type Object implements Interface @shareable { + a: ID + } + + type Query { + a: Interface! + b: Interface! + c: Object! + } + `), +}; + +const fjab: Subgraph = { + name: 'fjab', + url: '', + definitions: parse(` + interface Interface { + a: ID + } + + type Object implements Interface { + a: ID + } + + type Query { + d: Interface! + e: Object! + } + `), +}; + +const fkaa: Subgraph = { + name: 'fkaa', + url: '', + definitions: parse(` + type Object @authenticated @shareable { + a: ID + } + + type Query { + a: Object! + b: Object! + } + `), +}; + +const fkab: Subgraph = { + name: 'fkab', + url: '', + definitions: parse(` + type Object { + a: ID + } + + type Query { + c: Object! + } + `), +}; + +const flaa: Subgraph = { + name: 'flaa', + url: '', + definitions: parse(` + type Query { + a: Scalar! + b: Scalar! + } + + scalar Scalar @authenticated + `), +}; + +const flab: Subgraph = { + name: 'flab', + url: '', + definitions: parse(` + type Query { + c: Scalar! + } + + scalar Scalar + `), +}; + +const fmaa: Subgraph = { + name: 'fmaa', + url: '', + definitions: parse(` + interface Interface { + a: ID @authenticated + } + + type Object implements Interface @shareable { + a: ID + } + + type Query { + a: Interface! + b: Interface! + c: Object! + } + `), +}; + +const fmab: Subgraph = { + name: 'fmab', + url: '', + definitions: parse(` + interface Interface { + a: ID + } + + type Object implements Interface { + a: ID + } + + type Query { + d: Interface! + e: Object! + } + `), +}; + +const fnaa: Subgraph = { + name: 'fnaa', + url: '', + definitions: parse(` + type Object @shareable { + a: ID @authenticated + } + + type Query { + a: Object! + b: Object! + } + `), +}; + +const fnab: Subgraph = { + name: 'fnab', + url: '', + definitions: parse(` + type Object { + a: ID + } + + type Query { + c: Object! + } + `), +}; + +const foaa: Subgraph = { + name: 'foaa', + url: '', + definitions: parse(` + interface Interface { + id: ID! @requiresScopes(scopes: [["read:id"]]) + name: String! + } + + type Object implements Interface { + id: ID! + name: String! + } + + type Query { + interfaces: [Interface!]! + objects: [Object!]! + } `), }; From c4d4173f1d21db4210f0432b06ace5bf7d3f0952 Mon Sep 17 00:00:00 2001 From: Aenimus Date: Thu, 15 Jan 2026 10:57:22 +0000 Subject: [PATCH 2/3] chore: add further tests --- .../authorization-directives.test.ts | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/composition/tests/v1/directives/authorization-directives.test.ts b/composition/tests/v1/directives/authorization-directives.test.ts index 0399c4bb68..8e67e9e346 100644 --- a/composition/tests/v1/directives/authorization-directives.test.ts +++ b/composition/tests/v1/directives/authorization-directives.test.ts @@ -997,6 +997,58 @@ describe('Authorization directives tests', () => { expect(result.errors).toHaveLength(1); expect(result.errors[0]).toStrictEqual(orScopesLimitError(MAX_OR_SCOPES, ['Query.entity', 'Interface.enum'])); }); + + test('that inter-subgraph scopes reduce correctly #1', () => { + const result = federateSubgraphsSuccess([fqab, fqaa], ROUTER_COMPATIBILITY_VERSION_ONE); + expect(result.fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'ids', + typeName: QUERY, + requiresAuthentication: false, + requiredScopes: [['a'], ['b']], + requiredScopesByOR: [['a'], ['b']], + }, + ]); + expect(schemaToSortedNormalizedString(result.federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + REQUIRES_SCOPES_DIRECTIVE + + ` + type Query { + ids: [ID!]! @requiresScopes(scopes: [["a"], ["b"]]) + } + ` + + OPENFED_SCOPE, + ), + ); + }); + + test('that inter-subgraph scopes reduce correctly #2', () => { + const result = federateSubgraphsSuccess([fqac, fqaa], ROUTER_COMPATIBILITY_VERSION_ONE); + expect(result.fieldConfigurations).toStrictEqual([ + { + argumentNames: [], + fieldName: 'ids', + typeName: QUERY, + requiresAuthentication: false, + requiredScopes: [['a'], ['b']], + requiredScopesByOR: [['a'], ['b'], ['c']], + }, + ]); + expect(schemaToSortedNormalizedString(result.federatedGraphSchema)).toBe( + normalizeString( + SCHEMA_QUERY_DEFINITION + + REQUIRES_SCOPES_DIRECTIVE + + ` + type Query { + ids: [ID!]! @requiresScopes(scopes: [["a"], ["b"]]) + } + ` + + OPENFED_SCOPE, + ), + ); + }); }); test('that authorization directives generate the correct router configuration', () => { @@ -2483,3 +2535,57 @@ const foaa: Subgraph = { } `), }; + +const fpaa: Subgraph = { + name: 'fpaa', + url: '', + definitions: parse(` + type Query @shareable { + scalars: [Scalar!]! @requiresScopes(scopes: [["a", "b"], ["c"]]) + } + + scalar Scalar @requiresScopes(scopes: [["d", "e"], ["f"]]) + `), +}; + +const fpab: Subgraph = { + name: 'fpab', + url: '', + definitions: parse(` + type Query @shareable { + scalars: [Scalar!]! @requiresScopes(scopes: [["g", "h"], ["i"]]) + } + + scalar Scalar @requiresScopes(scopes: [["j", "k"], ["l"]]) + `), +}; + +const fqaa: Subgraph = { + name: 'fqaa', + url: '', + definitions: parse(` + type Query @shareable { + ids: [ID!]! @requiresScopes(scopes: [["a"], ["b"]]) + } + `), +}; + +const fqab: Subgraph = { + name: 'fqab', + url: '', + definitions: parse(` + type Query @shareable { + ids: [ID!]! @requiresScopes(scopes: [["a"], ["b"]]) + } + `), +}; + +const fqac: Subgraph = { + name: 'fqac', + url: '', + definitions: parse(` + type Query @shareable { + ids: [ID!]! @requiresScopes(scopes: [["a"], ["b"], ["c"]]) + } + `), +}; From b39a159bf214bd814844e890bcbb9ebde23dadaa Mon Sep 17 00:00:00 2001 From: Aenimus Date: Thu, 15 Jan 2026 11:05:54 +0000 Subject: [PATCH 3/3] chore: remove duplicate test --- .../authorization-directives.test.ts | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/composition/tests/v1/directives/authorization-directives.test.ts b/composition/tests/v1/directives/authorization-directives.test.ts index 8e67e9e346..f050d0f160 100644 --- a/composition/tests/v1/directives/authorization-directives.test.ts +++ b/composition/tests/v1/directives/authorization-directives.test.ts @@ -837,40 +837,6 @@ describe('Authorization directives tests', () => { ), ); }); - - test('that @authenticated on an Object field generates the correct router configuration', () => { - const { fieldConfigurations, federatedGraphSchema } = federateSubgraphsSuccess( - [fnaa, fnab], - ROUTER_COMPATIBILITY_VERSION_ONE, - ); - expect(fieldConfigurations).toStrictEqual([ - { - argumentNames: [], - fieldName: 'a', - requiredScopes: [], - requiredScopesByOR: [], - requiresAuthentication: true, - typeName: OBJECT, - }, - ]); - expect(schemaToSortedNormalizedString(federatedGraphSchema)).toBe( - normalizeString( - SCHEMA_QUERY_DEFINITION + - AUTHENTICATED_DIRECTIVE + - ` - type Object { - a: ID @authenticated - } - - type Query { - a: Object! - b: Object! - c: Object! - } - `, - ), - ); - }); }); describe('@requiresScopes tests', () => {