Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PubMatic analytics adapter to support bidCpmAdustment values #5354

Merged
merged 61 commits into from
Jun 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
33762d1
added support for pubcommon, digitrust, id5id
pm-harshad-mane Sep 12, 2019
0722354
added support for IdentityLink
pm-harshad-mane Sep 13, 2019
f2c32c0
changed the source for id5
pm-harshad-mane Sep 13, 2019
37163d1
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Sep 13, 2019
eaed987
added unit test cases
pm-harshad-mane Sep 13, 2019
602ee7e
changed source param for identityLink
pm-harshad-mane Sep 16, 2019
b6fcd36
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Sep 23, 2019
58381f3
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Sep 26, 2019
c9fb11b
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Oct 10, 2019
8ece7fd
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Oct 16, 2019
28d12a0
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Oct 16, 2019
05a55e1
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Oct 31, 2019
e8b10d5
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Nov 5, 2019
870085f
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Nov 12, 2019
844ce4e
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Nov 12, 2019
704eca3
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Nov 13, 2019
2565cb9
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Dec 4, 2019
1d75bd4
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Dec 4, 2019
6adde1e
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Dec 6, 2019
477c98a
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Dec 9, 2019
cef5422
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Dec 10, 2019
c110a7d
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Jan 9, 2020
e8fb062
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Feb 5, 2020
d77cd71
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Feb 17, 2020
817ce3f
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Feb 24, 2020
cda825e
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Feb 26, 2020
f34a3ec
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Feb 27, 2020
f106dc8
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 4, 2020
1f6937e
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 6, 2020
06ffe84
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 6, 2020
5448ceb
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 6, 2020
e9b90fe
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 11, 2020
a7a1d12
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 11, 2020
30b72df
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 26, 2020
76adbc9
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 30, 2020
50e13bc
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 30, 2020
a1c7ca1
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Mar 30, 2020
96fbadc
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Apr 1, 2020
4b026e2
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Apr 9, 2020
38740bc
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Apr 10, 2020
9daf778
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Apr 20, 2020
eff8828
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Apr 21, 2020
ede95de
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Apr 21, 2020
c98f1a1
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane Apr 23, 2020
312da6d
Merge remote-tracking branch 'upstream/master'
pm-harshad-mane May 18, 2020
3c8ece6
Merge remote-tracking branch 'upstream/master' into pm_analytics_gros…
pm-harshad-mane May 21, 2020
4fa6066
set gross ecpm using originalCpm
pm-harshad-mane May 22, 2020
50f24cb
using bidGrossCpmUSD to set eg
pm-harshad-mane May 27, 2020
f6b4843
lint
pm-harshad-mane May 27, 2020
3cbc5ed
fixed old cases
pm-harshad-mane May 27, 2020
dcc791e
added some tests
pm-harshad-mane May 27, 2020
adf1ae4
Merge remote-tracking branch 'upstream/master' into pm_analytics_gros…
pm-harshad-mane May 28, 2020
5cef987
removed comments
pm-harshad-mane May 29, 2020
b9cdce4
removed commented code , and unused import
pm-harshad-mane May 29, 2020
e9302a0
en related changes in test cases
pm-harshad-mane May 29, 2020
8193561
using pbjs.getHighestCpmBids, added test cases around it
pm-harshad-mane Jun 1, 2020
e3f83dc
passing highestCpmBids
pm-harshad-mane Jun 4, 2020
f58ce1a
fixed test cases
pm-harshad-mane Jun 4, 2020
850747c
Merge remote-tracking branch 'upstream/master' into pm_analytics_gros…
pm-harshad-mane Jun 9, 2020
0fca0d8
added notes
pm-harshad-mane Jun 9, 2020
ba572d0
using getGlobal() instead of $$PREBID_GLOBAL$$
pm-harshad-mane Jun 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 26 additions & 24 deletions modules/pubmaticAnalyticsAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import CONSTANTS from '../src/constants.json';
import { ajax } from '../src/ajax.js';
import { config } from '../src/config.js';
import * as utils from '../src/utils.js';
import { getGlobal } from '../src/prebidGlobal.js';

