diff --git a/package.json b/package.json
index bbb8c01d8d3683d141251401fd3ea39b58159da9..ed4d602cfc9b35d5c93d70fe68dbb24af04c95b1 100644
--- a/package.json
+++ b/package.json
@@ -197,7 +197,6 @@
     "aws-sdk-mock": "4.5.0",
     "babel-jest": "24.9.0",
     "babel-plugin-dynamic-import-node": "2.3.0",
-    "chai": "4.2.0",
     "copyfiles": "2.1.1",
     "cross-env": "5.2.1",
     "eslint": "6.4.0",
@@ -256,13 +255,10 @@
       }
     },
     "setupFiles": [
-      "./test/globals.js"
-    ],
-    "setupFilesAfterEnv": [
-      "./test/chai.js"
+      "./test/globals.ts"
     ],
     "snapshotSerializers": [
-      "./test/newline-snapshot-serializer.js"
+      "./test/newline-snapshot-serializer.ts"
     ],
     "transform": {
       "^.+\\.(j|t)s$": "babel-jest"
diff --git a/test/chai.js b/test/chai.js
deleted file mode 100644
index 41e09fc5389f881e86ec4f8b9711cb43f255d111..0000000000000000000000000000000000000000
--- a/test/chai.js
+++ /dev/null
@@ -1 +0,0 @@
-require('chai').should();
diff --git a/test/config/cli.spec.ts b/test/config/cli.spec.ts
index e18b434c26dabc7d0b0e956c9f479f5876e71780..24b4423029d4dc31057fba8be5b091c772fd3ef3 100644
--- a/test/config/cli.spec.ts
+++ b/test/config/cli.spec.ts
@@ -12,29 +12,29 @@ describe('config/cli', () => {
       const option: Partial<RenovateOptions> = {
         name: 'oneTwoThree',
       };
-      cli.getCliName(option).should.eql('--one-two-three');
+      expect(cli.getCliName(option)).toEqual('--one-two-three');
     });
     it('generates returns empty if CLI false', () => {
       const option: Partial<RenovateOptions> = {
         name: 'oneTwoThree',
         cli: false,
       };
-      cli.getCliName(option).should.eql('');
+      expect(cli.getCliName(option)).toEqual('');
     });
   });
   describe('.getConfig(argv)', () => {
     it('returns empty argv', () => {
-      cli.getConfig(argv).should.eql({});
+      expect(cli.getConfig(argv)).toEqual({});
     });
     it('supports boolean no value', () => {
       argv.push('--recreate-closed');
-      cli.getConfig(argv).should.eql({ recreateClosed: true });
+      expect(cli.getConfig(argv)).toEqual({ recreateClosed: true });
       argv = argv.slice(0, -1);
     });
     it('supports boolean space true', () => {
       argv.push('--recreate-closed');
       argv.push('true');
-      cli.getConfig(argv).should.eql({ recreateClosed: true });
+      expect(cli.getConfig(argv)).toEqual({ recreateClosed: true });
     });
     it('throws exception for invalid boolean value', () => {
       argv.push('--recreate-closed');
@@ -48,38 +48,38 @@ describe('config/cli', () => {
     it('supports boolean space false', () => {
       argv.push('--recreate-closed');
       argv.push('false');
-      cli.getConfig(argv).should.eql({ recreateClosed: false });
+      expect(cli.getConfig(argv)).toEqual({ recreateClosed: false });
     });
     it('supports boolean equals true', () => {
       argv.push('--recreate-closed=true');
-      cli.getConfig(argv).should.eql({ recreateClosed: true });
+      expect(cli.getConfig(argv)).toEqual({ recreateClosed: true });
     });
     it('supports boolean equals false', () => {
       argv.push('--recreate-closed=false');
-      cli.getConfig(argv).should.eql({ recreateClosed: false });
+      expect(cli.getConfig(argv)).toEqual({ recreateClosed: false });
     });
     it('supports list single', () => {
       argv.push('--labels=a');
-      cli.getConfig(argv).should.eql({ labels: ['a'] });
+      expect(cli.getConfig(argv)).toEqual({ labels: ['a'] });
     });
     it('supports list multiple', () => {
       argv.push('--labels=a,b,c');
-      cli.getConfig(argv).should.eql({ labels: ['a', 'b', 'c'] });
+      expect(cli.getConfig(argv)).toEqual({ labels: ['a', 'b', 'c'] });
     });
     it('supports string', () => {
       argv.push('--token=a');
-      cli.getConfig(argv).should.eql({ token: 'a' });
+      expect(cli.getConfig(argv)).toEqual({ token: 'a' });
     });
     it('supports repositories', () => {
       argv.push('foo');
       argv.push('bar');
-      cli.getConfig(argv).should.eql({ repositories: ['foo', 'bar'] });
+      expect(cli.getConfig(argv)).toEqual({ repositories: ['foo', 'bar'] });
     });
     it('parses json lists correctly', () => {
       argv.push(
         `--host-rules=[{"domainName":"docker.io","hostType":"docker","username":"user","password":"password"}]`
       );
-      cli.getConfig(argv).should.deep.equal({
+      expect(cli.getConfig(argv)).toEqual({
         hostRules: [
           {
             domainName: 'docker.io',
@@ -92,37 +92,37 @@ describe('config/cli', () => {
     });
     it('parses [] correctly as empty list of hostRules', () => {
       argv.push(`--host-rules=[]`);
-      cli.getConfig(argv).should.eql({
+      expect(cli.getConfig(argv)).toEqual({
         hostRules: [],
       });
     });
     it('parses an empty string correctly as empty list of hostRules', () => {
       argv.push(`--host-rules=`);
-      cli.getConfig(argv).should.eql({
+      expect(cli.getConfig(argv)).toEqual({
         hostRules: [],
       });
     });
     it('migrates --endpoints', () => {
       argv.push(`--endpoints=`);
-      cli.getConfig(argv).should.eql({
+      expect(cli.getConfig(argv)).toEqual({
         hostRules: [],
       });
     });
     it('parses json object correctly when empty', () => {
       argv.push(`--onboarding-config=`);
-      cli.getConfig(argv).should.deep.equal({
+      expect(cli.getConfig(argv)).toEqual({
         onboardingConfig: {},
       });
     });
     it('parses json {} object correctly', () => {
       argv.push(`--onboarding-config={}`);
-      cli.getConfig(argv).should.deep.equal({
+      expect(cli.getConfig(argv)).toEqual({
         onboardingConfig: {},
       });
     });
     it('parses json object correctly', () => {
       argv.push(`--onboarding-config={"extends": ["config:base"]}`);
-      cli.getConfig(argv).should.deep.equal({
+      expect(cli.getConfig(argv)).toEqual({
         onboardingConfig: {
           extends: ['config:base'],
         },
diff --git a/test/config/env.spec.ts b/test/config/env.spec.ts
index e7886e79167a94cc1126c503bbc247a2d13da281..401b387d563b37d18ad9445b364aee3c3294e368 100644
--- a/test/config/env.spec.ts
+++ b/test/config/env.spec.ts
@@ -112,20 +112,20 @@ describe('config/env', () => {
         name: 'foo',
         env: false,
       };
-      env.getEnvName(option).should.eql('');
+      expect(env.getEnvName(option)).toEqual('');
     });
     it('returns existing env', () => {
       const option: Partial<RenovateOptions> = {
         name: 'foo',
         env: 'FOO',
       };
-      env.getEnvName(option).should.eql('FOO');
+      expect(env.getEnvName(option)).toEqual('FOO');
     });
     it('generates RENOVATE_ env', () => {
       const option: Partial<RenovateOptions> = {
         name: 'oneTwoThree',
       };
-      env.getEnvName(option).should.eql('RENOVATE_ONE_TWO_THREE');
+      expect(env.getEnvName(option)).toEqual('RENOVATE_ONE_TWO_THREE');
     });
   });
 });
diff --git a/test/globals.js b/test/globals.ts
similarity index 53%
rename from test/globals.js
rename to test/globals.ts
index e485849aec82c519b50e0f27fde1b96cf7fd54f4..25fda8e2d76455d6c751d4e6d6167d1ee7ffb10e 100644
--- a/test/globals.js
+++ b/test/globals.ts
@@ -1,6 +1,6 @@
-const upath = require('upath');
-const os = require('os');
-const cache = require('../lib/workers/global/cache');
+import { join } from 'upath';
+import { tmpdir } from 'os';
+import { init } from '../lib/workers/global/cache';
 
 jest.mock('../lib/platform', () => ({
   platform: jest.genMockFromModule('../lib/platform/github'),
@@ -10,7 +10,7 @@ jest.mock('../lib/logger');
 
 global.repoCache = {};
 
-const tmpDir = process.env.RENOVATE_TMPDIR || process.env.TMPDIR || os.tmpdir();
-const cacheDir = upath.join(tmpDir, './renovate/cache/renovate');
+const tmpDir = process.env.RENOVATE_TMPDIR || process.env.TMPDIR || tmpdir();
+const cacheDir = join(tmpDir, './renovate/cache/renovate');
 
-cache.init(cacheDir);
+init(cacheDir);
diff --git a/test/manager/npm/update.spec.ts b/test/manager/npm/update.spec.ts
index da7cebc1f706a7d864b5ad5ce05c15dd6df15698..6eaed7f3c5502bfe38b4ae406624d4159f9138f8 100644
--- a/test/manager/npm/update.spec.ts
+++ b/test/manager/npm/update.spec.ts
@@ -23,7 +23,7 @@ describe('workers/branch/package-json', () => {
       };
       const outputContent = readFixture('outputs/011.json');
       const testContent = npmUpdater.updateDependency(input01Content, upgrade);
-      testContent.should.equal(outputContent);
+      expect(testContent).toEqual(outputContent);
     });
     it('replaces a github dependency value', () => {
       const upgrade = {
@@ -124,7 +124,7 @@ describe('workers/branch/package-json', () => {
       };
       const outputContent = readFixture('outputs/012.json');
       const testContent = npmUpdater.updateDependency(input01Content, upgrade);
-      testContent.should.equal(outputContent);
+      expect(testContent).toEqual(outputContent);
     });
     it('replaces only the second instance of a value', () => {
       const upgrade = {
@@ -134,7 +134,7 @@ describe('workers/branch/package-json', () => {
       };
       const outputContent = readFixture('outputs/013.json');
       const testContent = npmUpdater.updateDependency(input01Content, upgrade);
-      testContent.should.equal(outputContent);
+      expect(testContent).toEqual(outputContent);
     });
     it('handles the case where the desired version is already supported', () => {
       const upgrade = {
@@ -143,7 +143,7 @@ describe('workers/branch/package-json', () => {
         newValue: '1.5.8',
       };
       const testContent = npmUpdater.updateDependency(input01Content, upgrade);
-      testContent.should.equal(input01Content);
+      expect(testContent).toEqual(input01Content);
     });
     it('returns null if throws error', () => {
       const upgrade = {
diff --git a/test/newline-snapshot-serializer.js b/test/newline-snapshot-serializer.js
deleted file mode 100644
index 952af90d3e2e61c4068cf8b98723dcfdea09cacf..0000000000000000000000000000000000000000
--- a/test/newline-snapshot-serializer.js
+++ /dev/null
@@ -1,15 +0,0 @@
-let prev;
-
-module.exports = {
-  print(val) {
-    return JSON.stringify(val);
-  },
-
-  test(val) {
-    if (['prBody', 'prTitle'].some(str => str === prev)) {
-      return typeof val === 'string' && val.indexOf('\n') > -1;
-    }
-    prev = val;
-    return false;
-  },
-};
diff --git a/test/newline-snapshot-serializer.ts b/test/newline-snapshot-serializer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4a1c219f1884374c68fec21bc0a7c3d33f638686
--- /dev/null
+++ b/test/newline-snapshot-serializer.ts
@@ -0,0 +1,12 @@
+let prev: string;
+
+export function print(val: any) {
+  return JSON.stringify(val);
+}
+export function test(val: any) {
+  if (['prBody', 'prTitle'].some(str => str === prev)) {
+    return typeof val === 'string' && val.includes('\n');
+  }
+  prev = val;
+  return false;
+}
diff --git a/test/proxy.spec.js b/test/proxy.spec.ts
similarity index 100%
rename from test/proxy.spec.js
rename to test/proxy.spec.ts
diff --git a/test/renovate.spec.js b/test/renovate.spec.ts
similarity index 58%
rename from test/renovate.spec.js
rename to test/renovate.spec.ts
index c6e9afae4a9f2df0cce506b7c22d91e4bdc42da0..31379a8cf7cca634a38d125d159a91961e6ff54c 100644
--- a/test/renovate.spec.js
+++ b/test/renovate.spec.ts
@@ -1,7 +1,8 @@
-const renovateWorker = require('../lib/workers/global');
+import * as renovateWorker from '../lib/workers/global';
+
 require('../lib/.eslintrc');
 
-renovateWorker.start = jest.fn();
+Object.defineProperty(renovateWorker, 'start', { value: jest.fn() });
 
 describe('renovate', () => {
   it('starts', () => {
diff --git a/test/static-files.spec.js b/test/static-files.spec.ts
similarity index 76%
rename from test/static-files.spec.js
rename to test/static-files.spec.ts
index b4c4568bec9c0950eefe7f480d2cc268802d666e..4237df1a590c0ff69c8847c26cb3ff72ab92796f 100644
--- a/test/static-files.spec.js
+++ b/test/static-files.spec.ts
@@ -1,17 +1,18 @@
-const util = require('util');
+import util from 'util';
+
 const glob = util.promisify(require('glob'));
 
 const ignoredExtensions = ['js', 'ts', 'md', 'pyc', 'DS_Store', 'map'];
 
-function filterFiles(files) {
+function filterFiles(files: string[]) {
   return files.filter(file =>
     ignoredExtensions.every(extension => !file.endsWith(`.${extension}`))
   );
 }
 
-async function getFiles(dir) {
+async function getFiles(dir: string) {
   return filterFiles(await glob(`${dir}/**/*`, { dot: true, nodir: true })).map(
-    file => file.replace(`${dir}/`, '')
+    (file: string) => file.replace(`${dir}/`, '')
   );
 }
 
diff --git a/test/website-docs.spec.js b/test/website-docs.spec.ts
similarity index 94%
rename from test/website-docs.spec.js
rename to test/website-docs.spec.ts
index e5c0289fd0b60ad097905eed66143826ac051cc8..dc27a0268cde00ade8bed1da17806bdbeb27e35c 100644
--- a/test/website-docs.spec.js
+++ b/test/website-docs.spec.ts
@@ -1,5 +1,7 @@
-const fs = require('fs');
-const options = require('../lib/config/definitions').getOptions();
+import fs from 'fs';
+import { RenovateOptions } from '../lib/config/definitions';
+
+const options: RenovateOptions[] = require('../lib/config/definitions').getOptions();
 
 describe('docs', () => {
   const doc = fs.readFileSync('docs/usage/configuration-options.md', 'utf8');
diff --git a/yarn.lock b/yarn.lock
index 9378e44ff9763af75479977742969e742ecbe3b5..19bda84b339a4f92b9d97fb9d11b48bcc6ab2fac 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2149,7 +2149,7 @@ ccount@^1.0.0:
   resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.4.tgz#9cf2de494ca84060a2a8d2854edd6dfb0445f386"
   integrity sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w==
 
-chai@4.2.0, chai@^4.1.2:
+chai@^4.1.2:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5"
   integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==