backstage
184 строки · 5.3 Кб
1/*
2* Copyright 2020 The Backstage Authors
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17import { entityKindSchemaValidator } from '@backstage/catalog-model';18import type {19TemplateEntityV1beta3,20TemplateParametersV1beta3,21} from './TemplateEntityV1beta3';22import schema from './Template.v1beta3.schema.json';23
24const validator = entityKindSchemaValidator(schema);25
26describe('templateEntityV1beta3Validator', () => {27let entity: TemplateEntityV1beta3;28
29beforeEach(() => {30entity = {31apiVersion: 'scaffolder.backstage.io/v1beta3',32kind: 'Template',33metadata: {34name: 'test',35},36spec: {37type: 'website',38owner: 'team-b',39parameters: {40required: ['owner'],41'backstage:permissions': { tags: ['one', 'two'] },42properties: {43owner: {44type: 'string',45title: 'Owner',46description: 'Who is going to own this component',47},48},49},50steps: [51{52id: 'fetch',53name: 'Fetch',54action: 'fetch:plan',55input: {56url: './template',57},58if: '${{ parameters.owner }}',59'backstage:permissions': {60tags: ['one', 'two'],61},62},63],64output: {65fetchUrl: '${{ steps.fetch.output.targetUrl }}',66},67},68};69});70
71it('happy path: accepts valid data', async () => {72expect(validator(entity)).toBe(entity);73});74
75it('ignores unknown apiVersion', async () => {76(entity as any).apiVersion = 'backstage.io/v1beta0';77expect(validator(entity)).toBe(false);78});79
80it('ignores unknown kind', async () => {81(entity as any).kind = 'Wizard';82expect(validator(entity)).toBe(false);83});84
85it('rejects missing type', async () => {86delete (entity as any).spec.type;87expect(() => validator(entity)).toThrow(/type/);88});89
90it('accepts any other type', async () => {91(entity as any).spec.type = 'hallo';92expect(validator(entity)).toBe(entity);93});94
95it('accepts missing parameters', async () => {96delete (entity as any).spec.parameters;97expect(validator(entity)).toBe(entity);98});99
100it('accepts missing outputs', async () => {101delete (entity as any).spec.outputs;102expect(validator(entity)).toBe(entity);103});104
105it('rejects empty type', async () => {106(entity as any).spec.type = '';107expect(() => validator(entity)).toThrow(/type/);108});109
110it('rejects missing steps', async () => {111delete (entity as any).spec.steps;112expect(() => validator(entity)).toThrow(/steps/);113});114
115it('accepts step with missing id', async () => {116delete (entity as any).spec.steps[0].id;117expect(validator(entity)).toBe(entity);118});119
120it('accepts step with missing name', async () => {121delete (entity as any).spec.steps[0].name;122expect(validator(entity)).toBe(entity);123});124
125it('rejects step with missing action', async () => {126delete (entity as any).spec.steps[0].action;127expect(() => validator(entity)).toThrow(/action/);128});129
130it('accepts missing owner', async () => {131delete (entity as any).spec.owner;132expect(validator(entity)).toBe(entity);133});134
135it('rejects empty owner', async () => {136(entity as any).spec.owner = '';137expect(() => validator(entity)).toThrow(/owner/);138});139
140it('rejects wrong type owner', async () => {141(entity as any).spec.owner = 5;142expect(() => validator(entity)).toThrow(/owner/);143});144
145it('accepts missing if', async () => {146delete (entity as any).spec.steps[0].if;147expect(validator(entity)).toBe(entity);148});149
150it('accepts boolean in if', async () => {151(entity as any).spec.steps[0].if = true;152expect(validator(entity)).toBe(entity);153});154
155it('accepts empty if', async () => {156(entity as any).spec.steps[0].if = '';157expect(validator(entity)).toBe(entity);158});159
160it('rejects wrong type if', async () => {161(entity as any).spec.steps[0].if = 5;162expect(() => validator(entity)).toThrow(/if/);163});164
165it('rejects parameters with wrong backstage:permissions', async () => {166(entity.spec.parameters as TemplateParametersV1beta3)[167'backstage:permissions'168]!.tags = true as unknown as [];169expect(() => validator(entity)).toThrow(/must be array/);170
171(entity.spec.parameters as TemplateParametersV1beta3)[172'backstage:permissions'173] = true as {};174expect(() => validator(entity)).toThrow(/must be object/);175});176
177it('rejects steps with wrong backstage:permissions', async () => {178entity.spec.steps[0]['backstage:permissions']!.tags = true as unknown as [];179expect(() => validator(entity)).toThrow(/must be array/);180
181entity.spec.steps[0]['backstage:permissions'] = true as {};182expect(() => validator(entity)).toThrow(/must be object/);183});184});185