diff --git a/packages/happy-dom/src/window/IWindow.ts b/packages/happy-dom/src/window/IWindow.ts index 3cb9eed83..019cfc9b4 100644 --- a/packages/happy-dom/src/window/IWindow.ts +++ b/packages/happy-dom/src/window/IWindow.ts @@ -245,6 +245,10 @@ export default interface IWindow extends IEventTarget, NodeJS.Global { readonly sessionStorage: Storage; readonly localStorage: Storage; readonly performance: Performance; + readonly pageXOffset: number; + readonly pageYOffset: number; + readonly scrollX: number; + readonly scrollY: number; /** * Evaluates code. diff --git a/packages/happy-dom/src/window/Window.ts b/packages/happy-dom/src/window/Window.ts index ac232fb9a..1c1638b85 100644 --- a/packages/happy-dom/src/window/Window.ts +++ b/packages/happy-dom/src/window/Window.ts @@ -483,6 +483,42 @@ export default class Window extends EventTarget implements IWindow { this.document._onWindowReady(); } + /** + * The number of pixels that the document is currently scrolled horizontally + * + * @returns number + */ + public get scrollX(): number { + return this.document?.documentElement?.scrollLeft ?? 0; + } + + /** + * The read-only Window property pageXOffset is an alias for scrollX. + * + * @returns number + */ + public get pageXOffset(): number { + return this.scrollX; + } + + /** + * The number of pixels that the document is currently scrolled vertically + * + * @returns number + */ + public get scrollY(): number { + return this.document?.documentElement?.scrollTop ?? 0; + } + + /** + * The read-only Window property pageYOffset is an alias for scrollY. + * + * @returns number + */ + public get pageYOffset(): number { + return this.scrollY; + } + /** * The CSS interface holds useful CSS-related methods. * diff --git a/packages/happy-dom/test/window/Window.test.ts b/packages/happy-dom/test/window/Window.test.ts index 92fb7aa55..99304c204 100644 --- a/packages/happy-dom/test/window/Window.test.ts +++ b/packages/happy-dom/test/window/Window.test.ts @@ -667,37 +667,63 @@ describe('Window', () => { for (const functionName of ['scroll', 'scrollTo']) { describe(`${functionName}()`, () => { - it('Sets the properties scrollTop and scrollLeft.', () => { + it('Sets the properties scrollTop, scrollLeft, scrollY, scrollX, pageXOffset and pageYOffset', () => { window[functionName](50, 60); expect(window.document.documentElement.scrollLeft).toBe(50); expect(window.document.documentElement.scrollTop).toBe(60); + expect(window.pageXOffset).toBe(50); + expect(window.pageYOffset).toBe(60); + expect(window.scrollX).toBe(50); + expect(window.scrollY).toBe(60); }); - it('Sets the properties scrollTop and scrollLeft using object.', () => { + it('Sets the properties scrollTop, scrollLeft, scrollY, scrollX, pageXOffset and pageYOffset using object.', () => { window[functionName]({ left: 50, top: 60 }); expect(window.document.documentElement.scrollLeft).toBe(50); expect(window.document.documentElement.scrollTop).toBe(60); + expect(window.pageXOffset).toBe(50); + expect(window.pageYOffset).toBe(60); + expect(window.scrollX).toBe(50); + expect(window.scrollY).toBe(60); }); - it('Sets only the property scrollTop.', () => { + it('Sets only the property scrollTop, pageYOffset, and scrollY', () => { window[functionName]({ top: 60 }); expect(window.document.documentElement.scrollLeft).toBe(0); expect(window.document.documentElement.scrollTop).toBe(60); + expect(window.pageXOffset).toBe(0); + expect(window.pageYOffset).toBe(60); + expect(window.scrollX).toBe(0); + expect(window.scrollY).toBe(60); }); - it('Sets only the property scrollLeft.', () => { + it('Sets only the property scrollLeft, pageXOffset, and scrollX', () => { window[functionName]({ left: 60 }); expect(window.document.documentElement.scrollLeft).toBe(60); expect(window.document.documentElement.scrollTop).toBe(0); + expect(window.document.documentElement.scrollLeft).toBe(60); + expect(window.document.documentElement.scrollTop).toBe(0); + expect(window.pageXOffset).toBe(60); + expect(window.pageYOffset).toBe(0); + expect(window.scrollX).toBe(60); + expect(window.scrollY).toBe(0); }); - it('Sets the properties scrollTop and scrollLeft with animation.', async () => { + it('Sets the properties scrollTop, scrollLeft, scrollY, scrollX, pageXOffset and pageYOffset with animation.', async () => { window[functionName]({ left: 50, top: 60, behavior: 'smooth' }); expect(window.document.documentElement.scrollLeft).toBe(0); expect(window.document.documentElement.scrollTop).toBe(0); + expect(window.pageXOffset).toBe(0); + expect(window.pageYOffset).toBe(0); + expect(window.scrollX).toBe(0); + expect(window.scrollY).toBe(0); await window.happyDOM.whenAsyncComplete(); expect(window.document.documentElement.scrollLeft).toBe(50); expect(window.document.documentElement.scrollTop).toBe(60); + expect(window.pageXOffset).toBe(50); + expect(window.pageYOffset).toBe(60); + expect(window.scrollX).toBe(50); + expect(window.scrollY).toBe(60); }); }); }