test_bundle.js 7.4 KB
Newer Older
1 2 3
/* eslint-disable
  jasmine/no-global-setup, jasmine/no-unsafe-spy, no-underscore-dangle, no-console
*/
M
Mike Greiling 已提交
4

5
import $ from 'jquery';
6
import 'core-js/features/set-immediate';
J
Jacob Schatz 已提交
7
import 'vendor/jasmine-jquery';
8
import '~/commons';
W
Winnie Hellmann 已提交
9 10
import Vue from 'vue';
import VueResource from 'vue-resource';
11
import Translate from '~/vue_shared/translate';
12
import jasmineDiff from 'jasmine-diff';
13
import { config as testUtilsConfig } from '@vue/test-utils';
W
Winnie Hellmann 已提交
14

15
import { getDefaultAdapter } from '~/lib/utils/axios_utils';
16 17 18
import { FIXTURES_PATH, TEST_HOST } from './test_constants';

import customMatchers from './matchers';
19

20 21 22
// Tech debt issue TBD
testUtilsConfig.logModifiedComponents = false;

W
winh 已提交
23 24 25 26
const isHeadlessChrome = /\bHeadlessChrome\//.test(navigator.userAgent);
Vue.config.devtools = !isHeadlessChrome;
Vue.config.productionTip = false;

W
Winnie Hellmann 已提交
27 28
let hasVueWarnings = false;
Vue.config.warnHandler = (msg, vm, trace) => {
29 30
  // The following workaround is necessary, so we are able to use setProps from Vue test utils
  // see https://github.com/vuejs/vue-test-utils/issues/631#issuecomment-421108344
31
  const currentStack = new Error().stack;
32 33 34 35 36 37 38
  const isInVueTestUtils = currentStack
    .split('\n')
    .some(line => line.startsWith('    at VueWrapper.setProps ('));
  if (isInVueTestUtils) {
    return;
  }

W
Winnie Hellmann 已提交
39 40 41 42
  hasVueWarnings = true;
  fail(`${msg}${trace}`);
};

43
let hasVueErrors = false;
44
Vue.config.errorHandler = function(err) {
45 46 47 48
  hasVueErrors = true;
  fail(err);
};

W
Winnie Hellmann 已提交
49
Vue.use(VueResource);
50
Vue.use(Translate);
W
Winnie Hellmann 已提交
51

52
// enable test fixtures
53 54 55
jasmine.getFixtures().fixturesPath = FIXTURES_PATH;
jasmine.getJSONFixtures().fixturesPath = FIXTURES_PATH;

56 57 58
beforeAll(() => {
  jasmine.addMatchers(
    jasmineDiff(jasmine, {
L
Lukas Eipert 已提交
59 60
      colors: window.__karma__.config.color,
      inline: window.__karma__.config.color,
61 62 63 64
    }),
  );
  jasmine.addMatchers(customMatchers);
});
65

66
// globalize common libraries
G
gfyoung 已提交
67 68
window.$ = $;
window.jQuery = window.$;
69 70

// stub expected globals
71
window.gl = window.gl || {};
72
window.gl.TEST_HOST = TEST_HOST;
73
window.gon = window.gon || {};
M
Mike Greiling 已提交
74
window.gon.test_env = true;
75
window.gon.ee = process.env.IS_GITLAB_EE;
76
gon.relative_url_root = '';
77

78 79
let hasUnhandledPromiseRejections = false;

80
window.addEventListener('unhandledrejection', event => {
81 82 83 84 85
  hasUnhandledPromiseRejections = true;
  console.error('Unhandled promise rejection:');
  console.error(event.reason.stack || event.reason);
});

M
Mike Greiling 已提交
86 87 88 89 90 91 92 93 94 95 96
// Add global function to spy on a module's dependencies via rewire
window.spyOnDependency = (module, name) => {
  const dependency = module.__GetDependency__(name);
  const spy = jasmine.createSpy(name, dependency);
  module.__Rewire__(name, spy);
  return spy;
};

// Reset any rewired modules after each test (see babel-plugin-rewire)
afterEach(__rewire_reset_all__); // eslint-disable-line

M
Mike Greiling 已提交
97 98 99 100 101 102
// HACK: Chrome 59 disconnects if there are too many synchronous tests in a row
// because it appears to lock up the thread that communicates to Karma's socket
// This async beforeEach gets called on every spec and releases the JS thread long
// enough for the socket to continue to communicate.
// The downside is that it creates a minor performance penalty in the time it takes
// to run our unit tests.
W
Winnie Hellmann 已提交
103 104 105 106 107 108 109 110
beforeEach(done => done());

const builtinVueHttpInterceptors = Vue.http.interceptors.slice();

beforeEach(() => {
  // restore interceptors so we have no remaining ones from previous tests
  Vue.http.interceptors = builtinVueHttpInterceptors.slice();
});
M
Mike Greiling 已提交
111

112 113
let longRunningTestTimeoutHandle;

