From d6c8695c2cace59da0b70d6f42a089e22ae228b3 Mon Sep 17 00:00:00 2001
From: Sergey Pchelintsev <linz.sergey@gmail.com>
Date: Wed, 29 Nov 2017 16:04:11 +0200
Subject: [PATCH] Remove nightwatch in favour of puppeteer

---
 .gitignore                             |  4 +--
 .npmignore                             |  7 ++--
 .travis.yml                            | 37 ++++-----------------
 README.md                              |  4 +--
 e2e_helpers/assertions/assertBuffer.js | 45 --------------------------
 e2e_helpers/commands/.gitkeep          |  0
 e2e_helpers/globals.js                 | 21 ------------
 e2e_helpers/pages/helper.js            | 25 --------------
 example/index.js                       | 29 ++++++++---------
 nightwatch.json                        | 44 -------------------------
 package.json                           |  8 ++---
 test/_open-page.js                     | 13 ++++++++
 test/index.js                          | 26 +++++++++++++++
 tests/00_sanity-check.js               | 17 ----------
 tests/01_basic-text.js                 | 13 --------
 tests/02_multiline-text.js             | 12 -------
 tests/03_markup-text.js                | 13 --------
 17 files changed, 70 insertions(+), 248 deletions(-)
 delete mode 100644 e2e_helpers/assertions/assertBuffer.js
 delete mode 100644 e2e_helpers/commands/.gitkeep
 delete mode 100644 e2e_helpers/globals.js
 delete mode 100644 e2e_helpers/pages/helper.js
 delete mode 100644 nightwatch.json
 create mode 100644 test/_open-page.js
 create mode 100644 test/index.js
 delete mode 100644 tests/00_sanity-check.js
 delete mode 100644 tests/01_basic-text.js
 delete mode 100644 tests/02_multiline-text.js
 delete mode 100644 tests/03_markup-text.js

diff --git a/.gitignore b/.gitignore
index a0b2031..009ebad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-node_modules
+/node_modules
 .DS_Store
 reports
-selenium-debug.log
+/package-lock.json
diff --git a/.npmignore b/.npmignore
index ef5d2e3..bb66d28 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,5 +1,2 @@
-e2e_helpers
-tests
-nightwatch.json
-selenium-debug.log
-index.html
\ No newline at end of file
+test
+index.html
diff --git a/.travis.yml b/.travis.yml
index 1864d97..4b1e0ad 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,33 +1,10 @@
 language: node_js
 node_js:
-  - "4.2"
-
-env:
-  - E2E_BROWSER_VENDOR="internet explorer" E2E_PLATFORM="Windows 8.1" E2E_BROWSER_VERSION="latest"
-  - E2E_BROWSER_VENDOR="internet explorer" E2E_PLATFORM="Windows 10" E2E_BROWSER_VERSION="latest"
-  - E2E_BROWSER_VENDOR="MicrosoftEdge" E2E_PLATFORM="Windows 10" E2E_BROWSER_VERSION="latest"
-  - E2E_BROWSER_VENDOR="chrome" E2E_PLATFORM="Windows 8.1" E2E_BROWSER_VERSION="latest"
-  - E2E_BROWSER_VENDOR="chrome" E2E_PLATFORM="Windows 8.1" E2E_BROWSER_VERSION="latest-1"
-  - E2E_BROWSER_VENDOR="chrome" E2E_PLATFORM="Windows 10" E2E_BROWSER_VERSION="latest"
-  - E2E_BROWSER_VENDOR="chrome" E2E_PLATFORM="Windows 10" E2E_BROWSER_VERSION="latest-1"
-  - E2E_BROWSER_VENDOR="firefox" E2E_PLATFORM="Windows 8.1" E2E_BROWSER_VERSION="latest"
-  - E2E_BROWSER_VENDOR="firefox" E2E_PLATFORM="Windows 8.1" E2E_BROWSER_VERSION="latest-1"
-  - E2E_BROWSER_VENDOR="firefox" E2E_PLATFORM="Windows 10" E2E_BROWSER_VERSION="latest"
-  - E2E_BROWSER_VENDOR="firefox" E2E_PLATFORM="Windows 10" E2E_BROWSER_VERSION="latest-1"
-  # TODO: add workaround for chromedriver issue
-  # - E2E_BROWSER_VENDOR="chrome" E2E_PLATFORM="OS X 10.11" E2E_BROWSER_VERSION="latest"
-  # - E2E_BROWSER_VENDOR="chrome" E2E_PLATFORM="OS X 10.11" E2E_BROWSER_VERSION="latest-1"
-  # TODO: look into execCommand(“copy”) support in Safari
-  # window.document.queryCommandSupported('copy') - false in 9.1.1
-  # - E2E_BROWSER_VENDOR="safari" E2E_PLATFORM="OS X 10.11" E2E_BROWSER_VERSION="latest"
-  - E2E_BROWSER_VENDOR="firefox" E2E_PLATFORM="OS X 10.11" E2E_BROWSER_VERSION="latest"
-  - E2E_BROWSER_VENDOR="firefox" E2E_PLATFORM="OS X 10.11" E2E_BROWSER_VERSION="latest-1"
-
+  - 8
+before_install:
+  - export DISPLAY=:99.0;
+  - sh -e /etc/init.d/xvfb start;
 addons:
