Skip to content

Commit

Permalink
sync and merge with master
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolaslevy committed Nov 26, 2024
2 parents 6fdd10c + d6420de commit e642a9a
Show file tree
Hide file tree
Showing 12 changed files with 96 additions and 89 deletions.
21 changes: 16 additions & 5 deletions dist/vast-client-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -2070,7 +2070,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 @@ -2088,7 +2089,10 @@ class VASTParser extends EventEmitter {
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
super();
this.maxWrapperDepth = null;
this.rootErrorURLTemplates = [];
this.errorURLTemplates = [];
this.remainingAds = [];
this.parsingOptions = {};
this.fetcher = fetcher || null;
}

Expand Down Expand Up @@ -2220,12 +2224,15 @@ class VASTParser extends EventEmitter {
} = _ref;
// check if is a valid VAST document
if (!vastXml || !vastXml.documentElement || vastXml.documentElement.nodeName !== 'VAST') {
var _vastXml$documentElem;
this.emit('VAST-ad-parsed', {
type: 'ERROR',
url,
wrapperDepth
});
throw new Error('Invalid VAST XMLDocument');
// VideoAdServingTemplate node is used for VAST 1.0
const isNonSupportedVast = (vastXml === null || vastXml === void 0 || (_vastXml$documentElem = vastXml.documentElement) === null || _vastXml$documentElem === void 0 ? void 0 : _vastXml$documentElem.nodeName) === 'VideoAdServingTemplate';
throw new Error(isNonSupportedVast ? NON_SUPPORTED_VAST_VERSION : INVALID_VAST_ERROR);
}
const ads = [];
const childNodes = vastXml.documentElement.childNodes;
Expand Down Expand Up @@ -2442,8 +2449,8 @@ 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 @@ -2470,7 +2477,11 @@ 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 => {
var _creative$mediaFiles;
return ((_creative$mediaFiles = creative.mediaFiles) === null || _creative$mediaFiles === void 0 ? void 0 : _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(ad.errorURLTemplates.concat(vastResponse.errorURLTemplates), {
Expand Down
2 changes: 1 addition & 1 deletion dist/vast-client-node.min.js

Large diffs are not rendered by default.

21 changes: 16 additions & 5 deletions dist/vast-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2066,7 +2066,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 @@ -2084,7 +2085,10 @@ class VASTParser extends EventEmitter {
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
super();
this.maxWrapperDepth = null;
this.rootErrorURLTemplates = [];
this.errorURLTemplates = [];
this.remainingAds = [];
this.parsingOptions = {};
this.fetcher = fetcher || null;
}

Expand Down Expand Up @@ -2216,12 +2220,15 @@ class VASTParser extends EventEmitter {
} = _ref;
// check if is a valid VAST document
if (!vastXml || !vastXml.documentElement || vastXml.documentElement.nodeName !== 'VAST') {
var _vastXml$documentElem;
this.emit('VAST-ad-parsed', {
type: 'ERROR',
url,
wrapperDepth
});
throw new Error('Invalid VAST XMLDocument');
// VideoAdServingTemplate node is used for VAST 1.0
const isNonSupportedVast = (vastXml === null || vastXml === void 0 || (_vastXml$documentElem = vastXml.documentElement) === null || _vastXml$documentElem === void 0 ? void 0 : _vastXml$documentElem.nodeName) === 'VideoAdServingTemplate';
throw new Error(isNonSupportedVast ? NON_SUPPORTED_VAST_VERSION : INVALID_VAST_ERROR);
}
const ads = [];
const childNodes = vastXml.documentElement.childNodes;
Expand Down Expand Up @@ -2438,8 +2445,8 @@ 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 @@ -2466,7 +2473,11 @@ 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 => {
var _creative$mediaFiles;
return ((_creative$mediaFiles = creative.mediaFiles) === null || _creative$mediaFiles === void 0 ? void 0 : _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(ad.errorURLTemplates.concat(vastResponse.errorURLTemplates), {
Expand Down
2 changes: 1 addition & 1 deletion dist/vast-client.min.js

Large diffs are not rendered by default.

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
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@dailymotion/vast-client",
"author": "Dailymotion <[email protected]> (https://developer.dailymotion.com/)",
"version": "6.0.1",
"version": "6.0.2",
"description": "JavaScript VAST Client",
"keywords": [
"vast",
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
3 changes: 1 addition & 2 deletions src/fetcher/url_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,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 e642a9a

Please sign in to comment.