diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa07b3c..781afc4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@ CHANGELOG
 =========
 
 ## HEAD (Unreleased)
-_(none)_
+* @gkatsev cleared vttjs script handlers on dispose. Fixed tests ([view](https://github.com/videojs/video.js/pull/3189))
 
 --------------------
 
diff --git a/src/js/tech/tech.js b/src/js/tech/tech.js
index fa3873f..3f9a509 100644
--- a/src/js/tech/tech.js
+++ b/src/js/tech/tech.js
@@ -333,6 +333,10 @@ class Tech extends Component {
       script.onerror = () => {
         this.trigger('vttjserror');
       };
+      this.on('dispose', () => {
+        script.onload = null;
+        script.onerror = null;
+      });
       this.el().parentNode.appendChild(script);
       window['WebVTT'] = true;
     }
diff --git a/test/karma.conf.js b/test/karma.conf.js
index 4032699..a4ec7de 100644
--- a/test/karma.conf.js
+++ b/test/karma.conf.js
@@ -28,6 +28,7 @@ module.exports = function(config) {
 
     browserify: {
       debug: true,
+      plugin: ['proxyquireify/plugin'],
       transform: [
         require('babelify').configure({
           sourceMapRelative: './',
diff --git a/test/unit/tracks/text-track.test.js b/test/unit/tracks/text-track.test.js
index 1875e64..523f949 100644
--- a/test/unit/tracks/text-track.test.js
+++ b/test/unit/tracks/text-track.test.js
@@ -3,6 +3,9 @@ import EventTarget from '../../../src/js/event-target.js';
 import TextTrack from '../../../src/js/tracks/text-track.js';
 import TestHelpers from '../test-helpers.js';
 import log from '../../../src/js/utils/log.js';
+import proxyquireify from 'proxyquireify';
+
+const proxyquire = proxyquireify(require);
 
 const defaultTech = {
   textTracks() {},
@@ -276,20 +279,26 @@ test('tracks are parsed if vttjs is loaded', function() {
     };
   };
 
-  let xhr;
-  window.xhr.onCreate = (newXhr) => xhr = newXhr;
+  // use proxyquire to stub xhr module because IE8s XDomainRequest usage
+  let xhrHandler;
+  let TextTrack = proxyquire('../../../src/js/tracks/text-track.js', {
+    xhr(options, fn) {
+      xhrHandler  = fn;
+    }
+  });
 
   let tt = new TextTrack({
     tech: defaultTech,
     src: 'http://example.com'
   });
 
-  xhr.respond(200, {}, 'WebVTT\n');
+  xhrHandler(null, {}, 'WEBVTT\n');
 
   ok(parserCreated, 'WebVTT is loaded, so we can just parse');
 
   clock.restore();
   window.WebVTT = oldVTT;
+  TextTrack = proxyquire('../../../src/js/tracks/text-track.js', {});
 });
 
 test('tracks are parsed once vttjs is loaded', function() {
@@ -297,10 +306,15 @@ test('tracks are parsed once vttjs is loaded', function() {
   const oldVTT = window.WebVTT;
   let parserCreated = false;
 
-  window.WebVTT = true;
+  // use proxyquire to stub xhr module because IE8s XDomainRequest usage
+  let xhrHandler;
+  let TextTrack = proxyquire('../../../src/js/tracks/text-track.js', {
+    xhr(options, fn) {
+      xhrHandler  = fn;
+    }
+  });
 
-  let xhr;
-  window.xhr.onCreate = (newXhr) => xhr = newXhr;
+  window.WebVTT = true;
 
   let testTech = new EventTarget();
   testTech.textTracks = () => {};
@@ -311,7 +325,7 @@ test('tracks are parsed once vttjs is loaded', function() {
     src: 'http://example.com'
   });
 
-  xhr.respond(200, {}, 'WebVTT\n');
+  xhrHandler(null, {}, 'WEBVTT\n');
 
   ok(!parserCreated, 'WebVTT is not loaded, do not try to parse yet');
 
@@ -336,18 +350,28 @@ test('tracks are parsed once vttjs is loaded', function() {
 
   clock.restore();
   window.WebVTT = oldVTT;
+  TextTrack = proxyquire('../../../src/js/tracks/text-track.js', {});
 });
 
 test('stops processing if vttjs loading errored out', function() {
   const clock = sinon.useFakeTimers();
-  sinon.stub(log, 'error');
   const oldVTT = window.WebVTT;
   let parserCreated = false;
-
   window.WebVTT = true;
 
-  let xhr;
-  window.xhr.onCreate = (newXhr) => xhr = newXhr;
+  // use proxyquire to stub xhr module because IE8s XDomainRequest usage
+  let xhrHandler;
+  let errorMsg;
+  let TextTrack = proxyquire('../../../src/js/tracks/text-track.js', {
+    xhr(options, fn) {
+      xhrHandler  = fn;
+    },
+    '../utils/log.js': {
+      error(msg) {
+        errorMsg = msg;
+      }
+    }
+  });
 
   let testTech = new EventTarget();
   testTech.textTracks = () => {};
@@ -361,20 +385,19 @@ test('stops processing if vttjs loading errored out', function() {
     src: 'http://example.com'
   });
 
-  xhr.respond(200, {}, 'WebVTT\n');
+  xhrHandler(null, {}, 'WEBVTT\n');
 
   ok(!parserCreated, 'WebVTT is not loaded, do not try to parse yet');
 
   testTech.trigger('vttjserror');
-  let errorSpyCall = log.error.getCall(0);
   let offSpyCall = testTech.off.getCall(0);
 
-  ok(errorSpyCall.calledWithMatch('vttjs failed to load, stopping trying to process'),
+  ok(/^vttjs failed to load, stopping trying to process/.test(errorMsg),
      'vttjs failed to load, so, we logged an error');
   ok(!parserCreated, 'WebVTT is not loaded, do not try to parse yet');
   ok(offSpyCall, 'tech.off was called');
 
   clock.restore();
-  log.error.restore();
   window.WebVTT = oldVTT;
+  TextTrack = proxyquire('../../../src/js/tracks/text-track.js', {});
 });
