|
8 | 8 | // OS_ALLOW_DRIVER_CONNECT_FAILURE. |
9 | 9 |
|
10 | 10 | import { describe, it, expect, beforeEach, afterEach } from 'vitest'; |
| 11 | +import { ObjectLogger } from '@objectstack/core'; |
11 | 12 | import { ObjectQL } from './engine.js'; |
12 | 13 | import { DriverConnectError } from './driver-connect-errors.js'; |
13 | 14 |
|
@@ -138,28 +139,46 @@ describe('ObjectQL.init() — driver connect fail-fast (framework#3741)', () => |
138 | 139 | expect(warned).toContain('sql'); |
139 | 140 | }); |
140 | 141 |
|
141 | | - it('repeats the degraded banner on stderr, which `os serve` boot-quiet cannot swallow', async () => { |
142 | | - // `os serve` replaces process.stdout.write for the whole boot, and Logger |
143 | | - // sends `warn` to stdout — so a logger-only banner is invisible in exactly |
144 | | - // the deployment this flag exists for. |
| 142 | + it('repeats the degraded banner on stderr, which the operator log level cannot filter away', async () => { |
| 143 | + // The banner's `logger.warn` is dropped OUTRIGHT at `error`/`fatal`/`silent` |
| 144 | + // — `Logger.write()` returns before touching a stream — and a production |
| 145 | + // host at `error` is exactly the deployment this flag exists for. The stderr |
| 146 | + // copy is what survives that. |
| 147 | + // |
| 148 | + // This used to be justified by `os serve`'s boot-quiet stdout capture |
| 149 | + // instead; that swallowed the banner at EVERY level until framework#4012 |
| 150 | + // fixed it. Pinning the level filter keeps the test tied to the reason that |
| 151 | + // is still true. |
145 | 152 | process.env[ENV] = '1'; |
146 | 153 | const written: string[] = []; |
147 | | - const realWrite = process.stderr.write; |
| 154 | + const onStdout: string[] = []; |
| 155 | + const realErrWrite = process.stderr.write; |
| 156 | + const realOutWrite = process.stdout.write; |
148 | 157 | (process.stderr as { write: unknown }).write = (chunk: any) => { |
149 | 158 | written.push(String(chunk)); |
150 | 159 | return true; |
151 | 160 | }; |
| 161 | + (process.stdout as { write: unknown }).write = (chunk: any) => { |
| 162 | + onStdout.push(String(chunk)); |
| 163 | + return true; |
| 164 | + }; |
152 | 165 | try { |
153 | 166 | const engine = new ObjectQL({ |
154 | | - logger: { debug() {}, info() {}, warn() {}, error() {} }, |
| 167 | + // A REAL logger, silenced the way a production host silences it. |
| 168 | + logger: new ObjectLogger({ level: 'error' }), |
155 | 169 | } as any); |
156 | 170 | engine.registerDriver(fails('sql', 'down'), true); |
157 | 171 | await engine.init(); |
158 | 172 | } finally { |
159 | | - (process.stderr as { write: unknown }).write = realWrite; |
| 173 | + (process.stderr as { write: unknown }).write = realErrWrite; |
| 174 | + (process.stdout as { write: unknown }).write = realOutWrite; |
160 | 175 | } |
161 | 176 |
|
162 | 177 | expect(written.join('')).toContain('DEGRADED BOOT'); |
| 178 | + // The half that makes this a real pin: at `error` the logger emitted |
| 179 | + // NOTHING, so stderr is the only channel that carried the banner. Drop the |
| 180 | + // helper and this deployment goes silent. |
| 181 | + expect(onStdout.join('')).not.toContain('DEGRADED BOOT'); |
163 | 182 | }); |
164 | 183 |
|
165 | 184 | it('treats a falsy opt-in value as off — still fail-fast', async () => { |
|
0 commit comments