/// /////////// CONSTANTS //////////////
const ADAPTER_CODE = 'pubmatic';
Expand Down Expand Up @@ -124,7 +125,19 @@ function parseBidResponse(bid) {
if (typeof bid.getCpmInNewCurrency === 'function') {
return window.parseFloat(Number(bid.getCpmInNewCurrency(CURRENCY_USD)).toFixed(BID_PRECISION));
}
utils.logWarn(LOG_PRE_FIX + 'Could not determine the bidPriceUSD of the bid ', bid);
utils.logWarn(LOG_PRE_FIX + 'Could not determine the Net cpm in USD for the bid thus using bid.cpm', bid);
return bid.cpm
},
'bidGrossCpmUSD', () => {
if (typeof bid.originalCurrency === 'string' && bid.originalCurrency.toUpperCase() === CURRENCY_USD) {
return window.parseFloat(Number(bid.originalCpm).toFixed(BID_PRECISION));
}
// use currency conversion function if present
if (typeof getGlobal().convertCurrency === 'function') {
return window.parseFloat(Number(getGlobal().convertCurrency(bid.originalCpm, bid.originalCurrency, CURRENCY_USD)).toFixed(BID_PRECISION));
}
utils.logWarn(LOG_PRE_FIX + 'Could not determine the Gross cpm in USD for the bid, thus using bid.originalCpm', bid);
return bid.originalCpm
},
'dealId',
'currency',
Expand Down Expand Up @@ -152,20 +165,8 @@ function getDomainFromUrl(url) {
return a.hostname;
}

function getHighestBidForAdUnit(adUnit) {
return Object.keys(adUnit.bids).reduce(function(currentHighestBid, bidId) {
// todo: later we will need to consider grossECPM and netECPM
let bid = adUnit.bids[bidId];
if (bid.bidResponse && bid.bidResponse.bidPriceUSD > currentHighestBid.bidPriceUSD) {
currentHighestBid.bidPriceUSD = bid.bidResponse.bidPriceUSD;
currentHighestBid.bidId = bidId;
}
return currentHighestBid;
}, {bidId: '', bidPriceUSD: 0});
}

function gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId) {
const highestsBid = getHighestBidForAdUnit(adUnit);
function gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId, highestBid) {
highestBid = (highestBid && highestBid.length > 0) ? highestBid[0] : null;
return Object.keys(adUnit.bids).reduce(function(partnerBids, bidId) {
let bid = adUnit.bids[bidId];
partnerBids.push({
Expand All @@ -175,16 +176,15 @@ function gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId) {
'kgpv': bid.params.kgpv ? bid.params.kgpv : adUnitId,
'kgpsv': bid.params.kgpv ? bid.params.kgpv : adUnitId,
'psz': bid.bidResponse ? (bid.bidResponse.dimensions.width + 'x' + bid.bidResponse.dimensions.height) : '0x0',
'eg': bid.bidResponse ? bid.bidResponse.bidPriceUSD : 0, // todo: later we will need to consider grossECPM and netECPM, precision
'en': bid.bidResponse ? bid.bidResponse.bidPriceUSD : 0, // todo: later we will need to consider grossECPM and netECPM, precision
'eg': bid.bidResponse ? bid.bidResponse.bidGrossCpmUSD : 0,
'en': bid.bidResponse ? bid.bidResponse.bidPriceUSD : 0,
'di': bid.bidResponse ? (bid.bidResponse.dealId || EMPTY_STRING) : EMPTY_STRING,
'dc': bid.bidResponse ? (bid.bidResponse.dealChannel || EMPTY_STRING) : EMPTY_STRING,
'l1': bid.bidResponse ? bid.clientLatencyTimeMs : 0,
'l2': 0,
// 'ss': (bid.source === 'server' ? 1 : 0), // todo: is there any special handling required as per OW?
'ss': (s2sBidders.indexOf(bid.bidder) > -1) ? 1 : 0,
't': (bid.status == ERROR && bid.error.code == TIMEOUT_ERROR) ? 1 : 0,
'wb': highestsBid.bidId === bid.bidId ? 1 : 0,
'wb': (highestBid && highestBid.requestId === bid.bidId ? 1 : 0),
'mi': bid.bidResponse ? (bid.bidResponse.mi || undefined) : undefined,
'af': bid.bidResponse ? (bid.bidResponse.mediaType || undefined) : undefined,
'ocpm': bid.bidResponse ? (bid.bidResponse.originalCpm || 0) : 0,
Expand All @@ -194,7 +194,8 @@ function gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId) {
}, [])
}

function executeBidsLoggerCall(auctionId) {
function executeBidsLoggerCall(e, highestCpmBids) {
let auctionId = e.auctionId;
let referrer = config.getConfig('pageUrl') || cache.auctions[auctionId].referer || '';
let auctionCache = cache.auctions[auctionId];
let outputObj = { s: [] };
Expand Down Expand Up @@ -230,7 +231,7 @@ function executeBidsLoggerCall(auctionId) {
let slotObject = {
'sn': adUnitId,
'sz': adUnit.dimensions.map(e => e[0] + 'x' + e[1]),
'ps': gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId)
'ps': gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId, highestCpmBids.filter(bid => bid.adUnitCode === adUnitId))
};
slotsArray.push(slotObject);
return slotsArray;
Expand Down Expand Up @@ -263,8 +264,8 @@ function executeBidWonLoggerCall(auctionId, adUnitId) {
pixelURL += '&pdvid=' + enc(profileVersionId);
pixelURL += '&slot=' + enc(adUnitId);
pixelURL += '&pn=' + enc(winningBid.bidder);
pixelURL += '&en=' + enc(winningBid.bidResponse.bidPriceUSD); // todo: later we will need to consider grossECPM and netECPM
pixelURL += '&eg=' + enc(winningBid.bidResponse.bidPriceUSD); // todo: later we will need to consider grossECPM and netECPM
pixelURL += '&en=' + enc(winningBid.bidResponse.bidPriceUSD);
pixelURL += '&eg=' + enc(winningBid.bidResponse.bidGrossCpmUSD);
pixelURL += '&kgpv=' + enc(winningBid.params.kgpv || adUnitId);
ajax(
pixelURL,
Expand Down Expand Up @@ -345,8 +346,9 @@ function bidWonHandler(args) {

function auctionEndHandler(args) {
// if for the given auction bidderDonePendingCount == 0 then execute logger call sooners
let highestCpmBids = getGlobal().getHighestCpmBids() || [];
setTimeout(() => {
executeBidsLoggerCall.call(this, args.auctionId);
executeBidsLoggerCall.call(this, args, highestCpmBids);
}, (cache.auctions[args.auctionId].bidderDonePendingCount === 0 ? 500 : SEND_TIMEOUT));
}

Expand Down
3 changes: 1 addition & 2 deletions modules/pubmaticAnalyticsAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@ pbjs.enableAnalytics({
- Supports only Banner and Video media-type
- Does not supports Native media type
- Does not supports instream-video creative-render tracker
- BidCpmAdjustment: Bid CPM only after BidCpmAdjustment is logged
- If a currency module is NOT included and a bidder responds in a non-USD currency then PubMatic analytics bidder will not be able to log the bid CPM
- If a currency module is NOT included and a bidder responds in a non-USD currency then PubMatic analytics bidder will log values in original bid currency otherwise always logged in USD
133 changes: 129 additions & 4 deletions test/spec/modules/pubmaticAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ describe('pubmatic analytics adapter', function () {
});

it('Logger: best case + win tracker', function() {
sandbox.stub($$PREBID_GLOBAL$$, 'getHighestCpmBids').callsFake((key) => {
return [MOCK.BID_RESPONSE[0], MOCK.BID_RESPONSE[1]]
});

events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]);
Expand Down Expand Up @@ -387,6 +391,122 @@ describe('pubmatic analytics adapter', function () {
expect(data.en).to.equal('1.23');
});

it('bidCpmAdjustment: USD: Logger: best case + win tracker', function() {
const bidCopy = utils.deepClone(BID);
bidCopy.cpm = bidCopy.originalCpm * 2; // bidCpmAdjustment => bidCpm * 2

sandbox.stub($$PREBID_GLOBAL$$, 'getHighestCpmBids').callsFake((key) => {
return [bidCopy, MOCK.BID_RESPONSE[1]]
});

events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
events.emit(BID_RESPONSE, bidCopy);
events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]);
events.emit(BID_RESPONSE, bidCopy);
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
events.emit(AUCTION_END, MOCK.AUCTION_END);
events.emit(SET_TARGETING, MOCK.SET_TARGETING);
events.emit(BID_WON, MOCK.BID_WON[0]);
events.emit(BID_WON, MOCK.BID_WON[1]);

clock.tick(2000 + 1000);
expect(requests.length).to.equal(3); // 1 logger and 2 win-tracker
let request = requests[2]; // logger is executed late, trackers execute first
expect(request.url).to.equal('https://t.pubmatic.com/wl?pubid=9999&gdEn=1');
let data = getLoggerJsonFromRequest(request.requestBody);
expect(data.pubid).to.equal('9999');
expect(data.pid).to.equal('1111');
expect(data.s).to.be.an('array');
expect(data.s.length).to.equal(2);
// slot 1
expect(data.s[0].sn).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].sz).to.deep.equal(['640x480']);
expect(data.s[0].ps).to.be.an('array');
expect(data.s[0].ps.length).to.equal(1);
expect(data.s[0].ps[0].pn).to.equal('pubmatic');
expect(data.s[0].ps[0].bidid).to.equal('2ecff0db240757');
expect(data.s[0].ps[0].kgpv).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].ps[0].eg).to.equal(1.23);
expect(data.s[0].ps[0].en).to.equal(2.46);
expect(data.s[0].ps[0].wb).to.equal(1);
expect(data.s[0].ps[0].af).to.equal('video');
expect(data.s[0].ps[0].ocpm).to.equal(1.23);
expect(data.s[0].ps[0].ocry).to.equal('USD');
// tracker slot1
let firstTracker = requests[0].url;
expect(firstTracker.split('?')[0]).to.equal('https://t.pubmatic.com/wt');
data = {};
firstTracker.split('?')[1].split('&').map(e => e.split('=')).forEach(e => data[e[0]] = e[1]);
expect(data.pubid).to.equal('9999');
expect(data.tst).to.equal('1519767014');
expect(data.iid).to.equal('25c6d7f5-699a-4bfc-87c9-996f915341fa');
expect(data.eg).to.equal('1.23');
expect(data.en).to.equal('2.46');
});

it('bidCpmAdjustment: JPY: Logger: best case + win tracker', function() {
setConfig({
adServerCurrency: 'JPY',
rates: {
USD: {
JPY: 100
}
}
});
const bidCopy = utils.deepClone(BID);
bidCopy.originalCpm = 100;
bidCopy.originalCurrency = 'JPY';
bidCopy.currency = 'JPY';
bidCopy.cpm = bidCopy.originalCpm * 2; // bidCpmAdjustment => bidCpm * 2

events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
// events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]);
events.emit(BID_RESPONSE, bidCopy);
events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]);
events.emit(BID_RESPONSE, bidCopy);
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
events.emit(AUCTION_END, MOCK.AUCTION_END);
events.emit(SET_TARGETING, MOCK.SET_TARGETING);
events.emit(BID_WON, MOCK.BID_WON[0]);
events.emit(BID_WON, MOCK.BID_WON[1]);

clock.tick(2000 + 1000);
expect(requests.length).to.equal(3); // 1 logger and 2 win-tracker
let request = requests[2]; // logger is executed late, trackers execute first
expect(request.url).to.equal('https://t.pubmatic.com/wl?pubid=9999&gdEn=1');
let data = getLoggerJsonFromRequest(request.requestBody);
expect(data.pubid).to.equal('9999');
expect(data.pid).to.equal('1111');
expect(data.s).to.be.an('array');
expect(data.s.length).to.equal(2);
// slot 1
expect(data.s[0].sn).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].sz).to.deep.equal(['640x480']);
expect(data.s[0].ps).to.be.an('array');
expect(data.s[0].ps.length).to.equal(1);
expect(data.s[0].ps[0].pn).to.equal('pubmatic');
expect(data.s[0].ps[0].bidid).to.equal('2ecff0db240757');
expect(data.s[0].ps[0].kgpv).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].ps[0].eg).to.equal(1);
expect(data.s[0].ps[0].en).to.equal(200);
expect(data.s[0].ps[0].wb).to.equal(0); // bidPriceUSD is not getting set as currency module is not added, so unable to set wb to 1
expect(data.s[0].ps[0].af).to.equal('video');
expect(data.s[0].ps[0].ocpm).to.equal(100);
expect(data.s[0].ps[0].ocry).to.equal('JPY');
// tracker slot1
let firstTracker = requests[0].url;
expect(firstTracker.split('?')[0]).to.equal('https://t.pubmatic.com/wt');
data = {};
firstTracker.split('?')[1].split('&').map(e => e.split('=')).forEach(e => data[e[0]] = e[1]);
expect(data.pubid).to.equal('9999');
expect(data.tst).to.equal('1519767014');
expect(data.iid).to.equal('25c6d7f5-699a-4bfc-87c9-996f915341fa');
expect(data.eg).to.equal('1');
expect(data.en).to.equal('200'); // bidPriceUSD is not getting set as currency module is not added
});

