From 7ab31423b0a80917af4672f544f8b7ea9662d336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Chalk?= Date: Wed, 19 Feb 2025 13:03:14 +0100 Subject: [PATCH] feat(models): do not throw if docs url invalid, treat as missing and log warning --- packages/models/src/lib/audit.unit.test.ts | 10 +++++-- .../models/src/lib/implementation/schemas.ts | 17 +++++++++-- .../lib/implementation/schemas.unit.test.ts | 30 +++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/packages/models/src/lib/audit.unit.test.ts b/packages/models/src/lib/audit.unit.test.ts index 0f789bafd..0c637ca5d 100644 --- a/packages/models/src/lib/audit.unit.test.ts +++ b/packages/models/src/lib/audit.unit.test.ts @@ -23,14 +23,18 @@ describe('auditSchema', () => { ).not.toThrow(); }); - it('should throw for an invalid URL', () => { - expect(() => + it('should ignore invalid docs URL', () => { + expect( auditSchema.parse({ slug: 'consistent-test-it', title: 'Use a consistent test function.', docsUrl: 'invalid-url', } satisfies Audit), - ).toThrow('Invalid url'); + ).toEqual({ + slug: 'consistent-test-it', + title: 'Use a consistent test function.', + docsUrl: '', + }); }); }); diff --git a/packages/models/src/lib/implementation/schemas.ts b/packages/models/src/lib/implementation/schemas.ts index 135a84c13..2b887ba36 100644 --- a/packages/models/src/lib/implementation/schemas.ts +++ b/packages/models/src/lib/implementation/schemas.ts @@ -53,8 +53,21 @@ export const urlSchema = z.string().url(); /** Schema for a docsUrl */ export const docsUrlSchema = urlSchema .optional() - .or(z.literal('')) - .describe('Documentation site'); // allow empty string (no URL validation) + .or(z.literal('')) // allow empty string (no URL validation) + // eslint-disable-next-line unicorn/prefer-top-level-await, unicorn/catch-error-name + .catch(ctx => { + // if only URL validation fails, supress error since this metadata is optional anyway + if ( + ctx.error.errors.length === 1 && + ctx.error.errors[0]?.code === 'invalid_string' && + ctx.error.errors[0].validation === 'url' + ) { + console.warn(`Ignoring invalid docsUrl: ${ctx.input}`); + return ''; + } + throw ctx.error; + }) + .describe('Documentation site'); /** Schema for a title of a plugin, category and audit */ export const titleSchema = z diff --git a/packages/models/src/lib/implementation/schemas.unit.test.ts b/packages/models/src/lib/implementation/schemas.unit.test.ts index 82ed37143..4370cc963 100644 --- a/packages/models/src/lib/implementation/schemas.unit.test.ts +++ b/packages/models/src/lib/implementation/schemas.unit.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from 'vitest'; import { type TableCellValue, + docsUrlSchema, tableCellValueSchema, weightSchema, } from './schemas.js'; @@ -34,3 +35,32 @@ describe('weightSchema', () => { expect(() => weightSchema.parse(-1)).toThrow('too_small'); }); }); + +describe('docsUrlSchema', () => { + it('should accept a valid URL', () => { + expect(() => + docsUrlSchema.parse( + 'https://eslint.org/docs/latest/rules/no-unused-vars', + ), + ).not.toThrow(); + }); + + it('should accept an empty string', () => { + expect(() => docsUrlSchema.parse('')).not.toThrow(); + }); + + it('should tolerate invalid URL - treat as missing and log warning', () => { + expect( + docsUrlSchema.parse( + '/home/user/project/tools/eslint-rules/rules/my-custom-rule.ts', + ), + ).toBe(''); + expect(console.warn).toHaveBeenCalledWith( + 'Ignoring invalid docsUrl: /home/user/project/tools/eslint-rules/rules/my-custom-rule.ts', + ); + }); + + it('should throw if not a string', () => { + expect(() => docsUrlSchema.parse(false)).toThrow('invalid_type'); + }); +});