Skip to content

Commit

Permalink
Merge pull request #481 from dailymotion/fix-wrong-error
Browse files Browse the repository at this point in the history
Add support for non supported vast error
  • Loading branch information
ZacharieTFR authored Nov 26, 2024
2 parents 5d148f7 + a1fd2a2 commit 814e896
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 75 deletions.
1 change: 1 addition & 0 deletions docs/api/vast-parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Whenever an error occurs during the VAST parsing, the parser will call automatic

- `no_ad`: The VAST document is empty
- VAST error `101`: VAST schema validation error.
- VAST error `102`: VAST version of response not supported.
- VAST error `301`: Timeout of VAST URI provided in Wrapper element.
- VAST error `302`: Wrapper limit reached.
- VAST error `303`: No VAST response after one or more Wrappers.
Expand Down
18 changes: 18 additions & 0 deletions spec/samples/outdated-vast.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<VideoAdServingTemplate>
<Ad id="preroll-1">
<InLine>
<AdSystem>example-1</AdSystem>
<AdTitle>123456</AdTitle>
<Video>
<Duration>00:00:15</Duration>
<AdID>preroll-1</AdID>
<MediaFiles>
<MediaFile width="600" type="video/x-flv" height="396" delivery="progressive"
bitrate="496">
<URL><![CDATA[http://example.com/ads/mediafile1.flv]]></URL>
</MediaFile>
</MediaFiles>
</Video>
</InLine>
</Ad>
</VideoAdServingTemplate>
38 changes: 0 additions & 38 deletions spec/samples/wrapper-invalid-xmlfile.xml

This file was deleted.

51 changes: 22 additions & 29 deletions spec/vast_parser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,42 +27,18 @@ const nodeUrlHandler = {
const wrapperAVastUrl = urlFor('wrapper-a.xml');
const wrapperBVastUrl = urlFor('wrapper-b.xml');
const inlineSampleVastUrl = urlFor('sample.xml');
const inlineVpaidVastUrl = urlFor('vpaid.xml');
const inlineInvalidVastUrl = urlFor('invalid-xmlfile.xml');
const wrapperWithAttributesVastUrl = urlFor(
'wrapper-attributes-multiple-ads.xml'
);
const wrapperInvalidVastUrl = urlFor('wrapper-invalid-xmlfile.xml');
const vastWithErrorUrl = urlFor('empty-no-ad.xml');
const ad = {
id: null,
sequence: 1,
system: { value: 'VAST', version: null },
title: null,
description: null,
advertiser: null,
pricing: null,
survey: null,
errorURLTemplates: ['http://example.com/wrapperA-error'],
impressionURLTemplates: [],
creatives: [],
extensions: [],
adVerifications: [],
trackingEvents: { nonlinear: [], linear: [] },
videoClickTrackingURLTemplates: [],
videoCustomClickURLTemplates: [],
viewableImpression: [],
};

describe('VASTParser', () => {
let vastClient;
let VastParser;
let fetcher;
let inlineXml, invalidXml, errorXml, wrapperXml;
let inlineXml, invalidXml, errorXml, wrapperXml, outdatedXml;

beforeAll(async () => {
inlineXml = await nodeUrlHandler.get('./spec/samples/sample.xml');
errorXml = await nodeUrlHandler.get('./spec/samples/empty-no-ad.xml');
outdatedXml = await nodeUrlHandler.get('./spec/samples/outdated-vast.xml');
wrapperXml = await nodeUrlHandler.get(
'./spec/samples/wrapper-attributes-multiple-ads.xml'
);
Expand Down Expand Up @@ -136,6 +112,23 @@ describe('VASTParser', () => {
}
});

it('throw a error for non supported XML vast', () => {
try {
VastParser.parseVastXml(outdatedXml.xml, {
isRootVAST: true,
url: null,
wrapperDepth: 0,
});
} catch (e) {
expect(e.message).toBe('VAST response version not supported');
expect(VastParser.emit).toHaveBeenLastCalledWith('VAST-ad-parsed', {
type: 'ERROR',
url: null,
wrapperDepth: 0,
});
}
});

it('gets vast version from original vast', () => {
VastParser.parseVastXml(inlineXml.xml, {
isRootVAST: true,
Expand Down Expand Up @@ -480,20 +473,20 @@ describe('VASTParser', () => {
});

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

const response = await nodeUrlHandler.get(url);

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

const vastXML = await VastParser.parseVAST(response.xml, {
const vast = await VastParser.parseVAST(response.xml, {
url: url,
previousUrl: url,
});
// Response doesn't have any ads
expect(vastXML.ads).toEqual([]);
expect(vast.ads).toEqual([]);
// Error has been trigered
expect(dataTriggered.length).toBe(1);
expect(dataTriggered[0].ERRORCODE).toBe(301);
Expand Down
5 changes: 2 additions & 3 deletions src/fetcher/url_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ async function handleResponse(response) {
*/
function handleError(response) {
if (
window.location.protocol === 'https:' &&
window?.location?.protocol === 'https:' &&
response.url.includes('http://')
) {
return 'URLHandler: Cannot go from HTTPS to HTTP.';
Expand Down Expand Up @@ -66,8 +66,7 @@ async function get(url, options) {
...options,
signal: controller.signal,
credentials: options.withCredentials ? 'include' : 'omit',
})
.finally(()=>{
}).finally(() => {
clearTimeout(timer);
});

Expand Down
22 changes: 17 additions & 5 deletions src/parser/vast_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ const DEFAULT_EVENT_DATA = {
ERRORCODE: 900,
extensions: [],
};

const INVALID_VAST_ERROR = 'Invalid VAST XMLDocument';
const NON_SUPPORTED_VAST_VERSION = 'VAST response version not supported';
/**
* This class provides methods to fetch and parse a VAST document.
* @export
Expand All @@ -25,7 +26,10 @@ export class VASTParser extends EventEmitter {
constructor({ fetcher } = {}) {
super();
this.maxWrapperDepth = null;
this.rootErrorURLTemplates = [];
this.errorURLTemplates = [];
this.remainingAds = [];
this.parsingOptions = {};
this.fetcher = fetcher || null;
}

Expand Down Expand Up @@ -173,7 +177,12 @@ export class VASTParser extends EventEmitter {
url,
wrapperDepth,
});
throw new Error('Invalid VAST XMLDocument');
// VideoAdServingTemplate node is used for VAST 1.0
const isNonSupportedVast =
vastXml?.documentElement?.nodeName === 'VideoAdServingTemplate';
throw new Error(
isNonSupportedVast ? NON_SUPPORTED_VAST_VERSION : INVALID_VAST_ERROR
);
}

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

0 comments on commit 814e896

Please sign in to comment.