console/integration-tests/tests/api/policy/policy-check.spec.ts

339 lines
9.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import stripAnsi from 'strip-ansi';
import { ProjectType, RuleInstanceSeverityLevel, SchemaPolicyInput } from 'testkit/gql/graphql';
import { prepareProject } from 'testkit/registry-models';
import { createCLI } from '../../../testkit/cli';
export const createPolicy = (level: RuleInstanceSeverityLevel): SchemaPolicyInput => ({
rules: [
{
ruleId: 'require-description',
severity: level,
configuration: {
types: true,
},
},
],
});
describe('Schema policy checks', () => {
describe('model: composite', () => {
it('Federation project with policy with only warnings, should check only the part that was changed', async () => {
const { tokens, policy } = await prepareProject(ProjectType.Federation);
await policy.setOrganizationSchemaPolicy(
createPolicy(RuleInstanceSeverityLevel.Warning),
true,
);
const cli = createCLI(tokens.registry);
await cli.publish({
sdl: /* GraphQL */ `
type Product @key(fields: "id") {
id: ID!
title: String
url: String
}
extend type Query {
product(id: ID!): Product
}
`,
serviceName: 'products',
serviceUrl: 'https://api.com/products',
expect: 'latest-composable',
});
await cli.publish({
sdl: /* GraphQL */ `
type User @key(fields: "id") {
id: ID!
name: String!
}
extend type Query {
user(id: ID!): User
}
`,
serviceName: 'users',
serviceUrl: 'https://api.com/users',
expect: 'latest-composable',
});
const rawMessage = await cli.check({
sdl: /* GraphQL */ `
type User @key(fields: "id") {
id: ID!
name: String!
}
extend type Query {
user(id: ID!): User
field: String!
}
`,
serviceName: 'users',
expect: 'approved',
});
const message = stripAnsi(rawMessage);
expect(message.split('\n')).toEqual([
' Detected 1 change',
'',
' Safe changes:',
' - Field field was added to object type Query',
'',
'',
'⚠ Detected 1 warning',
'',
' - Description is required for type User (source: policy-require-description)',
'',
'View full report:',
expect.any(String),
]);
});
it('Federation project with policy with , should check only the part that was changed', async () => {
const { tokens, policy } = await prepareProject(ProjectType.Federation);
await policy.setOrganizationSchemaPolicy(createPolicy(RuleInstanceSeverityLevel.Error), true);
const cli = createCLI(tokens.registry);
await cli.publish({
sdl: /* GraphQL */ `
type Product @key(fields: "id") {
id: ID!
title: String
url: String
}
extend type Query {
product(id: ID!): Product
}
`,
serviceName: 'products',
serviceUrl: 'https://api.com/products',
expect: 'latest-composable',
});
await cli.publish({
sdl: /* GraphQL */ `
type User @key(fields: "id") {
id: ID!
name: String!
}
extend type Query {
user(id: ID!): User
}
`,
serviceName: 'users',
serviceUrl: 'https://api.com/users',
expect: 'latest-composable',
});
const rawMessage = await cli.check({
sdl: /* GraphQL */ `
type User @key(fields: "id") {
id: ID!
name: String!
}
extend type Query {
user(id: ID!): User
field: String!
}
`,
serviceName: 'users',
expect: 'rejected',
});
const message = stripAnsi(rawMessage);
expect(message).toContain(`Detected 1 error`);
expect(message.split('\n').slice(1)).toEqual([
'✖ Detected 1 error',
'',
' - Description is required for type User (source: policy-require-description)',
'',
' Detected 1 change',
'',
' Safe changes:',
' - Field field was added to object type Query',
'',
'View full report:',
expect.any(String),
'',
]);
});
});
describe('model: single', () => {
test('Single with policy with only warnings', async () => {
const { tokens, policy } = await prepareProject(ProjectType.Single);
await policy.setOrganizationSchemaPolicy(
createPolicy(RuleInstanceSeverityLevel.Warning),
true,
);
const cli = await createCLI(tokens.registry);
await cli.publish({
sdl: /* GraphQL */ `
type Query {
foo: String!
}
`,
expect: 'latest-composable',
});
const rawMessage = await cli.check({
sdl: /* GraphQL */ `
type Query {
foo: String!
user: User!
}
type User {
name: String!
}
`,
expect: 'approved',
});
const message = stripAnsi(rawMessage);
expect(message).toContain(`Detected 2 warnings`);
expect(message.split('\n')).toEqual([
' Detected 2 changes',
'',
' Safe changes:',
' - Type User was added',
' - Field user was added to object type Query',
'',
'',
'⚠ Detected 2 warnings',
'',
' - Description is required for type Query (source: policy-require-description)',
' - Description is required for type User (source: policy-require-description)',
'',
'View full report:',
expect.any(String),
]);
});
test('Single with policy with only errors', async () => {
const { tokens, policy } = await prepareProject(ProjectType.Single);
await policy.setOrganizationSchemaPolicy(createPolicy(RuleInstanceSeverityLevel.Error), true);
const cli = await createCLI(tokens.registry);
await cli.publish({
sdl: /* GraphQL */ `
type Query {
foo: String!
}
`,
expect: 'latest-composable',
});
const rawMessage = await cli.check({
sdl: /* GraphQL */ `
type Query {
foo: String!
user: User!
}
type User {
name: String!
}
`,
expect: 'rejected',
});
const message = stripAnsi(rawMessage);
expect(message).toContain(`Detected 2 errors`);
expect(message.split('\n').slice(1)).toEqual([
'✖ Detected 2 errors',
'',
' - Description is required for type Query (source: policy-require-description)',
' - Description is required for type User (source: policy-require-description)',
'',
' Detected 2 changes',
'',
' Safe changes:',
' - Type User was added',
' - Field user was added to object type Query',
'',
'View full report:',
expect.any(String),
'',
]);
});
test('Single with policy with both errors and warning', async () => {
const { tokens, policy } = await prepareProject(ProjectType.Single);
await policy.setOrganizationSchemaPolicy(
{
rules: [
{
ruleId: 'require-description',
severity: RuleInstanceSeverityLevel.Error,
configuration: {
types: true,
},
},
{
ruleId: 'require-deprecation-reason',
severity: RuleInstanceSeverityLevel.Warning,
},
],
},
true,
);
const cli = await createCLI(tokens.registry);
await cli.publish({
sdl: /* GraphQL */ `
type Query {
foo: String!
}
`,
expect: 'latest-composable',
});
const rawMessage = await cli.check({
sdl: /* GraphQL */ `
type Query {
foo: String! @deprecated(reason: "")
user: User!
}
type User {
name: String!
}
`,
expect: 'rejected',
});
const message = stripAnsi(rawMessage);
expect(message).toContain(`Detected 2 errors`);
expect(message).toContain(`Detected 1 warning`);
expect(message.split('\n').slice(1)).toEqual([
'✖ Detected 2 errors',
'',
' - Description is required for type Query (source: policy-require-description)',
' - Description is required for type User (source: policy-require-description)',
'',
'',
'⚠ Detected 1 warning',
'',
' - Deprecation reason is required for field foo in type Query. (source: policy-require-deprecation-reason)',
'',
' Detected 3 changes',
'',
' Safe changes:',
' - Type User was added',
' - Field user was added to object type Query',
' - Field Query.foo is deprecated',
'',
'View full report:',
expect.any(String),
'',
]);
});
});
});