1// Flags: --no-warnings
2'use strict';
3require('../../../common');
4const assert = require('node:assert');
5const test = require('node:test');
6const util = require('util');
7
8test('sync pass todo', (t) => {
9  t.todo();
10});
11
12test('sync pass todo with message', (t) => {
13  t.todo('this is a passing todo');
14});
15
16test('sync fail todo', (t) => {
17  t.todo();
18  throw new Error('thrown from sync fail todo');
19});
20
21test('sync fail todo with message', (t) => {
22  t.todo('this is a failing todo');
23  throw new Error('thrown from sync fail todo with message');
24});
25
26test('sync skip pass', (t) => {
27  t.skip();
28});
29
30test('sync skip pass with message', (t) => {
31  t.skip('this is skipped');
32});
33
34test('sync pass', (t) => {
35  t.diagnostic('this test should pass');
36});
37
38test('sync throw fail', () => {
39  throw new Error('thrown from sync throw fail');
40});
41
42test('async skip pass', async (t) => {
43  t.skip();
44});
45
46test('async pass', async () => {
47
48});
49
50test('async throw fail', async () => {
51  throw new Error('thrown from async throw fail');
52});
53
54test('async skip fail', async (t) => {
55  t.skip();
56  throw new Error('thrown from async throw fail');
57});
58
59test('async assertion fail', async () => {
60  // Make sure the assert module is handled.
61  assert.strictEqual(true, false);
62});
63
64test('resolve pass', () => {
65  return Promise.resolve();
66});
67
68test('reject fail', () => {
69  return Promise.reject(new Error('rejected from reject fail'));
70});
71
72test('unhandled rejection - passes but warns', () => {
73  Promise.reject(new Error('rejected from unhandled rejection fail'));
74});
75
76test('async unhandled rejection - passes but warns', async () => {
77  Promise.reject(new Error('rejected from async unhandled rejection fail'));
78});
79
80test('immediate throw - passes but warns', () => {
81  setImmediate(() => {
82    throw new Error('thrown from immediate throw fail');
83  });
84});
85
86test('immediate reject - passes but warns', () => {
87  setImmediate(() => {
88    Promise.reject(new Error('rejected from immediate reject fail'));
89  });
90});
91
92test('immediate resolve pass', () => {
93  return new Promise((resolve) => {
94    setImmediate(() => {
95      resolve();
96    });
97  });
98});
99
100test('subtest sync throw fail', async (t) => {
101  await t.test('+sync throw fail', (t) => {
102    t.diagnostic('this subtest should make its parent test fail');
103    throw new Error('thrown from subtest sync throw fail');
104  });
105});
106
107test('sync throw non-error fail', async (t) => {
108  throw Symbol('thrown symbol from sync throw non-error fail');
109});
110
111test('level 0a', { concurrency: 4 }, async (t) => {
112  t.test('level 1a', async (t) => {
113    const p1a = new Promise((resolve) => {
114      setTimeout(() => {
115        resolve();
116      }, 100);
117    });
118
119    return p1a;
120  });
121
122  test('level 1b', async (t) => {
123    const p1b = new Promise((resolve) => {
124      resolve();
125    });
126
127    return p1b;
128  });
129
130  t.test('level 1c', async (t) => {
131    const p1c = new Promise((resolve) => {
132      setTimeout(() => {
133        resolve();
134      }, 200);
135    });
136
137    return p1c;
138  });
139
140  t.test('level 1d', async (t) => {
141    const p1c = new Promise((resolve) => {
142      setTimeout(() => {
143        resolve();
144      }, 150);
145    });
146
147    return p1c;
148  });
149
150  const p0a = new Promise((resolve) => {
151    setTimeout(() => {
152      resolve();
153    }, 300);
154  });
155
156  return p0a;
157});
158
159test('top level', { concurrency: 2 }, async (t) => {
160  t.test('+long running', async (t) => {
161    return new Promise((resolve, reject) => {
162      setTimeout(resolve, 300).unref();
163    });
164  });
165
166  t.test('+short running', async (t) => {
167    t.test('++short running', async (t) => {});
168  });
169});
170
171test('invalid subtest - pass but subtest fails', (t) => {
172  setImmediate(() => {
173    t.test('invalid subtest fail', () => {
174      throw new Error('this should not be thrown');
175    });
176  });
177});
178
179test('sync skip option', { skip: true }, (t) => {
180  throw new Error('this should not be executed');
181});
182
183test('sync skip option with message', { skip: 'this is skipped' }, (t) => {
184  throw new Error('this should not be executed');
185});
186
187test('sync skip option is false fail', { skip: false }, (t) => {
188  throw new Error('this should be executed');
189});
190
191// A test with no arguments provided.
192test();
193
194// A test with only a named function provided.
195test(function functionOnly() {});
196
197// A test with only an anonymous function provided.
198test(() => {});
199
200// A test with only a name provided.
201test('test with only a name provided');
202
203// A test with an empty string name.
204test('');
205
206// A test with only options provided.
207test({ skip: true });
208
209// A test with only a name and options provided.
210test('test with a name and options provided', { skip: true });
211
212// A test with only options and a function provided.
213test({ skip: true }, function functionAndOptions() {});
214
215test('callback pass', (t, done) => {
216  setImmediate(done);
217});
218
219test('callback fail', (t, done) => {
220  setImmediate(() => {
221    done(new Error('callback failure'));
222  });
223});
224
225test('sync t is this in test', function(t) {
226  assert.strictEqual(this, t);
227});
228
229test('async t is this in test', async function(t) {
230  assert.strictEqual(this, t);
231});
232
233test('callback t is this in test', function(t, done) {
234  assert.strictEqual(this, t);
235  done();
236});
237
238test('callback also returns a Promise', async (t, done) => {
239  throw new Error('thrown from callback also returns a Promise');
240});
241
242test('callback throw', (t, done) => {
243  throw new Error('thrown from callback throw');
244});
245
246test('callback called twice', (t, done) => {
247  done();
248  done();
249});
250
251test('callback called twice in different ticks', (t, done) => {
252  setImmediate(done);
253  done();
254});
255
256test('callback called twice in future tick', (t, done) => {
257  setImmediate(() => {
258    done();
259    done();
260  });
261});
262
263test('callback async throw', (t, done) => {
264  setImmediate(() => {
265    throw new Error('thrown from callback async throw');
266  });
267});
268
269test('callback async throw after done', (t, done) => {
270  setImmediate(() => {
271    throw new Error('thrown from callback async throw after done');
272  });
273
274  done();
275});
276
277test('only is set but not in only mode', { only: true }, async (t) => {
278  // All of these subtests should run.
279  await t.test('running subtest 1');
280  t.runOnly(true);
281  await t.test('running subtest 2');
282  await t.test('running subtest 3', { only: true });
283  t.runOnly(false);
284  await t.test('running subtest 4');
285});
286
287test('custom inspect symbol fail', () => {
288  const obj = {
289    [util.inspect.custom]() {
290      return 'customized';
291    },
292    foo: 1,
293  };
294
295  throw obj;
296});
297
298test('custom inspect symbol that throws fail', () => {
299  const obj = {
300    [util.inspect.custom]() {
301      throw new Error('bad-inspect');
302    },
303    foo: 1,
304  };
305
306  throw obj;
307});
308
309test('subtest sync throw fails', async (t) => {
310  await t.test('sync throw fails at first', (t) => {
311    throw new Error('thrown from subtest sync throw fails at first');
312  });
313  await t.test('sync throw fails at second', (t) => {
314    throw new Error('thrown from subtest sync throw fails at second');
315  });
316});
317
318test('timed out async test', { timeout: 5 }, async (t) => {
319  return new Promise((resolve) => {
320    setTimeout(resolve, 100);
321  });
322});
323
324test('timed out callback test', { timeout: 5 }, (t, done) => {
325  setTimeout(done, 100);
326});
327
328
329test('large timeout async test is ok', { timeout: 30_000_000 }, async (t) => {
330  return new Promise((resolve) => {
331    setTimeout(resolve, 10);
332  });
333});
334
335test('large timeout callback test is ok', { timeout: 30_000_000 }, (t, done) => {
336  setTimeout(done, 10);
337});
338
339test('successful thenable', () => {
340  let thenCalled = false;
341  return {
342    get then() {
343      if (thenCalled) throw new Error();
344      thenCalled = true;
345      return (successHandler) => successHandler();
346    },
347  };
348});
349
350test('rejected thenable', () => {
351  let thenCalled = false;
352  return {
353    get then() {
354      if (thenCalled) throw new Error();
355      thenCalled = true;
356      return (_, errorHandler) => errorHandler('custom error');
357    },
358  };
359});
360
361test('unfinished test with uncaughtException', async () => {
362  await new Promise(() => {
363    setTimeout(() => { throw new Error('foo'); });
364  });
365});
366
367test('unfinished test with unhandledRejection', async () => {
368  await new Promise(() => {
369    setTimeout(() => Promise.reject(new Error('bar')));
370  });
371});
372
373// Verify that uncaught exceptions outside of any tests are handled after the
374// test harness has finished bootstrapping itself.
375setImmediate(() => {
376  throw new Error('uncaught from outside of a test');
377});
378
379test('assertion errors display actual and expected properly', async () => {
380  // Make sure the assert module is handled.
381  const circular = { bar: 2 };
382  circular.c = circular;
383  const tmpLimit = Error.stackTraceLimit;
384  Error.stackTraceLimit = 1;
385  try {
386    assert.deepEqual({ foo: 1, bar: 1 }, circular); // eslint-disable-line no-restricted-properties
387  } catch (err) {
388    Error.stackTraceLimit = tmpLimit;
389    throw err;
390  }
391});
392