mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-22 02:54:31 -07:00
jacob314/drag scrollbar (#12998)
This commit is contained in:
@@ -46,6 +46,7 @@ const TestScrollable = forwardRef(
|
||||
props: {
|
||||
id: string;
|
||||
scrollBy: (delta: number) => void;
|
||||
scrollTo?: (scrollTop: number) => void;
|
||||
getScrollState: () => ScrollState;
|
||||
},
|
||||
ref,
|
||||
@@ -58,6 +59,7 @@ const TestScrollable = forwardRef(
|
||||
ref: elementRef as RefObject<DOMElement>,
|
||||
getScrollState: props.getScrollState,
|
||||
scrollBy: props.scrollBy,
|
||||
scrollTo: props.scrollTo,
|
||||
hasFocus: () => true,
|
||||
flashScrollbar: () => {},
|
||||
},
|
||||
@@ -79,6 +81,82 @@ describe('ScrollProvider', () => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('calls scrollTo when clicking scrollbar track if available', async () => {
|
||||
const scrollBy = vi.fn();
|
||||
const scrollTo = vi.fn();
|
||||
const getScrollState = vi.fn(() => ({
|
||||
scrollTop: 0,
|
||||
scrollHeight: 100,
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
scrollBy={scrollBy}
|
||||
scrollTo={scrollTo}
|
||||
getScrollState={getScrollState}
|
||||
/>
|
||||
</ScrollProvider>,
|
||||
);
|
||||
|
||||
// Scrollbar is at x + width = 0 + 10 = 10.
|
||||
// Height is 10. y is 0.
|
||||
// Click at col 10, row 5.
|
||||
// Thumb height = 10/100 * 10 = 1.
|
||||
// Max thumb Y = 10 - 1 = 9.
|
||||
// Current thumb Y = 0.
|
||||
// Click at row 5 (relative Y = 5). This is outside the thumb (0).
|
||||
// It's a track click.
|
||||
|
||||
for (const callback of mockUseMouseCallbacks) {
|
||||
callback({
|
||||
name: 'left-press',
|
||||
col: 10,
|
||||
row: 5,
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
});
|
||||
}
|
||||
|
||||
expect(scrollTo).toHaveBeenCalled();
|
||||
expect(scrollBy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls scrollBy when clicking scrollbar track if scrollTo is not available', async () => {
|
||||
const scrollBy = vi.fn();
|
||||
const getScrollState = vi.fn(() => ({
|
||||
scrollTop: 0,
|
||||
scrollHeight: 100,
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
scrollBy={scrollBy}
|
||||
getScrollState={getScrollState}
|
||||
/>
|
||||
</ScrollProvider>,
|
||||
);
|
||||
|
||||
for (const callback of mockUseMouseCallbacks) {
|
||||
callback({
|
||||
name: 'left-press',
|
||||
col: 10,
|
||||
row: 5,
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
});
|
||||
}
|
||||
|
||||
expect(scrollBy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('batches multiple scroll events into a single update', async () => {
|
||||
const scrollBy = vi.fn();
|
||||
const getScrollState = vi.fn(() => ({
|
||||
@@ -234,4 +312,120 @@ describe('ScrollProvider', () => {
|
||||
expect(scrollBy).toHaveBeenCalledTimes(1);
|
||||
expect(scrollBy).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it('calls scrollTo when dragging scrollbar thumb if available', async () => {
|
||||
const scrollBy = vi.fn();
|
||||
const scrollTo = vi.fn();
|
||||
const getScrollState = vi.fn(() => ({
|
||||
scrollTop: 0,
|
||||
scrollHeight: 100,
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
scrollBy={scrollBy}
|
||||
scrollTo={scrollTo}
|
||||
getScrollState={getScrollState}
|
||||
/>
|
||||
</ScrollProvider>,
|
||||
);
|
||||
|
||||
// Start drag on thumb
|
||||
for (const callback of mockUseMouseCallbacks) {
|
||||
callback({
|
||||
name: 'left-press',
|
||||
col: 10,
|
||||
row: 0,
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
});
|
||||
}
|
||||
|
||||
// Move mouse down
|
||||
for (const callback of mockUseMouseCallbacks) {
|
||||
callback({
|
||||
name: 'move',
|
||||
col: 10,
|
||||
row: 5, // Move down 5 units
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
});
|
||||
}
|
||||
|
||||
// Release
|
||||
for (const callback of mockUseMouseCallbacks) {
|
||||
callback({
|
||||
name: 'left-release',
|
||||
col: 10,
|
||||
row: 5,
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
});
|
||||
}
|
||||
|
||||
expect(scrollTo).toHaveBeenCalled();
|
||||
expect(scrollBy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls scrollBy when dragging scrollbar thumb if scrollTo is not available', async () => {
|
||||
const scrollBy = vi.fn();
|
||||
const getScrollState = vi.fn(() => ({
|
||||
scrollTop: 0,
|
||||
scrollHeight: 100,
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
scrollBy={scrollBy}
|
||||
getScrollState={getScrollState}
|
||||
/>
|
||||
</ScrollProvider>,
|
||||
);
|
||||
|
||||
// Start drag on thumb
|
||||
for (const callback of mockUseMouseCallbacks) {
|
||||
callback({
|
||||
name: 'left-press',
|
||||
col: 10,
|
||||
row: 0,
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
});
|
||||
}
|
||||
|
||||
// Move mouse down
|
||||
for (const callback of mockUseMouseCallbacks) {
|
||||
callback({
|
||||
name: 'move',
|
||||
col: 10,
|
||||
row: 5,
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
});
|
||||
}
|
||||
|
||||
for (const callback of mockUseMouseCallbacks) {
|
||||
callback({
|
||||
name: 'left-release',
|
||||
col: 10,
|
||||
row: 5,
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
});
|
||||
}
|
||||
|
||||
expect(scrollBy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user