diff --git a/.gitignore b/.gitignore index bf673cb..5145b2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +e2e/GeocoderE2EApp + # OSX # .DS_Store diff --git a/.npmignore b/.npmignore index c41969c..1166e1e 100644 --- a/.npmignore +++ b/.npmignore @@ -1,5 +1,7 @@ img example +e2e +test # OSX # diff --git a/package.json b/package.json index 2cd8503..2d62e07 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "react native geocoding and reverse geocoding", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "npm run e2e", + "e2e": "e2e/prepare.sh && e2e/run.sh" }, "keywords": [ "react-component", @@ -26,5 +27,15 @@ "url": "https://github.com/devfd/react-native-geocoder/issues" }, "homepage": "https://github.com/devfd/react-native-geocoder", - "license": "MIT" + "license": "MIT", + "devDependencies": { + "appium": "^1.5.2", + "babel-core": "^6.8.0", + "babel-polyfill": "^6.8.0", + "babel-preset-react-native": "^1.8.0", + "chai": "^3.5.0", + "colors": "^1.1.2", + "mocha": "^2.4.5", + "wd": "^0.4.0" + } } diff --git a/test/globals.js b/test/globals.js new file mode 100644 index 0000000..9e4a4ae --- /dev/null +++ b/test/globals.js @@ -0,0 +1,10 @@ +require('babel-core/register')({ + presets: ["react-native"] +}); +require("babel-polyfill"); + +require('colors'); + +process.on('unhandledRejection', function(reason, p) { + throw new Error(reason); +}); diff --git a/test/helpers/logging.js b/test/helpers/logging.js new file mode 100644 index 0000000..1a733af --- /dev/null +++ b/test/helpers/logging.js @@ -0,0 +1,14 @@ +"use strict"; + +exports.configure = function (driver) { + // See whats going on + driver.on('status', function (info) { + console.log(info.cyan); + }); + driver.on('command', function (meth, path, data) { + console.log(' > ' + meth.yellow, path.grey, data || ''); + }); + driver.on('http', function (meth, path, data) { + console.log(' > ' + meth.magenta, path, (data || '').grey); + }); +}; diff --git a/test/index.spec.js b/test/index.spec.js new file mode 100644 index 0000000..07d6ff8 --- /dev/null +++ b/test/index.spec.js @@ -0,0 +1,84 @@ +import wd from 'wd'; +import path from 'path'; +import { expect } from 'chai'; + +const London = { + lat: 51.50853, + lng: -0.12574, +}; + +const Paris = { + lat: 48.85341, + lng: 2.3488, +}; + +describe ('react-native-geocoder', function() { + this.timeout(600000); + + let driver; + + before(() => { + driver = wd.promiseChainRemote({ + host: 'localhost', + port: 4723 + }); + require("./helpers/logging").configure(driver); + + return driver + .init({ + platformName: 'Android', + deviceName: 'Android Emulator', + newCommandTimeout: 60000, + app: path.resolve('e2e/GeocoderE2EApp/android/app/build/outputs/apk/app-debug.apk') + }) + .setImplicitWaitTimeout(3000); + // .waitForElementByXPath('//android.widget.Button[@text="Reload JS"]'). + // then((elem) => { + // elem.click(); + // }, (err) => { + // ignoring if Reload JS button can't be located + // }) + }); + + after(() => { + return driver.quit(); + }); + + + it ('displays default view', async () => { + await driver.waitForElementByXPath('//android.widget.EditText[1]', 30000); // wait for view to be initialized + await driver.waitForElementByXPath('//android.widget.EditText[2]'); + await driver.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Geocode")]'); + await driver.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Reverse")]'); + }); + + it ('geocodes address', async () => { + await driver.waitForElementByXPath('//android.widget.EditText[1]').sendKeys("London"); + await driver.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Geocode")]').click().click(); + + const locality = await driver.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Locality")]', 5000).text(); + expect(locality.split(':')[1].trim().toLowerCase()).to.contain('london'); + + const latlng = await driver.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "LatLng")]').text(); + const [lat, lng] = latlng.split(':')[1].split(',').map(v => 1 * v.trim()); + + expect(lat - London.lat).to.be.below(0.001); + expect(lng - London.lng).to.be.below(0.001); + }); + + it ('geocodes lat lng into address', async () => { + await driver.waitForElementByXPath('//android.widget.EditText[2]').sendKeys(`${Paris.lat} ${Paris.lng}`); + await driver.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Reverse")]').click().click(); + + const locality = await driver.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Locality")]', 5000).text(); + expect(locality.split(':')[1].trim().toLowerCase()).to.contain('paris'); + + const latlng = await driver.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "LatLng")]').text(); + const [lat, lng] = latlng.split(':')[1].split(',').map(v => 1 * v.trim()); + + expect(lat - Paris.lat).to.be.below(0.001); + expect(lng - Paris.lng).to.be.below(0.001); + }); + +}); +