# test.web/core/observers/tab.observer.test.ts

> 41 lines of code and 0 definitions.

Tree: Codebase Testing
Language: typescript
Canonical: https://banes-lab.com/anatomy/testing#file-testing-test-web-core-observers-tab-observer-test-ts
Source text: https://banes-lab.com/source/testing/test.web/core/observers/tab.observer.test.ts.txt

Listed in [test.web/core/observers](https://banes-lab.com/api/source/testing/test.web/core/observers.md), after [test.web/core/observers/route.observer.test.ts](https://banes-lab.com/source/testing/test.web/core/observers/route.observer.test.ts.md).

## Contained in

- [test.web/core/observers](https://banes-lab.com/anatomy/testing/folder-testing-test-web-core-observers.md)

## Source

```typescript
import { PINNED_CLASS, PIN_OFFSET_PX } from "@banes-lab/web/configuration/constants/tab.constants.ts";
import { afterEach, describe, expect, it } from "vitest";
import { createElement } from "@banes-lab/web/core/factories/element.factory.ts";
import { observePin } from "@banes-lab/web/core/observers/tab.observer.ts";

const ANCHOR_TOP = 200;

afterEach(() => {
    document.body.replaceChildren();
});

const mount = function mount(): {
    readonly anchor: HTMLElement;
    readonly scroller: HTMLElement;
    readonly tabs: HTMLElement;
} {
    const tabs = createElement("div");
    const anchor = createElement("div", { children: [tabs] });
    const scroller = createElement("main", { children: [anchor] });
    document.body.append(scroller);
    Object.defineProperty(anchor, "offsetTop", { configurable: true, value: ANCHOR_TOP });
    return { anchor, scroller, tabs };
};

describe("observePin", () => {
    it("pins the tabs once the scroller passes the anchor", () => {
        const { anchor, scroller, tabs } = mount();
        const dispose = observePin(scroller, anchor, tabs);
        scroller.scrollTop = ANCHOR_TOP;
        scroller.dispatchEvent(new Event("scroll"));
        expect(tabs.classList.contains(PINNED_CLASS)).toBe(true);
        scroller.scrollTop = ANCHOR_TOP - PIN_OFFSET_PX - 1;
        scroller.dispatchEvent(new Event("scroll"));
        expect(tabs.classList.contains(PINNED_CLASS)).toBe(false);
        dispose();
    });

    it("stops reacting after the disposer runs", () => {
        const { anchor, scroller, tabs } = mount();
        const dispose = observePin(scroller, anchor, tabs);
        dispose();
        scroller.scrollTop = ANCHOR_TOP;
        scroller.dispatchEvent(new Event("scroll"));
        expect(tabs.classList.contains(PINNED_CLASS)).toBe(false);
    });
});
```
