From c6e8177282b304e4e949f879db41e203fae9b995 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Thu, 17 May 2018 18:09:20 +0300 Subject: [PATCH] Inline AngularJS tests that use `inject` (#4495) * Inline AngularJS tests that use `inject` See https://docs.angularjs.org/guide/unit-testing#using-beforeall- for a code example. * More meaningful function name, minor refactoring * Linting * Minor regexp improvement * address review comments --- src/language-js/printer-estree.js | 33 ++--- .../__snapshots__/jsfmt.spec.js.snap | 124 ++++++++++++++++++ tests/test_declarations/angularjs_inject.js | 26 ++++ 3 files changed, 164 insertions(+), 19 deletions(-) create mode 100644 tests/test_declarations/angularjs_inject.js diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index f5928738..c573e9bb 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -3643,7 +3643,7 @@ function printFunctionParams(path, print, options, expandArg, printTypeParams) { const parent = path.getParentNode(); // don't break in specs, eg; `it("should maintain parens around done even when long", (done) => {})` - if (parent.type === "CallExpression" && isTestCall(parent)) { + if (isTestCall(parent)) { return concat([typeParams, "(", join(", ", printed), ")"]); } @@ -3984,10 +3984,7 @@ function printTypeParameters(path, options, print, paramsKey) { const grandparent = path.getNode(2); - const isParameterInTestCall = - grandparent != null && - grandparent.type === "CallExpression" && - isTestCall(grandparent); + const isParameterInTestCall = grandparent != null && isTestCall(grandparent); const shouldInline = isParameterInTestCall || @@ -5580,25 +5577,22 @@ function isObjectType(n) { return n.type === "ObjectTypeAnnotation" || n.type === "TSTypeLiteral"; } +const unitTestRe = /^(skip|[fx]?(it|describe|test))$/; + // eg; `describe("some string", (done) => {})` function isTestCall(n, parent) { - const unitTestRe = /^(skip|(f|x)?(it|describe|test))$/; - + if (n.type !== "CallExpression") { + return false; + } if (n.arguments.length === 1) { - if ( - n.callee.type === "Identifier" && - n.callee.name === "async" && - parent && - parent.type === "CallExpression" && - isTestCall(parent) - ) { + if (isAngularTestWrapper(n) && parent && isTestCall(parent)) { return isFunctionOrArrowExpression(n.arguments[0].type); } if (isUnitTestSetUp(n)) { return ( isFunctionOrArrowExpression(n.arguments[0].type) || - isIdentiferAsync(n.arguments[0]) + isAngularTestWrapper(n.arguments[0]) ); } } else if (n.arguments.length === 2) { @@ -5610,7 +5604,7 @@ function isTestCall(n, parent) { return ( (isFunctionOrArrowExpression(n.arguments[1].type) && n.arguments[1].params.length <= 1) || - isIdentiferAsync(n.arguments[1]) + isAngularTestWrapper(n.arguments[1]) ); } } @@ -5618,7 +5612,6 @@ function isTestCall(n, parent) { } function isSkipOrOnlyBlock(node) { - const unitTestRe = /^(skip|(f|x)?(it|describe|test))$/; return ( node.callee.type === "MemberExpression" && node.callee.object.type === "Identifier" && @@ -5633,11 +5626,13 @@ function isTemplateLiteral(node) { return node.type === "TemplateLiteral"; } -function isIdentiferAsync(node) { +// `inject` is used in AngularJS 1.x, `async` in Angular 2+ +// example: https://docs.angularjs.org/guide/unit-testing#using-beforeall- +function isAngularTestWrapper(node) { return ( node.type === "CallExpression" && node.callee.type === "Identifier" && - node.callee.name === "async" + (node.callee.name === "async" || node.callee.name === "inject") ); } diff --git a/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap b/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap index 6c066eb3..ee8b9b31 100644 --- a/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap +++ b/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap @@ -102,6 +102,130 @@ function x() { `; +exports[`angularjs_inject.js 1`] = ` +beforeEach(inject(($fooService, $barService) => { + // code +})); + +afterAll(inject(($fooService, $barService) => { + console.log('Hello'); +})); + +it('should create the app', inject(($fooService, $barService) => { + //code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(() => { + // code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(($fooServiceLongName, $barServiceLongName) => { + // code +})); + +/* +* isTestCall(parent) should only be called when parent exists +* and parent.type is CallExpression. This test makes sure that +* no errors are thrown when calling isTestCall(parent) +*/ +function x() { inject(() => {}) } +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +beforeEach(inject(($fooService, $barService) => { + // code +})); + +afterAll(inject(($fooService, $barService) => { + console.log("Hello"); +})); + +it("should create the app", inject(($fooService, $barService) => { + //code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(() => { + // code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(( + $fooServiceLongName, + $barServiceLongName +) => { + // code +})); + +/* +* isTestCall(parent) should only be called when parent exists +* and parent.type is CallExpression. This test makes sure that +* no errors are thrown when calling isTestCall(parent) +*/ +function x() { + inject(() => {}); +} + +`; + +exports[`angularjs_inject.js 2`] = ` +beforeEach(inject(($fooService, $barService) => { + // code +})); + +afterAll(inject(($fooService, $barService) => { + console.log('Hello'); +})); + +it('should create the app', inject(($fooService, $barService) => { + //code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(() => { + // code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(($fooServiceLongName, $barServiceLongName) => { + // code +})); + +/* +* isTestCall(parent) should only be called when parent exists +* and parent.type is CallExpression. This test makes sure that +* no errors are thrown when calling isTestCall(parent) +*/ +function x() { inject(() => {}) } +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +beforeEach(inject(($fooService, $barService) => { + // code +})); + +afterAll(inject(($fooService, $barService) => { + console.log("Hello"); +})); + +it("should create the app", inject(($fooService, $barService) => { + //code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(() => { + // code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(( + $fooServiceLongName, + $barServiceLongName +) => { + // code +})); + +/* +* isTestCall(parent) should only be called when parent exists +* and parent.type is CallExpression. This test makes sure that +* no errors are thrown when calling isTestCall(parent) +*/ +function x() { + inject(() => {}); +} + +`; + exports[`jest-each.js 1`] = ` describe.each\` a|b|expected diff --git a/tests/test_declarations/angularjs_inject.js b/tests/test_declarations/angularjs_inject.js new file mode 100644 index 00000000..97772951 --- /dev/null +++ b/tests/test_declarations/angularjs_inject.js @@ -0,0 +1,26 @@ +beforeEach(inject(($fooService, $barService) => { + // code +})); + +afterAll(inject(($fooService, $barService) => { + console.log('Hello'); +})); + +it('should create the app', inject(($fooService, $barService) => { + //code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(() => { + // code +})); + +it("does something really long and complicated so I have to write a very long name for the test", inject(($fooServiceLongName, $barServiceLongName) => { + // code +})); + +/* +* isTestCall(parent) should only be called when parent exists +* and parent.type is CallExpression. This test makes sure that +* no errors are thrown when calling isTestCall(parent) +*/ +function x() { inject(() => {}) }