P
Phil Hughes 已提交
114
beforeEach(done => {
115 116
  longRunningTestTimeoutHandle = setTimeout(() => {
    done.fail('Test is running too long!');
H
Heinrich Lee Yu 已提交
117
  }, 4000);
118 119 120 121 122 123 124
  done();
});

afterEach(() => {
  clearTimeout(longRunningTestTimeoutHandle);
});

125 126
const axiosDefaultAdapter = getDefaultAdapter();

127
// render all of our tests
128 129
const testContexts = [require.context('spec', true, /_spec$/)];

130
if (process.env.IS_GITLAB_EE) {
131 132
  testContexts.push(require.context('ee_spec', true, /_spec$/));
}
133 134 135 136 137 138 139 140 141 142 143 144

testContexts.forEach(context => {
  context.keys().forEach(path => {
    try {
      context(path);
    } catch (err) {
      console.log(err);
      console.error('[GL SPEC RUNNER ERROR] Unable to load spec: ', path);
      describe('Test bundle', function() {
        it(`includes '${path}'`, function() {
          expect(err).toBeNull();
        });
145
      });
146 147
    }
  });
148
});
149

W
Winnie Hellmann 已提交
150
describe('test errors', () => {
151
  beforeAll(done => {
152
    if (hasUnhandledPromiseRejections || hasVueWarnings || hasVueErrors) {
W
Winnie Hellmann 已提交
153 154 155 156 157 158 159 160 161 162 163 164 165
      setTimeout(done, 1000);
    } else {
      done();
    }
  });

  it('has no unhandled Promise rejections', () => {
    expect(hasUnhandledPromiseRejections).toBe(false);
  });

  it('has no Vue warnings', () => {
    expect(hasVueWarnings).toBe(false);
  });
166 167 168 169

  it('has no Vue error', () => {
    expect(hasVueErrors).toBe(false);
  });
170 171 172 173 174 175

  it('restores axios adapter after mocking', () => {
    if (getDefaultAdapter() !== axiosDefaultAdapter) {
      fail('axios adapter is not restored! Did you forget a restore() on MockAdapter?');
    }
  });
176 177
});

178 179 180 181 182
// if we're generating coverage reports, make sure to include all files so
// that we can catch files with 0% coverage
// see: https://github.com/deepsweet/istanbul-instrumenter-loader/issues/15
if (process.env.BABEL_ENV === 'coverage') {
  // exempt these files from the coverage report
183
  const troubleMakers = [
184
    './blob_edit/blob_bundle.js',
185
    './boards/components/modal/empty_state.vue',
186 187
    './boards/components/modal/footer.js',
    './boards/components/modal/header.js',
188
    './cycle_analytics/cycle_analytics_bundle.js',
189 190 191
    './cycle_analytics/components/stage_plan_component.js',
    './cycle_analytics/components/stage_staging_component.js',
    './cycle_analytics/components/stage_test_component.js',
192 193
    './commit/pipelines/pipelines_bundle.js',
    './diff_notes/diff_notes_bundle.js',
194 195
    './diff_notes/components/jump_to_discussion.js',
    './diff_notes/components/resolve_count.js',
196 197 198 199 200 201
    './dispatcher.js',
    './environments/environments_bundle.js',
    './graphs/graphs_bundle.js',
    './issuable/time_tracking/time_tracking_bundle.js',
    './main.js',
    './merge_conflicts/merge_conflicts_bundle.js',
202 203
    './merge_conflicts/components/inline_conflict_lines.js',
    './merge_conflicts/components/parallel_conflict_lines.js',
204 205
    './monitoring/monitoring_bundle.js',
    './network/network_bundle.js',
206
    './network/branch_graph.js',
207 208 209 210 211
    './profile/profile_bundle.js',
    './protected_branches/protected_branches_bundle.js',
    './snippet/snippet_bundle.js',
    './terminal/terminal_bundle.js',
    './users/users_bundle.js',
R
Regis Boudinot 已提交
212
    './issue_show/index.js',
213
    './pages/admin/application_settings/show/index.js',
214 215
  ];

216
  describe('Uncovered files', function() {
217 218
    const sourceFilesContexts = [require.context('~', true, /\.(js|vue)$/)];

219
    if (process.env.IS_GITLAB_EE) {
220 221 222
      sourceFilesContexts.push(require.context('ee', true, /\.(js|vue)$/));
    }

223 224 225 226
    const allTestFiles = testContexts.reduce(
      (accumulator, context) => accumulator.concat(context.keys()),
      [],
    );
J
Jacob Schatz 已提交
227 228 229

    $.holdReady(true);

230 231 232 233 234
    sourceFilesContexts.forEach(context => {
      context.keys().forEach(path => {
        // ignore if there is a matching spec file
        if (allTestFiles.indexOf(`${path.replace(/\.(js|vue)$/, '')}_spec`) > -1) {
          return;
235
        }
236 237 238 239 240 241 242 243 244 245

        it(`includes '${path}'`, function() {
          try {
            context(path);
          } catch (err) {
            if (troubleMakers.indexOf(path) === -1) {
              expect(err).toBeNull();
            }
          }
        });
246
      });
247 248
    });
  });
249
}