mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-05-17 07:59:40 +03:00
TrinsicObserver with tests
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { createDOM } from 'support/dom';
|
||||
import { getEnvironment } from 'environment';
|
||||
import { createSizeObserver } from 'overlayscrollbars/observers/SizeObserver';
|
||||
import { createTrinsicObserver } from 'overlayscrollbars/observers/TrinsicObserver';
|
||||
|
||||
const abc = {
|
||||
a: 1,
|
||||
@@ -12,6 +13,7 @@ export default () => {
|
||||
return [
|
||||
getEnvironment(),
|
||||
createSizeObserver(document.body, () => {}),
|
||||
createTrinsicObserver(document.body, () => {}),
|
||||
createDOM(
|
||||
'\
|
||||
<div class="os-host">\
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import './sizeobserver.scss';
|
||||
@import './trinsicobserver.scss';
|
||||
|
||||
#os-environment {
|
||||
position: fixed;
|
||||
|
||||
@@ -52,7 +52,7 @@ export const createSizeObserver = (
|
||||
onSizeChangedCallback(dir === true);
|
||||
};
|
||||
const offListeners: (() => void)[] = [];
|
||||
let appearCallback: (...args: any) => any = onSizeChangedCallbackProxy;
|
||||
let appearCallback: ((...args: any) => any) | null = appear ? onSizeChangedCallbackProxy : null;
|
||||
|
||||
if (ResizeObserverConstructor) {
|
||||
const resizeObserverInstance = new ResizeObserverConstructor(onSizeChangedCallbackProxy);
|
||||
@@ -81,7 +81,9 @@ export const createSizeObserver = (
|
||||
};
|
||||
const onResized = function () {
|
||||
rAFId = 0;
|
||||
if (!isDirty) return;
|
||||
if (!isDirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
cacheSize = currSize;
|
||||
onSizeChangedCallbackProxy();
|
||||
@@ -114,7 +116,7 @@ export const createSizeObserver = (
|
||||
height: scrollAmount,
|
||||
});
|
||||
reset();
|
||||
appearCallback = onScroll;
|
||||
appearCallback = appear ? onScroll : reset;
|
||||
}
|
||||
|
||||
if (direction) {
|
||||
@@ -140,7 +142,8 @@ export const createSizeObserver = (
|
||||
);
|
||||
}
|
||||
|
||||
if (appear) {
|
||||
// appearCallback is always needed on scroll-observer strategy to reset it
|
||||
if (appearCallback) {
|
||||
addClass(sizeObserver, classNameSizeObserverAppear);
|
||||
offListeners.push(on(sizeObserver, animationStartEventName, appearCallback));
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ export const createTrinsicObserver = (
|
||||
createSizeObserver(trinsicObserver, () => {
|
||||
const newSize = offsetSize(trinsicObserver);
|
||||
const newHeightIntrinsic = newSize.h === 0;
|
||||
|
||||
if (newHeightIntrinsic !== heightIntrinsic) {
|
||||
onTrinsicChangedCallback(false, newSize.h === 0);
|
||||
heightIntrinsic = newHeightIntrinsic;
|
||||
|
||||
@@ -75,7 +75,7 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any)
|
||||
|
||||
if (dimensions && (offsetSizeChanged || dirChanged)) {
|
||||
await waitFor(
|
||||
async () => {
|
||||
() => {
|
||||
if (offsetSizeChanged) {
|
||||
should.equal(sizeIterations, currSizeIterations + 1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
import 'overlayscrollbars.scss';
|
||||
import './index.scss';
|
||||
import should from 'should';
|
||||
import { waitFor } from '@testing-library/dom';
|
||||
import { generateSelectCallback, iterateSelect, selectOption } from '@/testing-browser/Select';
|
||||
import { timeout } from '@/testing-browser/timeout';
|
||||
import { setTestResult } from '@/testing-browser/TestResult';
|
||||
import { offsetSize } from 'support';
|
||||
|
||||
import { createTrinsicObserver } from 'overlayscrollbars/observers/TrinsicObserver';
|
||||
|
||||
const waitForOptions = {
|
||||
onTimeout(error: Error): Error {
|
||||
setTestResult(false);
|
||||
return error;
|
||||
},
|
||||
};
|
||||
|
||||
let heightIterations = 0;
|
||||
let heightIntrinsicCache: boolean;
|
||||
const envElm = document.querySelector('#env');
|
||||
const targetElm = document.querySelector('#target');
|
||||
const checkElm = document.querySelector('#check');
|
||||
const envHeightSelect: HTMLSelectElement | null = document.querySelector('#envHeight');
|
||||
const targetHeightSelect: HTMLSelectElement | null = document.querySelector('#targetHeight');
|
||||
const displaySelect: HTMLSelectElement | null = document.querySelector('#display');
|
||||
const startBtn: HTMLButtonElement | null = document.querySelector('#start');
|
||||
const changesSlot: HTMLButtonElement | null = document.querySelector('#changes');
|
||||
|
||||
const envElmSelectCallback = generateSelectCallback(envElm as HTMLElement);
|
||||
const targetElmSelectCallback = generateSelectCallback(targetElm as HTMLElement);
|
||||
|
||||
envHeightSelect?.addEventListener('change', envElmSelectCallback);
|
||||
targetHeightSelect?.addEventListener('change', targetElmSelectCallback);
|
||||
displaySelect?.addEventListener('change', targetElmSelectCallback);
|
||||
|
||||
envElmSelectCallback(envHeightSelect);
|
||||
targetElmSelectCallback(targetHeightSelect);
|
||||
targetElmSelectCallback(displaySelect);
|
||||
|
||||
const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any) => {
|
||||
interface IterateSelect {
|
||||
currHeightIterations: number;
|
||||
currHeightIntrinsic: boolean;
|
||||
}
|
||||
|
||||
await iterateSelect<IterateSelect>(select, {
|
||||
beforeEach() {
|
||||
const currHeightIterations = heightIterations;
|
||||
const currHeightIntrinsic = offsetSize(checkElm as HTMLElement).h === 0;
|
||||
return {
|
||||
currHeightIterations,
|
||||
currHeightIntrinsic,
|
||||
};
|
||||
},
|
||||
async check({ currHeightIterations, currHeightIntrinsic }) {
|
||||
const newHeightIntrinsic = offsetSize(checkElm as HTMLElement).h === 0;
|
||||
const trinsicHeightChanged = newHeightIntrinsic !== currHeightIntrinsic;
|
||||
|
||||
await waitFor(() => {
|
||||
if (trinsicHeightChanged) {
|
||||
should.equal(heightIterations, currHeightIterations + 1);
|
||||
}
|
||||
}, waitForOptions);
|
||||
},
|
||||
afterEach,
|
||||
});
|
||||
};
|
||||
|
||||
const iterateEnvHeight = async (afterEach?: () => any) => {
|
||||
await iterate(envHeightSelect, afterEach);
|
||||
};
|
||||
const iterateTargetHeight = async (afterEach?: () => any) => {
|
||||
await iterate(targetHeightSelect, afterEach);
|
||||
};
|
||||
const changeWhileHidden = async () => {
|
||||
selectOption(targetHeightSelect as HTMLSelectElement, 'targetHeightHundred');
|
||||
|
||||
const autoToHundred = async () => {
|
||||
selectOption(envHeightSelect as HTMLSelectElement, 'envHeightAuto');
|
||||
selectOption(displaySelect as HTMLSelectElement, 'displayNone');
|
||||
|
||||
await timeout(250);
|
||||
|
||||
selectOption(envHeightSelect as HTMLSelectElement, 'envHeightHundred');
|
||||
selectOption(displaySelect as HTMLSelectElement, 'displayBlock');
|
||||
|
||||
await waitFor(() => {
|
||||
should.equal(heightIntrinsicCache, false);
|
||||
}, waitForOptions);
|
||||
};
|
||||
|
||||
const hundredToAuto = async () => {
|
||||
selectOption(envHeightSelect as HTMLSelectElement, 'envHeightHundred');
|
||||
selectOption(displaySelect as HTMLSelectElement, 'displayNone');
|
||||
|
||||
await timeout(250);
|
||||
|
||||
selectOption(envHeightSelect as HTMLSelectElement, 'envHeightAuto');
|
||||
selectOption(displaySelect as HTMLSelectElement, 'displayBlock');
|
||||
|
||||
await waitFor(() => {
|
||||
should.equal(heightIntrinsicCache, true);
|
||||
}, waitForOptions);
|
||||
};
|
||||
|
||||
await autoToHundred();
|
||||
await hundredToAuto();
|
||||
await autoToHundred();
|
||||
await hundredToAuto();
|
||||
};
|
||||
|
||||
const start = async () => {
|
||||
setTestResult(null);
|
||||
|
||||
targetElm?.removeAttribute('style');
|
||||
await iterateEnvHeight();
|
||||
await iterateTargetHeight();
|
||||
await iterateEnvHeight(async () => {
|
||||
await iterateTargetHeight();
|
||||
});
|
||||
await changeWhileHidden();
|
||||
|
||||
setTestResult(true);
|
||||
};
|
||||
|
||||
startBtn?.addEventListener('click', start);
|
||||
|
||||
createTrinsicObserver(targetElm as HTMLElement, (widthIntrinsic: boolean, heightIntrinsic: boolean) => {
|
||||
if (heightIntrinsic !== heightIntrinsicCache) {
|
||||
heightIterations += 1;
|
||||
heightIntrinsicCache = heightIntrinsic;
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
if (changesSlot) {
|
||||
changesSlot.textContent = heightIterations.toString();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
export { start };
|
||||
@@ -0,0 +1,31 @@
|
||||
<div id="controls">
|
||||
<label for="display">display</label>
|
||||
<select name="display" id="display">
|
||||
<option value="displayBlock">block</option>
|
||||
<option value="displayNone">none</option>
|
||||
</select>
|
||||
<label for="envHeight">envHeight</label>
|
||||
<select name="envHeight" id="envHeight">
|
||||
<option value="envHeightAuto">auto</option>
|
||||
<option value="envHeightHundred">100%</option>
|
||||
<option value="envHeight200">200px</option>
|
||||
</select>
|
||||
<label for="targetHeight">targetHeight</label>
|
||||
<select name="targetHeight" id="targetHeight">
|
||||
<option value="targetHeightAuto">auto</option>
|
||||
<option value="targetHeightHundred">100%</option>
|
||||
<option value="targetHeight200">200px</option>
|
||||
</select>
|
||||
|
||||
<button id="start">start</button>
|
||||
<span>Detected changes: <span id="changes">0</span></span>
|
||||
</div>
|
||||
<div id="stage">
|
||||
<div>
|
||||
<div id="env">
|
||||
<div id="target">
|
||||
<div id="check"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,67 @@
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
#controls {
|
||||
flex: none;
|
||||
}
|
||||
#stage {
|
||||
flex: auto;
|
||||
position: relative;
|
||||
|
||||
& > div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: lightgoldenrodyellow;
|
||||
}
|
||||
}
|
||||
|
||||
#canvas > div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#env {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#target {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
// prevent container from reaching 0x0 dimensions for testing purposes
|
||||
min-width: 50px;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
#check {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.envHeightAuto,
|
||||
.targetHeightAuto {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.envHeight200,
|
||||
.targetHeight200 {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.envHeightHundred,
|
||||
.targetHeightHundred {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.displayNone {
|
||||
display: none;
|
||||
}
|
||||
.displayBlock {
|
||||
display: block;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import expectPuppeteer from 'expect-puppeteer';
|
||||
import url from './.build/build.html';
|
||||
|
||||
describe('Environment', () => {
|
||||
beforeAll(async () => {
|
||||
await page.goto(url);
|
||||
});
|
||||
|
||||
it('test', async () => {
|
||||
await expectPuppeteer(page).toClick('#start');
|
||||
await expectPuppeteer(page).toMatchElement('#testResult.passed', {
|
||||
timeout: 60000,
|
||||
});
|
||||
}, 60000);
|
||||
});
|
||||
Reference in New Issue
Block a user