[debugger-app] Add frontend code and tests to the Infra-PerCommit-* tryjobs.

Infra-PerCommit-Build:
  Will build debugger-app with "npx webpack --mode=production".

Infra-PerCommit-Medium:
  Will run Karma tests with "npx karma start".

Infra-PerCommit-Puppeteer:
  Will run any Puppeteer tests and upload screenshots to Gold.

Note: File package.json has been updated with a missing dependency. Do not forget to run "npm ci" from //debugger-app after this CL lands.

Change-Id: I499756f04b60307529081e60a8b5801cbf03bd55
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/324256
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Leandro Lovisolo <lovisolo@google.com>
Auto-Submit: Leandro Lovisolo <lovisolo@google.com>
diff --git a/Makefile b/Makefile
index be7c2ae..c4fcf7a 100644
--- a/Makefile
+++ b/Makefile
@@ -99,6 +99,7 @@
 	# Other apps can be built in alphabetical order.
 	cd am && $(MAKE) build-frontend-ci
 	cd ct && $(MAKE) build-frontend-ci
+	cd debugger-app && $(MAKE) build-frontend-ci
 	cd golden && $(MAKE) build-frontend-ci
 	cd hashtag && $(MAKE) build-frontend-ci
 	cd leasing && $(MAKE) build-frontend-ci
@@ -144,6 +145,7 @@
 	# Other apps can be tested in alphabetical order.
 	cd am && $(MAKE) test-frontend-ci
 	cd ct && $(MAKE) test-frontend-ci
+	cd debugger-app && $(MAKE) test-frontend-ci
 	cd demos && $(MAKE) test-frontend-ci
 	cd golden && $(MAKE) test-frontend-ci
 	cd machine && $(MAKE) test-frontend-ci
diff --git a/debugger-app/Makefile b/debugger-app/Makefile
index ffff64b..9b9c0e7 100644
--- a/debugger-app/Makefile
+++ b/debugger-app/Makefile
@@ -1,5 +1,8 @@
 KGO := CGO_ENABLED=0 GOOS=linux go build
 
+node_modules: package.json
+	npm ci
+
 .PHONY: test
 test: go-test js-test
 	true
@@ -16,9 +19,24 @@
 js-test-debug:
 	npx karma start --no-single-run
 
-node_modules: package.json
-	npm ci
+.PHONY: puppeteer-test
+puppeteer-test:
+	NODE_OPTIONS="--max-old-space-size=$(NODE_MEMORY_LIMIT)" npx mocha -r ts-node/register ./**/*_puppeteer_test.ts
+
+.PHONY: puppeteer-test-debug
+puppeteer-test-debug:
+	NODE_OPTIONS="--max-old-space-size=$(NODE_MEMORY_LIMIT)" npx mocha -r ts-node/register ./**/*_puppeteer_test.ts --inspect-brk
 
 .PHONY: serve
 serve:
-	npx webpack-dev-server --watch-poll --mode=development
\ No newline at end of file
+	npx webpack-dev-server --watch-poll --mode=development
+
+.PHONY: build-frontend-ci
+build-frontend-ci:
+	npm ci
+	npx webpack --mode=production
+
+.PHONY: test-frontend-ci
+test-frontend-ci:
+	npm ci
+	xvfb-run --auto-servernum --server-args "-screen 0 1280x1024x24" npx karma start --single-run
diff --git a/debugger-app/package-lock.json b/debugger-app/package-lock.json
index 9b53f10..ee9e871 100644
--- a/debugger-app/package-lock.json
+++ b/debugger-app/package-lock.json
@@ -62,12 +62,6 @@
       "integrity": "sha512-aN5IAC8QNtSUdQzxu7lGBgYAOuU1tmRU4c9dIq5OKGf/SBVjXo+ffM2wEjudAWbgpOhy60nLoAGH1xm8fpCKFQ==",
       "dev": true
     },
