Skip to content

Commit 556fcd1

Browse files
committed
Handle non supported vast error
1 parent 5d148f7 commit 556fcd1

File tree

5 files changed

+59
-75
lines changed

5 files changed

+59
-75
lines changed

spec/samples/outdated-vast.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<VideoAdServingTemplate>
2+
<Ad id="preroll-1">
3+
<InLine>
4+
<AdSystem>example-1</AdSystem>
5+
<AdTitle>123456</AdTitle>
6+
<Video>
7+
<Duration>00:00:15</Duration>
8+
<AdID>preroll-1</AdID>
9+
<MediaFiles>
10+
<MediaFile width="600" type="video/x-flv" height="396" delivery="progressive"
11+
bitrate="496">
12+
<URL><![CDATA[http://example.com/ads/mediafile1.flv]]></URL>
13+
</MediaFile>
14+
</MediaFiles>
15+
</Video>
16+
</InLine>
17+
</Ad>
18+
</VideoAdServingTemplate>

spec/samples/wrapper-invalid-xmlfile.xml

Lines changed: 0 additions & 38 deletions
This file was deleted.

spec/vast_parser.spec.js

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,42 +27,18 @@ const nodeUrlHandler = {
2727
const wrapperAVastUrl = urlFor('wrapper-a.xml');
2828
const wrapperBVastUrl = urlFor('wrapper-b.xml');
2929
const inlineSampleVastUrl = urlFor('sample.xml');
30-
const inlineVpaidVastUrl = urlFor('vpaid.xml');
3130
const inlineInvalidVastUrl = urlFor('invalid-xmlfile.xml');
32-
const wrapperWithAttributesVastUrl = urlFor(
33-
'wrapper-attributes-multiple-ads.xml'
34-
);
35-
const wrapperInvalidVastUrl = urlFor('wrapper-invalid-xmlfile.xml');
36-
const vastWithErrorUrl = urlFor('empty-no-ad.xml');
37-
const ad = {
38-
id: null,
39-
sequence: 1,
40-
system: { value: 'VAST', version: null },
41-
title: null,
42-
description: null,
43-
advertiser: null,
44-
pricing: null,
45-
survey: null,
46-
errorURLTemplates: ['http://example.com/wrapperA-error'],
47-
impressionURLTemplates: [],
48-
creatives: [],
49-
extensions: [],
50-
adVerifications: [],
51-
trackingEvents: { nonlinear: [], linear: [] },
52-
videoClickTrackingURLTemplates: [],
53-
videoCustomClickURLTemplates: [],
54-
viewableImpression: [],
55-
};
5631

5732
describe('VASTParser', () => {
5833
let vastClient;
5934
let VastParser;
6035
let fetcher;
61-
let inlineXml, invalidXml, errorXml, wrapperXml;
36+
let inlineXml, invalidXml, errorXml, wrapperXml, outdatedXml;
6237

6338
beforeAll(async () => {
6439
inlineXml = await nodeUrlHandler.get('./spec/samples/sample.xml');
6540
errorXml = await nodeUrlHandler.get('./spec/samples/empty-no-ad.xml');
41+
outdatedXml = await nodeUrlHandler.get('./spec/samples/outdated-vast.xml');
6642
wrapperXml = await nodeUrlHandler.get(
6743
'./spec/samples/wrapper-attributes-multiple-ads.xml'
6844
);
@@ -136,6 +112,23 @@ describe('VASTParser', () => {
136112
}
137113
});
138114

115+
it('throw a error for non supported XML vast', () => {
116+
try {
117+
VastParser.parseVastXml(outdatedXml.xml, {
118+
isRootVAST: true,
119+
url: null,
120+
wrapperDepth: 0,
121+
});
122+
} catch (e) {
123+
expect(e.message).toBe('VAST response version not supported');
124+
expect(VastParser.emit).toHaveBeenLastCalledWith('VAST-ad-parsed', {
125+
type: 'ERROR',
126+
url: null,
127+
wrapperDepth: 0,
128+
});
129+
}
130+
});
131+
139132
it('gets vast version from original vast', () => {
140133
VastParser.parseVastXml(inlineXml.xml, {
141134
isRootVAST: true,
@@ -480,20 +473,20 @@ describe('VASTParser', () => {
480473
});
481474

482475
describe('Wrapper URL unavailable/timeout', () => {
483-
it('sould emits a VAST-error and track', async () => {
476+
it('should emits a VAST-error and track', async () => {
484477
const url = './spec/samples/wrapper-unavailable-url.xml';
485478

486479
const response = await nodeUrlHandler.get(url);
487480

488481
fetcher.setOptions({ ...options, url: url, previousUrl: url });
489482
VastParser.fetchingCallback = fetcher.fetchVAST.bind(fetcher);
490483

491-
const vastXML = await VastParser.parseVAST(response.xml, {
484+
const vast = await VastParser.parseVAST(response.xml, {
492485
url: url,
493486
previousUrl: url,
494487
});
495488
// Response doesn't have any ads
496-
expect(vastXML.ads).toEqual([]);
489+
expect(vast.ads).toEqual([]);
497490
// Error has been trigered
498491
expect(dataTriggered.length).toBe(1);
499492
expect(dataTriggered[0].ERRORCODE).toBe(301);

src/fetcher/url_handler.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ async function handleResponse(response) {
3636
*/
3737
function handleError(response) {
3838
if (
39-
window.location.protocol === 'https:' &&
39+
window?.location?.protocol === 'https:' &&
4040
response.url.includes('http://')
4141
) {
4242
return 'URLHandler: Cannot go from HTTPS to HTTP.';
@@ -66,8 +66,7 @@ async function get(url, options) {
6666
...options,
6767
signal: controller.signal,
6868
credentials: options.withCredentials ? 'include' : 'omit',
69-
})
70-
.finally(()=>{
69+
}).finally(() => {
7170
clearTimeout(timer);
7271
});
7372

src/parser/vast_parser.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ const DEFAULT_EVENT_DATA = {
1010
ERRORCODE: 900,
1111
extensions: [],
1212
};
13-
13+
const INVALID_VAST_ERROR = 'Invalid VAST XMLDocument';
14+
const NON_SUPPORTED_VAST_VERSION = 'VAST response version not supported';
1415
/**
1516
* This class provides methods to fetch and parse a VAST document.
1617
* @export
@@ -25,7 +26,10 @@ export class VASTParser extends EventEmitter {
2526
constructor({ fetcher } = {}) {
2627
super();
2728
this.maxWrapperDepth = null;
29+
this.rootErrorURLTemplates = [];
30+
this.errorURLTemplates = [];
2831
this.remainingAds = [];
32+
this.parsingOptions = {};
2933
this.fetcher = fetcher || null;
3034
}
3135

@@ -173,7 +177,12 @@ export class VASTParser extends EventEmitter {
173177
url,
174178
wrapperDepth,
175179
});
176-
throw new Error('Invalid VAST XMLDocument');
180+
// VideoAdServingTemplate node is used for VAST 1.0
181+
const isNonSupportedVast =
182+
vastXml?.documentElement?.nodeName === 'VideoAdServingTemplate';
183+
throw new Error(
184+
isNonSupportedVast ? NON_SUPPORTED_VAST_VERSION : INVALID_VAST_ERROR
185+
);
177186
}
178187

179188
const ads = [];
@@ -414,8 +423,8 @@ export class VASTParser extends EventEmitter {
414423
})
415424
.catch((err) => {
416425
// Timeout of VAST URI provided in Wrapper element, or of VAST URI provided in a subsequent Wrapper element.
417-
// (URI was either unavailable or reached a timeout as defined by the video player.)
418-
ad.errorCode = 301;
426+
// (URI was either unavailable or reached a timeout as defined by the video player)
427+
ad.errorCode = err.message === NON_SUPPORTED_VAST_VERSION ? 102 : 301;
419428
ad.errorMessage = err.message;
420429
resolve(ad);
421430
});
@@ -440,7 +449,10 @@ export class VASTParser extends EventEmitter {
440449
// - No Creative case - The parser has dealt with soma <Ad><Wrapper> or/and an <Ad><Inline> elements
441450
// but no creative was found
442451
const ad = vastResponse.ads[index];
443-
if ((ad.errorCode || ad.creatives.length === 0) && !ad.VASTAdTagURI) {
452+
const noMediaFilesAvailable = !ad.creatives.some(
453+
(creative) => creative.mediaFiles?.length > 0
454+
);
455+
if ((ad.errorCode || noMediaFilesAvailable) && !ad.VASTAdTagURI) {
444456
// If VASTAdTagURI is in the vastResponse, it means we are dealing with a Wrapper when using parseVAST from the VASTParser.
445457
// In that case, we dont want to modify the vastResponse since the creatives node is not required in a wrapper.
446458
this.trackVastError(

0 commit comments

Comments
 (0)