Pārlūkot izejas kodu

Set up UI tests

Danilo Bargen 6 gadi atpakaļ
vecāks
revīzija
88f2d71017
8 mainītis faili ar 869 papildinājumiem un 42 dzēšanām
  1. 41 9
      .circleci/config.yml
  2. 10 1
      README.md
  3. 733 21
      package-lock.json
  4. 6 2
      package.json
  5. 2 8
      tests/ui/compose_area.ts
  6. 0 1
      tests/ui/main.ts
  7. 16 0
      tests/ui/run.sh
  8. 61 0
      tests/ui/run.ts

+ 41 - 9
.circleci/config.yml

@@ -1,29 +1,59 @@
 version: 2
 
 references:
-  test-steps: &test-steps
+  unittest-steps: &unittest-steps
     - checkout
     - restore_cache:
         keys:
           - v1-dependencies-{{ .Environment.CIRCLE_JOB }}-{{ arch }}-{{ checksum "package.json" }}
     - run: npm install
     - run: npm run build
-    - run: npm run build:tests
-    - run: npm test
+    - run: npm run build:unittests
+    - run: npm run test:unittests
     - save_cache:
         key: v1-dependencies-{{ .Environment.CIRCLE_JOB }}-{{ arch }}-{{ checksum "package.json" }}
         paths:
           - node_modules
 
 jobs:
-  test-node8:
+  unittest-node8:
     docker:
       - image: circleci/node:8-browsers
-    steps: *test-steps
-  test-node9:
+    steps: *unittest-steps
+  unittest-node9:
     docker:
       - image: circleci/node:9-browsers
-    steps: *test-steps
+    steps: *unittest-steps
+  uitest-firefox:
+    docker:
+      - image: circleci/node:9-browsers
+    steps:
+      - checkout
+      - restore_cache:
+          keys:
+            - v1-dependencies-{{ .Environment.CIRCLE_JOB }}-{{ arch }}-{{ checksum "package.json" }}
+      - run: npm install
+      - run: npm run build:uitests
+      - run: npm run test:uitests firefox:headless
+      - save_cache:
+          key: v1-dependencies-{{ .Environment.CIRCLE_JOB }}-{{ arch }}-{{ checksum "package.json" }}
+          paths:
+            - node_modules
+  uitest-chrome:
+    docker:
+      - image: circleci/node:9-browsers
+    steps:
+      - checkout
+      - restore_cache:
+          keys:
+            - v1-dependencies-{{ .Environment.CIRCLE_JOB }}-{{ arch }}-{{ checksum "package.json" }}
+      - run: npm install
+      - run: npm run build:uitests
+      - run: npm run test:uitests chrome:headless
+      - save_cache:
+          key: v1-dependencies-{{ .Environment.CIRCLE_JOB }}-{{ arch }}-{{ checksum "package.json" }}
+          paths:
+            - node_modules
   lint:
     docker:
       - image: circleci/node:8-browsers
@@ -39,6 +69,8 @@ workflows:
   version: 2
   build:
     jobs:
-      - test-node8
-      - test-node9
+      - unittest-node8
+      - unittest-node9
+      - uitest-firefox
+      - uitest-chrome
       - lint

+ 10 - 1
README.md

@@ -64,11 +64,20 @@ Web on a server, please follow the instructions at
 
 ## Testing
 
-To run tests:
+To run unit tests:
 
     npm run build && npm run build:tests
     firefox tests/testsuite.html
 
+To run UI tests:
+
+    npm run test:unittests <browser>
+
+For example:
+
+    npm run test:unittests firefox
+    npm run test:unittests chromium:headless
+
 To run linting checks:
 
     npm run lint

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 733 - 21
package-lock.json


+ 6 - 2
package.json

@@ -7,13 +7,16 @@
     "build:js": "browserify -p tsify src/app.ts -t [ babelify --presets [ es2015 ] --extensions .ts ] -p [ browserify-header --file header.js ] -o dist/app.js",
     "build:css": "node-sass -o public/css/ --output-style compressed src/sass/",
     "build:css:watch": "node-sass -w -r --source-map true --source-map-embed true -o public/css/ --output-style compressed src/sass/",
-    "build:tests": "npm run build:unittests && npm run build:uitests",
+    "build:tests": "echo -e 'NOTE: Use either \"npm build:unittests\" or \"npm build:uitests\"\n' && exit 1",
     "build:unittests": "browserify -p tsify tests/ts/main.ts -t [ babelify --presets [ es2015 ] --extensions .ts ] -o dist/ts-tests.js",
     "build:uitests": "npm run build:css && browserify -p tsify tests/ui/main.ts -t [ babelify --presets [ es2015 ] --extensions .ts ] -o dist/ui-tests.js",
     "dist": "npm run build && echo \"\" && node dist/build-package.js",
     "serve:live": "echo 'NOTE: serve:live command has been renamed to devserver'",
     "devserver": "npm run build:css && concurrently --kill-others --names \"css,server\" -p name \"npm run build:css:watch\" \"budo src/app.ts:dist/app.js -d public -d . -d src --live -- -d -p tsify -t [ babelify --presets [ es2015 ] --extensions .ts ]\"",