-    "@types/clone": {
-      "version": "0.1.30",
-      "resolved": "https://registry.npmjs.org/@types/clone/-/clone-0.1.30.tgz",
-      "integrity": "sha1-5zZWSMG0ITalnH1QQGN7O1yDthQ=",
-      "dev": true
-    },
     "@types/connect": {
       "version": "3.4.33",
       "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
@@ -191,23 +185,6 @@
       "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==",
       "dev": true
     },
-    "@types/parse5": {
-      "version": "0.0.31",
-      "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-0.0.31.tgz",
-      "integrity": "sha1-6Cekk6RDsVbhtYKi5MO9wAQPLuc=",
-      "dev": true,
-      "requires": {
-        "@types/node": "6.0.*"
-      },
-      "dependencies": {
-        "@types/node": {
-          "version": "6.0.118",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.118.tgz",
-          "integrity": "sha512-N33cKXGSqhOYaPiT4xUGsYlPPDwFtQM/6QxJxuMXA/7BcySW+lkn2yigWP7vfs4daiL/7NJNU6DMCqg5N4B+xQ==",
-          "dev": true
-        }
-      }
-    },
     "@types/qs": {
       "version": "6.9.5",
       "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz",
@@ -505,21 +482,6 @@
         "negotiator": "0.6.2"
       }
     },
-    "acorn": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-      "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
-      "dev": true
-    },
-    "acorn-jsx": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
-      "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
-      "dev": true,
-      "requires": {
-        "acorn": "^3.0.4"
-      }
-    },
     "after": {
       "version": "0.8.2",
       "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
@@ -1102,12 +1064,6 @@
         "multicast-dns-service-types": "^1.1.0"
       }
     },
-    "bower": {
-      "version": "1.8.8",
-      "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.8.tgz",
-      "integrity": "sha512-1SrJnXnkP9soITHptSO+ahx3QKp3cVzn8poI6ujqc5SeOkg5iqM1pK9H+DSc2OQ8SnO0jC/NG4Ur/UIwy7574A==",
-      "dev": true
-    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1617,12 +1573,6 @@
         "source-map": "~0.6.0"
       }
     },
-    "clone": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
-      "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
-      "dev": true
-    },
     "clone-deep": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@@ -1763,32 +1713,6 @@
         "typedarray": "^0.0.6"
       }
     },
-    "configstore": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/configstore/-/configstore-1.4.0.tgz",
-      "integrity": "sha1-w1eB0FAdJowlxUuLF/YkDopPsCE=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "graceful-fs": "^4.1.2",
-        "mkdirp": "^0.5.0",
-        "object-assign": "^4.0.1",
-        "os-tmpdir": "^1.0.0",
-        "osenv": "^0.1.0",
-        "uuid": "^2.0.1",
-        "write-file-atomic": "^1.1.2",
-        "xdg-basedir": "^2.0.0"
-      },
-      "dependencies": {
-        "uuid": {
-          "version": "2.0.3",
-          "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
-          "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
     "connect": {
       "version": "3.7.0",
       "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
@@ -2317,19 +2241,6 @@
         "regexp.prototype.flags": "^1.2.0"
       }
     },
-    "deep-extend": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
-      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
-      "dev": true,
-      "optional": true
-    },
-    "deep-is": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
-      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
-      "dev": true
-    },
     "default-gateway": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz",
@@ -2544,24 +2455,6 @@
         "buffer-indexof": "^1.0.0"
       }
     },
-    "doctrine": {
-      "version": "0.7.2",
-      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz",
-      "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=",
-      "dev": true,
-      "requires": {
-        "esutils": "^1.1.6",
-        "isarray": "0.0.1"
-      },
-      "dependencies": {
-        "isarray": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
-          "dev": true
-        }
-      }
-    },
     "dom-serialize": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz",
@@ -2574,27 +2467,6 @@
         "void-elements": "^2.0.0"
       }
     },
