Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
/* eslint-env jest */
import 'jest'
import '../../polyfill/IntersectionObserver'
import {
  createObserver,
  findObserverElement,
  getPooled,
  observeElement,
  observerElementsMap,
  unobserveElement
} from '../observer'

const IntersectionObserver = window.IntersectionObserver || global.IntersectionObserver
const defaultOptions = { rootMargin: '-10% 0%', threshold: [0, 0.5, 1] }
const noop = () => {}

afterEach(() => {
  observerElementsMap.clear()
})

function resetGlobalIntersectionObserver(CurrentIntersectionObserver) {
  window.IntersectionObserver = CurrentIntersectionObserver
  global.CurrentIntersectionObserver = IntersectionObserver
  return CurrentIntersectionObserver
}
resetGlobalIntersectionObserver(IntersectionObserver)

test('createObserver creates a new IntersectionObserver instance', () => {
  const CurrentIntersectionObserver = resetGlobalIntersectionObserver(jest.fn())
  
  const observer = createObserver(defaultOptions)
  const mockInstance = CurrentIntersectionObserver.mock.instances[0]
  expect(mockInstance).toBeInstanceOf(CurrentIntersectionObserver)
  expect(observer).toEqual(mockInstance)

  resetGlobalIntersectionObserver(IntersectionObserver)
})

describe('#getPooled', () => {
  let instance

  beforeEach(() => {
    instance = new IntersectionObserver(noop, defaultOptions)
    observerElementsMap.set(instance)
  })

  test('returns nothing given options did not match', () => {
    expect(getPooled()).toBeNull()
    expect(getPooled({ rootMargin: '-20% 0%', threshold: 1 })).toBeNull()
    expect(getPooled({ rootMargin: '-10% 0%', threshold: 0 })).toBeNull()
    expect(getPooled({ threshold: 0.5 })).toBeNull()
  })

  test('returns nothing given threshold did not match', () => {
    expect(
      getPooled({ rootMargin: '-10% 0%', threshold: [0, 0.5, 1, 0.25] })
    ).toBeNull()
    expect(
      getPooled({ rootMargin: '-10% 0%', threshold: [1, 0.5, 0] })
    ).toBeNull()
  })

  test('throws if rootMargin cannot be parsed', () => {
    expect(() =>
      getPooled({ rootMargin: '-10% 0', threshold: 0 })
    ).toThrowErrorMatchingSnapshot()
  })

  test('retrieves an existing IntersectionObserver instance given all options match', () => {
    expect(getPooled(defaultOptions)).toEqual(instance)
  })

  test('createObserver returns a pooled IntersectionObserver instance', () => {
    const observer = createObserver(defaultOptions)
    expect(observer).toEqual(getPooled(defaultOptions))
  })
})

describe('#observeElement', () => {
  test('observing a React instance when observer is already in observerElementsMap', () => {
    const observer = createObserver(defaultOptions)
    const spy = jest.spyOn(observer, 'observe')
    const targets = new Set()
    observerElementsMap.set(observer, targets)
    const element = { target: { nodeType: 1, id: 1 }, observer }
    observeElement(element)

    expect(Array.from(targets)[0]).toEqual(element)
    expect(spy).toBeCalled()
  })

  test('observing a React instance when observer is not in observerElementsMap yet', () => {
    const observer = createObserver(defaultOptions)
    const spy = jest.spyOn(observer, 'observe')
    const element = { target: { nodeType: 1, id: 2 }, observer }
    observeElement(element)
    const targets = Array.from(observerElementsMap.get(observer))

    expect(targets[0]).toEqual(element)
    expect(spy).toBeCalled()
  })
})

describe('#unobserveElement', () => {
  test('unobserving a React instance while instance still in use by other observables', () => {
    const observer = createObserver(defaultOptions)
    const spy = jest.spyOn(observer, 'unobserve')
    const element1 = { target: { nodeType: 1, id: 1 }, observer }
    const element2 = { target: { nodeType: 1, id: 2 }, observer }
    observeElement(element1)
    observeElement(element2)
    unobserveElement(element1)

    expect(observerElementsMap.has(observer)).toBeTruthy()
    expect(spy.mock.calls[0][0]).toEqual({ nodeType: 1, id: 1 })
  })

  test('unobserving a React instance while instance is not in use anymore', () => {
    const observer = createObserver(defaultOptions)
    const spy = jest.spyOn(observer, 'disconnect')
    const element = { target: { nodeType: 1, id: 1 }, observer }
    observeElement(element)
    unobserveElement(element)

    expect(observerElementsMap.has(observer)).toBeFalsy()
    expect(spy).toBeCalled()
  })
})

describe('#findObserverElement', () => {
  test('given an entry and no observer returns null', () => {
    const observer = createObserver()
    const entry = { target: { nodeType: 1, id: 1 }, observer }
    observeElement(entry)
    const instance = findObserverElement(null, entry)
    expect(instance).toBeNull()
  })

  test('given an entry without target property throws', () => {
    createObserver()
    expect(() => observeElement({})).toThrowErrorMatchingSnapshot()
  })

  test('an entry matches the observer - single observer instance', () => {
    const observer = createObserver()
    const entry = { target: { nodeType: 1, id: 1 }, observer }
    observeElement(entry)
    const instance = findObserverElement(observer, entry)
    expect(instance).toEqual(entry)
  })

  test('an entry matches the observer - multiple observer instances', () => {
    const observer1 = createObserver()
    const observer2 = createObserver(defaultOptions)
    const entry1 = { target: { nodeType: 1, id: 1 }, observer: observer1 }
    const entry2 = { target: { nodeType: 1, id: 1 }, observer: observer2 }
    observeElement(entry1)
    observeElement(entry2)
    const instance1 = findObserverElement(observer1, entry1)
    const instance2 = findObserverElement(observer2, entry2)
    expect(instance1).toEqual(entry1)
    expect(instance2).toEqual(entry2)
  })

  test('multiple entries match one observer', () => {
    const observer = createObserver()
    const entry1 = { target: { nodeType: 1, id: 1 }, observer }
    const entry2 = { target: { nodeType: 1, id: 2 }, observer }
    observeElement(entry1)
    observeElement(entry2)
    const instance1 = findObserverElement(observer, entry1)
    const instance2 = findObserverElement(observer, entry2)
    expect(instance1).toEqual(entry1)
    expect(instance2).toEqual(entry2)
  })

  test('multiple entries match multiple observers', () => {
    const observer1 = createObserver()
    const observer2 = createObserver(defaultOptions)
    const entry1 = { target: { nodeType: 1, id: 1 }, observer: observer1 }
    const entry2 = { target: { nodeType: 1, id: 2 }, observer: observer2 }
    observeElement(entry1)
    observeElement(entry2)
    const instance1 = findObserverElement(observer1, entry1)
    const instance2 = findObserverElement(observer2, entry2)
    expect(instance1).toEqual(entry1)
    expect(instance2).toEqual(entry2)
  })
})