video-ad-sdk
Version:
VAST/VPAID SDK that allows video ads to be played on top of any player
249 lines (198 loc) • 6.83 kB
text/typescript
import {loadResource} from '../../resources/loadResource'
import {renderIcon} from '../renderIcon'
import {updateIcon} from '../updateIcon'
import {canBeRendered} from '../canBeRendered'
jest.mock('../../resources/loadResource')
jest.mock('../updateIcon')
jest.mock('../canBeRendered')
let config: any
let icon: any
let iconResource: HTMLImageElement
let placeholder: HTMLElement
beforeEach(() => {
placeholder = document.createElement('div')
iconResource = document.createElement('img')
config = {
placeholder
}
icon = {
height: 5,
left: 0,
top: 0,
updated: true,
width: 5,
xPosition: 'left',
yPosition: 'top'
}
})
afterEach(() => {
config = null
icon = null
;(iconResource as any) = null
;(placeholder as any) = null
})
test('renderIcon must fail if there was a problem creating the icon', () => {
const loadingError = new Error('problem loading icon')
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.reject(loadingError)
)
expect(renderIcon(icon, config)).rejects.toBe(loadingError)
})
test('renderIcon must fail if the icon can not be rendered', () => {
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => icon)
;(canBeRendered as jest.Mock).mockImplementation(() => false)
expect(renderIcon(icon, config)).rejects.toThrow("Icon can't be rendered")
})
test('must append the icon to the placeholder if three is no problem', async () => {
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => icon)
;(canBeRendered as jest.Mock).mockImplementation(() => true)
await renderIcon(icon, config)
expect(placeholder.contains(iconResource)).toBe(true)
})
test('renderIcon must reuse previously created icons', async () => {
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => icon)
;(canBeRendered as jest.Mock).mockImplementation(() => true)
const renderedIcon = await renderIcon(icon, config)
;(loadResource as jest.Mock).mockClear()
await renderIcon(renderedIcon, config)
expect(loadResource).not.toHaveBeenCalled()
expect(placeholder.contains(iconResource)).toBe(true)
})
test('renderIcon must return the updated icon', () => {
const updatedIcon = {...icon}
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => updatedIcon)
;(canBeRendered as jest.Mock).mockImplementation(() => true)
expect(renderIcon(icon, config)).resolves.toBe(updatedIcon)
})
test('renderIcon must style the icon element', async () => {
const updatedIcon = {
height: 3,
left: 1,
top: 4,
updated: true,
width: 6
}
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => updatedIcon)
;(canBeRendered as jest.Mock).mockImplementation(() => true)
await renderIcon(icon, config)
const {element: iconElement} = icon
expect(iconElement.style.position).toEqual('absolute')
expect(iconElement.style.left).toEqual(`${updatedIcon.left}px`)
expect(iconElement.style.top).toEqual(`${updatedIcon.top}px`)
expect(iconElement.style.height).toEqual(`${updatedIcon.height}px`)
expect(iconElement.style.width).toEqual(`${updatedIcon.width}px`)
})
test('renderIcon must wrap the resource with an anchor', async () => {
const updatedIcon = {
height: 3,
left: 1,
top: 4,
width: 6
}
icon.foo = true
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => updatedIcon)
;(canBeRendered as jest.Mock).mockImplementation(() => true)
await renderIcon(icon, config)
const {element: iconElement} = icon
expect(iconElement).toBeInstanceOf(HTMLAnchorElement)
expect(iconElement.href).toBe('')
expect(iconElement.target).toBe('')
expect(iconResource.parentNode).toBe(iconElement)
expect(iconResource.style.width).toBe('100%')
expect(iconResource.style.height).toBe('100%')
})
test('renderIcon element anchor must have the clickThrough url if passed', async () => {
const updatedIcon = {
height: 3,
left: 1,
top: 4,
width: 6
}
icon.iconClickThrough = 'http://test.example.com/iconClickThrough'
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => updatedIcon)
;(canBeRendered as jest.Mock).mockImplementation(() => true)
await renderIcon(icon, config)
const {element: iconElement} = icon
expect(iconElement).toBeInstanceOf(HTMLAnchorElement)
expect(iconElement.href).toBe(icon.iconClickThrough)
expect(iconElement.target).toBe('_blank')
})
test('renderIcon element anchor on click must call the passed onIconClick method', async () => {
const updatedIcon = {
height: 3,
left: 1,
top: 4,
width: 6
}
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => updatedIcon)
;(canBeRendered as jest.Mock).mockImplementation(() => true)
config.onIconClick = jest.fn()
await renderIcon(icon, config)
const {element: iconElement} = icon
iconElement.click()
expect(config.onIconClick).toHaveBeenCalledTimes(1)
expect(config.onIconClick).toHaveBeenCalledWith(icon)
})
test('renderIcon must add the element if it has no parentNode', async () => {
const updatedIcon = {
height: 3,
left: 1,
top: 4,
updated: false,
width: 6
}
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => updatedIcon)
;(canBeRendered as jest.Mock).mockImplementation(() => true)
await renderIcon(icon, config)
expect(icon.element.parentNode).toBe(placeholder)
})
test('renderIcon must must remove an icon that can no longer be rendered', async () => {
const updatedIcon = {
height: 3,
left: 1,
top: 4,
updated: true,
width: 6
}
;(loadResource as jest.Mock).mockImplementation(() =>
Promise.resolve(iconResource)
)
;(updateIcon as jest.Mock).mockImplementation(() => updatedIcon)
;(canBeRendered as jest.Mock).mockImplementation(() => true)
await renderIcon(icon, config)
expect(icon.element.parentNode).toBe(placeholder)
;(canBeRendered as jest.Mock).mockImplementation(() => false)
try {
await renderIcon(icon, config)
} catch {
// Do nothing
}
expect(icon.element.parentNode).toBeNull()
})