-    "dom5": {
-      "version": "1.3.6",
-      "resolved": "https://registry.npmjs.org/dom5/-/dom5-1.3.6.tgz",
-      "integrity": "sha1-pwiKn8XzsI3J9u2kx6uuskGUXg0=",
-      "dev": true,
-      "requires": {
-        "@types/clone": "^0.1.29",
-        "@types/node": "^4.0.30",
-        "@types/parse5": "^0.0.31",
-        "clone": "^1.0.2",
-        "parse5": "^1.4.1"
-      },
-      "dependencies": {
-        "@types/node": {
-          "version": "4.9.4",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-4.9.4.tgz",
-          "integrity": "sha512-nKoiCZ87x6+fs26bNHjy07AQt6f46nFEitGH0P9JmWbY6tEyum6LLfLf7SIsKFh4DnBWsyUM2gYhaQAt+aA0Sw==",
-          "dev": true
-        }
-      }
-    },
     "domain-browser": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
@@ -2921,39 +2793,6 @@
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
       "dev": true
     },
-    "escodegen": {
-      "version": "1.14.3",
-      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
-      "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
-      "dev": true,
-      "requires": {
-        "esprima": "^4.0.1",
-        "estraverse": "^4.2.0",
-        "esutils": "^2.0.2",
-        "optionator": "^0.8.1",
-        "source-map": "~0.6.1"
-      },
-      "dependencies": {
-        "esprima": {
-          "version": "4.0.1",
-          "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-          "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-          "dev": true
-        },
-        "estraverse": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
-          "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
-          "dev": true
-        },
-        "esutils": {
-          "version": "2.0.3",
-          "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-          "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-          "dev": true
-        }
-      }
-    },
     "eslint-scope": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
@@ -2972,24 +2811,6 @@
         }
       }
     },
-    "espree": {
-      "version": "3.5.4",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
-      "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
-      "dev": true,
-      "requires": {
-        "acorn": "^5.5.0",
-        "acorn-jsx": "^3.0.0"
-      },
-      "dependencies": {
-        "acorn": {
-          "version": "5.7.4",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz",
-          "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==",
-          "dev": true
-        }
-      }
-    },
     "esprima": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
@@ -3013,18 +2834,6 @@
         }
       }
     },
-    "estraverse": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-3.1.0.tgz",
-      "integrity": "sha1-FeKKRGuLgrxwDMyLlseK9NoNbLo=",
-      "dev": true
-    },
-    "esutils": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz",
-      "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=",
-      "dev": true
-    },
     "etag": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -3289,12 +3098,6 @@
       "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
       "dev": true
     },
-    "fast-levenshtein": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
-      "dev": true
-    },
     "fastparse": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
@@ -3753,34 +3556,6 @@
         "minimatch": "~3.0.2"
       }
     },
-    "got": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/got/-/got-3.3.1.tgz",
-      "integrity": "sha1-5dDtSvVfw+701WAHdp2YGSvLLso=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "duplexify": "^3.2.0",
-        "infinity-agent": "^2.0.0",
-        "is-redirect": "^1.0.0",
-        "is-stream": "^1.0.0",
-        "lowercase-keys": "^1.0.0",
-        "nested-error-stacks": "^1.0.0",
-        "object-assign": "^3.0.0",
-        "prepend-http": "^1.0.0",
-        "read-all-stream": "^3.0.0",
-        "timed-out": "^2.0.0"
-      },
-      "dependencies": {
-        "object-assign": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
-          "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
     "graceful-fs": {
       "version": "4.2.4",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
@@ -4285,33 +4060,6 @@
         }
       }
     },
