test: fix tests

This commit is contained in:
mathuo 2024-06-19 22:09:21 +01:00
parent b96ccf00ce
commit cf8f18dbbd
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
4 changed files with 165 additions and 59 deletions

View File

@ -1,11 +1,31 @@
import { Overlay } from '../../dnd/overlay'; import { Overlay } from '../../dnd/overlay';
const mockGetBoundingClientRect = ({ left, top, height, width }: { left: number, top: number, height: number, width: number }) => { const mockGetBoundingClientRect = ({
const result = { left, top, height, width, right: left + width, bottom: top + height, x: left, y: top }; left,
top,
height,
width,
}: {
left: number;
top: number;
height: number;
width: number;
}) => {
const result = {
left,
top,
height,
width,
right: left + width,
bottom: top + height,
x: left,
y: top,
};
return { return {
...result, toJSON: () => (result) ...result,
} toJSON: () => result,
} };
};
describe('overlay', () => { describe('overlay', () => {
test('toJSON, top left', () => { test('toJSON, top left', () => {
@ -30,14 +50,26 @@ describe('overlay', () => {
container.childNodes.item(0) as HTMLElement, container.childNodes.item(0) as HTMLElement,
'getBoundingClientRect' 'getBoundingClientRect'
).mockImplementation(() => { ).mockImplementation(() => {
return mockGetBoundingClientRect({ left: 80, top: 100, width: 40, height: 50 }); return mockGetBoundingClientRect({
left: 80,
top: 100,
width: 40,
height: 50,
});
}); });
jest.spyOn(container, 'getBoundingClientRect').mockImplementation( jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => { () => {
return mockGetBoundingClientRect({ left: 20, top: 30, width: 100, height: 100 }); return mockGetBoundingClientRect({
left: 20,
top: 30,
width: 100,
height: 100,
});
} }
); );
cut.setBounds();
expect(cut.toJSON()).toEqual({ expect(cut.toJSON()).toEqual({
top: 70, top: 70,
left: 60, left: 60,
@ -68,14 +100,26 @@ describe('overlay', () => {
container.childNodes.item(0) as HTMLElement, container.childNodes.item(0) as HTMLElement,
'getBoundingClientRect' 'getBoundingClientRect'
).mockImplementation(() => { ).mockImplementation(() => {
return mockGetBoundingClientRect({ left: 80, top: 100, width: 40, height: 50 }); return mockGetBoundingClientRect({
left: 80,
top: 100,
width: 40,
height: 50,
});
}); });
jest.spyOn(container, 'getBoundingClientRect').mockImplementation( jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => { () => {
return mockGetBoundingClientRect({ left: 20, top: 30, width: 100, height: 100 }); return mockGetBoundingClientRect({
left: 20,
top: 30,
width: 100,
height: 100,
});
} }
); );
cut.setBounds();
expect(cut.toJSON()).toEqual({ expect(cut.toJSON()).toEqual({
bottom: -20, bottom: -20,
right: 0, right: 0,
@ -106,14 +150,26 @@ describe('overlay', () => {
container.childNodes.item(0) as HTMLElement, container.childNodes.item(0) as HTMLElement,
'getBoundingClientRect' 'getBoundingClientRect'
).mockImplementation(() => { ).mockImplementation(() => {
return mockGetBoundingClientRect({ left: 80, top: 100, width: 40, height: 50 }); return mockGetBoundingClientRect({
left: 80,
top: 100,
width: 40,
height: 50,
});
}); });
jest.spyOn(container, 'getBoundingClientRect').mockImplementation( jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => { () => {
return mockGetBoundingClientRect({ left: 20, top: 30, width: 100, height: 100 }); return mockGetBoundingClientRect({
left: 20,
top: 30,
width: 100,
height: 100,
});
} }
); );
cut.setBounds();
expect(cut.toJSON()).toEqual({ expect(cut.toJSON()).toEqual({
top: 70, top: 70,
left: 60, left: 60,
@ -144,14 +200,26 @@ describe('overlay', () => {
container.childNodes.item(0) as HTMLElement, container.childNodes.item(0) as HTMLElement,
'getBoundingClientRect' 'getBoundingClientRect'
).mockImplementation(() => { ).mockImplementation(() => {
return mockGetBoundingClientRect({ left: 80, top: 100, width: 40, height: 50 }); return mockGetBoundingClientRect({
left: 80,
top: 100,
width: 40,
height: 50,
});
}); });
jest.spyOn(container, 'getBoundingClientRect').mockImplementation( jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => { () => {
return mockGetBoundingClientRect({ left: 20, top: 30, width: 100, height: 100 }); return mockGetBoundingClientRect({
left: 20,
top: 30,
width: 100,
height: 100,
});
} }
); );
cut.setBounds();
expect(cut.toJSON()).toEqual({ expect(cut.toJSON()).toEqual({
bottom: -20, bottom: -20,
right: 0, right: 0,
@ -184,11 +252,21 @@ describe('overlay', () => {
expect(element).toBeTruthy(); expect(element).toBeTruthy();
jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => { jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => {
return mockGetBoundingClientRect({ left: 300, top: 400, width: 200, height: 100 }); return mockGetBoundingClientRect({
left: 300,
top: 400,
width: 200,
height: 100,
});
}); });
jest.spyOn(container, 'getBoundingClientRect').mockImplementation( jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => { () => {
return mockGetBoundingClientRect({ left: 0, top: 0, width: 1000, height: 1000 }); return mockGetBoundingClientRect({
left: 0,
top: 0,
width: 1000,
height: 1000,
});
} }
); );
@ -224,11 +302,21 @@ describe('overlay', () => {
expect(element).toBeTruthy(); expect(element).toBeTruthy();
jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => { jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => {
return mockGetBoundingClientRect({ left: 500, top: 500, width: 200, height: 100 }); return mockGetBoundingClientRect({
left: 500,
top: 500,
width: 200,
height: 100,
});
}); });
jest.spyOn(container, 'getBoundingClientRect').mockImplementation( jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => { () => {
return mockGetBoundingClientRect({ left: 0, top: 0, width: 1000, height: 1000 }); return mockGetBoundingClientRect({
left: 0,
top: 0,
width: 1000,
height: 1000,
});
} }
); );

View File

@ -40,6 +40,9 @@ export class Overlay extends CompositeDisposable {
private static MINIMUM_HEIGHT = 20; private static MINIMUM_HEIGHT = 20;
private static MINIMUM_WIDTH = 20; private static MINIMUM_WIDTH = 20;
private verticalAlignment: 'top' | 'bottom' | undefined;
private horiziontalAlignment: 'left' | 'right' | undefined;
set minimumInViewportWidth(value: number | undefined) { set minimumInViewportWidth(value: number | undefined) {
this.options.minimumInViewportWidth = value; this.options.minimumInViewportWidth = value;
} }
@ -78,10 +81,10 @@ export class Overlay extends CompositeDisposable {
this.setBounds({ this.setBounds({
height: this.options.height, height: this.options.height,
width: this.options.width, width: this.options.width,
...("top" in this.options && { top: this.options.top }), ...('top' in this.options && { top: this.options.top }),
...("bottom" in this.options && { bottom: this.options.bottom }), ...('bottom' in this.options && { bottom: this.options.bottom }),
...("left" in this.options && { left: this.options.left }), ...('left' in this.options && { left: this.options.left }),
...("right" in this.options && { right: this.options.right }) ...('right' in this.options && { right: this.options.right }),
}); });
} }
@ -92,21 +95,25 @@ export class Overlay extends CompositeDisposable {
if (typeof bounds.width === 'number') { if (typeof bounds.width === 'number') {
this._element.style.width = `${bounds.width}px`; this._element.style.width = `${bounds.width}px`;
} }
if ("top" in bounds && typeof bounds.top === 'number') { if ('top' in bounds && typeof bounds.top === 'number') {
this._element.style.top = `${bounds.top}px`; this._element.style.top = `${bounds.top}px`;
this._element.style.bottom = "auto"; this._element.style.bottom = 'auto';
this.verticalAlignment = 'top';
} }
if ("bottom" in bounds && typeof bounds.bottom === 'number') { if ('bottom' in bounds && typeof bounds.bottom === 'number') {
this._element.style.bottom = `${bounds.bottom}px`; this._element.style.bottom = `${bounds.bottom}px`;
this._element.style.top = "auto"; this._element.style.top = 'auto';
this.verticalAlignment = 'bottom';
} }
if ("left" in bounds && typeof bounds.left === 'number') { if ('left' in bounds && typeof bounds.left === 'number') {
this._element.style.left = `${bounds.left}px`; this._element.style.left = `${bounds.left}px`;
this._element.style.right = "auto"; this._element.style.right = 'auto';
this.horiziontalAlignment = 'left';
} }
if ("right" in bounds && typeof bounds.right === 'number') { if ('right' in bounds && typeof bounds.right === 'number') {
this._element.style.right = `${bounds.right}px`; this._element.style.right = `${bounds.right}px`;
this._element.style.left = "auto"; this._element.style.left = 'auto';
this.horiziontalAlignment = 'right';
} }
const containerRect = this.options.container.getBoundingClientRect(); const containerRect = this.options.container.getBoundingClientRect();
@ -120,44 +127,44 @@ export class Overlay extends CompositeDisposable {
// a minimum height of minimumViewportHeight must be inside the viewport // a minimum height of minimumViewportHeight must be inside the viewport
const yOffset = Math.max(0, this.getMinimumHeight(overlayRect.height)); const yOffset = Math.max(0, this.getMinimumHeight(overlayRect.height));
if ("top" in bounds && typeof bounds.top === 'number') { if (this.verticalAlignment === 'top') {
const top = clamp( const top = clamp(
overlayRect.top - containerRect.top, overlayRect.top - containerRect.top,
-yOffset, -yOffset,
Math.max(0, containerRect.height - overlayRect.height + yOffset) Math.max(0, containerRect.height - overlayRect.height + yOffset)
); );
this._element.style.top = `${top}px`; this._element.style.top = `${top}px`;
this._element.style.bottom = "auto"; this._element.style.bottom = 'auto';
} }
if ("bottom" in bounds && typeof bounds.bottom === 'number') { if (this.verticalAlignment === 'bottom') {
const bottom = clamp( const bottom = clamp(
containerRect.bottom - overlayRect.bottom, containerRect.bottom - overlayRect.bottom,
-yOffset, -yOffset,
Math.max(0, containerRect.height - overlayRect.height + yOffset) Math.max(0, containerRect.height - overlayRect.height + yOffset)
); );
this._element.style.bottom = `${bottom}px`; this._element.style.bottom = `${bottom}px`;
this._element.style.top = "auto"; this._element.style.top = 'auto';
} }
if ("left" in bounds && typeof bounds.left === 'number') { if (this.horiziontalAlignment === 'left') {
const left = clamp( const left = clamp(
overlayRect.left - containerRect.left, overlayRect.left - containerRect.left,
-xOffset, -xOffset,
Math.max(0, containerRect.width - overlayRect.width + xOffset) Math.max(0, containerRect.width - overlayRect.width + xOffset)
); );
this._element.style.left = `${left}px`; this._element.style.left = `${left}px`;
this._element.style.right = "auto"; this._element.style.right = 'auto';
} }
if ("right" in bounds && typeof bounds.right === 'number') { if (this.horiziontalAlignment === 'right') {
const right = clamp( const right = clamp(
containerRect.right - overlayRect.right, containerRect.right - overlayRect.right,
-xOffset, -xOffset,
Math.max(0, containerRect.width - overlayRect.width + xOffset) Math.max(0, containerRect.width - overlayRect.width + xOffset)
); );
this._element.style.right = `${right}px`; this._element.style.right = `${right}px`;
this._element.style.left = "auto"; this._element.style.left = 'auto';
} }
this._onDidChange.fire(); this._onDidChange.fire();
@ -169,17 +176,17 @@ export class Overlay extends CompositeDisposable {
const result: any = {}; const result: any = {};
if (this._element.style.top !== "auto") { if (this.verticalAlignment === 'top') {
result.top = parseFloat(this._element.style.top); result.top = parseFloat(this._element.style.top);
} else if (this._element.style.bottom !== "auto") { } else if (this.verticalAlignment === 'bottom') {
result.bottom = parseFloat(this._element.style.bottom); result.bottom = parseFloat(this._element.style.bottom);
} else { } else {
result.top = element.top - container.top; result.top = element.top - container.top;
} }
if (this._element.style.left !== "auto") { if (this.horiziontalAlignment === 'left') {
result.left = parseFloat(this._element.style.left); result.left = parseFloat(this._element.style.left);
} else if (this._element.style.right !== "auto") { } else if (this.horiziontalAlignment === 'right') {
result.right = parseFloat(this._element.style.right); result.right = parseFloat(this._element.style.right);
} else { } else {
result.left = element.left - container.left; result.left = element.left - container.left;
@ -256,7 +263,10 @@ export class Overlay extends CompositeDisposable {
); );
const bottom = clamp( const bottom = clamp(
offset.y - y + containerRect.height - overlayRect.height, offset.y -
y +
containerRect.height -
overlayRect.height,
-yOffset, -yOffset,
Math.max( Math.max(
0, 0,
@ -437,7 +447,9 @@ export class Overlay extends CompositeDisposable {
startPosition!.originalY + startPosition!.originalY +
startPosition!.originalHeight > startPosition!.originalHeight >
containerRect.height containerRect.height
? this.getMinimumHeight(containerRect.height) ? this.getMinimumHeight(
containerRect.height
)
: Math.max( : Math.max(
0, 0,
startPosition!.originalY + startPosition!.originalY +

View File

@ -1008,7 +1008,7 @@ export class DockviewComponent
this.options.floatingGroupBounds?.minimumWidthWithinViewport; this.options.floatingGroupBounds?.minimumWidthWithinViewport;
} }
group.overlay.setBounds({}); group.overlay.setBounds();
} }
} }

View File

@ -9,6 +9,12 @@ export interface Box {
width: number; width: number;
} }
export type AnchoredBox = type TopLeft = { top: number; left: number };
({ top: number, height: number } | { bottom: number, height: number }) & type TopRight = { top: number; right: number };
({ left: number, width: number } | { right: number, width: number }); type BottomLeft = { bottom: number; left: number };
type BottomRight = { bottom: number; right: number };
type AnchorPosition = TopLeft | TopRight | BottomLeft | BottomRight;
type Size = { width: number; height: number };
export type AnchoredBox = Size & AnchorPosition;