Add build/test coverage for DDC & friends. (#63)

diff --git a/.travis.yml b/.travis.yml
index 4f9b88c..a784107 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,19 +1,53 @@
 language: dart
-sudo: false
-dart:
-  - dev
-  - 2.0.0-dev.23.0
-addons:
-  # otherwise a number of tests in test/security/html_sanitizer_test.dart fail
-  firefox: "latest"
-dart_task:
-  - dartanalyzer: --fatal-warnings .
-  - dartfmt
-  - test: --platform vm
-  # Disable parallelism on Firefox (-j 1)
-  # Causes flakiness – need to investigate
-  - test: --platform firefox -j 1
 
+# Gives more resources on Travis (8GB Ram, 2 CPUs).
+# Do not remove without verifying w/ Travis.
+sudo: required
+addons:
+  chrome: stable
+
+# Build stages: https://docs.travis-ci.com/user/build-stages/.
+stages:
+  - presubmit
+  - build
+  - testing
+
+# 1. Run dartfmt, dartanalyzer, pub run test (VM).
+# 2. Then run a build.
+# 3. Then run tests compiled via dartdevc and dart2js.
+jobs:
+  include:
+    - stage: presubmit
+      script: ./tool/travis.sh dartfmt
+      dart: dev
+    - stage: presubmit
+      script: ./tool/travis.sh dartanalyzer
+      dart: dev
+    - stage: build
+      script: ./tool/travis.sh dartdevc_build
+      dart: dev
+    - stage: testing
+      script: ./tool/travis.sh vm_test
+      dart: dev
+    - stage: testing
+      script: ./tool/travis.sh dartdevc_test
+      dart: dev
+    - stage: testing
+      script: ./tool/travis.sh dart2js_test
+      dart: dev
+
+# Only building master means that we don't run two builds for each pull request.
+branches:
+  only: [master]
+
+# Incremental pub cache and builds.
 cache:
   directories:
     - $HOME/.pub-cache
+    - .dart_tool
+
+# Necessary for Chrome and Firefox to run
+before_install:
+ - export DISPLAY=:99.0
+ - sh -e /etc/init.d/xvfb start
+ - "t=0; until (xdpyinfo -display :99 &> /dev/null || test $t -gt 10); do sleep 1; let t=$t+1; done"
diff --git a/dart_test.yaml b/dart_test.yaml
new file mode 100644
index 0000000..d2b9d1d
--- /dev/null
+++ b/dart_test.yaml
@@ -0,0 +1,22 @@
+presets:
+  # When run with -P travis, we have different settings/options.
+  #
+  # 1: We don't use Chrome --headless:
+  # 2: We use --reporter expanded
+  # 3: We skip anything tagged "fails-on-travis".
+  travis:
+    # TODO(https://github.com/dart-lang/test/issues/772)
+    override_platforms:
+      chrome:
+        settings:
+          headless: false
+
+    # Don't run any tests that are tagged ["fails-on-travis"].
+    exclude_tags: "fails-on-travis"
+
+    # https://github.com/dart-lang/test/blob/master/doc/configuration.md#reporter
+    reporter: expanded
+
+platforms:
+  - chrome
+  - vm
diff --git a/pubspec.yaml b/pubspec.yaml
index cf97a32..7241145 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -12,4 +12,7 @@
   quiver: '>=0.24.0 <0.29.0'
 dev_dependencies:
   dart_style: '^1.0.9'
-  test: '^0.12.0'
+  build_runner: ^0.7.11
+  build_test: ^0.10.0
+  build_web_compilers: ^0.3.1
+  test: ^0.12.0
diff --git a/test/list_change_test.dart b/test/list_change_test.dart
index 8560688..858b27b 100644
--- a/test/list_change_test.dart
+++ b/test/list_change_test.dart
@@ -90,7 +90,7 @@
     });
 
     test('Delete Empty', () {
-      var model = toObservable([1]);
+      var model = toObservable(<dynamic>[1]);
       var copy = model.toList();
       var changes = model.listChanges.first;
 
diff --git a/tool/travis.sh b/tool/travis.sh
new file mode 100755
index 0000000..0e584b9
--- /dev/null
+++ b/tool/travis.sh
@@ -0,0 +1,65 @@
+# Copyright 2018 the Dart project authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/bash
+
+if [ "$#" == "0" ]; then
+  echo -e '\033[31mAt least one task argument must be provided!\033[0m'
+  exit 1
+fi
+
+EXIT_CODE=0
+
+while (( "$#" )); do
+  TASK=$1
+  case $TASK in
+  dartfmt) echo
+    echo -e '\033[1mTASK: dartfmt\033[22m'
+    echo -e 'dartfmt -n --set-exit-if-changed .'
+    dartfmt -n --set-exit-if-changed . || EXIT_CODE=$?
+    ;;
+  dartanalyzer) echo
+    echo -e '\033[1mTASK: dartanalyzer\033[22m'
+    echo -e 'dartanalyzer --fatal-warnings .'
+    dartanalyzer --fatal-warnings . || EXIT_CODE=$?
+    ;;
+  vm_test) echo
+    echo -e '\033[1mTASK: vm_test\033[22m'
+    echo -e 'pub run test -P travis -p vm -x requires-dart2'
+    pub run test -p vm || EXIT_CODE=$?
+    ;;
+  dartdevc_build) echo
+    echo -e '\033[1mTASK: build\033[22m'
+    echo -e 'pub run build_runner build --fail-on-severe'
+    pub run build_runner build --fail-on-severe || EXIT_CODE=$?
+    ;;
+  dartdevc_test) echo
+    echo -e '\033[1mTASK: dartdevc_test\033[22m'
+    echo -e 'pub run build_runner test -- -P travis -p chrome'
+    pub run build_runner test -- -p chrome || EXIT_CODE=$?
+    ;;
+  dart2js_test) echo
+    echo -e '\033[1mTASK: dart2js_test\033[22m'
+    echo -e 'pub run test -P travis -p chrome -x requires-dart2'
+    pub run test -p chrome || EXIT_CODE=$?
+    ;;
+  *) echo -e "\033[31mNot expecting TASK '${TASK}'. Error!\033[0m"
+    EXIT_CODE=1
+    ;;
+  esac
+
+  shift
+done
+
+exit $EXIT_CODE