-    "hydrolysis": {
-      "version": "1.25.0",
-      "resolved": "https://registry.npmjs.org/hydrolysis/-/hydrolysis-1.25.0.tgz",
-      "integrity": "sha1-pPsUo3oeA7DbUtiqpXxoInKhTYQ=",
-      "dev": true,
-      "requires": {
-        "acorn": "^3.2.0",
-        "babel-polyfill": "^6.2.0",
-        "doctrine": "^0.7.0",
-        "dom5": "1.1.0",
-        "escodegen": "^1.7.0",
-        "espree": "^3.1.3",
-        "estraverse": "^3.1.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "dependencies": {
-        "dom5": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/dom5/-/dom5-1.1.0.tgz",
-          "integrity": "sha1-Ogx3AMCDq0xNJpOKeLDwxtzDd5Q=",
-          "dev": true,
-          "requires": {
-            "parse5": "^1.4.1"
-          }
-        }
-      }
-    },
     "iconv-lite": {
       "version": "0.4.24",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -4419,13 +4167,6 @@
       "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
       "dev": true
     },
-    "infinity-agent": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/infinity-agent/-/infinity-agent-2.0.3.tgz",
-      "integrity": "sha1-ReDi/3qesDCyfWK3SzdEt6esQhY=",
-      "dev": true,
-      "optional": true
-    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -4646,13 +4387,6 @@
       "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=",
       "dev": true
     },
-    "is-npm": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
-      "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=",
-      "dev": true,
-      "optional": true
-    },
     "is-number": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -4712,13 +4446,6 @@
         "isobject": "^3.0.1"
       }
     },
-    "is-redirect": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
-      "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=",
-      "dev": true,
-      "optional": true
-    },
     "is-regex": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
@@ -5154,32 +4881,12 @@
       "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
       "dev": true
     },
-    "latest-version": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-1.0.1.tgz",
-      "integrity": "sha1-cs/Ebj6NG+ZR4eu1Tqn26pbzdLs=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "package-json": "^1.0.0"
-      }
-    },
     "lazy-cache": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
       "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
       "dev": true
     },
-    "levn": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
-      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "~1.1.2",
-        "type-check": "~0.3.2"
-      }
-    },
     "lit-html": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.3.0.tgz",
@@ -5336,13 +5043,6 @@
         "lower-case": "^1.1.2"
       }
     },
-    "lowercase-keys": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
-      "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
-      "dev": true,
-      "optional": true
-    },
     "lru-cache": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -5856,12 +5556,6 @@
         "to-regex": "^3.0.1"
       }
     },
-    "native-promise-only": {
-      "version": "0.7.6-a",
-      "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.7.6-a.tgz",
-      "integrity": "sha1-skvQRRQJzDRA91W/QNJAKHkgaNA=",
-      "dev": true
-    },
     "ncname": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz",
@@ -5883,16 +5577,6 @@
       "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
       "dev": true
     },
-    "nested-error-stacks": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-1.0.2.tgz",
-      "integrity": "sha1-GfYZWRUZ8JZ2mlupqG5u7sgjw88=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "inherits": "~2.0.1"
-      }
-    },
     "nice-try": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@@ -6403,20 +6087,6 @@
         }
       }
     },
-    "optionator": {
-      "version": "0.8.3",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
-      "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
-      "dev": true,
-      "requires": {
-        "deep-is": "~0.1.3",
-        "fast-levenshtein": "~2.0.6",
-        "levn": "~0.3.0",
-        "prelude-ls": "~1.1.2",
-        "type-check": "~0.3.2",
-        "word-wrap": "~1.2.3"
-      }
-    },
     "original": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
@@ -6499,17 +6169,6 @@
       "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
       "dev": true
     },
-    "package-json": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/package-json/-/package-json-1.2.0.tgz",
-      "integrity": "sha1-yOysCUInzfdqMWh07QXifMk5oOA=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "got": "^3.2.0",
-        "registry-url": "^3.0.0"
-      }
-    },
     "pako": {
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@@ -6565,12 +6224,6 @@
       "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
       "dev": true
     },
-    "parse5": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz",
-      "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=",
-      "dev": true
-    },
     "parseqs": {
       "version": "0.0.5",
       "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
@@ -6910,12 +6563,6 @@
       "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
       "dev": true
     },
-    "prelude-ls": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
-      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
-      "dev": true
-    },
     "prepend-http": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
