CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
earlyInputCapture.test.ts350 linesDownload Raw Back to utils
1/**2 * @license3 * Copyright 2026 Qwen Team4 * SPDX-License-Identifier: Apache-2.05 */6 7import { describe, it, expect, beforeEach, afterEach } from 'vitest';8import {9  startEarlyInputCapture,10  stopEarlyInputCapture,11  getAndClearCapturedInput,12  stopAndGetCapturedInput,13  hasCapturedInput,14  resetCaptureState,15} from './earlyInputCapture.js';16import { PassThrough } from 'node:stream';17 18describe('earlyInputCapture', () => {19  let mockStdin: PassThrough;20  let originalStdin: typeof process.stdin;21  let originalIsTTY: boolean;22 23  beforeEach(() => {24    resetCaptureState();25 26    // Save original stdin27    originalStdin = process.stdin;28    originalIsTTY = process.stdin.isTTY ?? false;29 30    // Create mock stdin31    mockStdin = new PassThrough();32    Object.defineProperty(process, 'stdin', {33      value: mockStdin,34      writable: true,35      configurable: true,36    });37    Object.defineProperty(process.stdin, 'isTTY', {38      value: true,39      writable: true,40      configurable: true,41    });42 43    delete process.env['QWEN_CODE_DISABLE_EARLY_CAPTURE'];44  });45 46  afterEach(() => {47    resetCaptureState();48 49    // Restore original stdin50    Object.defineProperty(process, 'stdin', {51      value: originalStdin,52      writable: true,53      configurable: true,54    });55    Object.defineProperty(process.stdin, 'isTTY', {56      value: originalIsTTY,57      writable: true,58      configurable: true,59    });60  });61 62  describe('capture lifecycle', () => {63    it('should start and stop capture correctly', () => {64      startEarlyInputCapture();65      expect(hasCapturedInput()).toBe(false);66 67      mockStdin.write(Buffer.from('a'));68      expect(hasCapturedInput()).toBe(true);69 70      stopEarlyInputCapture();71      const input = getAndClearCapturedInput();72      expect(input.toString()).toBe('a');73    });74 75    it('should not capture after stop', () => {76      startEarlyInputCapture();77      mockStdin.write(Buffer.from('a'));78      stopEarlyInputCapture();79      mockStdin.write(Buffer.from('b'));80 81      const input = getAndClearCapturedInput();82      expect(input.toString()).toBe('a');83    });84 85    it('should not start capture if not TTY', () => {86      Object.defineProperty(process.stdin, 'isTTY', { value: false });87      startEarlyInputCapture();88      mockStdin.write(Buffer.from('a'));89      stopEarlyInputCapture();90 91      expect(hasCapturedInput()).toBe(false);92    });93 94    it('should not start capture twice', () => {95      startEarlyInputCapture();96      startEarlyInputCapture(); // Second call should be ignored97 98      mockStdin.write(Buffer.from('a'));99      stopEarlyInputCapture();100 101      const input = getAndClearCapturedInput();102      expect(input.toString()).toBe('a');103    });104 105    it('stopAndGetCapturedInput should atomically stop and return input', () => {106      startEarlyInputCapture();107      mockStdin.write(Buffer.from('hello'));108 109      const input = stopAndGetCapturedInput();110      expect(input.toString()).toBe('hello');111 112      // Further writes should not be captured113      mockStdin.write(Buffer.from('world'));114      expect(hasCapturedInput()).toBe(false);115    });116  });117 118  describe('terminal response filtering', () => {119    it('should filter DEC private mode responses (ESC [ ?)', () => {120      startEarlyInputCapture();121      // DEC private mode response: ESC [ ? 1 0 0 4 h122      mockStdin.write(Buffer.from('\x1b[?1004h'));123      stopEarlyInputCapture();124 125      const input = getAndClearCapturedInput();126      expect(input.length).toBe(0);127    });128 129    it('should filter DA2 responses (ESC [ >)', () => {130      startEarlyInputCapture();131      // DA2 response: ESC [ > 0 ; 9 5 ; 0 c132      mockStdin.write(Buffer.from('\x1b[>0;95;0c'));133      stopEarlyInputCapture();134 135      const input = getAndClearCapturedInput();136      expect(input.length).toBe(0);137    });138 139    it('should filter OSC sequences (ESC ])', () => {140      startEarlyInputCapture();141      // OSC sequence: ESC ] 0 ; title BEL142      mockStdin.write(Buffer.from('\x1b]0;window title\x07'));143      stopEarlyInputCapture();144 145      const input = getAndClearCapturedInput();146      expect(input.length).toBe(0);147    });148 149    it('should filter DCS sequences (ESC P)', () => {150      startEarlyInputCapture();151      // DCS sequence: ESC P ... ST152      mockStdin.write(Buffer.from('\x1bP$data\x1b\\'));153      stopEarlyInputCapture();154 155      const input = getAndClearCapturedInput();156      expect(input.length).toBe(0);157    });158 159    it('should keep user input mixed with terminal responses', () => {160      startEarlyInputCapture();161      // Mix of user input and terminal response162      mockStdin.write(Buffer.from('a\x1b[?1004hb\x1b]0;title\x07c'));163      stopEarlyInputCapture();164 165      const input = getAndClearCapturedInput();166      expect(input.toString()).toBe('abc');167    });168 169    it('should keep arrow key sequences (user input)', () => {170      startEarlyInputCapture();171      // Arrow up: ESC [ A (this is a user input, not terminal response)172      mockStdin.write(Buffer.from('\x1b[A'));173      stopEarlyInputCapture();174 175      const input = getAndClearCapturedInput();176      // Arrow key sequence should be kept (it's user input)177      expect(input.toString()).toBe('\x1b[A');178    });179 180    it('should keep function key sequences (user input)', () => {181      startEarlyInputCapture();182      // F1: ESC O P183      mockStdin.write(Buffer.from('\x1bOP'));184      stopEarlyInputCapture();185 186      const input = getAndClearCapturedInput();187      expect(input.toString()).toBe('\x1bOP');188    });189 190    it('should filter terminal responses split across chunks', () => {191      startEarlyInputCapture();192      mockStdin.write(Buffer.from('\x1b[?1004'));193      mockStdin.write(Buffer.from('h'));194      stopEarlyInputCapture();195 196      const input = getAndClearCapturedInput();197      expect(input.length).toBe(0);198    });199 200    it('should keep user input around split terminal responses', () => {201      startEarlyInputCapture();202      mockStdin.write(Buffer.from('a\x1b[?100'));203      mockStdin.write(Buffer.from('4hbc'));204      stopEarlyInputCapture();205 206      const input = getAndClearCapturedInput();207      expect(input.toString()).toBe('abc');208    });209 210    it('should filter terminal responses split at ESC[ prefix', () => {211      startEarlyInputCapture();212      mockStdin.write(Buffer.from('\x1b['));213      mockStdin.write(Buffer.from('?1004h'));214      stopEarlyInputCapture();215 216      const input = getAndClearCapturedInput();217      expect(input.length).toBe(0);218    });219 220    it('should filter terminal responses split at ESC prefix', () => {221      startEarlyInputCapture();222      mockStdin.write(Buffer.from('\x1b'));223      mockStdin.write(Buffer.from('[?1004h'));224      stopEarlyInputCapture();225 226      const input = getAndClearCapturedInput();227      expect(input.length).toBe(0);228    });229 230    it('should drop incomplete DEC private response on capture end', () => {231      startEarlyInputCapture();232      mockStdin.write(Buffer.from('\x1b[?1004'));233      stopEarlyInputCapture();234 235      const input = getAndClearCapturedInput();236      expect(input.length).toBe(0);237    });238 239    it('should drop incomplete OSC sequence on capture end', () => {240      startEarlyInputCapture();241      mockStdin.write(Buffer.from('\x1b]0;title'));242      stopEarlyInputCapture();243 244      const input = getAndClearCapturedInput();245      expect(input.length).toBe(0);246    });247 248    it('should keep arrow key sequence split across chunks', () => {249      startEarlyInputCapture();250      mockStdin.write(Buffer.from('\x1b['));251      mockStdin.write(Buffer.from('A'));252      stopEarlyInputCapture();253 254      const input = getAndClearCapturedInput();255      expect(input.toString()).toBe('\x1b[A');256    });257 258    it('should drop incomplete ESC[ prefix on capture end', () => {259      startEarlyInputCapture();260      mockStdin.write(Buffer.from('\x1b['));261      stopEarlyInputCapture();262 263      const input = getAndClearCapturedInput();264      expect(input.toString()).toBe('');265    });266 267    it('should replay standalone ESC on capture end', () => {268      startEarlyInputCapture();269      mockStdin.write(Buffer.from('\x1b'));270      stopEarlyInputCapture();271 272      const input = getAndClearCapturedInput();273      expect(input.toString()).toBe('\x1b');274    });275  });276 277  describe('UTF-8 handling', () => {278    it('should capture simple ASCII characters', () => {279      startEarlyInputCapture();280      mockStdin.write(Buffer.from('abc'));281      stopEarlyInputCapture();282 283      const input = getAndClearCapturedInput();284      expect(input.toString()).toBe('abc');285    });286 287    it('should capture UTF-8 multibyte characters', () => {288      startEarlyInputCapture();289      mockStdin.write(Buffer.from('你好世界'));290      stopEarlyInputCapture();291 292      const input = getAndClearCapturedInput();293      expect(input.toString()).toBe('你好世界');294    });295 296    it('should capture emoji', () => {297      startEarlyInputCapture();298      mockStdin.write(Buffer.from('👋🎉'));299      stopEarlyInputCapture();300 301      const input = getAndClearCapturedInput();302      expect(input.toString()).toBe('👋🎉');303    });304  });305 306  describe('edge cases', () => {307    it('should handle empty input', () => {308      startEarlyInputCapture();309      stopEarlyInputCapture();310 311      const input = getAndClearCapturedInput();312      expect(input.length).toBe(0);313    });314 315    it('should clear captured input after getAndClearCapturedInput', () => {316      startEarlyInputCapture();317      mockStdin.write(Buffer.from('test'));318      stopEarlyInputCapture();319 320      const input1 = getAndClearCapturedInput();321      expect(input1.toString()).toBe('test');322 323      const input2 = getAndClearCapturedInput();324      expect(input2.length).toBe(0);325    });326 327    it('should skip when QWEN_CODE_DISABLE_EARLY_CAPTURE is set', () => {328      process.env['QWEN_CODE_DISABLE_EARLY_CAPTURE'] = '1';329      startEarlyInputCapture();330      mockStdin.write(Buffer.from('a'));331      stopEarlyInputCapture();332 333      expect(hasCapturedInput()).toBe(false);334    });335 336    it('should limit buffer size', () => {337      startEarlyInputCapture();338 339      // Write more than 64KB340      const largeData = Buffer.alloc(100 * 1024, 'a');341      mockStdin.write(largeData);342      stopEarlyInputCapture();343 344      const input = getAndClearCapturedInput();345      // Should be truncated to 64KB346      expect(input.length).toBeLessThanOrEqual(64 * 1024);347    });348  });349});350 
basant307/AI_Governance_Project · CoolFace