Skip to content
File

Blob: src/workerd/api/node/tests/domain-nodejs-test.js

javascript190 lines
1// Copyright (c) 2025 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4import * as domain from 'node:domain';
5import { strictEqual, throws, ok } from 'node:assert';
6import { EventEmitter } from 'node:events';
7 
8export const domainTest = {
9 test() {
10 // Note: test was generated by claude with manual tweaks
11 
12 // Test that Domain class exists and is a constructor
13 strictEqual(typeof domain.Domain, 'function');
14 
15 // Test that createDomain function exists
16 strictEqual(typeof domain.createDomain, 'function');
17 
18 // Test that create export exists (should be a Domain instance)
19 ok(domain.create instanceof domain.Domain);
20 
21 // Test that active is null (domains are non-operational)
22 strictEqual(domain.active, null);
23 
24 // Test creating a new domain
25 const d = domain.createDomain();
26 ok(d instanceof domain.Domain);
27 ok(d instanceof EventEmitter); // Domain extends EventEmitter
28 
29 // Test that Domain has expected properties
30 strictEqual(d.members, undefined);
31 
32 // Test domain methods exist and are functions
33 strictEqual(typeof d.enter, 'function');
34 strictEqual(typeof d.exit, 'function');
35 strictEqual(typeof d.add, 'function');
36 strictEqual(typeof d.remove, 'function');
37 strictEqual(typeof d.run, 'function');
38 strictEqual(typeof d.intercept, 'function');
39 strictEqual(typeof d.bind, 'function');
40 strictEqual(typeof d._errorHandler, 'function');
41 
42 // Test enter() method - should be no-op (not throw)
43 d.enter();
44 
45 // Test exit() method - should be no-op (not throw)
46 d.exit();
47 
48 // Test add() method - should be no-op (not throw)
49 const ee = new EventEmitter();
50 d.add(ee);
51 d.add(null);
52 d.add(undefined);
53 d.add('string');
54 d.add(123);
55 
56 // Test remove() method - should be no-op (not throw)
57 d.remove(ee);
58 d.remove(null);
59 d.remove(undefined);
60 d.remove('string');
61 d.remove(123);
62 
63 // Test run() method - should execute function and return result
64 let callCount = 0;
65 const testFn = function (...args) {
66 callCount++;
67 strictEqual(this, d); // this should be the domain
68 return args.reduce((a, b) => a + b, 0);
69 };
70 
71 const result = d.run(testFn, 1, 2, 3, 4);
72 strictEqual(result, 10);
73 strictEqual(callCount, 1);
74 
75 // Test run() with function that throws
76 const errorFn = function () {
77 throw new Error('test error');
78 };
79 throws(() => {
80 d.run(errorFn);
81 }, /test error/);
82 
83 // Test run() with no arguments
84 const noArgFn = function () {
85 return 'no args';
86 };
87 strictEqual(d.run(noArgFn), 'no args');
88 
89 // Test intercept() method - should return the callback directly
90 const callback1 = function () {
91 return 'callback1';
92 };
93 const intercepted = d.intercept(callback1);
94 strictEqual(intercepted, callback1);
95 strictEqual(intercepted(), 'callback1');
96 
97 // Test bind() method - should return the callback directly
98 const callback2 = function () {
99 return 'callback2';
100 };
101 const bound = d.bind(callback2);
102 strictEqual(bound, callback2);
103 strictEqual(bound(), 'callback2');
104 
105 // Test _errorHandler() method - should throw the error passed to it
106 const testError = new Error('test error handler');
107 throws(() => {
108 d._errorHandler(testError);
109 }, testError);
110 
111 throws(() => {
112 d._errorHandler('string error');
113 }, /string error/);
114 
115 throws(() => {
116 d._errorHandler(null);
117 });
118 
119 // Test that multiple domains can be created independently
120 const d1 = domain.createDomain();
121 const d2 = domain.createDomain();
122 ok(d1 !== d2);
123 ok(d1 instanceof domain.Domain);
124 ok(d2 instanceof domain.Domain);
125 
126 // Test that domains inherit from EventEmitter properly
127 let emitted = false;
128 d1.on('test', () => {
129 emitted = true;
130 });
131 d1.emit('test');
132 strictEqual(emitted, true);
133 
134 // Test domain with async function (should work normally)
135 let _asyncResult = null;
136 const asyncFn = async function (value) {
137 return Promise.resolve(value * 2);
138 };
139 
140 const asyncPromise = d.run(asyncFn, 5);
141 ok(asyncPromise instanceof Promise);
142 
143 // Test that EventEmitter.usingDomains is set to false
144 strictEqual(EventEmitter.usingDomains, false);
145 
146 // Test default export
147 strictEqual(typeof domain.default, 'object');
148 strictEqual(domain.default.Domain, domain.Domain);
149 strictEqual(domain.default.active, domain.active);
150 strictEqual(domain.default.createDomain, domain.createDomain);
151 strictEqual(domain.default.create, domain.create);
152 
153 // Test edge cases with run()
154 // Test with null function (should throw)
155 throws(() => {
156 d.run(null);
157 });
158 
159 throws(() => {
160 d.run(undefined);
161 });
162 
163 throws(() => {
164 d.run('not a function');
165 });
166 
167 // Test intercept with non-function (should still return it)
168 const nonFunction = 'not a function';
169 strictEqual(d.intercept(nonFunction), nonFunction);
170 
171 // Test bind with non-function (should still return it)
172 strictEqual(d.bind(nonFunction), nonFunction);
173 
174 // Test that domain methods can be called multiple times safely
175 d.enter();
176 d.enter();
177 d.exit();
178 d.exit();
179 
180 // Test members property remains undefined after operations
181 d.add(new EventEmitter());
182 d.remove(new EventEmitter());
183 d.enter();
184 d.exit();
185 strictEqual(d.members, undefined);
186 
187 console.log('All domain module tests passed!');
188 },
189};