@@ -7171,30 +6818,6 @@
         }
       }
     },
-    "rc": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
-      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "deep-extend": "^0.6.0",
-        "ini": "~1.3.0",
-        "minimist": "^1.2.0",
-        "strip-json-comments": "~2.0.1"
-      }
-    },
-    "read-all-stream": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz",
-      "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "pinkie-promise": "^2.0.0",
-        "readable-stream": "^2.0.0"
-      }
-    },
     "read-pkg": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
@@ -7338,16 +6961,6 @@
         "es-abstract": "^1.17.0-next.1"
       }
     },
-    "registry-url": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
-      "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "rc": "^1.0.1"
-      }
-    },
     "relateurl": {
       "version": "0.2.7",
       "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
@@ -7734,16 +7347,6 @@
       "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
       "dev": true
     },
-    "semver-diff": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
-      "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "semver": "^5.0.3"
-      }
-    },
     "send": {
       "version": "0.17.1",
       "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
@@ -7952,13 +7555,6 @@
         }
       }
     },
-    "slide": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
-      "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=",
-      "dev": true,
-      "optional": true
-    },
     "snake-case": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz",
@@ -8542,35 +8138,6 @@
       "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
       "dev": true
     },
-    "string-length": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz",
-      "integrity": "sha1-VpcPscOFWOnnC3KL894mmsRa36w=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "strip-ansi": "^3.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-          "dev": true,
-          "optional": true
-        },
-        "strip-ansi": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-regex": "^2.0.0"
-          }
-        }
-      }
-    },
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -8743,13 +8310,6 @@
       "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
       "dev": true
     },
-    "timed-out": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz",
-      "integrity": "sha1-84sK6B03R9YoAB9B2vxlKs5nHAo=",
-      "dev": true,
-      "optional": true
-    },
     "timers-browserify": {
       "version": "2.0.11",
       "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz",
@@ -8984,15 +8544,6 @@
       "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
       "dev": true
     },
-    "type-check": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
-      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "~1.1.2"
-      }
-    },
     "type-detect": {
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
@@ -9175,79 +8726,6 @@
       "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
       "dev": true
     },
-    "update-notifier": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-0.5.0.tgz",
-      "integrity": "sha1-B7XcIGazYnqztPUwEw9+3doHpMw=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "chalk": "^1.0.0",
-        "configstore": "^1.0.0",
-        "is-npm": "^1.0.0",
-        "latest-version": "^1.0.0",
-        "repeating": "^1.1.2",
-        "semver-diff": "^2.0.0",
-        "string-length": "^1.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-          "dev": true,
-          "optional": true
-        },
-        "ansi-styles": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-          "dev": true,
-          "optional": true
-        },
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^2.2.1",
-            "escape-string-regexp": "^1.0.2",
-            "has-ansi": "^2.0.0",
-            "strip-ansi": "^3.0.0",
-            "supports-color": "^2.0.0"
-          }
-        },
-        "repeating": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz",
-          "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "is-finite": "^1.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-regex": "^2.0.0"
-          }
-        },
-        "supports-color": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
     "upper-case": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
@@ -9420,27 +8898,6 @@
       "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
       "dev": true
     },
-    "vulcanize": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/vulcanize/-/vulcanize-1.5.1.tgz",
-      "integrity": "sha1-m/OcFSV61iEiC85UErRUIbGnK6g=",
-      "dev": true,
-      "requires": {
-        "dom5": "^1.0.2",
-        "es6-promise": "^2.1.0",
-        "hydrolysis": "^1.5.0",
-        "nopt": "^3.0.1",
-        "update-notifier": "^0.5.0"
-      },
-      "dependencies": {
-        "es6-promise": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz",
-          "integrity": "sha1-lu258v2wGZWCKyY92KratnSBgbw=",
-          "dev": true
-        }
-      }
-    },
     "watchpack": {
       "version": "1.7.4",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz",
@@ -10037,12 +9494,6 @@
       "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
       "dev": true
     },
