diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000..d6d5b6e0bd --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "useTabs": false, + "tabWidth": 2, + "printWidth": 140, + "singleQuote": true, + "arrowParens": "always", + "trailingComma": "none" +} diff --git a/detox/src/android/espressoapi/DetoxAction.js b/detox/src/android/espressoapi/DetoxAction.js index c0aabe94f8..61b00d5c93 100644 --- a/detox/src/android/espressoapi/DetoxAction.js +++ b/detox/src/android/espressoapi/DetoxAction.js @@ -7,34 +7,30 @@ function sanitize_android_edge(edge) { switch (edge) { - case "left": + case 'left': return 1; - case "right": + case 'right': return 2; - case "top": + case 'top': return 3; - case "bottom": + case 'bottom': return 4; default: - throw new Error( - `edge must be a 'left'/'right'/'top'/'bottom', got ${edge}` - ); + throw new Error(`edge must be a 'left'/'right'/'top'/'bottom', got ${edge}`); } } function sanitize_android_direction(direction) { switch (direction) { - case "left": + case 'left': return 1; - case "right": + case 'right': return 2; - case "up": + case 'up': return 3; - case "down": + case 'down': return 4; default: - throw new Error( - `direction must be a 'left'/'right'/'up'/'down', got ${direction}` - ); + throw new Error(`direction must be a 'left'/'right'/'up'/'down', got ${direction}`); } } class DetoxAction { diff --git a/detox/src/android/espressoapi/DetoxMatcher.js b/detox/src/android/espressoapi/DetoxMatcher.js index cc2107a693..0d4e5275cc 100644 --- a/detox/src/android/espressoapi/DetoxMatcher.js +++ b/detox/src/android/espressoapi/DetoxMatcher.js @@ -6,8 +6,7 @@ function sanitize_matcher(matcher) { - const originalMatcher = - typeof matcher._call === "function" ? matcher._call() : matcher._call; + const originalMatcher = typeof matcher._call === 'function' ? matcher._call() : matcher._call; return originalMatcher.type ? originalMatcher.value : originalMatcher; } class DetoxMatcher { diff --git a/detox/src/ios/earlgreyapi/GREYActions.js b/detox/src/ios/earlgreyapi/GREYActions.js index ff01f28295..1806530673 100644 --- a/detox/src/ios/earlgreyapi/GREYActions.js +++ b/detox/src/ios/earlgreyapi/GREYActions.js @@ -7,36 +7,32 @@ function sanitize_greyDirection(action) { switch (action) { - case "left": + case 'left': return 1; - case "right": + case 'right': return 2; - case "up": + case 'up': return 3; - case "down": + case 'down': return 4; default: - throw new Error( - `GREYAction.GREYDirection must be a 'left'/'right'/'up'/'down', got ${action}` - ); + throw new Error(`GREYAction.GREYDirection must be a 'left'/'right'/'up'/'down', got ${action}`); } } function sanitize_greyContentEdge(action) { switch (action) { - case "left": + case 'left': return 0; - case "right": + case 'right': return 1; - case "top": + case 'top': return 2; - case "bottom": + case 'bottom': return 3; default: - throw new Error( - `GREYAction.GREYContentEdge must be a 'left'/'right'/'top'/'bottom', got ${action}` - ); + throw new Error(`GREYAction.GREYContentEdge must be a 'left'/'right'/'top'/'bottom', got ${action}`); } } class GREYActions { diff --git a/detox/src/ios/earlgreyapi/GREYConditionDetox.js b/detox/src/ios/earlgreyapi/GREYConditionDetox.js index 991ed45398..24465797cf 100644 --- a/detox/src/ios/earlgreyapi/GREYConditionDetox.js +++ b/detox/src/ios/earlgreyapi/GREYConditionDetox.js @@ -7,7 +7,7 @@ function sanitize_greyElementInteraction(value) { return { - type: "Invocation", + type: 'Invocation', value }; } diff --git a/detox/src/ios/earlgreyapi/GREYMatchers.js b/detox/src/ios/earlgreyapi/GREYMatchers.js index 09775d094f..e75776d015 100644 --- a/detox/src/ios/earlgreyapi/GREYMatchers.js +++ b/detox/src/ios/earlgreyapi/GREYMatchers.js @@ -9,59 +9,57 @@ function sanitize_uiAccessibilityTraits(value) { let traits = 0; for (let i = 0; i < value.length; i++) { switch (value[i]) { - case "button": + case 'button': traits |= 1; break; - case "link": + case 'link': traits |= 2; break; - case "header": + case 'header': traits |= 4; break; - case "search": + case 'search': traits |= 8; break; - case "image": + case 'image': traits |= 16; break; - case "selected": + case 'selected': traits |= 32; break; - case "plays": + case 'plays': traits |= 64; break; - case "key": + case 'key': traits |= 128; break; - case "text": + case 'text': traits |= 256; break; - case "summary": + case 'summary': traits |= 512; break; - case "disabled": + case 'disabled': traits |= 1024; break; - case "frequentUpdates": + case 'frequentUpdates': traits |= 2048; break; - case "startsMedia": + case 'startsMedia': traits |= 4096; break; - case "adjustable": + case 'adjustable': traits |= 8192; break; - case "allowsDirectInteraction": + case 'allowsDirectInteraction': traits |= 16384; break; - case "pageTurn": + case 'pageTurn': traits |= 32768; break; default: throw new Error( - `Unknown trait '${ - value[i] - }', see list in https://facebook.github.io/react-native/docs/accessibility.html#accessibilitytraits-ios` + `Unknown trait '${value[i]}', see list in https://facebook.github.io/react-native/docs/accessibility.html#accessibilitytraits-ios` ); } } @@ -70,19 +68,17 @@ function sanitize_uiAccessibilityTraits(value) { } function sanitize_greyContentEdge(action) { switch (action) { - case "left": + case 'left': return 0; - case "right": + case 'right': return 1; - case "top": + case 'top': return 2; - case "bottom": + case 'bottom': return 3; default: - throw new Error( - `GREYAction.GREYContentEdge must be a 'left'/'right'/'top'/'bottom', got ${action}` - ); + throw new Error(`GREYAction.GREYContentEdge must be a 'left'/'right'/'top'/'bottom', got ${action}`); } } class GREYMatchers { diff --git a/generation/.prettierignore b/generation/.prettierignore new file mode 100644 index 0000000000..5da7fb8f9e --- /dev/null +++ b/generation/.prettierignore @@ -0,0 +1,3 @@ +package.json +package-lock.json + diff --git a/generation/.prettierrc b/generation/.prettierrc deleted file mode 100644 index 082bcddc9f..0000000000 --- a/generation/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "useTabs": true -} \ No newline at end of file diff --git a/generation/__tests__/android.js b/generation/__tests__/android.js index fad556b06c..d87d335cea 100644 --- a/generation/__tests__/android.js +++ b/generation/__tests__/android.js @@ -1,57 +1,54 @@ -const fs = require("fs"); -const remove = require("remove"); -const androidGenerator = require("../adapters/android"); +const fs = require('fs'); +const remove = require('remove'); +const androidGenerator = require('../adapters/android'); -describe("Android generation", () => { +describe('Android generation', () => { let ExampleClass; let exampleContent; beforeAll(() => { // Generate the code to test - fs.mkdirSync("./__tests__/generated-android"); + fs.mkdirSync('./__tests__/generated-android'); const files = { - "./fixtures/example.java": "./__tests__/generated-android/example.js" + './fixtures/example.java': './__tests__/generated-android/example.js' }; - console.log("==> generating android files"); + console.log('==> generating android files'); androidGenerator(files); - console.log("==> loading android files"); + console.log('==> loading android files'); // Load - ExampleClass = require("./generated-android/example.js"); - exampleContent = fs.readFileSync( - "./__tests__/generated-android/example.js", - "utf8" - ); + ExampleClass = require('./generated-android/example.js'); + exampleContent = fs.readFileSync('./__tests__/generated-android/example.js', 'utf8'); }); afterAll(() => { // Clean up - remove.removeSync("./__tests__/generated-android"); + remove.removeSync('./__tests__/generated-android'); }); - describe("methods", () => { - it("should expose the functions", () => { + describe('methods', () => { + it('should expose the functions', () => { expect(ExampleClass.multiClick).toBeInstanceOf(Function); }); - it("should generate type checks", () => { + it('should generate type checks', () => { expect(() => { - ExampleClass.multiClick("FOO"); + ExampleClass.multiClick('FOO'); }).toThrowErrorMatchingSnapshot(); }); - it("should return adapter calls", () => { + it('should return adapter calls', () => { const result = ExampleClass.multiClick(3); - expect(result.method).toBe("multiClick"); - expect(result.target.value).toBe("com.wix.detox.espresso.DetoxAction"); - expect(result.args[0].type).toBe("Integer"); + expect(result.method).toBe('multiClick'); + expect(result.target.value).toBe('com.wix.detox.espresso.DetoxAction'); + expect(result.args[0].type).toBe('Integer'); expect(result.args[0].value).toBe(3); expect(result).toMatchSnapshot(); }); - it("should add a sanitizer for the function with the correct name", () => { + it('should add a sanitizer for the function with the correct name', () => { const fn = ExampleClass.scrollInDirection; expect(() => { @@ -59,22 +56,22 @@ describe("Android generation", () => { }).toThrowError(); expect(() => { - fn("down", 42); + fn('down', 42); }).not.toThrowError(); - expect(fn("down", 42)).toMatchSnapshot(); + expect(fn('down', 42)).toMatchSnapshot(); }); }); - describe("validation", () => { - describe("Matcher", () => { - it("should fail getting no object", () => { + describe('validation', () => { + describe('Matcher', () => { + it('should fail getting no object', () => { expect(() => { - ExampleClass.matcherForAnd("I am a string", "I am one too"); + ExampleClass.matcherForAnd('I am a string', 'I am one too'); }).toThrowErrorMatchingSnapshot(); }); - it("should fail with a wrong class", () => { + it('should fail with a wrong class', () => { class AnotherClass {} const x = new AnotherClass(); @@ -88,8 +85,8 @@ describe("Android generation", () => { class Matcher { _call() { return { - target: { type: "Class", value: "Detox.Matcher" }, - method: "matchNicely" + target: { type: 'Class', value: 'Detox.Matcher' }, + method: 'matchNicely' }; } } diff --git a/generation/__tests__/global-functions.js b/generation/__tests__/global-functions.js index f391aa08f8..edd6131aaa 100644 --- a/generation/__tests__/global-functions.js +++ b/generation/__tests__/global-functions.js @@ -1,129 +1,116 @@ -const globals = require("../core/global-functions"); +const globals = require('../core/global-functions'); -describe("globals", () => { - describe("sanitize_android_direction", () => { - it("should return numbers for strings", () => { - expect(globals.sanitize_android_direction("left")).toBe(1); - expect(globals.sanitize_android_direction("right")).toBe(2); - expect(globals.sanitize_android_direction("up")).toBe(3); - expect(globals.sanitize_android_direction("down")).toBe(4); +describe('globals', () => { + describe('sanitize_android_direction', () => { + it('should return numbers for strings', () => { + expect(globals.sanitize_android_direction('left')).toBe(1); + expect(globals.sanitize_android_direction('right')).toBe(2); + expect(globals.sanitize_android_direction('up')).toBe(3); + expect(globals.sanitize_android_direction('down')).toBe(4); }); - it("should fail with unknown value", () => { + it('should fail with unknown value', () => { expect(() => { - globals.sanitize_android_direction("kittens"); + globals.sanitize_android_direction('kittens'); }).toThrowErrorMatchingSnapshot(); }); }); - describe("sanitize_android_edge", () => { - it("should return numbers for strings", () => { - expect(globals.sanitize_android_edge("left")).toBe(1); - expect(globals.sanitize_android_edge("right")).toBe(2); - expect(globals.sanitize_android_edge("top")).toBe(3); - expect(globals.sanitize_android_edge("bottom")).toBe(4); + describe('sanitize_android_edge', () => { + it('should return numbers for strings', () => { + expect(globals.sanitize_android_edge('left')).toBe(1); + expect(globals.sanitize_android_edge('right')).toBe(2); + expect(globals.sanitize_android_edge('top')).toBe(3); + expect(globals.sanitize_android_edge('bottom')).toBe(4); }); - it("should fail with unknown value", () => { + it('should fail with unknown value', () => { expect(() => { - globals.sanitize_android_edge("kittens"); + globals.sanitize_android_edge('kittens'); }).toThrowErrorMatchingSnapshot(); }); }); - describe("sanitize_greyDirection", () => { - it("should return numbers for strings", () => { - expect(globals.sanitize_greyDirection("left")).toBe(1); - expect(globals.sanitize_greyDirection("right")).toBe(2); - expect(globals.sanitize_greyDirection("up")).toBe(3); - expect(globals.sanitize_greyDirection("down")).toBe(4); + describe('sanitize_greyDirection', () => { + it('should return numbers for strings', () => { + expect(globals.sanitize_greyDirection('left')).toBe(1); + expect(globals.sanitize_greyDirection('right')).toBe(2); + expect(globals.sanitize_greyDirection('up')).toBe(3); + expect(globals.sanitize_greyDirection('down')).toBe(4); }); - it("should fail with unknown value", () => { + it('should fail with unknown value', () => { expect(() => { - globals.sanitize_greyDirection("kittens"); + globals.sanitize_greyDirection('kittens'); }).toThrowErrorMatchingSnapshot(); }); }); - describe("sanitize_greyContentEdge", () => { - it("should return numbers for strings", () => { - expect(globals.sanitize_greyContentEdge("left")).toBe(0); - expect(globals.sanitize_greyContentEdge("right")).toBe(1); - expect(globals.sanitize_greyContentEdge("top")).toBe(2); - expect(globals.sanitize_greyContentEdge("bottom")).toBe(3); + describe('sanitize_greyContentEdge', () => { + it('should return numbers for strings', () => { + expect(globals.sanitize_greyContentEdge('left')).toBe(0); + expect(globals.sanitize_greyContentEdge('right')).toBe(1); + expect(globals.sanitize_greyContentEdge('top')).toBe(2); + expect(globals.sanitize_greyContentEdge('bottom')).toBe(3); }); - it("should fail with unknown value", () => { + it('should fail with unknown value', () => { expect(() => { - globals.sanitize_greyContentEdge("kittens"); + globals.sanitize_greyContentEdge('kittens'); }).toThrowErrorMatchingSnapshot(); }); }); - describe("sanitize_uiAccessibilityTraits", () => { - it("should return numbers for traits", () => { - expect(globals.sanitize_uiAccessibilityTraits(["button"])).toBe(1); + describe('sanitize_uiAccessibilityTraits', () => { + it('should return numbers for traits', () => { + expect(globals.sanitize_uiAccessibilityTraits(['button'])).toBe(1); [ - "button", - "link", - "header", - "search", - "image", - "selected", - "plays", - "key", - "text", - "summary", - "disabled", - "frequentUpdates", - "startsMedia", - "adjustable", - "allowsDirectInteraction", - "pageTurn" - ].forEach(trait => { - expect(typeof globals.sanitize_uiAccessibilityTraits([trait])).toBe( - "number" - ); + 'button', + 'link', + 'header', + 'search', + 'image', + 'selected', + 'plays', + 'key', + 'text', + 'summary', + 'disabled', + 'frequentUpdates', + 'startsMedia', + 'adjustable', + 'allowsDirectInteraction', + 'pageTurn' + ].forEach((trait) => { + expect(typeof globals.sanitize_uiAccessibilityTraits([trait])).toBe('number'); }); }); - it("should combine the traits", () => { - expect( - globals.sanitize_uiAccessibilityTraits([ - "summary", - "allowsDirectInteraction" - ]) - ).toBe(16896); + it('should combine the traits', () => { + expect(globals.sanitize_uiAccessibilityTraits(['summary', 'allowsDirectInteraction'])).toBe(16896); }); - it("should throw if unknown trait is accessed", () => { - expect(() => - globals.sanitize_uiAccessibilityTraits(["unknown"]) - ).toThrowErrorMatchingSnapshot(); + it('should throw if unknown trait is accessed', () => { + expect(() => globals.sanitize_uiAccessibilityTraits(['unknown'])).toThrowErrorMatchingSnapshot(); }); }); const matcherInvocation = { - target: { type: "Class", value: "Detox.Matcher" }, - method: "matchNicely" + target: { type: 'Class', value: 'Detox.Matcher' }, + method: 'matchNicely' }; - describe("sanitize_matcher", () => { + describe('sanitize_matcher', () => { it("should return the object if it's no function", () => { - expect(globals.sanitize_matcher({ _call: matcherInvocation })).toEqual( - matcherInvocation - ); + expect(globals.sanitize_matcher({ _call: matcherInvocation })).toEqual(matcherInvocation); }); it("should return the ._call property if it's a function", () => { const matcherLikeObj = { _call: () => matcherInvocation }; - expect(globals.sanitize_matcher(matcherLikeObj)).toEqual( - matcherInvocation - ); + expect(globals.sanitize_matcher(matcherLikeObj)).toEqual(matcherInvocation); }); it("should unwrap the object if it's in an invocation", () => { - const invoke = { type: "Invocation", value: matcherInvocation }; + const invoke = { type: 'Invocation', value: matcherInvocation }; const invokeCalled = { _call: invoke }; const invokeThunk = { _call: () => invoke }; @@ -131,19 +118,19 @@ describe("globals", () => { expect(globals.sanitize_matcher(invokeThunk)).toEqual(matcherInvocation); }); - it("should not call on string", () => { + it('should not call on string', () => { const matcherLikeObj = { - _call: "I am a call" + _call: 'I am a call' }; - expect(globals.sanitize_matcher(matcherLikeObj)).toBe("I am a call"); + expect(globals.sanitize_matcher(matcherLikeObj)).toBe('I am a call'); }); }); - describe("sanitize_greyElementInteraction", () => { - it("should wrap the argument in an invocation", () => { - expect(globals.sanitize_greyElementInteraction("Foo")).toEqual({ - type: "Invocation", - value: "Foo" + describe('sanitize_greyElementInteraction', () => { + it('should wrap the argument in an invocation', () => { + expect(globals.sanitize_greyElementInteraction('Foo')).toEqual({ + type: 'Invocation', + value: 'Foo' }); }); }); diff --git a/generation/__tests__/helpers.js b/generation/__tests__/helpers.js index ba895e5684..776484f5f0 100644 --- a/generation/__tests__/helpers.js +++ b/generation/__tests__/helpers.js @@ -1,17 +1,13 @@ -const { methodNameToSnakeCase } = require("../helpers"); +const { methodNameToSnakeCase } = require('../helpers'); -describe("helpers", () => { - describe("methodNameToSnakeCase", () => { - it("should not fail with empty string", () => { - expect(() => methodNameToSnakeCase("")).not.toThrow(); +describe('helpers', () => { + describe('methodNameToSnakeCase', () => { + it('should not fail with empty string', () => { + expect(() => methodNameToSnakeCase('')).not.toThrow(); }); - it("should return the correct snake case method name", () => { - expect( - methodNameToSnakeCase( - "actionForScrollInDirection:amount:xOriginStartPercentage:yOriginStartPercentage:" - ) - ).toMatchSnapshot(); + it('should return the correct snake case method name', () => { + expect(methodNameToSnakeCase('actionForScrollInDirection:amount:xOriginStartPercentage:yOriginStartPercentage:')).toMatchSnapshot(); }); }); }); diff --git a/generation/__tests__/ios.js b/generation/__tests__/ios.js index e99d678d98..6e67d89405 100644 --- a/generation/__tests__/ios.js +++ b/generation/__tests__/ios.js @@ -1,52 +1,45 @@ -const fs = require("fs"); -const remove = require("remove"); -const iosGenerator = require("../adapters/ios"); +const fs = require('fs'); +const remove = require('remove'); +const iosGenerator = require('../adapters/ios'); -describe("iOS generation", () => { +describe('iOS generation', () => { let ExampleClass; let exampleContent; beforeAll(() => { // Generate the code to test - fs.mkdirSync("./__tests__/generated-ios"); + fs.mkdirSync('./__tests__/generated-ios'); const files = { - "./fixtures/example.h": "./__tests__/generated-ios/example.js" + './fixtures/example.h': './__tests__/generated-ios/example.js' }; - console.log("==> generating earl grey files"); + console.log('==> generating earl grey files'); iosGenerator(files); - console.log("==> loading earl grey files"); + console.log('==> loading earl grey files'); // Load - ExampleClass = require("./generated-ios/example.js"); - exampleContent = fs.readFileSync( - "./__tests__/generated-ios/example.js", - "utf8" - ); + ExampleClass = require('./generated-ios/example.js'); + exampleContent = fs.readFileSync('./__tests__/generated-ios/example.js', 'utf8'); }); - it("should export the class", () => { - expect(ExampleClass.actionForMultipleTapsWithCount).toBeInstanceOf( - Function - ); + it('should export the class', () => { + expect(ExampleClass.actionForMultipleTapsWithCount).toBeInstanceOf(Function); }); - describe("Comments", () => { - it("should include single line comments", () => { - expect(exampleContent.indexOf("Single Line Comment here")).not.toBe(-1); + describe('Comments', () => { + it('should include single line comments', () => { + expect(exampleContent.indexOf('Single Line Comment here')).not.toBe(-1); }); - it("should include multi line comments", () => { - expect( - exampleContent.indexOf("Multi Line Comment here\nAwesome") - ).not.toBe(-1); + it('should include multi line comments', () => { + expect(exampleContent.indexOf('Multi Line Comment here\nAwesome')).not.toBe(-1); }); }); - describe("Error handling", () => { - it("should throw error for wrong type", () => { + describe('Error handling', () => { + it('should throw error for wrong type', () => { expect(() => { - ExampleClass.actionForMultipleTapsWithCount("foo"); + ExampleClass.actionForMultipleTapsWithCount('foo'); }).toThrowErrorMatchingSnapshot(); expect(() => { @@ -62,33 +55,23 @@ describe("iOS generation", () => { }).not.toThrow(); }); - it("should throw error for not in accepted range", () => { + it('should throw error for not in accepted range', () => { expect(() => { - ExampleClass.actionForScrollInDirectionAmountXOriginStartPercentageYOriginStartPercentage( - "flipside", - 3, - 4, - 5 - ); + ExampleClass.actionForScrollInDirectionAmountXOriginStartPercentageYOriginStartPercentage('flipside', 3, 4, 5); }).toThrowErrorMatchingSnapshot(); expect(() => { - ExampleClass.actionForScrollInDirectionAmountXOriginStartPercentageYOriginStartPercentage( - "down", - 3, - 4, - 5 - ); + ExampleClass.actionForScrollInDirectionAmountXOriginStartPercentageYOriginStartPercentage('down', 3, 4, 5); }).not.toThrow(); }); - it("should thow error for CGPoint with wrong x and y values", () => { + it('should thow error for CGPoint with wrong x and y values', () => { expect(() => { ExampleClass.actionForMultipleTapsWithCountAtPoint(3, { x: 3, y: 4 }); }).not.toThrow(); expect(() => { - ExampleClass.actionForMultipleTapsWithCountAtPoint(3, { x: "3", y: 4 }); + ExampleClass.actionForMultipleTapsWithCountAtPoint(3, { x: '3', y: 4 }); }).toThrowErrorMatchingSnapshot(); expect(() => { @@ -97,258 +80,237 @@ describe("iOS generation", () => { }); }); - describe("Invocations", () => { - it("should return the invocation object for methods", () => { + describe('Invocations', () => { + it('should return the invocation object for methods', () => { const result = ExampleClass.actionForMultipleTapsWithCount(3); - expect(result.target.type).toBe("Class"); - expect(result.target.value).toBe("GREYActions"); + expect(result.target.type).toBe('Class'); + expect(result.target.value).toBe('GREYActions'); - expect(result.method).toBe("actionForMultipleTapsWithCount:"); + expect(result.method).toBe('actionForMultipleTapsWithCount:'); expect(result.args.length).toBe(1); - expect(result.args[0].type).toBe("NSInteger"); + expect(result.args[0].type).toBe('NSInteger'); expect(result.args[0].value).toBe(3); expect(result).toMatchSnapshot(); }); - it("should return the invocation object for methods with objects as args", () => { + it('should return the invocation object for methods with objects as args', () => { const result = ExampleClass.actionForMultipleTapsWithCountAtPoint(3, { x: 3, y: 4 }); - expect(result.target.type).toBe("Class"); - expect(result.target.value).toBe("GREYActions"); + expect(result.target.type).toBe('Class'); + expect(result.target.value).toBe('GREYActions'); - expect(result.method).toBe("actionForMultipleTapsWithCount:atPoint:"); + expect(result.method).toBe('actionForMultipleTapsWithCount:atPoint:'); expect(result.args.length).toBe(2); - expect(result.args[0].type).toBe("NSInteger"); + expect(result.args[0].type).toBe('NSInteger'); expect(result.args[0].value).toBe(3); - expect(result.args[1].type).toBe("CGPoint"); + expect(result.args[1].type).toBe('CGPoint'); expect(result.args[1].value).toEqual({ x: 3, y: 4 }); expect(result).toMatchSnapshot(); }); - it("should return the invocation object for methods with strings", () => { - const result = ExampleClass.actionForTypeText("Foo"); + it('should return the invocation object for methods with strings', () => { + const result = ExampleClass.actionForTypeText('Foo'); - expect(result.args[0].type).toBe("NSString"); + expect(result.args[0].type).toBe('NSString'); expect(result).toMatchSnapshot(); }); - it("should sanitize the directions", () => { - const result = ExampleClass.actionForScrollInDirectionAmountXOriginStartPercentageYOriginStartPercentage( - "down", - 3, - 4, - 5 - ); + it('should sanitize the directions', () => { + const result = ExampleClass.actionForScrollInDirectionAmountXOriginStartPercentageYOriginStartPercentage('down', 3, 4, 5); - expect(result.args[0].type).toBe("NSInteger"); + expect(result.args[0].type).toBe('NSInteger'); expect(result.args[0].value).toBe(4); expect(result).toMatchSnapshot(); }); - it("should sanitize the content edge", () => { - const result = ExampleClass.actionForScrollToContentEdge("bottom"); + it('should sanitize the content edge', () => { + const result = ExampleClass.actionForScrollToContentEdge('bottom'); - expect(result.args[0].type).toBe("NSInteger"); + expect(result.args[0].type).toBe('NSInteger'); expect(result.args[0].value).toBe(3); }); }); - describe("filter functions with unknown arguments", () => { - it("should not have a function with one unkown type", () => { + describe('filter functions with unknown arguments', () => { + it('should not have a function with one unkown type', () => { expect(ExampleClass.actionWithUnknownType).not.toBeDefined(); }); - it("should not have a function with one kown and one unknown type", () => { + it('should not have a function with one kown and one unknown type', () => { expect(ExampleClass.actionWithKnownAndUnknownType).not.toBeDefined(); }); }); - describe("special case: id", () => { - it("should not wrap the args in type id, but pass them in as they are", () => { + describe('special case: id', () => { + it('should not wrap the args in type id, but pass them in as they are', () => { const ancestorMatcher = { - type: "Invocation", + type: 'Invocation', value: { target: { - type: "Class", - value: "GREYMatchers" + type: 'Class', + value: 'GREYMatchers' }, - method: "matcherForAccessibilityID:", - args: ["Grandson883"] + method: 'matcherForAccessibilityID:', + args: ['Grandson883'] } }; const currentMatcher = { - type: "Invocation", + type: 'Invocation', value: { target: { - type: "Class", - value: "GREYMatchers" + type: 'Class', + value: 'GREYMatchers' }, - method: "matcherForAccessibilityID:", - args: ["Grandfather883"] + method: 'matcherForAccessibilityID:', + args: ['Grandfather883'] } }; - const result = ExampleClass.detoxMatcherForBothAndAncestorMatcher( - currentMatcher, - ancestorMatcher - ); + const result = ExampleClass.detoxMatcherForBothAndAncestorMatcher(currentMatcher, ancestorMatcher); expect(result).toEqual({ target: { - type: "Class", - value: "GREYActions" + type: 'Class', + value: 'GREYActions' }, - method: "detoxMatcherForBoth:andAncestorMatcher:", + method: 'detoxMatcherForBoth:andAncestorMatcher:', args: [ { - type: "Invocation", + type: 'Invocation', value: { target: { - type: "Class", - value: "GREYMatchers" + type: 'Class', + value: 'GREYMatchers' }, - method: "matcherForAccessibilityID:", - args: ["Grandfather883"] + method: 'matcherForAccessibilityID:', + args: ['Grandfather883'] } }, { - type: "Invocation", + type: 'Invocation', value: { target: { - type: "Class", - value: "GREYMatchers" + type: 'Class', + value: 'GREYMatchers' }, - method: "matcherForAccessibilityID:", - args: ["Grandson883"] + method: 'matcherForAccessibilityID:', + args: ['Grandson883'] } } ] }); }); - it("should fail with wrongly formatted matchers", () => { + it('should fail with wrongly formatted matchers', () => { expect(() => { const ancestorMatcher = { - type: "Invocation", + type: 'Invocation', value: { target: { - type: "Class", - value: "GREYMatchers" + type: 'Class', + value: 'GREYMatchers' }, - method: "matcherForAccessibilityID:", - args: ["Grandson883"] + method: 'matcherForAccessibilityID:', + args: ['Grandson883'] } }; const currentAction = { - type: "Invocation", + type: 'Invocation', value: { target: { - type: "Class", - value: "GREYAction" + type: 'Class', + value: 'GREYAction' }, - method: "matcherForAccessibilityID:", - args: ["Grandfather883"] + method: 'matcherForAccessibilityID:', + args: ['Grandfather883'] } }; - ExampleClass.detoxMatcherForBothAndAncestorMatcher( - currentAction, - ancestorMatcher - ); + ExampleClass.detoxMatcherForBothAndAncestorMatcher(currentAction, ancestorMatcher); }).toThrowErrorMatchingSnapshot(); expect(() => { const ancestorAction = { - type: "Invocation", + type: 'Invocation', value: { target: { - type: "Class", - value: "GREYAction" + type: 'Class', + value: 'GREYAction' }, - method: "matcherForAccessibilityID:", - args: ["Grandson883"] + method: 'matcherForAccessibilityID:', + args: ['Grandson883'] } }; const currentMatcher = { - type: "Invocation", + type: 'Invocation', value: { target: { - type: "Class", - value: "GREYMatchers" + type: 'Class', + value: 'GREYMatchers' }, - method: "matcherForAccessibilityID:", - args: ["Grandfather883"] + method: 'matcherForAccessibilityID:', + args: ['Grandfather883'] } }; - ExampleClass.detoxMatcherForBothAndAncestorMatcher( - currentMatcher, - ancestorAction - ); + ExampleClass.detoxMatcherForBothAndAncestorMatcher(currentMatcher, ancestorAction); }).toThrowErrorMatchingSnapshot(); expect(() => { const ancestorMatcher = { - type: "Invocation", + type: 'Invocation', value: { target: { - type: "Class", - value: "GREYAction" + type: 'Class', + value: 'GREYAction' }, - method: "matcherForAccessibilityID:", - args: ["Grandson883"] + method: 'matcherForAccessibilityID:', + args: ['Grandson883'] } }; const currentMatcher = { - type: "Invocation", + type: 'Invocation', value: { - method: "matcherForAccessibilityID:", - args: ["Grandfather883"] + method: 'matcherForAccessibilityID:', + args: ['Grandfather883'] } }; - ExampleClass.detoxMatcherForBothAndAncestorMatcher( - currentMatcher, - ancestorMatcher - ); + ExampleClass.detoxMatcherForBothAndAncestorMatcher(currentMatcher, ancestorMatcher); }).toThrowErrorMatchingSnapshot(); }); }); - describe("helper functions", () => { - it("should include them, if they are used", () => { + describe('helper functions', () => { + it('should include them, if they are used', () => { // GREYDirection is included, so sanitize_greyDirection should be there - expect( - exampleContent.indexOf("function sanitize_greyDirection") - ).not.toBe(-1); + expect(exampleContent.indexOf('function sanitize_greyDirection')).not.toBe(-1); }); - it("should not include them, if they are unused", () => { + it('should not include them, if they are unused', () => { // UIAccessibilityTraits is not included, so sanitize_uiAccessibilityTraits should not be there - expect( - exampleContent.indexOf("function sanitize_uiAccessibilityTraits") - ).toBe(-1); + expect(exampleContent.indexOf('function sanitize_uiAccessibilityTraits')).toBe(-1); }); }); - describe("instance methods", () => { - it("should expose the instance methods as static ones", () => { + describe('instance methods', () => { + it('should expose the instance methods as static ones', () => { expect(ExampleClass.performAction).toBeInstanceOf(Function); }); - it("should have the first arg set as invocation", () => { - expect(ExampleClass.performAction("MyClass", "Foo")).toEqual({ + it('should have the first arg set as invocation', () => { + expect(ExampleClass.performAction('MyClass', 'Foo')).toEqual({ target: { - type: "Invocation", - value: "MyClass" + type: 'Invocation', + value: 'MyClass' }, - method: "performAction:", + method: 'performAction:', args: [ { - type: "NSString", - value: "Foo" + type: 'NSString', + value: 'Foo' } ] }); @@ -357,6 +319,6 @@ describe("iOS generation", () => { afterAll(() => { // Clean up - remove.removeSync("./__tests__/generated-ios"); + remove.removeSync('./__tests__/generated-ios'); }); }); diff --git a/generation/adapters/android.js b/generation/adapters/android.js index 1e91e7fb45..929f4ba0fb 100644 --- a/generation/adapters/android.js +++ b/generation/adapters/android.js @@ -1,53 +1,48 @@ -const t = require("babel-types"); -const generator = require("../core/generator"); -const { callGlobal } = require("../helpers"); +const t = require('babel-types'); +const generator = require('../core/generator'); +const { callGlobal } = require('../helpers'); -const { - isNumber, - isString, - isBoolean, - isOfClass -} = require("../core/type-checks"); +const { isNumber, isString, isBoolean, isOfClass } = require('../core/type-checks'); const typeCheckInterfaces = { Integer: isNumber, Double: isNumber, String: isString, boolean: isBoolean, - "Matcher": isOfClass("Matcher") + 'Matcher': isOfClass('Matcher') }; const contentSanitizersForFunction = { scrollInDirection: { - argumentName: "direction", - newType: "String", - name: "sanitize_android_direction", - value: callGlobal("sanitize_android_direction") + argumentName: 'direction', + newType: 'String', + name: 'sanitize_android_direction', + value: callGlobal('sanitize_android_direction') }, swipeInDirection: { - argumentName: "direction", - newType: "String", - name: "sanitize_android_direction", - value: callGlobal("sanitize_android_direction") + argumentName: 'direction', + newType: 'String', + name: 'sanitize_android_direction', + value: callGlobal('sanitize_android_direction') }, scrollToEdge: { - argumentName: "edge", - newType: "String", - name: "sanitize_android_edge", - value: callGlobal("sanitize_android_edge") + argumentName: 'edge', + newType: 'String', + name: 'sanitize_android_edge', + value: callGlobal('sanitize_android_edge') }, - "Matcher": { - type: "String", - name: "sanitize_matcher", - value: callGlobal("sanitize_matcher") + 'Matcher': { + type: 'String', + name: 'sanitize_matcher', + value: callGlobal('sanitize_matcher') } }; const contentSanitizersForType = { - "Matcher": { - type: "Invocation", - name: "sanitize_matcher", - value: callGlobal("sanitize_matcher") + 'Matcher': { + type: 'Invocation', + name: 'sanitize_matcher', + value: callGlobal('sanitize_matcher') } }; @@ -55,18 +50,10 @@ module.exports = generator({ typeCheckInterfaces, contentSanitizersForFunction, contentSanitizersForType, - supportedTypes: [ - "Integer", - "int", - "double", - "Double", - "boolean", - "String", - "Matcher" - ], + supportedTypes: ['Integer', 'int', 'double', 'Double', 'boolean', 'String', 'Matcher'], renameTypesMap: { - int: "Integer", // TODO: add test - double: "Double" + int: 'Integer', // TODO: add test + double: 'Double' }, classValue: ({ package: pkg, name }) => `${pkg}.${name}` }); diff --git a/generation/adapters/ios.js b/generation/adapters/ios.js index 731b4acd82..30df668659 100644 --- a/generation/adapters/ios.js +++ b/generation/adapters/ios.js @@ -1,5 +1,5 @@ -const t = require("babel-types"); -const generator = require("../core/generator"); +const t = require('babel-types'); +const generator = require('../core/generator'); const { isNumber, isString, @@ -11,8 +11,8 @@ const { isGreyElementInteraction, isArray, isDefined -} = require("../core/type-checks"); -const { callGlobal } = require("../helpers"); +} = require('../core/type-checks'); +const { callGlobal } = require('../helpers'); const typeCheckInterfaces = { NSInteger: isNumber, @@ -23,37 +23,37 @@ const typeCheckInterfaces = { float: isNumber, NSString: isString, BOOL: isBoolean, - "NSDate *": isNumber, - GREYDirection: isOneOf(["left", "right", "up", "down"]), - GREYContentEdge: isOneOf(["left", "right", "top", "bottom"]), - GREYPinchDirection: isOneOf(["outward", "inward"]), - "id": isGreyAction, - "id": isGreyMatcher, - "GREYElementInteraction*": isGreyElementInteraction, + 'NSDate *': isNumber, + GREYDirection: isOneOf(['left', 'right', 'up', 'down']), + GREYContentEdge: isOneOf(['left', 'right', 'top', 'bottom']), + GREYPinchDirection: isOneOf(['outward', 'inward']), + 'id': isGreyAction, + 'id': isGreyMatcher, + 'GREYElementInteraction*': isGreyElementInteraction, UIAccessibilityTraits: isArray, - id: isDefined, + id: isDefined }; const contentSanitizersForType = { GREYDirection: { - type: "NSInteger", - name: "sanitize_greyDirection", - value: callGlobal("sanitize_greyDirection") + type: 'NSInteger', + name: 'sanitize_greyDirection', + value: callGlobal('sanitize_greyDirection') }, GREYContentEdge: { - type: "NSInteger", - name: "sanitize_greyContentEdge", - value: callGlobal("sanitize_greyContentEdge") + type: 'NSInteger', + name: 'sanitize_greyContentEdge', + value: callGlobal('sanitize_greyContentEdge') }, UIAccessibilityTraits: { - type: "NSInteger", - name: "sanitize_uiAccessibilityTraits", - value: callGlobal("sanitize_uiAccessibilityTraits") + type: 'NSInteger', + name: 'sanitize_uiAccessibilityTraits', + value: callGlobal('sanitize_uiAccessibilityTraits') }, - "GREYElementInteraction*": { - type: "Invocation", - name: "sanitize_greyElementInteraction", - value: callGlobal("sanitize_greyElementInteraction") + 'GREYElementInteraction*': { + type: 'Invocation', + name: 'sanitize_greyElementInteraction', + value: callGlobal('sanitize_greyElementInteraction') } }; @@ -62,26 +62,26 @@ module.exports = generator({ contentSanitizersForFunction: {}, contentSanitizersForType, supportedTypes: [ - "CGFloat", - "CGPoint", - "GREYContentEdge", - "GREYDirection", - "GREYElementInteraction*", - "NSInteger", - "NSString *", - "NSString", - "NSUInteger", - "id", - "id", - "CFTimeInterval", - "UIAccessibilityTraits", - "id" + 'CGFloat', + 'CGPoint', + 'GREYContentEdge', + 'GREYDirection', + 'GREYElementInteraction*', + 'NSInteger', + 'NSString *', + 'NSString', + 'NSUInteger', + 'id', + 'id', + 'CFTimeInterval', + 'UIAccessibilityTraits', + 'id' ], renameTypesMap: { - NSUInteger: "NSInteger", - "NSString *": "NSString", - CFTimeInterval: "CGFloat" + NSUInteger: 'NSInteger', + 'NSString *': 'NSString', + CFTimeInterval: 'CGFloat' }, classValue: ({ name }) => name, - blacklistedFunctionNames: ["init"] + blacklistedFunctionNames: ['init'] }); diff --git a/generation/check-for-git-changes.sh b/generation/check-for-git-changes.sh new file mode 100755 index 0000000000..f6ed2252ec --- /dev/null +++ b/generation/check-for-git-changes.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +git stash +npm run build + +if [[ $TRAVIS && $(git diff) ]]; then + printf "\n\n" + echo "There seem to be changes after running the code generation." + echo "This might be because you updated a native dependency and forgot to run the code generation." + echo "If this is the case run 'cd generation && npm run build'" + printf "\n" + echo "Another source of this error might be that you have changed generated code and checked it in." + echo "You should not be doing this, please change the source of the generated code and not the code itself." + printf "\n" + echo "$(git diff)" + git stash pop + exit 1 +else + git stash pop +fi \ No newline at end of file diff --git a/generation/core/generator.js b/generation/core/generator.js index 4413dba855..14687ac4e9 100644 --- a/generation/core/generator.js +++ b/generation/core/generator.js @@ -1,11 +1,11 @@ -const t = require("babel-types"); -const template = require("babel-template"); -const objectiveCParser = require("objective-c-parser"); -const javaMethodParser = require("java-method-parser"); -const generate = require("babel-generator").default; -const fs = require("fs"); - -const { methodNameToSnakeCase } = require("../helpers"); +const t = require('babel-types'); +const template = require('babel-template'); +const objectiveCParser = require('objective-c-parser'); +const javaMethodParser = require('java-method-parser'); +const generate = require('babel-generator').default; +const fs = require('fs'); + +const { methodNameToSnakeCase } = require('../helpers'); let globalFunctionUsage = {}; module.exports = function getGenerator({ typeCheckInterfaces, @@ -60,9 +60,7 @@ module.exports = function getGenerator({ } function filterMethodsWithBlacklistedName({ name }) { - return !blacklistedFunctionNames.find( - blacklisted => name.indexOf(blacklisted) !== -1 - ); + return !blacklistedFunctionNames.find((blacklisted) => name.indexOf(blacklisted) !== -1); } function filterMethodsWithUnsupportedParams(method) { @@ -76,15 +74,7 @@ module.exports = function getGenerator({ function createExport(json) { return t.expressionStatement( - t.assignmentExpression( - "=", - t.memberExpression( - t.identifier("module"), - t.identifier("exports"), - false - ), - t.identifier(json.name) - ) + t.assignmentExpression('=', t.memberExpression(t.identifier('module'), t.identifier('exports'), false), t.identifier(json.name)) ); } @@ -92,11 +82,11 @@ module.exports = function getGenerator({ const args = json.args.map(({ name }) => t.identifier(name)); if (!json.static) { - args.unshift(t.identifier("element")); + args.unshift(t.identifier('element')); } const m = t.classMethod( - "method", + 'method', t.identifier(methodNameToSnakeCase(json.name)), args, t.blockStatement(createMethodBody(classJson, json)), @@ -106,9 +96,8 @@ module.exports = function getGenerator({ if (json.comment) { const comment = { - type: - json.comment.indexOf("\n") === -1 ? "LineComment" : "BlockComment", - value: json.comment + "\n" + type: json.comment.indexOf('\n') === -1 ? 'LineComment' : 'BlockComment', + value: json.comment + '\n' }; m.leadingComments = m.leadingComments || []; @@ -128,25 +117,21 @@ module.exports = function getGenerator({ function createMethodBody(classJson, json) { const sanitizedJson = Object.assign({}, json, { - args: json.args.map(argJson => sanitizeArgumentType(argJson)) + args: json.args.map((argJson) => sanitizeArgumentType(argJson)) }); - const allTypeChecks = createTypeChecks( - sanitizedJson, - sanitizedJson.name - ).reduce( - (carry, item) => - item instanceof Array ? [...carry, ...item] : [...carry, item], + const allTypeChecks = createTypeChecks(sanitizedJson, sanitizedJson.name).reduce( + (carry, item) => (item instanceof Array ? [...carry, ...item] : [...carry, item]), [] ); - const typeChecks = allTypeChecks.filter(check => typeof check === "object"); + const typeChecks = allTypeChecks.filter((check) => typeof check === 'object'); const returnStatement = createReturnStatement(classJson, sanitizedJson); return [...typeChecks, returnStatement]; } function createTypeChecks(json, functionName) { - const checks = json.args.map(arg => createTypeCheck(arg, functionName)); - checks.filter(check => Boolean(check)); + const checks = json.args.map((arg) => createTypeCheck(arg, functionName)); + checks.filter((check) => Boolean(check)); return checks; } @@ -156,13 +141,8 @@ module.exports = function getGenerator({ return contentSanitizersForType[json.type].value(json.name); } - if ( - contentSanitizersForFunction[functionName] && - contentSanitizersForFunction[functionName].argumentName === json.name - ) { - globalFunctionUsage[ - contentSanitizersForFunction[functionName].name - ] = true; + if (contentSanitizersForFunction[functionName] && contentSanitizersForFunction[functionName].argumentName === json.name) { + globalFunctionUsage[contentSanitizersForFunction[functionName].name] = true; return contentSanitizersForFunction[functionName].value(json.name); } @@ -178,13 +158,7 @@ module.exports = function getGenerator({ } // These types need no wrapping with {type: ..., value: } - const plainArgumentTypes = [ - "id", - "id", - "id", - "GREYElementInteraction*", - "String" - ]; + const plainArgumentTypes = ['id', 'id', 'id', 'GREYElementInteraction*', 'String']; function shouldBeWrapped({ type }) { return !plainArgumentTypes.includes(type); @@ -192,17 +166,11 @@ module.exports = function getGenerator({ function createReturnStatement(classJson, json) { const args = json.args.map( - arg => + (arg) => shouldBeWrapped(arg) ? t.objectExpression([ - t.objectProperty( - t.identifier("type"), - t.stringLiteral(addArgumentTypeSanitizer(arg)) - ), - t.objectProperty( - t.identifier("value"), - addArgumentContentSanitizerCall(arg, json.name) - ) + t.objectProperty(t.identifier('type'), t.stringLiteral(addArgumentTypeSanitizer(arg))), + t.objectProperty(t.identifier('value'), addArgumentContentSanitizerCall(arg, json.name)) ]) : addArgumentContentSanitizerCall(arg, json.name) ); @@ -210,37 +178,26 @@ module.exports = function getGenerator({ return t.returnStatement( t.objectExpression([ t.objectProperty( - t.identifier("target"), + t.identifier('target'), t.objectExpression([ - t.objectProperty( - t.identifier("type"), - t.stringLiteral(json.static ? "Class" : "Invocation") - ), - t.objectProperty( - t.identifier("value"), - json.static - ? t.stringLiteral(classValue(classJson)) - : t.identifier("element") - ) + t.objectProperty(t.identifier('type'), t.stringLiteral(json.static ? 'Class' : 'Invocation')), + t.objectProperty(t.identifier('value'), json.static ? t.stringLiteral(classValue(classJson)) : t.identifier('element')) ]) ), - t.objectProperty(t.identifier("method"), t.stringLiteral(json.name)), - t.objectProperty(t.identifier("args"), t.arrayExpression(args)) + t.objectProperty(t.identifier('method'), t.stringLiteral(json.name)), + t.objectProperty(t.identifier('args'), t.arrayExpression(args)) ]) ); } function createTypeCheck(json, functionName) { const optionalSanitizer = contentSanitizersForFunction[functionName]; - const type = - optionalSanitizer && optionalSanitizer.argumentName === json.name - ? optionalSanitizer.newType - : json.type; + const type = optionalSanitizer && optionalSanitizer.argumentName === json.name ? optionalSanitizer.newType : json.type; const typeCheckCreator = typeCheckInterfaces[type]; const isListOfChecks = typeCheckCreator instanceof Array; return isListOfChecks - ? typeCheckCreator.map(singleCheck => singleCheck(json)) - : typeof typeCheckCreator === "function" + ? typeCheckCreator.map((singleCheck) => singleCheck(json)) + : typeof typeCheckCreator === 'function' ? typeCheckCreator(json) : t.emptyStatement(); } @@ -248,61 +205,46 @@ module.exports = function getGenerator({ return function generator(files) { Object.entries(files).forEach(([inputFile, outputFile]) => { globalFunctionUsage = {}; - const input = fs.readFileSync(inputFile, "utf8"); - const isObjectiveC = inputFile[inputFile.length - 1] === "h"; + const input = fs.readFileSync(inputFile, 'utf8'); + const isObjectiveC = inputFile[inputFile.length - 1] === 'h'; - const json = isObjectiveC - ? objectiveCParser(input) - : javaMethodParser(input); + const json = isObjectiveC ? objectiveCParser(input) : javaMethodParser(input); // set default name if (!json.name) { - const pathFragments = outputFile.split("/"); - json.name = pathFragments[pathFragments.length - 1].replace(".js", ""); + const pathFragments = outputFile.split('/'); + json.name = pathFragments[pathFragments.length - 1].replace('.js', ''); } const ast = t.program([createClass(json), createExport(json)]); const output = generate(ast); - const commentBefore = - "/**\n\n\tThis code is generated.\n\tFor more information see generation/README.md.\n*/\n\n"; + const commentBefore = '/**\n\n\tThis code is generated.\n\tFor more information see generation/README.md.\n*/\n\n'; // Add global helper functions - const globalFunctionsStr = fs.readFileSync( - __dirname + "/global-functions.js", - "utf8" - ); - const globalFunctionsSource = globalFunctionsStr.substr( - 0, - globalFunctionsStr.indexOf("module.exports") - ); + const globalFunctionsStr = fs.readFileSync(__dirname + '/global-functions.js', 'utf8'); + const globalFunctionsSource = globalFunctionsStr.substr(0, globalFunctionsStr.indexOf('module.exports')); // Only include global functions that are actually used const usedGlobalFunctions = Object.entries(globalFunctionUsage) .filter(([key, value]) => value) .map(([key]) => key); const globalFunctions = usedGlobalFunctions - .map(name => { + .map((name) => { const start = globalFunctionsSource.indexOf(`function ${name}`); const end = globalFunctionsSource.indexOf(`// END ${name}`); return globalFunctionsSource.substr(start, end - start); }) - .join("\n"); + .join('\n'); - const code = [commentBefore, globalFunctions, output.code].join("\n"); - fs.writeFileSync(outputFile, code, "utf8"); + const code = [commentBefore, globalFunctions, output.code].join('\n'); + fs.writeFileSync(outputFile, code, 'utf8'); // Output methods that were not created due to missing argument support - const unsupportedMethods = json.methods.filter( - x => !filterMethodsWithUnsupportedParams(x) - ); + const unsupportedMethods = json.methods.filter((x) => !filterMethodsWithUnsupportedParams(x)); if (unsupportedMethods.length) { - console.log( - `Could not generate the following methods for ${json.name}` - ); - unsupportedMethods.forEach(method => { - const methodArgs = method.args - .filter(methodArg => !supportedTypes.includes(methodArg.type)) - .map(methodArg => methodArg.type); + console.log(`Could not generate the following methods for ${json.name}`); + unsupportedMethods.forEach((method) => { + const methodArgs = method.args.filter((methodArg) => !supportedTypes.includes(methodArg.type)).map((methodArg) => methodArg.type); console.log(`\t ${method.name} misses ${methodArgs}`); }); } diff --git a/generation/core/global-functions.js b/generation/core/global-functions.js index 4c763b40fe..8ac4a2dc22 100644 --- a/generation/core/global-functions.js +++ b/generation/core/global-functions.js @@ -4,71 +4,63 @@ function sanitize_android_direction(direction) { switch (direction) { - case "left": + case 'left': return 1; - case "right": + case 'right': return 2; - case "up": + case 'up': return 3; - case "down": + case 'down': return 4; default: - throw new Error( - `direction must be a 'left'/'right'/'up'/'down', got ${direction}` - ); + throw new Error(`direction must be a 'left'/'right'/'up'/'down', got ${direction}`); } } // END sanitize_android_direction function sanitize_android_edge(edge) { switch (edge) { - case "left": + case 'left': return 1; - case "right": + case 'right': return 2; - case "top": + case 'top': return 3; - case "bottom": + case 'bottom': return 4; default: - throw new Error( - `edge must be a 'left'/'right'/'top'/'bottom', got ${edge}` - ); + throw new Error(`edge must be a 'left'/'right'/'top'/'bottom', got ${edge}`); } } // END sanitize_android_edge function sanitize_greyDirection(action) { switch (action) { - case "left": + case 'left': return 1; - case "right": + case 'right': return 2; - case "up": + case 'up': return 3; - case "down": + case 'down': return 4; default: - throw new Error( - `GREYAction.GREYDirection must be a 'left'/'right'/'up'/'down', got ${action}` - ); + throw new Error(`GREYAction.GREYDirection must be a 'left'/'right'/'up'/'down', got ${action}`); } } // END sanitize_greyDirection function sanitize_greyContentEdge(action) { switch (action) { - case "left": + case 'left': return 0; - case "right": + case 'right': return 1; - case "top": + case 'top': return 2; - case "bottom": + case 'bottom': return 3; default: - throw new Error( - `GREYAction.GREYContentEdge must be a 'left'/'right'/'top'/'bottom', got ${action}` - ); + throw new Error(`GREYAction.GREYContentEdge must be a 'left'/'right'/'top'/'bottom', got ${action}`); } } // END sanitize_greyContentEdge @@ -76,59 +68,57 @@ function sanitize_uiAccessibilityTraits(value) { let traits = 0; for (let i = 0; i < value.length; i++) { switch (value[i]) { - case "button": + case 'button': traits |= 1; break; - case "link": + case 'link': traits |= 2; break; - case "header": + case 'header': traits |= 4; break; - case "search": + case 'search': traits |= 8; break; - case "image": + case 'image': traits |= 16; break; - case "selected": + case 'selected': traits |= 32; break; - case "plays": + case 'plays': traits |= 64; break; - case "key": + case 'key': traits |= 128; break; - case "text": + case 'text': traits |= 256; break; - case "summary": + case 'summary': traits |= 512; break; - case "disabled": + case 'disabled': traits |= 1024; break; - case "frequentUpdates": + case 'frequentUpdates': traits |= 2048; break; - case "startsMedia": + case 'startsMedia': traits |= 4096; break; - case "adjustable": + case 'adjustable': traits |= 8192; break; - case "allowsDirectInteraction": + case 'allowsDirectInteraction': traits |= 16384; break; - case "pageTurn": + case 'pageTurn': traits |= 32768; break; default: throw new Error( - `Unknown trait '${ - value[i] - }', see list in https://facebook.github.io/react-native/docs/accessibility.html#accessibilitytraits-ios` + `Unknown trait '${value[i]}', see list in https://facebook.github.io/react-native/docs/accessibility.html#accessibilitytraits-ios` ); } } @@ -137,14 +127,13 @@ function sanitize_uiAccessibilityTraits(value) { } // END sanitize_uiAccessibilityTraits function sanitize_matcher(matcher) { - const originalMatcher = - typeof matcher._call === "function" ? matcher._call() : matcher._call; + const originalMatcher = typeof matcher._call === 'function' ? matcher._call() : matcher._call; return originalMatcher.type ? originalMatcher.value : originalMatcher; } // END sanitize_matcher function sanitize_greyElementInteraction(value) { return { - type: "Invocation", + type: 'Invocation', value }; } // END sanitize_greyElementInteraction diff --git a/generation/core/type-checks.js b/generation/core/type-checks.js index 9b9212774d..414afc52db 100644 --- a/generation/core/type-checks.js +++ b/generation/core/type-checks.js @@ -1,17 +1,14 @@ -const t = require("babel-types"); -const template = require("babel-template"); -const { - generateTypeCheck, - generateIsOneOfCheck -} = require("babel-generate-guard-clauses"); +const t = require('babel-types'); +const template = require('babel-template'); +const { generateTypeCheck, generateIsOneOfCheck } = require('babel-generate-guard-clauses'); -const isNumber = generateTypeCheck("number"); -const isString = generateTypeCheck("string"); -const isBoolean = generateTypeCheck("boolean"); +const isNumber = generateTypeCheck('number'); +const isString = generateTypeCheck('string'); +const isBoolean = generateTypeCheck('boolean'); const isPoint = [ - generateTypeCheck("object"), - generateTypeCheck("number", { selector: "x" }), - generateTypeCheck("number", { selector: "y" }) + generateTypeCheck('object'), + generateTypeCheck('number', { selector: 'x' }), + generateTypeCheck('number', { selector: 'y' }) ]; const isOneOf = generateIsOneOfCheck; function isGreyMatcher({ name }) { @@ -90,13 +87,14 @@ function isOfClass(className) { } function isDefined() { - return ({ name }) => template(` + return ({ name }) => + template(` if (!ARG) { throw new Error('${name} should be truthy, but it is "' + ARG + '"'); } - `)({ - ARG: t.identifier(name) - }); + `)({ + ARG: t.identifier(name) + }); } module.exports = { diff --git a/generation/package.json b/generation/package.json index aa336668ed..56ed960421 100644 --- a/generation/package.json +++ b/generation/package.json @@ -6,6 +6,7 @@ "private": true, "scripts": { "build": "./index.js", + "pretest": "./check-for-git-changes.sh", "test": "jest", "precommit": "lint-staged", "format": "prettier ./**/*.{js,json,css,md} --write" @@ -13,7 +14,10 @@ "author": "DanielMSchmidt ", "license": "MIT", "lint-staged": { - "*.{js,json,css,md}": ["prettier --write", "git add"] + "*.{js,json,css,md}": [ + "prettier --write", + "git add" + ] }, "dependencies": { "babel-generate-guard-clauses": "2.0.5", @@ -31,7 +35,9 @@ "prettier": "^1.8.2" }, "jest": { - "coveragePathIgnorePatterns": ["/index.js"], + "coveragePathIgnorePatterns": [ + "/index.js" + ], "resetMocks": true, "resetModules": true, "coverageThreshold": { diff --git a/generation/utils/downloadEspresso.js b/generation/utils/downloadEspresso.js index 826bc27d39..3c999907bf 100644 --- a/generation/utils/downloadEspresso.js +++ b/generation/utils/downloadEspresso.js @@ -1,17 +1,17 @@ // Gets a fully qualified class path of espresso and downloads it in a temp dir -const os = require("os"); -const downloadFileSync = require("download-file-sync"); -const fs = require("fs"); +const os = require('os'); +const downloadFileSync = require('download-file-sync'); +const fs = require('fs'); module.exports = function downloadEspresso(fullyQualifiedClass) { const tmpDir = os.tmpdir(); - const path = fullyQualifiedClass.replace(/\./g, "/"); + const path = fullyQualifiedClass.replace(/\./g, '/'); const fileContent = downloadFileSync( `http://android.googlesource.com/platform/frameworks/testing/+/android-support-test/espresso/core/src/main/java/${path}.java?format=TEXT` ); - const result = Buffer.from(fileContent, "base64").toString("ascii"); - const filePath = tmpDir + "/download.java"; + const result = Buffer.from(fileContent, 'base64').toString('ascii'); + const filePath = tmpDir + '/download.java'; fs.writeFileSync(filePath, result); return filePath; };