feat(auth): improve API key authentication flow (#11760)

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
Gal Zahavi
2025-10-29 18:58:08 -07:00
committed by GitHub
parent 6c8a48db13
commit 06035d5d43
25 changed files with 1216 additions and 76 deletions

View File

@@ -14,6 +14,7 @@ import type {
TextBufferState,
TextBufferAction,
VisualLayout,
TextBufferOptions,
} from './text-buffer.js';
import {
useTextBuffer,
@@ -101,6 +102,43 @@ describe('textBufferReducer', () => {
});
});
describe('insert action with options', () => {
it('should filter input using inputFilter option', () => {
const action: TextBufferAction = { type: 'insert', payload: 'a1b2c3' };
const options: TextBufferOptions = {
inputFilter: (text) => text.replace(/[0-9]/g, ''),
};
const state = textBufferReducer(initialState, action, options);
expect(state.lines).toEqual(['abc']);
expect(state.cursorCol).toBe(3);
});
it('should strip newlines when singleLine option is true', () => {
const action: TextBufferAction = {
type: 'insert',
payload: 'hello\nworld',
};
const options: TextBufferOptions = { singleLine: true };
const state = textBufferReducer(initialState, action, options);
expect(state.lines).toEqual(['helloworld']);
expect(state.cursorCol).toBe(10);
});
it('should apply both inputFilter and singleLine options', () => {
const action: TextBufferAction = {
type: 'insert',
payload: 'h\ne\nl\nl\no\n1\n2\n3',
};
const options: TextBufferOptions = {
singleLine: true,
inputFilter: (text) => text.replace(/[0-9]/g, ''),
};
const state = textBufferReducer(initialState, action, options);
expect(state.lines).toEqual(['hello']);
expect(state.cursorCol).toBe(5);
});
});
describe('backspace action', () => {
it('should remove a character', () => {
const stateWithText: TextBufferState = {
@@ -1520,6 +1558,75 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
});
});
describe('inputFilter', () => {
it('should filter input based on the provided filter function', () => {
const { result } = renderHook(() =>
useTextBuffer({
viewport,
isValidPath: () => false,
inputFilter: (text) => text.replace(/[^0-9]/g, ''),
}),
);
act(() => result.current.insert('a1b2c3'));
expect(getBufferState(result).text).toBe('123');
});
it('should handle empty result from filter', () => {
const { result } = renderHook(() =>
useTextBuffer({
viewport,
isValidPath: () => false,
inputFilter: (text) => text.replace(/[^0-9]/g, ''),
}),
);
act(() => result.current.insert('abc'));
expect(getBufferState(result).text).toBe('');
});
it('should filter pasted text', () => {
const { result } = renderHook(() =>
useTextBuffer({
viewport,
isValidPath: () => false,
inputFilter: (text) => text.toUpperCase(),
}),
);
act(() => result.current.insert('hello', { paste: true }));
expect(getBufferState(result).text).toBe('HELLO');
});
it('should not filter newlines if they are allowed by the filter', () => {
const { result } = renderHook(() =>
useTextBuffer({
viewport,
isValidPath: () => false,
inputFilter: (text) => text, // Allow everything including newlines
}),
);
act(() => result.current.insert('a\nb'));
// The insert function splits by newline and inserts separately if it detects them.
// If the filter allows them, they should be handled correctly by the subsequent logic in insert.
expect(getBufferState(result).text).toBe('a\nb');
});
it('should filter before newline check in insert', () => {
const { result } = renderHook(() =>
useTextBuffer({
viewport,
isValidPath: () => false,
inputFilter: (text) => text.replace(/\n/g, ''), // Filter out newlines
}),
);
act(() => result.current.insert('a\nb'));
expect(getBufferState(result).text).toBe('ab');
});
});
describe('stripAnsi', () => {
it('should correctly strip ANSI escape codes', () => {
const textWithAnsi = '\x1B[31mHello\x1B[0m World';
@@ -1587,6 +1694,74 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
expect(getBufferState(result).text).toBe('hello world');
});
});
describe('singleLine mode', () => {
it('should not insert a newline character when singleLine is true', () => {
const { result } = renderHook(() =>
useTextBuffer({
viewport,
isValidPath: () => false,
singleLine: true,
}),
);
act(() => result.current.insert('\n'));
const state = getBufferState(result);
expect(state.text).toBe('');
expect(state.lines).toEqual(['']);
});
it('should not create a new line when newline() is called and singleLine is true', () => {
const { result } = renderHook(() =>
useTextBuffer({
initialText: 'ab',
viewport,
isValidPath: () => false,
singleLine: true,
}),
);
act(() => result.current.move('end')); // cursor at [0,2]
act(() => result.current.newline());
const state = getBufferState(result);
expect(state.text).toBe('ab');
expect(state.lines).toEqual(['ab']);
expect(state.cursor).toEqual([0, 2]);
});
it('should not handle "Enter" key as newline when singleLine is true', () => {
const { result } = renderHook(() =>
useTextBuffer({
viewport,
isValidPath: () => false,
singleLine: true,
}),
);
act(() =>
result.current.handleInput({
name: 'return',
ctrl: false,
meta: false,
shift: false,
paste: false,
sequence: '\r',
}),
);
expect(getBufferState(result).lines).toEqual(['']);
});
it('should strip newlines from pasted text when singleLine is true', () => {
const { result } = renderHook(() =>
useTextBuffer({
viewport,
isValidPath: () => false,
singleLine: true,
}),
);
act(() => result.current.insert('hello\nworld', { paste: true }));
const state = getBufferState(result);
expect(state.text).toBe('helloworld');
expect(state.lines).toEqual(['helloworld']);
});
});
});
describe('offsetToLogicalPos', () => {