-    "word-wrap": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
-      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
-      "dev": true
-    },
     "wordwrap": {
       "version": "0.0.2",
       "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
@@ -10064,18 +9515,6 @@
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
       "dev": true
     },
-    "write-file-atomic": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz",
-      "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "graceful-fs": "^4.1.11",
-        "imurmurhash": "^0.1.4",
-        "slide": "^1.1.5"
-      }
-    },
     "ws": {
       "version": "6.2.1",
       "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
@@ -10085,16 +9524,6 @@
         "async-limiter": "~1.0.0"
       }
     },
-    "xdg-basedir": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz",
-      "integrity": "sha1-7byQPMOF/ARSPZZqM1UEtVBNG9I=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "os-homedir": "^1.0.0"
-      }
-    },
     "xml-char-classes": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz",
diff --git a/debugger-app/package.json b/debugger-app/package.json
index 244731b..4e316b8 100644
--- a/debugger-app/package.json
+++ b/debugger-app/package.json
@@ -31,6 +31,7 @@
     "karma-chrome-launcher": "~3.1.0",
     "karma-firefox-launcher": "~1.2.0",
     "karma-mocha": "~1.3.0",
+    "karma-sinon": "^1.0.5",
     "karma-webpack": "~4.0.2",
     "mini-css-extract-plugin": "^0.9.0",
     "mocha": "~6.2.0",
diff --git a/puppeteer-tests/docker/run-tests.sh b/puppeteer-tests/docker/run-tests.sh
index 7923aee..caa7d98 100755
--- a/puppeteer-tests/docker/run-tests.sh
+++ b/puppeteer-tests/docker/run-tests.sh
@@ -49,56 +49,56 @@
 # The buildbot repository should be mounted at /src.                           #
 ################################################################################
 
-cp -r /src/.mocharc.json                 /tests
+cp -r /src/.mocharc.json                    /tests
 
 mkdir /tests/infra-sk
