UNPKG

video-ad-sdk

Version:

VAST/VPAID SDK that allows video ads to be played on top of any player

659 lines (598 loc) 19.2 kB
import { inlineAd, inlineParsedXML, legacyVpaidInlineAd, podParsedXML, vpaidInlineAd, wrapperAd, vastWrapperXML, vastVpaidInlineXML, wrapperParsedXML, noAdParsedXML } from '../../../fixtures' import type { ParsedXML, ParsedAd, Attributes, MediaFile, InteractiveFile } from '../../types' import { getAds, getCreativeData, getAdErrorURI, getClickThrough, getClickTracking, getCustomClick, getFirstAd, getImpression, getViewable, getNotViewable, getViewUndetermined, getInteractiveCreativeFiles, getInteractiveFiles, getLinearTrackingEvents, getMediaFiles, getSkipOffset, getVASTAdTagURI, getVastErrorURI, getWrapperOptions, hasAdPod, getPodAdSequence, isPodAd, isInline, isWrapper } from '..' const clone = <T extends Record<string, any>>(object: T): T => JSON.parse(JSON.stringify(object)) test('getVastErrorURI must return the error uri of the VAST element', () => { expect(getVastErrorURI(inlineParsedXML)).toBeUndefined() expect(getVastErrorURI(noAdParsedXML)).toEqual([ 'https://test.example.com/error/[ERRORCODE]', 'https://test.example.com/error2/[ERRORCODE]' ]) expect(getVastErrorURI(undefined as unknown as ParsedXML)).toBeUndefined() expect(getVastErrorURI({} as ParsedXML)).toBeUndefined() }) test('getAds must return the ads of the passed adResponse or undefined otherwise', () => { expect(getAds(wrapperParsedXML)).toEqual([wrapperAd]) expect(getAds(noAdParsedXML)).toEqual([]) expect(getAds({} as ParsedXML)).toEqual([]) expect(getAds(undefined as unknown as ParsedXML)).toEqual([]) }) test('getFirstAd must return the first ad of the passed adResponse or undefined otherwise', () => { expect(getFirstAd(wrapperParsedXML)).toEqual(wrapperAd) expect(getFirstAd({} as ParsedXML)).toBeUndefined() }) test('getFirsAd must return the firs ad in the sequence if the passed VAST has an ad pod', () => { const ad = getFirstAd(podParsedXML) expect(ad?.attributes?.id).toBe('1234') }) test('isWrapper must return true if the ad contains a wrapper and false otherwise', () => { expect(isWrapper(wrapperAd)).toBe(true) expect(isWrapper(inlineAd)).toBe(false) expect(isWrapper({} as ParsedAd)).toBe(false) expect(isWrapper(undefined as unknown as ParsedAd)).toBe(false) expect(isWrapper(1 as unknown as ParsedAd)).toBe(false) }) test('isInline must return true if the ad contains a wrapper and false otherwise', () => { expect(isInline(inlineAd)).toBe(true) expect(isInline(wrapperAd)).toBe(false) expect(isInline({} as ParsedAd)).toBe(false) expect(isInline(undefined as unknown as ParsedAd)).toBe(false) expect(isInline(1 as unknown as ParsedAd)).toBe(false) }) test('getVASTAdTagURI must return the VASTAdTagURI from the wrapper ad or undefined otherwise', () => { expect(getVASTAdTagURI(wrapperAd)).toBe( 'https://test.example.com/vastadtaguri' ) expect(getVASTAdTagURI(inlineAd)).toBeUndefined() }) test('hasAdPod must return true if the passed ads have an ad pod and false otherwise', () => { expect(hasAdPod(podParsedXML)).toBe(true) expect(hasAdPod(inlineParsedXML)).toBe(false) expect(hasAdPod({} as ParsedAd)).toBe(false) expect(hasAdPod(undefined as unknown as ParsedAd)).toBe(false) }) test('hasAdPod must return false if the there is only one ad with a sequence', () => { const podAds = getAds(podParsedXML) if (podParsedXML.elements) podParsedXML.elements[0].elements = [podAds[1]] expect(hasAdPod(podParsedXML)).toBe(false) if (podParsedXML.elements) podParsedXML.elements[0].elements = podAds }) test('getPodAdSequence mus return the sequence of the ad or false otherwise', () => { const ads = getAds(podParsedXML) expect(getPodAdSequence(ads[0])).toBeUndefined() expect(getPodAdSequence(ads[1])).toBe(1) }) test('isPodAd must return true if the ad has a sequence and false otherwise', () => { const ads = getAds(podParsedXML) expect(isPodAd(ads[0])).toBe(false) expect(isPodAd(ads[1])).toBe(true) }) test('getWrapperOptions must return the options of the ad or {} otherwise', () => { expect(getWrapperOptions(inlineAd)).toEqual({}) expect(getWrapperOptions(wrapperAd)).toEqual({allowMultipleAds: true}) const wrapperAdClone = clone<ParsedXML>(wrapperAd) const wrapperAttributes = wrapperAdClone.elements?.[0] .attributes as Attributes wrapperAttributes.allowMultipleAds = 'false' expect(getWrapperOptions(wrapperAdClone)).toEqual({allowMultipleAds: false}) wrapperAttributes.allowMultipleAds = 'true' wrapperAttributes.followAdditionalWrappers = 'false' expect(getWrapperOptions(wrapperAdClone)).toEqual({ allowMultipleAds: true, followAdditionalWrappers: false }) wrapperAttributes.fallbackOnNoAd = 'true' expect(getWrapperOptions(wrapperAdClone)).toEqual({ allowMultipleAds: true, fallbackOnNoAd: true, followAdditionalWrappers: false }) }) test('getAdErrorURI must return the error uri of the inline/wrapper or undefined if missing', () => { expect(getAdErrorURI(inlineAd)).toEqual(['https://test.example.com/error']) expect(getAdErrorURI(wrapperAd)).toEqual([ 'https://test.example.com/error/[ERRORCODE]' ]) expect(getAdErrorURI(undefined as unknown as ParsedAd)).toBeUndefined() expect(getAdErrorURI({} as ParsedAd)).toBeUndefined() }) test('getImpression must return the imression uri of the inline/wrapper or undefined if missing', () => { expect(getImpression(inlineAd)).toEqual([ 'https://test.example.com/impression' ]) expect(getImpression(wrapperAd)).toEqual([ 'https://test.example.com/impression' ]) expect(getImpression(undefined as unknown as ParsedAd)).toBeUndefined() expect(getImpression({} as ParsedAd)).toBeUndefined() }) test('getViewable must return the viewable uri of the inline/wrapper or undefined if missing', () => { expect(getViewable(inlineAd)).toEqual(['https://test.example.com/viewable']) expect(getViewable(wrapperAd)).toBeUndefined() expect(getViewable(undefined as unknown as ParsedAd)).toBeUndefined() expect(getViewable({} as ParsedAd)).toBeUndefined() }) test('getNotViewable must return the not visible uri of the inline/wrapper or undefined if missing', () => { expect(getNotViewable(inlineAd)).toEqual([ 'https://test.example.com/notViewable' ]) expect(getNotViewable(wrapperAd)).toBeUndefined() expect(getNotViewable(undefined as unknown as ParsedAd)).toBeUndefined() expect(getNotViewable({} as ParsedAd)).toBeUndefined() }) test('getViewUndetermined must return the undetermined view uri of the inline/wrapper or undetermined if missing', () => { expect(getViewUndetermined(inlineAd)).toEqual([ 'https://test.example.com/notDetermined' ]) expect(getViewUndetermined(wrapperAd)).toBeUndefined() expect(getViewUndetermined(undefined as unknown as ParsedAd)).toBeUndefined() expect(getViewUndetermined({} as ParsedAd)).toBeUndefined() }) test('getMediaFiles must return undefined for wrong ads', () => { expect(getMediaFiles(undefined as unknown as ParsedAd)).toBeUndefined() expect(getMediaFiles({} as ParsedAd)).toBeUndefined() expect(getMediaFiles(wrapperAd)).toBeUndefined() }) test('getMediaFiles must return the mediafiles', () => { const mediaFiles = getMediaFiles(inlineAd) as MediaFile[] expect(mediaFiles).toBeInstanceOf(Array) expect(mediaFiles.length).toBe(3) expect(mediaFiles[0]).toEqual({ bitrate: '600', codec: undefined, delivery: 'progressive', height: '1080', id: undefined, maintainAspectRatio: 'true', maxBitrate: undefined, minBitrate: undefined, scalable: 'true', src: 'https://test.example.com/test1920x1080.mp4', type: 'video/mp4', universalAdId: '8465', width: '1920' }) }) test('getMediaFiles must add the apiFramework if present', () => { const mediaFiles = getMediaFiles(vpaidInlineAd) as MediaFile[] expect(mediaFiles).toBeInstanceOf(Array) expect(mediaFiles.length).toBe(2) expect(mediaFiles[0]).toEqual( expect.objectContaining({ apiFramework: 'VPAID', src: 'https://test.example.com/html5.js', type: 'text/javascript' }) ) }) test('getInteractiveCreativeFiles must return undefined for wrong ads', () => { expect( getInteractiveCreativeFiles(undefined as unknown as ParsedAd) ).toBeUndefined() expect(getInteractiveCreativeFiles({} as ParsedAd)).toBeUndefined() expect(getInteractiveCreativeFiles(wrapperAd)).toBeUndefined() }) test('getInteractiveCreativeFiles must return the mediafiles', () => { const interactiveFiles = getInteractiveCreativeFiles( vpaidInlineAd ) as InteractiveFile[] expect(interactiveFiles).toBeInstanceOf(Array) expect(interactiveFiles.length).toBe(2) expect(interactiveFiles[0]).toEqual({ apiFramework: 'VPAID', src: 'https://test.example.com/html5.js', type: 'text/javascript' }) expect(interactiveFiles[1]).toEqual({ apiFramework: 'VPAID', src: 'https://test.example.com/flash.swf', type: 'application/x-shockwave-flash' }) }) test('getLinearTrackingEvents must return undefined if there are no linear tracking events', () => { expect( getLinearTrackingEvents(undefined as unknown as ParsedAd) ).toBeUndefined() expect(getLinearTrackingEvents({} as ParsedAd)).toBeUndefined() expect(getLinearTrackingEvents(noAdParsedXML)).toBeUndefined() }) test('getLinearTrackingEvents must return the linear tracking events', () => { expect(getLinearTrackingEvents(inlineAd)).toEqual([ { event: 'creativeView', offset: undefined, uri: 'https://test.example.com/creativeView' }, { event: 'start', offset: undefined, uri: 'https://test.example.com/start' }, { event: 'closeLinear', offset: undefined, uri: 'https://test.example.com/closeLinear' }, { event: 'midpoint', offset: undefined, uri: 'https://test.example.com/midpoint' }, { event: 'firstQuartile', offset: undefined, uri: 'https://test.example.com/firstQuartile' }, { event: 'thirdQuartile', offset: undefined, uri: 'https://test.example.com/thirdQuartile' }, { event: 'complete', offset: undefined, uri: 'https://test.example.com/complete' }, { event: 'timeSpentViewing', offset: 5000, uri: 'https://test.example.com/timeSpentViewing' }, { event: 'timeSpentViewing', offset: '15%', uri: 'https://test.example.com/timeSpentViewing2' } ]) expect(getLinearTrackingEvents(wrapperAd)).toEqual([ { event: 'start', offset: undefined, uri: 'https://test.example.com/start' }, { event: 'start', offset: undefined, uri: 'https://test.example.com/start2' }, { event: 'firstQuartile', offset: undefined, uri: 'https://test.example.com/firstQuartile' }, { event: 'firstQuartile', offset: undefined, uri: 'https://test.example.com/firstQuartile2' }, { event: 'midpoint', offset: undefined, uri: 'https://test.example.com/midpoint' }, { event: 'midpoint', offset: undefined, uri: 'https://test.example.com/midpoint2' }, { event: 'thirdQuartile', offset: undefined, uri: 'https://test.example.com/thirdQuartile' }, { event: 'thirdQuartile', offset: undefined, uri: 'https://test.example.com/thirdQuartile2' }, { event: 'closeLinear', offset: undefined, uri: 'https://test.example.com/closeLinear2' }, { event: 'complete', offset: undefined, uri: 'https://test.example.com/complete' }, { event: 'complete', offset: undefined, uri: 'https://test.example.com/complete2' }, { event: 'playerExpand', offset: undefined, uri: 'https://test.example.com/playerExpand' }, { event: 'playerExpand', offset: undefined, uri: 'https://test.example.com/playerExpand2' }, { event: 'playerCollapse', offset: undefined, uri: 'https://test.example.com/playerCollapse' }, { event: 'playerCollapse', offset: undefined, uri: 'https://test.example.com/playerCollapse2' }, { event: 'mute', offset: undefined, uri: 'https://test.example.com/mute' }, { event: 'mute', offset: undefined, uri: 'https://test.example.com/mute2' }, { event: 'unmute', offset: undefined, uri: 'https://test.example.com/unmute' }, { event: 'unmute', offset: undefined, uri: 'https://test.example.com/unmute2' }, { event: 'rewind', offset: undefined, uri: 'https://test.example.com/rewind' }, { event: 'rewind', offset: undefined, uri: 'https://test.example.com/rewind2' }, { event: 'skip', offset: undefined, uri: 'https://test.example.com/skip' }, { event: 'skip', offset: undefined, uri: 'https://test.example.com/skip2' }, { event: 'pause', offset: undefined, uri: 'https://test.example.com/pause' }, { event: 'pause', offset: undefined, uri: 'https://test.example.com/pause2' }, { event: 'progress', offset: 5000, uri: 'https://test.example.com/progress' }, { event: 'progress', offset: '15%', uri: 'https://test.example.com/progress2' }, { event: 'resume', offset: undefined, uri: 'https://test.example.com/resume' }, { event: 'resume', offset: undefined, uri: 'https://test.example.com/resume2' }, { event: 'fullscreen', offset: undefined, uri: 'https://test.example.com/fullscreen' }, { event: 'fullscreen', offset: undefined, uri: 'https://test.example.com/fullscreen2' }, { event: 'creativeView', offset: undefined, uri: 'https://test.example.com/creativeView' }, { event: 'creativeView', offset: undefined, uri: 'https://test.example.com/creativeView2' }, { event: 'exitFullscreen', offset: undefined, uri: 'https://test.example.com/exitfullscreen' }, { event: 'exitFullscreen', offset: undefined, uri: 'https://test.example.com/exitfullscreen' }, { event: 'acceptInvitationLinear', offset: undefined, uri: 'https://test.example.com/acceptinvitationlinear' }, { event: 'acceptInvitationLinear', offset: undefined, uri: 'https://test.example.com/acceptinvitationlinear2' }, { event: 'closeLinear', offset: undefined, uri: 'https://test.example.com/closelinear' }, { event: 'closeLinear', offset: undefined, uri: 'https://test.example.com/closelinear' } ]) }) test('getLinearTrackingEvents must return undefined if you filter by event and are no tracking events after filtering', () => { expect(getLinearTrackingEvents(inlineAd, 'progress')).toBeUndefined() }) test('getLinearTrackingEvents must return the linear progress events if you filter by progress', () => { expect(getLinearTrackingEvents(wrapperAd, 'progress')).toEqual([ { event: 'progress', offset: 5000, uri: 'https://test.example.com/progress' }, { event: 'progress', offset: '15%', uri: 'https://test.example.com/progress2' } ]) }) test('getClickThrough must return undefined if there is none', () => { expect(getClickThrough(undefined as unknown as ParsedAd)).toBeUndefined() expect(getClickThrough({} as ParsedAd)).toBeUndefined() expect(getClickThrough(wrapperAd)).toBeUndefined() }) test('getClickThrough must return the clickThrough uri', () => { expect(getClickThrough(inlineAd)).toEqual( 'https://test.example.com/clickthrough' ) }) test('getClickTracking must return undefined if there is none', () => { expect(getClickTracking(undefined as unknown as ParsedAd)).toBeUndefined() expect(getClickTracking({} as ParsedAd)).toBeUndefined() }) test('getClickTracking must return the clickThrough uri', () => { expect(getClickTracking(inlineAd)).toEqual([ 'https://test.example.com/clicktracking' ]) expect(getClickTracking(wrapperAd)).toEqual([ 'https://test.example.com/clicktracking' ]) }) test('getCustomClick must return undefined if there is none', () => { expect(getCustomClick(undefined as unknown as ParsedAd)).toBeUndefined() expect(getCustomClick({} as ParsedAd)).toBeUndefined() }) test('getCustomClick must return the clickThrough uri', () => { expect(getCustomClick(inlineAd)).toEqual([ 'https://test.example.com/customclick' ]) expect(getCustomClick(wrapperAd)).toEqual([ 'https://test.example.com/customclick' ]) }) test('getSkipOffset must return undefined if there none', () => { expect(getSkipOffset(undefined as unknown as ParsedAd)).toBeUndefined() expect(getSkipOffset({} as ParsedAd)).toBeUndefined() expect(getSkipOffset(wrapperAd)).toBeUndefined() }) test('getSkipOffset must return the parsed skipoffset', () => { expect(getSkipOffset(inlineAd)).toEqual(5000) }) test('getInteractiveFiles must return undefined for wrong ads', () => { expect(getInteractiveFiles(undefined as unknown as ParsedAd)).toBeUndefined() expect(getInteractiveFiles({} as ParsedAd)).toBeUndefined() expect(getInteractiveFiles(wrapperAd)).toBeUndefined() }) test('getInteractiveFiles must return undefined if there is no vpaid ad', () => { expect(getInteractiveFiles(inlineAd)).toBeUndefined() }) test('getInteractiveFiles must return the interactive files', () => { const interactiveFiles = getInteractiveFiles( vpaidInlineAd ) as InteractiveFile[] expect(interactiveFiles).toBeInstanceOf(Array) expect(interactiveFiles.length).toBe(2) expect(interactiveFiles[0]).toEqual({ apiFramework: 'VPAID', src: 'https://test.example.com/html5.js', type: 'text/javascript' }) expect(interactiveFiles[1]).toEqual({ apiFramework: 'VPAID', src: 'https://test.example.com/flash.swf', type: 'application/x-shockwave-flash' }) }) test('getInteractiveFiles must return vast2 interactive files', () => { const interactiveFiles = getInteractiveFiles( legacyVpaidInlineAd ) as InteractiveFile[] expect(interactiveFiles).toBeInstanceOf(Array) expect(interactiveFiles.length).toBe(2) expect(interactiveFiles[0]).toEqual({ apiFramework: 'VPAID', src: 'https://test.example.com/html5.js', type: 'text/javascript' }) expect(interactiveFiles[1]).toEqual({ apiFramework: 'VPAID', src: 'https://test.example.com/flash.swf', type: 'application/x-shockwave-flash' }) }) test('getCreativeData must return the adParameters', () => { expect(getCreativeData(vastWrapperXML)).toEqual({ AdParameters: undefined, xmlEncoded: false }) expect(getCreativeData(vastVpaidInlineXML)).toEqual({ AdParameters: 'AD_PARAMETERS_DATA <![CDATA[nested cdata]]>', xmlEncoded: false }) })