UNPKG

6.13 kBJavaScriptView Raw
1"use strict";
2/**
3 * @module Core
4 */
5var __importDefault = (this && this.__importDefault) || function (mod) {
6 return (mod && mod.__esModule) ? mod : { "default": mod };
7};
8Object.defineProperty(exports, "__esModule", { value: true });
9exports.Test = void 0;
10/*
11 * japa
12 *
13 * (c) Harminder Virk <virk@adonisjs.com>
14 *
15 * For the full copyright and license information, please view the LICENSE
16 * file that was distributed with this source code.
17*/
18const is_ci_1 = __importDefault(require("is-ci"));
19const retry_1 = __importDefault(require("retry"));
20const time_span_1 = __importDefault(require("time-span"));
21const Emitter_1 = require("../Emitter");
22const Callable_1 = require("../Callable");
23const utils_1 = require("../utils");
24const Exceptions_1 = require("../Exceptions");
25const Contracts_1 = require("../Contracts");
26/**
27 * Test class is used for running and defining a test. It supports following
28 * top level config properties.
29 *
30 * - skip : Skip the test
31 * - skipInCI : Skip the test on CI
32 * - runInCI : Run only in CI
33 */
34class Test {
35 constructor(title, _resolveFn, _callback, options) {
36 this.title = title;
37 this._resolveFn = _resolveFn;
38 this._callback = _callback;
39 /**
40 * Regression message is set when the passes, but it was meant
41 * to fail
42 */
43 this._regressionMessage = '';
44 /**
45 * How many times, we should retry the function before marking
46 * it as failed
47 */
48 this._retries = 0;
49 /**
50 * The time spent to run the test. This includes the hooks
51 * time.
52 */
53 this._duration = 0;
54 /**
55 * The test error (if any)
56 */
57 this._error = null;
58 /**
59 * Has test been executed
60 */
61 this._completed = false;
62 this._todo = typeof (this._callback) !== 'function';
63 this._timeout = options.timeout;
64 this._regression = options.regression;
65 if (options.skip) {
66 this._skip = true;
67 }
68 else if (options.skipInCI && is_ci_1.default) {
69 this._skip = true;
70 }
71 else if (options.runInCI && !is_ci_1.default) {
72 this._skip = true;
73 }
74 }
75 /**
76 * Returns a boolean, telling if exception is hard. Hard exceptions
77 * fails the regression tests too
78 */
79 get _isHardException() {
80 return (0, utils_1.isCoreException)(this._error);
81 }
82 /**
83 * Runs test for given number retries
84 */
85 _runTest() {
86 return new Promise((resolve, reject) => {
87 const op = retry_1.default.operation({ retries: this._retries, factor: 1 });
88 op.attempt(async () => {
89 (0, Callable_1.Callable)(this._resolveFn, this._callback, this._timeout)
90 .then(resolve)
91 .catch((error) => {
92 if (op.retry(error)) {
93 return;
94 }
95 reject(op.mainError());
96 });
97 });
98 });
99 }
100 /**
101 * The JSON representation of the test. This is emitted
102 * as an event to show test state.
103 */
104 toJSON() {
105 let status = Contracts_1.ITestStatus.PENDING;
106 if (this._todo) {
107 status = Contracts_1.ITestStatus.TODO;
108 }
109 else if (this._skip) {
110 status = Contracts_1.ITestStatus.SKIPPED;
111 }
112 else if (this._completed && this._error) {
113 status = (this._regression && !this._isHardException) ? Contracts_1.ITestStatus.PASSED : Contracts_1.ITestStatus.FAILED;
114 }
115 else if (this._completed && !this._error) {
116 status = Contracts_1.ITestStatus.PASSED;
117 }
118 return {
119 title: this.title,
120 status: status,
121 regression: this._regression,
122 regressionMessage: this._regressionMessage,
123 duration: this._duration,
124 error: this._error,
125 };
126 }
127 /**
128 * Retry a test for the given number of counts, before marking
129 * it as failed.
130 */
131 retry(counts) {
132 if (typeof (counts) !== 'number') {
133 throw new Error('"test.retry" expects a number value');
134 }
135 this._retries = counts;
136 return this;
137 }
138 /**
139 * Set explicit timeout for the given test.
140 */
141 timeout(duration) {
142 if (typeof (duration) !== 'number') {
143 throw new Error('"test.timeout" expects a number value');
144 }
145 this._timeout = duration;
146 return this;
147 }
148 /**
149 * Runs the test. If retries are defined, then the test will be retried for the
150 * given number of times before marked as failed. When retrying hooks are not
151 * executed again.
152 *
153 * ```js
154 * // stack
155 * [before hook 1, before hook 2]
156 * [test] (2 retries)
157 * [after hook 1]
158 *
159 * + before hook 1
160 * + before hook 2
161 * test (original attempt = failed)
162 * test (1st attempt = passed)
163 * + after hook 1
164 * ```
165 */
166 async run() {
167 Emitter_1.emitter.emit(Contracts_1.IEvents.TESTSTARTED, this.toJSON());
168 const start = (0, time_span_1.default)();
169 /* istanbul ignore else */
170 if (!this._todo && !this._skip) {
171 /**
172 * Run the actual test
173 */
174 try {
175 await this._runTest();
176 /**
177 * Mark test as failed, when is regression but passed
178 */
179 if (this._regression) {
180 throw new Exceptions_1.RegressionException('Expected regression test to fail');
181 }
182 }
183 catch (error) {
184 this._error = error;
185 if (!this._isHardException && this._regression) {
186 this._regressionMessage = error.message;
187 }
188 }
189 }
190 this._duration = start.rounded();
191 this._completed = true;
192 Emitter_1.emitter.emit(Contracts_1.IEvents.TESTCOMPLETED, this.toJSON());
193 }
194}
195exports.Test = Test;