-cp -r /src/infra-sk/package*             /tests/infra-sk
-cp -r /src/infra-sk/*.ts                 /tests/infra-sk
-cp -r /src/infra-sk/tsconfig.json        /tests/infra-sk
-cp -r /src/infra-sk/modules              /tests/infra-sk
-cp -r /src/infra-sk/pulito               /tests/infra-sk
+cp -r /src/infra-sk/package*                /tests/infra-sk
+cp -r /src/infra-sk/*.ts                    /tests/infra-sk
+cp -r /src/infra-sk/tsconfig.json           /tests/infra-sk
+cp -r /src/infra-sk/modules                 /tests/infra-sk
+cp -r /src/infra-sk/pulito                  /tests/infra-sk
 
 mkdir /tests/puppeteer-tests
-cp -r /src/puppeteer-tests/package*      /tests/puppeteer-tests
-cp -r /src/puppeteer-tests/*.ts          /tests/puppeteer-tests
-cp -r /src/puppeteer-tests/tsconfig.json /tests/puppeteer-tests
+cp -r /src/puppeteer-tests/package*         /tests/puppeteer-tests
+cp -r /src/puppeteer-tests/*.ts             /tests/puppeteer-tests
+cp -r /src/puppeteer-tests/tsconfig.json    /tests/puppeteer-tests
 
 mkdir /tests/golden
-cp -r /src/golden/package*               /tests/golden
-cp -r /src/golden/webpack.config.ts      /tests/golden
-cp -r /src/golden/tsconfig.json          /tests/golden
-cp -r /src/golden/modules                /tests/golden
-cp -r /src/golden/demo-page-assets       /tests/golden
+cp -r /src/golden/package*                  /tests/golden
+cp -r /src/golden/webpack.config.ts         /tests/golden
+cp -r /src/golden/tsconfig.json             /tests/golden
+cp -r /src/golden/modules                   /tests/golden
+cp -r /src/golden/demo-page-assets          /tests/golden
 
 mkdir /tests/perf
-cp -r /src/perf/package*                 /tests/perf
-cp -r /src/perf/webpack.config.ts        /tests/perf
-cp -r /src/perf/tsconfig.json            /tests/perf
-cp -r /src/perf/modules                  /tests/perf
+cp -r /src/perf/package*                    /tests/perf
+cp -r /src/perf/webpack.config.ts           /tests/perf
+cp -r /src/perf/tsconfig.json               /tests/perf
+cp -r /src/perf/modules                     /tests/perf
 
 mkdir /tests/am
-cp -r /src/am/package*                   /tests/am
-cp -r /src/am/webpack.config.ts          /tests/am
-cp -r /src/am/tsconfig.json              /tests/am
-cp -r /src/am/modules                    /tests/am
+cp -r /src/am/package*                      /tests/am
+cp -r /src/am/webpack.config.ts             /tests/am
+cp -r /src/am/tsconfig.json                 /tests/am
+cp -r /src/am/modules                       /tests/am
 
 mkdir /tests/ct
-cp -r /src/ct/package*                   /tests/ct
-cp -r /src/ct/webpack.config.ts          /tests/ct
-cp -r /src/ct/tsconfig.json              /tests/ct
-cp -r /src/ct/modules                    /tests/ct
+cp -r /src/ct/package*                      /tests/ct
+cp -r /src/ct/webpack.config.ts             /tests/ct
+cp -r /src/ct/tsconfig.json                 /tests/ct
+cp -r /src/ct/modules                       /tests/ct
 
 mkdir /tests/new_element
-cp -r /src/new_element/package*          /tests/new_element
-cp -r /src/new_element/webpack.config.ts /tests/new_element
-cp -r /src/new_element/tsconfig.json     /tests/new_element
-cp -r /src/new_element/modules           /tests/new_element
+cp -r /src/new_element/package*             /tests/new_element
+cp -r /src/new_element/webpack.config.ts    /tests/new_element
+cp -r /src/new_element/tsconfig.json        /tests/new_element
+cp -r /src/new_element/modules              /tests/new_element
 
 mkdir /tests/fiddlek
-cp -r /src/fiddlek/package*              /tests/fiddlek
-cp -r /src/fiddlek/webpack.config.ts     /tests/fiddlek
-cp -r /src/fiddlek/tsconfig.json         /tests/fiddlek
-cp -r /src/fiddlek/modules               /tests/fiddlek
+cp -r /src/fiddlek/package*                 /tests/fiddlek
+cp -r /src/fiddlek/webpack.config.ts        /tests/fiddlek
+cp -r /src/fiddlek/tsconfig.json            /tests/fiddlek
+cp -r /src/fiddlek/modules                  /tests/fiddlek
 
 mkdir /tests/task_scheduler
 cp -r /src/task_scheduler/package*          /tests/task_scheduler
@@ -106,6 +106,12 @@
 cp -r /src/task_scheduler/tsconfig.json     /tests/task_scheduler
 cp -r /src/task_scheduler/modules           /tests/task_scheduler
 
+mkdir /tests/debugger-app
+cp -r /src/debugger-app/package*            /tests/debugger-app
+cp -r /src/debugger-app/webpack.config.ts   /tests/debugger-app
+cp -r /src/debugger-app/tsconfig.json       /tests/debugger-app
+cp -r /src/debugger-app/modules             /tests/debugger-app
+
 ################################################################################
 # Install node modules.                                                        #
 ################################################################################
@@ -137,6 +143,9 @@
 cd /tests/task_scheduler
 npm ci
 
+cd /tests/debugger-app
+npm ci
+
 ################################################################################
 # Run tests.                                                                   #
 ################################################################################
@@ -173,3 +182,6 @@
 
 cd /tests/task_scheduler
 npx mocha -r ts-node/register ./**/*_puppeteer_test.ts
+
+cd /tests/debugger-app
+npx mocha -r ts-node/register ./**/*_puppeteer_test.ts