it('Logger: when bid is not submitted, default bid status 1 check: pubmatic set as s2s', function() {
events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
Expand Down Expand Up @@ -463,6 +583,11 @@ describe('pubmatic analytics adapter', function () {

it('Logger: post-timeout check with bid response', function() {
// db = 1 and t = 1 means bidder did NOT respond with a bid but we got a timeout notification

sandbox.stub($$PREBID_GLOBAL$$, 'getHighestCpmBids').callsFake((key) => {
return [MOCK.BID_RESPONSE[1]]
});

events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]);
Expand Down Expand Up @@ -492,7 +617,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(1);
expect(data.s[1].ps[0].wb).to.equal(1);
expect(data.s[1].ps[0].wb).to.equal(1); // todo
expect(data.s[1].ps[0].af).to.equal('banner');
expect(data.s[1].ps[0].ocpm).to.equal(1.52);
expect(data.s[1].ps[0].ocry).to.equal('USD');
Expand Down Expand Up @@ -538,8 +663,8 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].kgpv).to.equal('this-is-a-kgpv');
expect(data.s[1].ps[0].kgpsv).to.equal('this-is-a-kgpv');
expect(data.s[1].ps[0].psz).to.equal('728x90');
expect(data.s[1].ps[0].eg).to.equal(undefined); // bidPriceUSD is not getting set as currency module is not added
expect(data.s[1].ps[0].en).to.equal(undefined); // bidPriceUSD is not getting set as currency module is not added
expect(data.s[1].ps[0].eg).to.equal(1);
expect(data.s[1].ps[0].en).to.equal(100);
expect(data.s[1].ps[0].di).to.equal('the-deal-id');
expect(data.s[1].ps[0].dc).to.equal('PMP');
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
Expand All @@ -552,5 +677,5 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].ocpm).to.equal(100);
expect(data.s[1].ps[0].ocry).to.equal('JPY');
});
})
});
});