fix: Preload should reliably preload initial load (#2466)
This commit is contained in:
committed by
dermotduffy
parent
bc366626f1
commit
d8ad347dfa
@@ -31,6 +31,10 @@ describe('LazyLoadController', () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(global.document, 'addEventListener');
|
||||
vi.spyOn(global.document, 'removeEventListener');
|
||||
Object.defineProperty(document, 'visibilityState', {
|
||||
value: 'visible',
|
||||
writable: true,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -44,7 +48,7 @@ describe('LazyLoadController', () => {
|
||||
|
||||
it('should not be loaded by default when lazy load is set to true', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration(true);
|
||||
controller.setConfiguration({ lazyLoad: true });
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
});
|
||||
|
||||
@@ -63,7 +67,10 @@ describe('LazyLoadController', () => {
|
||||
|
||||
it('should remove handlers and listeners on destroy', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration(true, ['unselected', 'hidden']);
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['unselected', 'hidden'],
|
||||
});
|
||||
controller.hostConnected();
|
||||
|
||||
const listener = vi.fn();
|
||||
@@ -92,17 +99,83 @@ describe('LazyLoadController', () => {
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
expect(listener).not.toBeCalled();
|
||||
|
||||
controller.setConfiguration(false);
|
||||
controller.setConfiguration({ lazyLoad: false });
|
||||
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
expect(listener).toBeCalled();
|
||||
});
|
||||
|
||||
it('should re-evaluate unload when conditions change while loaded', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration({ lazyLoad: true });
|
||||
controller.hostConnected();
|
||||
|
||||
callIntersectionHandler(true);
|
||||
callVisibilityHandler(true);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
callIntersectionHandler(false);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['unselected'],
|
||||
});
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
});
|
||||
|
||||
it('should unload via `hidden` immediately when toggled on a hidden tab', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration({ lazyLoad: false });
|
||||
controller.hostConnected();
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
callVisibilityHandler(false);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['hidden'],
|
||||
});
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
});
|
||||
|
||||
it('should reset omitted fields to their defaults', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['unselected'],
|
||||
forceSelected: true,
|
||||
});
|
||||
controller.hostConnected();
|
||||
|
||||
callVisibilityHandler(true);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
// Each call is a complete snapshot: omitting `forceSelected` resets it
|
||||
// to false, and omitting `lazyUnloadConditions` resets it to []. With
|
||||
// forceSelected reset and intersection then dropping, no `unselected`
|
||||
// condition remains to act on it, so the host stays loaded.
|
||||
controller.setConfiguration({ lazyLoad: true });
|
||||
|
||||
callIntersectionHandler(false);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
// Re-introducing `unselected` while not intersecting (and with
|
||||
// forceSelected still defaulted to false) must now unload, proving
|
||||
// forceSelected was actually reset by the previous call.
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['unselected'],
|
||||
});
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('should lazy load', () => {
|
||||
it('should load when both visible and intersecting', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration(true);
|
||||
controller.setConfiguration({ lazyLoad: true });
|
||||
controller.hostConnected();
|
||||
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
@@ -120,7 +193,7 @@ describe('LazyLoadController', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
|
||||
// No lazy loading.
|
||||
controller.setConfiguration(false);
|
||||
controller.setConfiguration({ lazyLoad: false });
|
||||
controller.hostConnected();
|
||||
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
@@ -147,7 +220,10 @@ describe('LazyLoadController', () => {
|
||||
'when unload conditions are: %s',
|
||||
(unloadConditions: LazyUnloadCondition[], shouldBeLoaded: boolean) => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration(true, unloadConditions);
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: unloadConditions,
|
||||
});
|
||||
controller.hostConnected();
|
||||
|
||||
callIntersectionHandler(true);
|
||||
@@ -170,7 +246,10 @@ describe('LazyLoadController', () => {
|
||||
'when unload conditions are: %s',
|
||||
(unloadConditions: LazyUnloadCondition[], shouldBeLoaded: boolean) => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration(true, unloadConditions);
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: unloadConditions,
|
||||
});
|
||||
controller.hostConnected();
|
||||
|
||||
callIntersectionHandler(true);
|
||||
@@ -184,10 +263,114 @@ describe('LazyLoadController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('should force selected', () => {
|
||||
it('should load when forced selected even if not intersecting', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration({ lazyLoad: true });
|
||||
controller.hostConnected();
|
||||
|
||||
callVisibilityHandler(true);
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
|
||||
controller.setConfiguration({ forceSelected: true });
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not load while document is already hidden on connect', () => {
|
||||
Object.defineProperty(document, 'visibilityState', {
|
||||
value: 'hidden',
|
||||
writable: true,
|
||||
});
|
||||
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['hidden'],
|
||||
});
|
||||
controller.hostConnected();
|
||||
|
||||
controller.setConfiguration({ forceSelected: true });
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
|
||||
callVisibilityHandler(true);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
});
|
||||
|
||||
it('should stay loaded with `unselected` unload condition while forced selected', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['unselected'],
|
||||
forceSelected: true,
|
||||
});
|
||||
controller.hostConnected();
|
||||
|
||||
callVisibilityHandler(true);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
callIntersectionHandler(false);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
});
|
||||
|
||||
it('should still unload via `hidden` while forced selected', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['hidden'],
|
||||
forceSelected: true,
|
||||
});
|
||||
controller.hostConnected();
|
||||
|
||||
callVisibilityHandler(true);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
callVisibilityHandler(false);
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
});
|
||||
|
||||
it('should unload after force-selected is released and `unselected` applies', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['unselected'],
|
||||
forceSelected: true,
|
||||
});
|
||||
controller.hostConnected();
|
||||
|
||||
callVisibilityHandler(true);
|
||||
callIntersectionHandler(false);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['unselected'],
|
||||
forceSelected: false,
|
||||
});
|
||||
expect(controller.isLoaded()).toBe(false);
|
||||
});
|
||||
|
||||
it('should keep selected stream loaded with default `unload: []`', () => {
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration({ lazyLoad: true });
|
||||
controller.hostConnected();
|
||||
|
||||
controller.setConfiguration({ forceSelected: true });
|
||||
callVisibilityHandler(true);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
|
||||
controller.setConfiguration({ forceSelected: false });
|
||||
callIntersectionHandler(false);
|
||||
expect(controller.isLoaded()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should call listeners', () => {
|
||||
const listener = vi.fn();
|
||||
const controller = new LazyLoadController(createLitElement());
|
||||
controller.setConfiguration(true, ['unselected', 'hidden']);
|
||||
controller.setConfiguration({
|
||||
lazyLoad: true,
|
||||
lazyUnloadConditions: ['unselected', 'hidden'],
|
||||
});
|
||||
controller.hostConnected();
|
||||
controller.addListener(listener);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user