-    "test": "npm run build:tests && karma start --single-run --log-level=debug --colors",
+    "testserver": "budo -d public -d . -d src -p 7777",
+    "test": "echo -e 'NOTE: Use either \"npm test:unittests\" or \"npm test:uitests\"\n' && exit 1",
+    "test:unittests": "npm run build:unittests && karma start --single-run --log-level=debug --colors",
+    "test:uitests": "npm run build:uitests && bash tests/ui/run.sh",
     "lint": "tslint -c tslint.json --project tsconfig.json --exclude \"**/src/config.ts\"",
     "clean": "rm -rf js/ build/ dist/app*"
   },
@@ -79,6 +82,7 @@
     "karma-chrome-launcher": "^2.2.0",
     "karma-firefox-launcher": "^1.1.0",
     "karma-jasmine": "^1.1.2",
+    "testcafe": "^0.23.2",
     "tslint": "~5.10"
   }
 }

+ 2 - 8
tests/ui/compose_area.ts

@@ -54,22 +54,16 @@ export function init() {
                         conf.url.indexOf('directives/') !== -1 ||
                         conf.url.indexOf('components/') !== -1) {
                         conf.url = '../../src/' + conf.url;
-                    } else if (conf.url.indexOf('css/') !== -1 ||
-                        conf.url.indexOf('fonts/') !== -1 ||
-                        conf.url.indexOf('i18n/') !== -1 ||
-                        conf.url.indexOf('img/') !== -1 ||
-                        conf.url.indexOf('libs/') !== -1 ||
-                        conf.url.indexOf('sounds/') !== -1) {
-                        conf.url = '../../public/' + conf.url;
                     }
                     return conf;
                 },
             };
         }]);
     }]);
+
 }
 
-export class ComposeAreaController {
+class ComposeAreaController {
     public static $inject = [];
 
     public initialData: threema.InitialConversationData;

+ 0 - 1
tests/ui/main.ts

@@ -3,7 +3,6 @@
  *
  * This file is part of Threema Web.
  */
-
 import {init as initComposeArea} from './compose_area';
 
 // Expose global functions

+ 16 - 0
tests/ui/run.sh

@@ -0,0 +1,16 @@
+#!/bin/bash
+if [ $# -lt 1 ]; then
+    echo "Error: Please specify a browser target argument"
+    exit 1
+fi
+
+bin_path=node_modules/.bin
+browser=$1
+shift
+
+$bin_path/concurrently \
+    --kill-others \
+    -s first \
+    --names \"server,test\" \
+    "npm run testserver" \
+    "$bin_path/testcafe $browser tests/ui/run.ts $*"

+ 61 - 0
tests/ui/run.ts

@@ -0,0 +1,61 @@
+/**
+ * Copyright © 2016-2018 Threema GmbH (https://threema.ch/).
+ *
+ * This file is part of Threema Web.
+ */
+// tslint:disable:no-unused-expression
+
+import { Selector, ClientFunction } from 'testcafe';
+
+// NOTE: These tests use test cafe.
+// See http://devexpress.github.io/testcafe/documentation/getting-started/ for
+// documentation on how to write UI tests.
+
+fixture `Compose Area`
+    .page `http://localhost:7777/tests/ui/compose_area.html`;
+
+test('Show and hide emoji selector', async (t) => {
+    const keyboard = await Selector('.emoji-keyboard');
+
+    // Not visible initially
+    await t.expect(keyboard.visible).eql(false);
+
+    // Show
+    await t.click('.emoji-trigger');
+
+    // Visible
+    await t.expect(keyboard.visible).eql(true);
+
+    // Hide
+    await t.click('.emoji-trigger');
+
+    // Visible
+    await t.expect(keyboard.visible).eql(false);
+});
+
+test('Insert emoji', async (t) => {
+    // Show emoji keyboard
+    await t.click('.emoji-trigger');
+
+    // Insert woman zombie emoji
+    await t.click('.e1._1f9df-2640');
+
+    // Insert beer
+    await t.click('.e1-food').click('.e1._1f37b');
+
+    // Ensure both have been inserted
+    const getChildNodeCount = await ClientFunction(() => {
+        return document.querySelector('div.compose').childNodes.length;
+    });
+    await t.expect(await getChildNodeCount()).eql(2);
+
+    const firstEmoji = await Selector('div.compose img').nth(0)();
+    await t.expect(firstEmoji.tagName).eql('img');
+    await t.expect(firstEmoji.attributes.title).eql(':woman_zombie:');
+    await t.expect(firstEmoji.classNames).eql(['e1']);
+
+    const secondEmoji = await Selector('div.compose img').nth(1)();
+    await t.expect(secondEmoji.tagName).eql('img');
+    await t.expect(secondEmoji.attributes.title).eql(':beers:');
+    await t.expect(secondEmoji.classNames).eql(['e1']);
+});

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels