From b4970f4cad2727cd805c792c48f9e37afdc95f4c Mon Sep 17 00:00:00 2001 From: js07 <19861096+js07@users.noreply.github.com> Date: Thu, 4 Nov 2021 19:46:55 -0400 Subject: [PATCH 1/6] Fix lint checks missing some ESM components Run rule checks on nodes of type `ExportDefaultDeclaration` instead of `Program` --- index.js | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/index.js b/index.js index 6d06b03..e471ea3 100644 --- a/index.js +++ b/index.js @@ -6,10 +6,7 @@ function isModuleExports(node) { } function isDefaultExport(node) { - if (!node) return false; - if (node.type !== "Program" || !node.body || !node.body.length) return false; - if (node?.body[0]?.type !== "ExportDefaultDeclaration") return false; - return true; + return node?.type === "ExportDefaultDeclaration" } function isObjectWithProperties(node) { @@ -49,7 +46,7 @@ function findPropertyWithName(name, propertyArray) { function componentContainsPropertyCheck(context, node, propertyName, message) { let component; if (isDefaultExport(node)) { - component = node?.body[0]?.declaration; + component = node.declaration; } if (node.expression) { @@ -85,9 +82,8 @@ function getProps(moduleProperties) { function componentPropsContainsPropertyCheck(context, node, propertyName) { let component; if (isDefaultExport(node)) { - component = node?.body[0]?.declaration; + component = node.declaration; } - if (node.expression) { const { left, @@ -125,7 +121,7 @@ function componentPropsContainsPropertyCheck(context, node, propertyName) { function optionalComponentPropsHaveDefaultProperty(context, node) { let component; if (isDefaultExport(node)) { - component = node?.body[0]?.declaration; + component = node.declaration; } if (node.expression) { @@ -172,7 +168,7 @@ function optionalComponentPropsHaveDefaultProperty(context, node) { function checkComponentIsSourceAndReturnTargetProp(node, propertyName) { let component; if (isDefaultExport(node)) { - component = node?.body[0]?.declaration; + component = node.declaration; } if (node.expression) { @@ -221,7 +217,7 @@ function componentSourceDescriptionCheck(context, node) { function componentVersionTsMacroCheck(context, node) { let component; if (isDefaultExport(node)) { - component = node?.body[0]?.declaration; + component = node.declaration; } if (node.expression) { @@ -247,7 +243,7 @@ function componentVersionTsMacroCheck(context, node) { } } -// Rules run on two different AST node types: ExpressionStatement (CJS) and Program (ESM) +// Rules run on two different AST node types: ExpressionStatement (CJS) and ExportDefaultDeclaration (ESM) module.exports = { rules: { "required-properties-key": { @@ -256,7 +252,7 @@ module.exports = { ExpressionStatement(node) { componentContainsPropertyCheck(context, node, "key"); }, - Program(node) { + ExportDefaultDeclaration(node) { componentContainsPropertyCheck(context, node, "key"); }, }; @@ -268,7 +264,7 @@ module.exports = { ExpressionStatement(node) { componentContainsPropertyCheck(context, node, "name"); }, - Program(node) { + ExportDefaultDeclaration(node) { componentContainsPropertyCheck(context, node, "name"); }, }; @@ -280,7 +276,7 @@ module.exports = { ExpressionStatement(node) { componentContainsPropertyCheck(context, node, "version"); }, - Program(node) { + ExportDefaultDeclaration(node) { componentContainsPropertyCheck(context, node, "version"); }, }; @@ -292,7 +288,7 @@ module.exports = { ExpressionStatement(node) { componentContainsPropertyCheck(context, node, "description"); }, - Program(node) { + ExportDefaultDeclaration(node) { componentContainsPropertyCheck(context, node, "description"); }, }; @@ -304,7 +300,7 @@ module.exports = { ExpressionStatement(node) { componentContainsPropertyCheck(context, node, "type", "Components must export a type property (\"source\" or \"action\")"); }, - Program(node) { + ExportDefaultDeclaration(node) { componentContainsPropertyCheck(context, node, "type", "Components must export a type property (\"source\" or \"action\")"); }, }; @@ -316,7 +312,7 @@ module.exports = { ExpressionStatement(node) { componentPropsContainsPropertyCheck(context, node, "label"); }, - Program(node) { + ExportDefaultDeclaration(node) { componentPropsContainsPropertyCheck(context, node, "label"); }, }; @@ -328,7 +324,7 @@ module.exports = { ExpressionStatement(node) { componentPropsContainsPropertyCheck(context, node, "description"); }, - Program(node) { + ExportDefaultDeclaration(node) { componentPropsContainsPropertyCheck(context, node, "description"); }, }; @@ -340,7 +336,7 @@ module.exports = { ExpressionStatement(node) { optionalComponentPropsHaveDefaultProperty(context, node); }, - Program(node) { + ExportDefaultDeclaration(node) { optionalComponentPropsHaveDefaultProperty(context, node); }, }; @@ -352,7 +348,7 @@ module.exports = { ExpressionStatement(node) { componentSourceNameCheck(context, node); }, - Program(node) { + ExportDefaultDeclaration(node) { componentSourceNameCheck(context, node); }, }; @@ -364,7 +360,7 @@ module.exports = { ExpressionStatement(node) { componentSourceDescriptionCheck(context, node); }, - Program(node) { + ExportDefaultDeclaration(node) { componentSourceDescriptionCheck(context, node); }, }; @@ -376,7 +372,7 @@ module.exports = { ExpressionStatement(node) { componentVersionTsMacroCheck(context, node); }, - Program(node) { + ExportDefaultDeclaration(node) { componentVersionTsMacroCheck(context, node); }, }; From eca654449e226a92695784af6d0d7e4fbb088ef2 Mon Sep 17 00:00:00 2001 From: js07 <19861096+js07@users.noreply.github.com> Date: Thu, 4 Nov 2021 19:52:53 -0400 Subject: [PATCH 2/6] Bump package version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 04d3cb4..20224c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-pipedream", - "version": "0.2.1", + "version": "0.2.2", "description": "ESLint plugin for Pipedream components: https://pipedream.com/docs/components/api/", "main": "index.js", "scripts": { From 80107139062fde68f17e55e5d610acef0cd81db1 Mon Sep 17 00:00:00 2001 From: js07 <19861096+js07@users.noreply.github.com> Date: Fri, 5 Nov 2021 13:04:36 -0400 Subject: [PATCH 3/6] Fix missing semicolon --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index e471ea3..9469e38 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,7 @@ function isModuleExports(node) { } function isDefaultExport(node) { - return node?.type === "ExportDefaultDeclaration" + return node?.type === "ExportDefaultDeclaration"; } function isObjectWithProperties(node) { From e8481e58727eeae6e2fed6a8f9ea23360a2d544f Mon Sep 17 00:00:00 2001 From: js07 <19861096+js07@users.noreply.github.com> Date: Mon, 8 Nov 2021 13:29:53 -0500 Subject: [PATCH 4/6] Fix lint error & package-lock.json version --- index.js | 3 ++- package-lock.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 9469e38..73f104a 100644 --- a/index.js +++ b/index.js @@ -243,7 +243,8 @@ function componentVersionTsMacroCheck(context, node) { } } -// Rules run on two different AST node types: ExpressionStatement (CJS) and ExportDefaultDeclaration (ESM) +// Rules run on two different AST node types: ExpressionStatement (CJS) and +// ExportDefaultDeclaration (ESM) module.exports = { rules: { "required-properties-key": { diff --git a/package-lock.json b/package-lock.json index 7919cf7..e2fa358 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-pipedream", - "version": "0.1.0", + "version": "0.2.2", "lockfileVersion": 1, "requires": true, "dependencies": { From dfaf3d2740b61f7b5a7d7ec29a4d04ac5c4d9eae Mon Sep 17 00:00:00 2001 From: js07 <19861096+js07@users.noreply.github.com> Date: Mon, 8 Nov 2021 14:29:03 -0500 Subject: [PATCH 5/6] Add test cases for lines above export default declaration --- tests/rules.test.js | 358 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) diff --git a/tests/rules.test.js b/tests/rules.test.js index 230e06e..45da297 100644 --- a/tests/rules.test.js +++ b/tests/rules.test.js @@ -31,6 +31,13 @@ function convertObjectToESMExportString(obj) { return `export default ${JSON.stringify(obj)}`; } +function withPrecedingStatement(code) { + return ` + import foo from "bar"; + ${code} + `; +} + ruleTester.run("required-properties-key-test", rules["required-properties-key"], { valid: [ { @@ -349,3 +356,354 @@ ruleTester.run("ts-version-test", rules["no-ts-version"], { }, ], }); + +RuleTester.describe("On ESM export default with preceding statements", () => { + ruleTester.run("required-properties-key-test", rules["required-properties-key"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToESMExportString(requiredPropertyKeyMissing)), + errors: [ + { + message: "Components must export a key property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + ], + }, + ], + }); + + ruleTester.run("required-properties-key-test", rules["required-properties-key"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(requiredPropertyKeyMissing)), + errors: [ + { + message: "Components must export a key property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + ], + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(requiredPropertyKeyMissing)), + errors: [ + { + message: "Components must export a key property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + ], + }, + ], + }); + + ruleTester.run("required-properties-name-test", rules["required-properties-name"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(requiredPropertyNameMissing)), + errors: [ + { + message: "Components must export a name property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + ], + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(requiredPropertyNameMissing)), + errors: [ + { + message: "Components must export a name property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + ], + }, + ], + }); + + ruleTester.run("required-properties-description-test", rules["required-properties-description"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement( + convertObjectToCJSExportString(requiredPropertyDescriptionMissing), + ), + errors: [ + { + message: "Components must export a description property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + ], + }, + { + code: withPrecedingStatement( + convertObjectToESMExportString(requiredPropertyDescriptionMissing), + ), + errors: [ + { + message: "Components must export a description property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + ], + }, + ], + }); + + ruleTester.run("required-properties-version-test", rules["required-properties-version"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement( + convertObjectToCJSExportString(requiredPropertyVersionMissing), + ), + errors: [ + { + message: "Components must export a version property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + ], + }, + { + code: withPrecedingStatement( + convertObjectToESMExportString(requiredPropertyVersionMissing), + ), + errors: [ + { + message: "Components must export a version property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + ], + }, + ], + }); + + ruleTester.run("required-properties-type-test", rules["required-properties-type"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(requiredPropertyTypeMissing)), + errors: [ + { + message: "Components must export a type property (\"source\" or \"action\")", + }, + ], + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(requiredPropertyTypeMissing)), + errors: [ + { + message: "Components must export a type property (\"source\" or \"action\")", + }, + ], + }, + ], + }); + + ruleTester.run("default-value-required-for-optional-props-test", rules["default-value-required-for-optional-props"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement( + convertObjectToCJSExportString(optionalPropWithoutDefaultValue), + ), + errors: [ + { + message: "Component prop test is marked \"optional\", so it may need a \"default\" property. See https://pipedream.com/docs/components/guidelines/#default-values", + }, + ], + }, + { + code: withPrecedingStatement( + convertObjectToESMExportString(optionalPropWithoutDefaultValue), + ), + errors: [ + { + message: "Component prop test is marked \"optional\", so it may need a \"default\" property. See https://pipedream.com/docs/components/guidelines/#default-values", + }, + ], + }, + ], + }); + + ruleTester.run("props-label-test", rules["props-label"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(missingPropsLabel)), + errors: [ + { + message: "Component prop test must have a label. See https://pipedream.com/docs/components/guidelines/#props", + }, + ], + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(missingPropsLabel)), + errors: [ + { + message: "Component prop test must have a label. See https://pipedream.com/docs/components/guidelines/#props", + }, + ], + }, + ], + }); + + ruleTester.run("props-description-test", rules["props-description"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(missingPropsDescription)), + errors: [ + { + message: "Component prop test must have a description. See https://pipedream.com/docs/components/guidelines/#props", + }, + ], + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(missingPropsDescription)), + errors: [ + { + message: "Component prop test must have a description. See https://pipedream.com/docs/components/guidelines/#props", + }, + ], + }, + ], + }); + + ruleTester.run("source-name-test", rules["source-name"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(badSourceName)), + errors: [ + { + message: "Source names should start with \"New\". See https://pipedream.com/docs/components/guidelines/#source-name", + }, + ], + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(badSourceName)), + errors: [ + { + message: "Source names should start with \"New\". See https://pipedream.com/docs/components/guidelines/#source-name", + }, + ], + }, + ], + }); + + ruleTester.run("source-description-test", rules["source-description"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(badSourceDescription)), + errors: [ + { + message: "Source descriptions should start with \"Emit new\". See https://pipedream.com/docs/components/guidelines/#source-description", + }, + ], + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(badSourceDescription)), + errors: [ + { + message: "Source descriptions should start with \"Emit new\". See https://pipedream.com/docs/components/guidelines/#source-description", + }, + ], + }, + ], + }); + + ruleTester.run("ts-version-test", rules["no-ts-version"], { + valid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(valid)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToCJSExportString(tsVersion)), + errors: [ + { + message: "{{ts}} macro should be removed before committing", + }, + ], + }, + { + code: withPrecedingStatement(convertObjectToESMExportString(tsVersion)), + errors: [ + { + message: "{{ts}} macro should be removed before committing", + }, + ], + }, + ], + }); +}); From f9df3970a832166e5c4090165dd7a1c2df9f2c0d Mon Sep 17 00:00:00 2001 From: js07 <19861096+js07@users.noreply.github.com> Date: Mon, 8 Nov 2021 15:07:27 -0500 Subject: [PATCH 6/6] Refactor `rules.test.js` for new test cases --- tests/rules.test.js | 766 +++++++------------------------------------- 1 file changed, 122 insertions(+), 644 deletions(-) diff --git a/tests/rules.test.js b/tests/rules.test.js index 45da297..008b68c 100644 --- a/tests/rules.test.js +++ b/tests/rules.test.js @@ -38,672 +38,150 @@ function withPrecedingStatement(code) { `; } -ruleTester.run("required-properties-key-test", rules["required-properties-key"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(requiredPropertyKeyMissing), - errors: [ - { - message: "Components must export a key property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - { - code: convertObjectToESMExportString(requiredPropertyKeyMissing), - errors: [ - { - message: "Components must export a key property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - ], -}); - -ruleTester.run("required-properties-name-test", rules["required-properties-name"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(requiredPropertyNameMissing), - errors: [ - { - message: "Components must export a name property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - { - code: convertObjectToESMExportString(requiredPropertyNameMissing), - errors: [ - { - message: "Components must export a name property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - ], -}); - -ruleTester.run("required-properties-description-test", rules["required-properties-description"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(requiredPropertyDescriptionMissing), - errors: [ - { - message: "Components must export a description property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - { - code: convertObjectToESMExportString(requiredPropertyDescriptionMissing), - errors: [ - { - message: "Components must export a description property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - ], -}); - -ruleTester.run("required-properties-version-test", rules["required-properties-version"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(requiredPropertyVersionMissing), - errors: [ - { - message: "Components must export a version property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - { - code: convertObjectToESMExportString(requiredPropertyVersionMissing), - errors: [ - { - message: "Components must export a version property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - ], -}); - -ruleTester.run("required-properties-type-test", rules["required-properties-type"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(requiredPropertyTypeMissing), - errors: [ - { - message: "Components must export a type property (\"source\" or \"action\")", - }, - ], - }, - { - code: convertObjectToESMExportString(requiredPropertyTypeMissing), - errors: [ - { - message: "Components must export a type property (\"source\" or \"action\")", - }, - ], - }, - ], -}); - -ruleTester.run("default-value-required-for-optional-props-test", rules["default-value-required-for-optional-props"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(optionalPropWithoutDefaultValue), - errors: [ - { - message: "Component prop test is marked \"optional\", so it may need a \"default\" property. See https://pipedream.com/docs/components/guidelines/#default-values", - }, - ], - }, - { - code: convertObjectToESMExportString(optionalPropWithoutDefaultValue), - errors: [ - { - message: "Component prop test is marked \"optional\", so it may need a \"default\" property. See https://pipedream.com/docs/components/guidelines/#default-values", - }, - ], - }, - ], -}); - -ruleTester.run("props-label-test", rules["props-label"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(missingPropsLabel), - errors: [ - { - message: "Component prop test must have a label. See https://pipedream.com/docs/components/guidelines/#props", - }, - ], - }, - { - code: convertObjectToESMExportString(missingPropsLabel), - errors: [ - { - message: "Component prop test must have a label. See https://pipedream.com/docs/components/guidelines/#props", - }, - ], - }, - ], -}); - -ruleTester.run("props-description-test", rules["props-description"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(missingPropsDescription), - errors: [ - { - message: "Component prop test must have a description. See https://pipedream.com/docs/components/guidelines/#props", - }, - ], - }, - { - code: convertObjectToESMExportString(missingPropsDescription), - errors: [ - { - message: "Component prop test must have a description. See https://pipedream.com/docs/components/guidelines/#props", - }, - ], - }, - ], -}); - -ruleTester.run("source-name-test", rules["source-name"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(badSourceName), - errors: [ - { - message: "Source names should start with \"New\". See https://pipedream.com/docs/components/guidelines/#source-name", - }, - ], - }, - { - code: convertObjectToESMExportString(badSourceName), - errors: [ - { - message: "Source names should start with \"New\". See https://pipedream.com/docs/components/guidelines/#source-name", - }, - ], - }, - ], -}); - -ruleTester.run("source-description-test", rules["source-description"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(badSourceDescription), - errors: [ - { - message: "Source descriptions should start with \"Emit new\". See https://pipedream.com/docs/components/guidelines/#source-description", - }, - ], - }, - { - code: convertObjectToESMExportString(badSourceDescription), - errors: [ - { - message: "Source descriptions should start with \"Emit new\". See https://pipedream.com/docs/components/guidelines/#source-description", - }, - ], - }, - ], -}); - -ruleTester.run("ts-version-test", rules["no-ts-version"], { - valid: [ - { - code: convertObjectToCJSExportString(valid), - }, - { - code: convertObjectToESMExportString(valid), - }, - ], - invalid: [ - { - code: convertObjectToCJSExportString(tsVersion), - errors: [ - { - message: "{{ts}} macro should be removed before committing", - }, - ], - }, - { - code: convertObjectToESMExportString(tsVersion), - errors: [ - { - message: "{{ts}} macro should be removed before committing", - }, - ], - }, - ], -}); - -RuleTester.describe("On ESM export default with preceding statements", () => { - ruleTester.run("required-properties-key-test", rules["required-properties-key"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement(convertObjectToESMExportString(requiredPropertyKeyMissing)), - errors: [ - { - message: "Components must export a key property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - ], - }); - - ruleTester.run("required-properties-key-test", rules["required-properties-key"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(requiredPropertyKeyMissing)), - errors: [ - { - message: "Components must export a key property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(requiredPropertyKeyMissing)), - errors: [ - { - message: "Components must export a key property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - ], - }); - - ruleTester.run("required-properties-name-test", rules["required-properties-name"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(requiredPropertyNameMissing)), - errors: [ - { - message: "Components must export a name property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(requiredPropertyNameMissing)), - errors: [ - { - message: "Components must export a name property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - ], - }); - - ruleTester.run("required-properties-description-test", rules["required-properties-description"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement( - convertObjectToCJSExportString(requiredPropertyDescriptionMissing), - ), - errors: [ - { - message: "Components must export a description property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - { - code: withPrecedingStatement( - convertObjectToESMExportString(requiredPropertyDescriptionMissing), - ), - errors: [ - { - message: "Components must export a description property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - ], - }); - - ruleTester.run("required-properties-version-test", rules["required-properties-version"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement( - convertObjectToCJSExportString(requiredPropertyVersionMissing), - ), - errors: [ - { - message: "Components must export a version property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - { - code: withPrecedingStatement( - convertObjectToESMExportString(requiredPropertyVersionMissing), - ), - errors: [ - { - message: "Components must export a version property. See https://pipedream.com/docs/components/guidelines/#required-metadata", - }, - ], - }, - ], - }); - - ruleTester.run("required-properties-type-test", rules["required-properties-type"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(requiredPropertyTypeMissing)), - errors: [ - { - message: "Components must export a type property (\"source\" or \"action\")", - }, - ], - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(requiredPropertyTypeMissing)), - errors: [ - { - message: "Components must export a type property (\"source\" or \"action\")", - }, - ], - }, - ], - }); - - ruleTester.run("default-value-required-for-optional-props-test", rules["default-value-required-for-optional-props"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement( - convertObjectToCJSExportString(optionalPropWithoutDefaultValue), - ), - errors: [ - { - message: "Component prop test is marked \"optional\", so it may need a \"default\" property. See https://pipedream.com/docs/components/guidelines/#default-values", - }, - ], - }, - { - code: withPrecedingStatement( - convertObjectToESMExportString(optionalPropWithoutDefaultValue), - ), - errors: [ - { - message: "Component prop test is marked \"optional\", so it may need a \"default\" property. See https://pipedream.com/docs/components/guidelines/#default-values", - }, - ], - }, - ], - }); - - ruleTester.run("props-label-test", rules["props-label"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(missingPropsLabel)), - errors: [ - { - message: "Component prop test must have a label. See https://pipedream.com/docs/components/guidelines/#props", - }, - ], - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(missingPropsLabel)), - errors: [ - { - message: "Component prop test must have a label. See https://pipedream.com/docs/components/guidelines/#props", - }, - ], - }, - ], - }); - - ruleTester.run("props-description-test", rules["props-description"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(missingPropsDescription)), - errors: [ - { - message: "Component prop test must have a description. See https://pipedream.com/docs/components/guidelines/#props", - }, - ], - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(missingPropsDescription)), - errors: [ - { - message: "Component prop test must have a description. See https://pipedream.com/docs/components/guidelines/#props", - }, - ], - }, - ], - }); - - ruleTester.run("source-name-test", rules["source-name"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(badSourceName)), - errors: [ - { - message: "Source names should start with \"New\". See https://pipedream.com/docs/components/guidelines/#source-name", - }, - ], - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(badSourceName)), - errors: [ - { - message: "Source names should start with \"New\". See https://pipedream.com/docs/components/guidelines/#source-name", - }, - ], - }, - ], - }); +function makeComponentTestCase ({ + ruleName, + name = `${ruleName}-test`, + validComponent = valid, + invalidComponent, + errorMessage, +}) { + return { + name, + ruleName, + validComponent, + invalidComponent, + errorMessage, + }; +} - ruleTester.run("source-description-test", rules["source-description"], { +const componentTestConfigs = [ + { + ruleName: "required-properties-key", + invalidComponent: requiredPropertyKeyMissing, + errorMessage: "Components must export a key property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + { + ruleName: "required-properties-name", + invalidComponent: requiredPropertyNameMissing, + errorMessage: "Components must export a name property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + { + ruleName: "required-properties-description", + invalidComponent: requiredPropertyDescriptionMissing, + errorMessage: "Components must export a description property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + { + ruleName: "required-properties-version", + invalidComponent: requiredPropertyVersionMissing, + errorMessage: "Components must export a version property. See https://pipedream.com/docs/components/guidelines/#required-metadata", + }, + { + ruleName: "required-properties-type", + invalidComponent: requiredPropertyTypeMissing, + errorMessage: "Components must export a type property (\"source\" or \"action\")", + }, + { + ruleName: "default-value-required-for-optional-props", + invalidComponent: optionalPropWithoutDefaultValue, + errorMessage: "Component prop test is marked \"optional\", so it may need a \"default\" property. See https://pipedream.com/docs/components/guidelines/#default-values", + }, + { + ruleName: "props-label", + invalidComponent: missingPropsLabel, + errorMessage: "Component prop test must have a label. See https://pipedream.com/docs/components/guidelines/#props", + }, + { + ruleName: "props-description", + invalidComponent: missingPropsDescription, + errorMessage: "Component prop test must have a description. See https://pipedream.com/docs/components/guidelines/#props", + }, + { + ruleName: "source-name", + invalidComponent: badSourceName, + errorMessage: "Source names should start with \"New\". See https://pipedream.com/docs/components/guidelines/#source-name", + }, + { + ruleName: "source-description", + invalidComponent: badSourceDescription, + errorMessage: "Source descriptions should start with \"Emit new\". See https://pipedream.com/docs/components/guidelines/#source-description", + }, + { + name: "ts-version-test", + ruleName: "no-ts-version", + invalidComponent: tsVersion, + errorMessage: "{{ts}} macro should be removed before committing", + }, +]; + +const componentTestCases = componentTestConfigs.map(makeComponentTestCase); + +// Run `ruleTester.run` on each test case +componentTestCases.forEach((testCase) => { + const { + name, + ruleName, + validComponent, + invalidComponent, + errorMessage, + } = testCase; + ruleTester.run(name, rules[ruleName], { valid: [ { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), + code: convertObjectToCJSExportString(validComponent), }, { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), + code: convertObjectToESMExportString(validComponent), }, ], invalid: [ { - code: withPrecedingStatement(convertObjectToCJSExportString(badSourceDescription)), + code: convertObjectToCJSExportString(invalidComponent), errors: [ { - message: "Source descriptions should start with \"Emit new\". See https://pipedream.com/docs/components/guidelines/#source-description", + message: errorMessage, }, ], }, { - code: withPrecedingStatement(convertObjectToESMExportString(badSourceDescription)), + code: convertObjectToESMExportString(invalidComponent), errors: [ { - message: "Source descriptions should start with \"Emit new\". See https://pipedream.com/docs/components/guidelines/#source-description", + message: errorMessage, }, ], }, ], }); +}); - ruleTester.run("ts-version-test", rules["no-ts-version"], { - valid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(valid)), - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(valid)), - }, - ], - invalid: [ - { - code: withPrecedingStatement(convertObjectToCJSExportString(tsVersion)), - errors: [ - { - message: "{{ts}} macro should be removed before committing", - }, - ], - }, - { - code: withPrecedingStatement(convertObjectToESMExportString(tsVersion)), - errors: [ - { - message: "{{ts}} macro should be removed before committing", - }, - ], - }, - ], +RuleTester.describe("On ESM export default with preceding statements", () => { + // Run each test case on ESM default export components with preceding statements + // (lines above the `export default` declaration) + componentTestCases.forEach((testCase) => { + const { + name, + ruleName, + validComponent, + invalidComponent, + errorMessage, + } = testCase; + ruleTester.run(name, rules[ruleName], { + valid: [ + { + code: withPrecedingStatement(convertObjectToESMExportString(validComponent)), + }, + ], + invalid: [ + { + code: withPrecedingStatement(convertObjectToESMExportString(invalidComponent)), + errors: [ + { + message: errorMessage, + }, + ], + }, + ], + }); }); }); +