@unito/integration-sdk
Version:
Integration SDK
123 lines (119 loc) • 4.81 kB
text/typescript
import { RuleTester } from 'eslint';
import test from 'node:test';
import rule from '../../src/eslint/rules/no-throw-new-error.js';
const ruleTester = new RuleTester({
languageOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
});
const HANDLER_FILE = '/repo/integrations/foo/src/handlers/item.ts';
test('no-throw-new-error', () => {
ruleTester.run('no-throw-new-error', rule, {
valid: [
{
name: 'throw typed HttpErrors',
filename: HANDLER_FILE,
code: `function f() { throw new HttpErrors.NotFoundError('not found'); }`,
},
{
name: 'throw user-defined typed error',
filename: HANDLER_FILE,
code: `function f() { throw new ProviderRateLimitError('slow down'); }`,
},
{
name: 'rethrow caught error',
filename: HANDLER_FILE,
code: `function f() { try { g(); } catch (e) { throw e; } }`,
},
{
name: 'allowlist: cache.ts may throw raw Error',
filename: '/repo/integrations/foo/src/cache.ts',
code: `function hash(v) { if (v === undefined) { throw new Error('Cannot hash undefined value.'); } }`,
},
{
name: 'allowlist: scripts/ may throw raw Error',
filename: '/repo/integrations/foo/src/scripts/createBatch.ts',
code: `async function main() { throw new Error('Failed to fetch credentials'); }`,
},
{
name: 'allowlist: script/ (singular) may throw raw Error',
filename: '/repo/integrations/foo/src/script/credentialsHelper.ts',
code: `async function main() { throw new Error('No access token found in credential payload'); }`,
},
{
name: 'allowlist: errors.ts (typed error definitions) may throw raw',
filename: '/repo/integrations/foo/src/errors.ts',
code: `class FooError extends Error { constructor(m) { super(m); throw new Error('init'); } }`,
},
{
name: 'allowlist: helpers/stringHelper.ts may throw raw Error',
filename: '/repo/integrations/foo/src/helpers/stringHelper.ts',
code: `function decode(s) { if (s === undefined) { throw new Error('String to encode is undefined'); } }`,
},
{
name: 'allowlist message: "only supported in tests"',
filename: HANDLER_FILE,
code: `async function deleteItem() { throw new Error('Deleting issues is only supported in tests'); }`,
},
{
name: 'allowlist message: assertNever',
filename: HANDLER_FILE,
code: `function check(x) { throw new Error('assertNever: ' + x); }`,
},
{
name: 'throw a literal value (not an Error constructor) — out of scope',
filename: HANDLER_FILE,
code: `function f() { throw 'plain string'; }`,
},
{
name: 'throw custom subclass of Error',
filename: HANDLER_FILE,
code: `class FooError extends Error {}\nfunction f() { throw new FooError('boom'); }`,
},
{
name: 'MemberExpression callee like globalThis.Error is out of scope (edge case)',
filename: HANDLER_FILE,
code: `function f() { throw new globalThis.Error('x'); }`,
},
],
invalid: [
{
name: 'throw new Error in handler',
filename: HANDLER_FILE,
code: `function f() { throw new Error('Item not found'); }`,
errors: [{ messageId: 'rawThrow', data: { name: 'Error' } }],
},
{
name: 'throw Error without `new` (still an Error instance)',
filename: HANDLER_FILE,
code: `function f() { throw Error('Item not found'); }`,
errors: [{ messageId: 'rawThrow', data: { name: 'Error' } }],
},
{
name: 'throw new TypeError in handler',
filename: HANDLER_FILE,
code: `function f() { throw new TypeError('Invalid input'); }`,
errors: [{ messageId: 'rawThrow', data: { name: 'TypeError' } }],
},
{
name: 'throw new RangeError in handler',
filename: HANDLER_FILE,
code: `function f() { throw new RangeError('out of range'); }`,
errors: [{ messageId: 'rawThrow', data: { name: 'RangeError' } }],
},
{
name: 'throw new Error w/ template literal does not match allowlist',
filename: HANDLER_FILE,
code: 'function f(t) { throw new Error(`Unsupported item type "${t}"`); }',
errors: [{ messageId: 'rawThrow', data: { name: 'Error' } }],
},
{
name: 'throw new Error w/ template literal — partial allowlist match should NOT exempt',
filename: HANDLER_FILE,
code: 'function f(t) { throw new Error(`Unsupported item type "${t}" - only supported in production`); }',
errors: [{ messageId: 'rawThrow', data: { name: 'Error' } }],
},
],
});
});