-  sauce_connect:
-    username: "sudodoki"
-    access_key:
-      secure: "MBHn7+lxuJ0uNuFC8HjIZtosuOHICNW52fEhvtnJhXmaGOUXGLrQFUCvECJOoGrdOWmkiFaGgYINdF57HbYpyAICmv51UBlzHYftkTspYooH5+vni0ezPPpvxqNpUM/dlwfrdzC/ag97VYDeIxdYRKREwhRsNd5npE0Zrx1xmvzmnpdqdVhQ7Z/wQUDjv7talKC2fkaIYP+wEhVblnr18u0phFLqyADNsCV7D9QmILQWC4ieSz6ylTW9fb69B4rZElLj+D8qGvyvgmLnu+dK4Vlh0WuTdmVZ8TZS4OeBRIbjq/Mi2vMVuQLXz3DTiGWRZeDOBB5PYm/orgjgsnNg5hPx6t7yc4ypcBYf2gHxc31lV9VZRb10py33D8qPtcmPptwIWlsCQ4ANDyOwxck0FejMpjT+Ktkyme4nAvt9op289x8KKI0w8W7nHIB930lEookJCeMHWjyycPLJDTwYe60zBS24vNRF46ixhfpeO1zGw8nEj5qqSoEltunCOQ3Uvl25tNEuk9R649TyWbegjTuS4txqAsSjUnVMGvRBcZef4YyOQsggos1YbJMNnFSvDH9VaPYiJbg/qR7tb0YJ8gtAC9/6iqba6EZadkJQe9DHs6qu5zuoiwfSgBZTON2oWL6AGwySADm44SL7ikKJN8Zb8bLjQ1o15KinBVKLuOk="
-
-script:
-  - REMOTE_SELENIUM=true npm test -- -e saucelabs
+  apt:
+    packages:
+      - xsel
diff --git a/README.md b/README.md
index cc6a606..3d52056 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ copy('Text', {
 
 Works everywhere where `prompt`* is available. Works best (i.e. without additional keystrokes) in Chrome, FF, Safari 10+, and, supposedly, IE/Edge.
 
-Note: **does not work on some older iOS devices.**  
+Note: **does not work on some older iOS devices.**
 `*` – even though **Safari 8** has `prompt`, you cannot specify prefilled content for prompt modal – thus it **doesn't work** as expected.
 
 # Installation
@@ -56,7 +56,7 @@ You will have `window.copyToClipboard` exposed for you to use.
 + [April 2015 update on Cut and Copy Commands](http://updates.html5rocks.com/2015/04/cut-and-copy-commands)
 
 # Running Tests
-This project has some automated tests, that will run using [nightwatch](nightwatchjs.org) on top of [selenium](http://www.seleniumhq.org/).
+This project has some automated tests, that will run using [ava](https://github.com/avajs/ava) on top of [puppeteer](https://github.com/GoogleChrome/puppeteer).
 
 ```
 npm i
diff --git a/e2e_helpers/assertions/assertBuffer.js b/e2e_helpers/assertions/assertBuffer.js
deleted file mode 100644
index 65e642c..0000000
--- a/e2e_helpers/assertions/assertBuffer.js
+++ /dev/null
@@ -1,45 +0,0 @@
-'use strict';
-const util = require('util');
-const os = require('os');
-
-const modificatorKey = (() => {
-  const usesCommandKey = () =>
-    (process.env.REMOTE_SELENIUM
-      ? (process.env.E2E_PLATFORM || '').match(/os\sx/i)
-      : os.type().toLowerCase() === 'darwin')
-
-  return usesCommandKey()
-    ? 'COMMAND'
-    : 'CONTROL';
-})()
-
-exports.assertion = function(expected) {
-  this.message = "Checking buffer contents";
-  this.expected = (expected instanceof RegExp) ? "to match " + expected : expected;
-
-  this.pass = function(value) {
-    return (expected instanceof RegExp)
-      ? expected.test(value)
-      : value === expected
-  };
-
-  this.value = function(value) {
-    return value;
-  };
-  // TODO: generate element instead of using eisting one?
-  this.command = function(callback) {
-    return this.api
-      .url(this.api.launchUrl)
-      .waitForElementVisible('[data-test="placeholder"]', 500)
-      .click('[data-test="placeholder"]')
-      // This is not going to work in Chromedriver on Mac — https://bugs.chromium.org/p/chromedriver/issues/detail?id=30
-      .keys([this.api.Keys[modificatorKey], 'v'])
-      .pause(10)
-      .keys(this.api.Keys[modificatorKey])
-      .pause(10)
-      .getValue('[data-test="placeholder"]', function(result) {
-         callback(result.value)
-      });
-  };
-
-};
diff --git a/e2e_helpers/commands/.gitkeep b/e2e_helpers/commands/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/e2e_helpers/globals.js b/e2e_helpers/globals.js
deleted file mode 100644
index 3d1b127..0000000
--- a/e2e_helpers/globals.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict';
-const http = require('http')
-const nodeStatic = require('node-static');
-const fileServer = new nodeStatic.Server('./example');
-let server;
-module.exports = {
-  before: function (next) {
-    console.log('Server started');
-      server = http.createServer(function (request, response) {
-          request.addListener('end', function () {
-              fileServer.serve(request, response);
-          }).resume();
-      }).listen(8080);
-
-      next()
-  },
-  after: function (next) {
-    server.close();
-    next()
-  }
-}
diff --git a/e2e_helpers/pages/helper.js b/e2e_helpers/pages/helper.js
deleted file mode 100644
index 33afc35..0000000
--- a/e2e_helpers/pages/helper.js
+++ /dev/null
@@ -1,25 +0,0 @@
-'use strict';
-const os = require('os');
-const modificatorKey = (os.type().toLowerCase() === 'darwin')
- ? 'COMMAND'
- : 'CONTROL';
-
-module.exports = function(browser) {
-   return {
-      resetBuffer: function (text) {
-        return browser
-          .url(browser.launchUrl)
-          .waitForElementVisible('[data-test="placeholder"]', 500)
-          .click('[data-test="placeholder"]')
-          .keys(text || "some text to reset the clipboard")
-          .pause(10)
-          .keys([browser.Keys[modificatorKey], 'a'])
-          .keys(browser.Keys[modificatorKey])
-          .pause(10)
-          .keys([browser.Keys[modificatorKey], 'c'])
-          .keys(browser.Keys[modificatorKey])
-          .keys(browser.Keys.DELETE)
-          .pause(10);
-      }
-   }
-}
diff --git a/example/index.js b/example/index.js
index 860068d..8fd8f00 100644
--- a/example/index.js
+++ b/example/index.js
@@ -20,21 +20,21 @@ function copy(text, options) {
     range = document.createRange();
     selection = document.getSelection();
 
-    mark = document.createElement('mark');
+    mark = document.createElement('span');
     mark.textContent = text;
-    mark.setAttribute('style', [
-      // prevents scrolling to the end of the page
-      'position: fixed',
-      'top: 0',
-      'clip: rect(0, 0, 0, 0)',
-      // used to preserve spaces and line breaks
-      'white-space: pre',
-      // do not inherit user-select (it may be `none`)
-      '-webkit-user-select: text',
-      '-moz-user-select: text',
-      '-ms-user-select: text',
-      'user-select: text',
-    ].join(';'));
+    // reset user styles for span element
+    mark.style.all = 'unset';
+    // prevents scrolling to the end of the page
+    mark.style.position = 'fixed';
+    mark.style.top = 0;
+    mark.style.clip = 'rect(0, 0, 0, 0)';
+    // used to preserve spaces and line breaks
+    mark.style.whiteSpace = 'pre';
+    // do not inherit user-select (it may be `none`)
+    mark.style.webkitUserSelect = 'text';
+    mark.style.MozUserSelect = 'text';
+    mark.style.msUserSelect = 'text';
+    mark.style.userSelect = 'text';
 
     document.body.appendChild(mark);
 
@@ -79,7 +79,6 @@ function copy(text, options) {
 module.exports = copy;
 
 },{"toggle-selection":2}],2:[function(require,module,exports){
-var module = module || {};
 
 module.exports = function () {
   var selection = document.getSelection();
diff --git a/nightwatch.json b/nightwatch.json
deleted file mode 100644
index e343394..0000000
--- a/nightwatch.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
-  "src_folders" : ["tests"],
-  "output_folder" : "reports",
-  "page_objects_path": "e2e_helpers/pages",
-  "custom_commands_path" : "e2e_helpers/commands",
-  "custom_assertions_path" : "e2e_helpers/assertions",
-  "globals_path" : "e2e_helpers/globals.js",
-  "selenium" : {
-    "start_process" : true,
-    "server_path" : "./node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.53.0.jar",
-    "log_path" : "",
-    "host" : "127.0.0.1",
-    "port" : 4444,
-    "cli_args" : {
-      "webdriver.chrome.driver" : "",
-      "webdriver.ie.driver" : ""
-    }
-  },
-  "test_settings" : {
-    "default" : {
-      "launch_url" : "http://localhost:8080",
-      "selenium_port"  : 4444,
-      "selenium_host"  : "localhost",
-      "silent": true,
-      "screenshots" : {
-        "enabled" : true,
-        "path" : "reports"
-      }
-    },
-    "saucelabs" : {
-      "selenium_host": "ondemand.saucelabs.com",
-      "selenium_port": 80,
-      "username" : "${SAUCE_USERNAME}",
-      "access_key" : "${SAUCE_ACCESS_KEY}",
-      "desiredCapabilities": {
-        "name": "test-firefox",
-        "browserName": "${E2E_BROWSER_VENDOR}",
-        "platform": "${E2E_PLATFORM}",
-        "version": "${E2E_BROWSER_VERSION}",
-        "tunnel-identifier": "${TRAVIS_JOB_NUMBER}"
-      }
-    }
-  }
-}
diff --git a/package.json b/package.json
index fdb25f5..0c836a6 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
   "types": "index.d.ts",
   "scripts": {
     "pretest": "browserify ./index.js -o ./example/index.js --standalone copyToClipboard",
-    "test": "nightwatch"
+    "test": "ava"
   },
   "keywords": [
     "clipboard",
@@ -32,9 +32,9 @@
     "example": "example"
   },
   "devDependencies": {
+    "ava": "^0.24.0",
     "browserify": "^13.0.1",
-    "nightwatch": "^0.9.1",
-    "node-static": "^0.7.7",
-    "selenium-server-standalone-jar": "2.53.0"
+    "clipboardy": "^1.2.2",
+    "puppeteer": "^0.13.0"
   }
 }
diff --git a/test/_open-page.js b/test/_open-page.js
new file mode 100644
index 0000000..39396e9
--- /dev/null
+++ b/test/_open-page.js
@@ -0,0 +1,13 @@
+const puppeteer = require('puppeteer');
+const path = require('path');
+
+let browser;
+
+module.exports = async () => {
+  if(!browser) {
+    browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--allow-no-sandbox-job'] });
+  }
+  let page = await browser.newPage();
+  await page.goto(`file://${path.resolve(__dirname, '../example/index.html')}`);
+  return page;
+}
diff --git a/test/index.js b/test/index.js
new file mode 100644
index 0000000..a930f31
--- /dev/null
+++ b/test/index.js
@@ -0,0 +1,26 @@
+const openPage = require('./_open-page');
+const test = require('ava').serial;
+const clipboardy = require('clipboardy');
+
+test('Sanity check', async t => {
+  let page = await openPage();
+  t.is(await page.$eval('[data-test="heading"]', el => el.innerText), 'copy-to-clipboard Repo');
+});
+
+test('Basic Text Copy', async t => {
+  let page = await openPage();
+  await page.click('[data-test="init-basic-text"]');
+  t.is(await clipboardy.read(), "Hello, I'm new content from your clipboard");
+});
+
+test('Multiline Text Copy', async t => {
+  let page = await openPage();
+  await page.click('[data-test="init-multiline-text"]');
+  t.is(await clipboardy.read(), "This would be\nsome multiline text\nfor us to copy");
+});
+
+test('Text w/ Markup Copy', async t => {
+  let page = await openPage();
+  await page.click('[data-test="init-markup-text"]');
+  t.is(await clipboardy.read(), "<script>\n  alert\('this is some script'\)\n</script>");
+});
diff --git a/tests/00_sanity-check.js b/tests/00_sanity-check.js
deleted file mode 100644
index 5d17ef3..0000000
--- a/tests/00_sanity-check.js
+++ /dev/null
@@ -1,17 +0,0 @@
-'use strict';
-module.exports = {
-  'Sanity check' : function (browser) {
-    browser
-      .url(browser.launchUrl)
-      // uncomment for debug purposes
-      // .getLogTypes(function(result) {
-      //   console.log(result);
-      // })
-      // .getLog('browser', function(result) {
-      //   console.log(result);
-      // })
-      .waitForElementVisible('body', 1000)
-      .assert.containsText('[data-test="heading"]', 'copy-to-clipboard Repo')
-      .end();
-  }
-};
diff --git a/tests/01_basic-text.js b/tests/01_basic-text.js
deleted file mode 100644
index c1103cf..0000000
--- a/tests/01_basic-text.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict';
-// is it better to use before/after to reset buffer?
-module.exports = {
-  'Basic Text Copy' : function (browser) {
-    browser
-      .page.helper().resetBuffer()
-      .url(browser.launchUrl)
-      .waitForElementVisible('[data-test="init-basic-text"]', 1000)
-      .click('[data-test="init-basic-text"]')
-      .assert.assertBuffer("Hello, I'm new content from your clipboard")
-      .end();
-  }
-};
diff --git a/tests/02_multiline-text.js b/tests/02_multiline-text.js
deleted file mode 100644
index 0dc1f74..0000000
--- a/tests/02_multiline-text.js
+++ /dev/null
@@ -1,12 +0,0 @@
-'use strict';
-module.exports = {
-  'Multiline Text Copy' : function (browser) {
-    browser
-      .page.helper().resetBuffer()
-      .url(browser.launchUrl)
-      .waitForElementVisible('[data-test="init-multiline-text"]', 1000)
-      .click('[data-test="init-multiline-text"]')
-      .assert.assertBuffer("This would be\nsome multiline text\nfor us to copy")
-      .end();
-  }
-};
diff --git a/tests/03_markup-text.js b/tests/03_markup-text.js
deleted file mode 100644
index 3f2b512..0000000
--- a/tests/03_markup-text.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict';
-module.exports = {
-  'Text w/ Markup Copy' : function (browser) {
-    browser
-      .page.helper().resetBuffer()
-      .url(browser.launchUrl)
-      .waitForElementVisible('[data-test="init-markup-text"]', 1000)
-      .click('[data-test="init-markup-text"]')
-      // using regexp instead of actual match because of chrome issue
-      .assert.assertBuffer(/<script>\n\s+alert\('this is some script'\)\n<\/script>\n*/m)
-      .end();
-  }
-};