import { expect } from "chai"; import { Offer } from "../../../src/models/offer"; import offerInfo from "../../fixtures/offer"; const offerData: any = offerInfo.data.offerById; describe("Offer", () => { let offer: any; beforeEach(() => { offer = new Offer(offerData); }); context("on initialise", () => { it("sets this.rawResponse", () => { expect(offer.rawResponse).to.eql(offerData); }); it("sets this.offerId", () => { expect(offer.id).to.equal(offerData.id); }); it("sets this.productName", () => { expect(offer.productName).to.equal(offerData.product.name); }); it("sets this.displayName", () => { expect(offer.displayName).to.equal(offerData.displayName); }); it("sets this.productType", () => { expect(offer.productType).to.equal("BUNDLE"); }); it("sets this.productCode", () => { expect(offer.productCode).to.equal(offerData.product.code); }); it("sets this.pricing", () => { expect(offer.pricing).to.eql(offerData.pricing); }); it("sets this.printProductCode", () => { expect(offer.printProductCode).to.eql("N5D"); }); it("sets this.digitalProductCode", () => { expect(offer.digitalProductCode).to.eql("P1"); }); it("throws an error if offerData is undefined", () => { // @ts-ignore expect(() => new Offer(undefined)).to.throw(); }); it("throws an error if offerData is an empty object", () => { expect(() => new Offer({} as any)).to.throw(); }); it("throws an error if initialised with a malformed offer response", () => { expect(() => new Offer("" as any)).to.throw(); }); }); context("getCountryPricing", () => { const pricing = [ { country: "AUS" }, { country: "GBR" }, { country: "AUS" }, { country: "GBR" }, ]; it("returns charges of the country specified", () => { const response = [{ country: "GBR" }, { country: "GBR" }]; expect(offer.getCountryPricing("GBR", pricing)).to.eql(response); }); it("throws an error when country could not be found", () => { expect(() => offer.getCountryPricing()).to.throw(); }); it("throws error when pricing array is undefined", () => { expect(() => offer.getCountryPricing("GBR")).to.throw(); }); it("throws error when countryCode is undefined", () => { expect(() => offer.getCountryPricing(undefined, pricing)).to.throw(); }); it("throws error when call is made with an empty object array", () => { expect(() => offer.getCountryPricing("GBR", [{}])).to.throw(); }); it("throws error when call is made with an empty array", () => { expect(() => offer.getCountryPricing("GBR", [])).to.throw(); }); it("throws error when countryCode and pricing is undefined", () => { expect(() => offer.getCountryPricing()).to.throw(); }); it("throws error when call is made with an incorrect parameters", () => { expect(() => offer.getCountryPricing("hello")).to.throw(); }); }); context("getCurrency", () => { it("returns currency code for the country given", () => { expect(offer.getCurrency("GBR")).to.equal("GBP"); }); it("throws an error when currency code could not be found", () => { expect(() => offer.getCurrency("ZZZ")).to.throw(); }); it("throws an error when currency code is not given", () => { expect(() => offer.getCurrency()).to.throw(); }); it("throws an error when currency code is not a string", () => { expect(() => offer.getCurrency({})).to.throw(); }); }); context("getBillingCountries", () => { it("get all countries that this offer is restricted to", () => { offer.pricing = [ { country: "AUS" }, { country: "GBR" }, { country: "JPN" }, { country: "USA" }, ]; expect(offer.getBillingCountries()).to.eql(["AUS", "GBR", "JPN", "USA"]); }); it("throws an error when pricing is undefined", () => { offer.pricing = undefined; expect(() => offer.getBillingCountries()).to.throw(); }); }); context("getBillingCountriesForCurrency", () => { it("get all countries that offer GBP as a currency", () => { offer.pricing = [ { country: "GIB", currency: "GBP" }, { country: "GBR", currency: "GBP" }, { country: "JPN" }, { country: "USA" }, ]; expect(offer.getBillingCountriesForCurrency("GBP")).to.eql([ "GIB", "GBR", ]); }); it("throws an error when the offer has no prices for that currency", () => { offer.pricing = [ { country: "GIB", currency: "GBP" }, { country: "GBR", currency: "GBP" }, { country: "JPN" }, { country: "USA" }, ]; expect(() => offer.getBillingCountriesForCurrency("USD")).to.throw(); }); it("throws an error when pricing is undefined", () => { offer.pricing = undefined; expect(() => offer.getBillingCountriesForCurrency("GBP")).to.throw(); }); }); context("isStandard", () => { it("returns TRUE if offer is a Standard digital product", () => { offer.productCode = "P1"; expect(offer.isStandard()).to.be.true; }); it("returns TRUE if offer is a Standard 6 days a week product", () => { offer.productCode = "P1N6D"; expect(offer.isStandard()).to.be.true; }); it("returns TRUE if offer is a Standard 5 days a week product", () => { offer.productCode = "P1N5D"; expect(offer.isStandard()).to.be.true; }); it("returns TRUE if offer is a Standard weekend product", () => { offer.productCode = "P1NWE"; expect(offer.isStandard()).to.be.true; }); it("returns FALSE if offer is a NOT a Standard product", () => { offer.productCode = "P2"; expect(offer.isStandard()).to.be.false; }); it("returns FALSE if offer does NOT have a Standard product code", () => { offer.productCode = "P2P2"; expect(offer.isStandard()).to.be.false; }); it("returns FALSE if offer product type is undefined", () => { offer.productCode = undefined; expect(offer.isStandard()).to.be.false; }); }); context("isPremium", () => { it("returns TRUE if offer is a Premium digital product", () => { offer.productCode = "P2"; expect(offer.isPremium()).to.be.true; }); it("returns TRUE if offer is a Premium 6 days a week product", () => { offer.productCode = "P2N6D"; expect(offer.isPremium()).to.be.true; }); it("returns TRUE if offer is a Premium 5 days a week product", () => { offer.productCode = "P2N5D"; expect(offer.isPremium()).to.be.true; }); it("returns TRUE if offer is a Premium weekend product", () => { offer.productCode = "P2NWE"; expect(offer.isPremium()).to.be.true; }); it("returns FALSE if offer is a NOT a Premium product", () => { offer.productCode = "P1"; expect(offer.isPremium()).to.be.false; }); it("returns FALSE if offer does NOT have a premium product code", () => { offer.productCode = "P1P1"; expect(offer.isPremium()).to.be.false; }); it("returns FALSE if offer product type is undefined", () => { offer.productCode = undefined; expect(offer.isPremium()).to.be.false; }); }); describe("digital offer", () => { context("isDigital", () => { it("returns TRUE if offer is a digital product", () => { offer.productType = "DIGITAL"; expect(offer.isDigital()).to.be.true; }); it("returns FALSE if offer is not a digital product", () => { offer.productType = "BUNDLE"; expect(offer.isDigital()).to.be.false; }); }); }); describe("print or bundle offer", () => { context("isPrint", () => { it("returns TRUE if offer is a print product", () => { offer.productType = "PRINT"; expect(offer.isPrint()).to.be.true; }); it("returns FALSE if offer is not a print product", () => { offer.productType = "BUNDLE"; expect(offer.isPrint()).to.be.false; }); }); context("isBundle", () => { it("returns TRUE if offer is a bundle", () => { offer.productType = "BUNDLE"; expect(offer.isBundle()).to.be.true; }); it("returns FALSE if offer is not a bundle product", () => { offer.productType = "DIGITAL"; expect(offer.isBundle()).to.be.false; }); it("returns FALSE if offer product type is undefined", () => { offer.productType = undefined; expect(offer.isBundle()).to.be.false; }); }); context("getFulfilmentPricing", () => { const pricing = [ { option: { code: "HD", displayName: "Home Delivery" } }, ]; it("returns charge based on fulfilment option", () => { const response = [ { option: { code: "HD", displayName: "Home Delivery" } }, ]; expect(offer.getFulfilmentPricing("HD", pricing)).to.eql(response); }); it("throws error when fulfilment option is not given", () => { expect(() => offer.getFulfilmentPricing(undefined, pricing)).to.throw(); }); it("throws error when fulfilmentOption could not be found", () => { expect(() => offer.getFulfilmentPricing("PV", pricing)).to.throw(); }); it("throws error when fulfilmentOption could not be found", () => { expect(() => offer.getFulfilmentPricing("PV", [])).to.throw(); }); it("throws error when fulfilmentOption could not be found", () => { expect(() => offer.getFulfilmentPricing("PV", [{}])).to.throw(); }); it("throws error when pricing array is undefined for getFulfilmentPricing", () => { expect(() => offer.getFulfilmentPricing("HD")).to.throw(); }); it("throws error when pricing array is undefined for getFulfilmentPricing", () => { expect(() => offer.getFulfilmentPricing()).to.throw(); }); }); context("getTermPricing", () => { const pricing = offerData.pricing; it("returns pricing for a given payment term", () => { expect(offer.getTermPricing("monthly", pricing)).to.eql( offerData.pricing[0] ); }); it("throws an error when pricing for a given payment term does not exist", () => { expect(() => offer.getTermPricing("monthly", "nothing")).to.throw(); }); it("throws an error when pricing for a given payment term is undefined", () => { expect(() => offer.getTermPricing("monthly", "pricing")).to.throw(); }); it("throws an error when pricing does not exist", () => { expect(() => offer.getTermPricing("monthly", [])).to.throw(); }); it("throws an error when pricing undefined", () => { expect(() => offer.getTermPricing("monthly")).to.throw(); }); it("throws an error when pricing and term are undefined", () => { expect(() => offer.getTermPricing()).to.throw(); }); it("throws an error when term and pricing are malformed", () => { expect(() => offer.getTermPricing({}, {})).to.throw(); }); }); context("charges", () => { const response = [ { subscriptionName: "Monthly", subscriptionCode: "P1M", subscriptionAutoRenewTerm: true, subscriptionTermType: "EVERGREEN", subscriptionPaymentDue: undefined, currency: "GBP", symbol: "£", value: "51.00", option: { code: "HD", displayName: "Home Delivery" }, trialValue: null, }, { subscriptionName: "Annual", subscriptionCode: "P1Y", subscriptionAutoRenewTerm: true, subscriptionTermType: "EVERGREEN", subscriptionPaymentDue: undefined, currency: "GBP", symbol: "£", value: "550.00", option: { code: "HD", displayName: "Home Delivery" }, trialValue: null, }, { subscriptionName: "Monthly", subscriptionCode: "P1M", subscriptionAutoRenewTerm: true, subscriptionTermType: "EVERGREEN", subscriptionPaymentDue: undefined, currency: "USD", symbol: "$", value: "55.00", option: { code: "PV", displayName: "Paper Voucher" }, trialValue: null, }, { subscriptionName: "Annual", subscriptionCode: "P1Y", subscriptionAutoRenewTerm: true, subscriptionTermType: "EVERGREEN", subscriptionPaymentDue: undefined, currency: "USD", symbol: "$", value: "555.00", option: { code: "PV", displayName: "Paper Voucher" }, trialValue: null, }, { subscriptionName: "Annual", subscriptionCode: "P1Y", subscriptionAutoRenewTerm: true, subscriptionTermType: "EVERGREEN", subscriptionPaymentDue: undefined, currency: "CAD", symbol: "$", value: "555.00", option: { code: "PV", displayName: "Paper Voucher" }, trialValue: null, }, ]; context("getAvailableCharges", () => { it("returns formatted pricing based on country code", () => { expect(offer.getAvailableCharges("GBR")).to.eql([ response[0], response[1], ]); }); it("returns formatted pricing based on country code and fulfilmentOption", () => { expect(offer.getAvailableCharges("GBR", "HD")).to.eql([ response[0], response[1], ]); }); it("returns formatted pricing for all prices when countryCode and fulfilmentOption are not given", () => { expect(offer.getAvailableCharges()).to.eql(response); }); it("returns formatted pricing based on country code when countryCode is given but fulfilmentOption in undefined", () => { expect(offer.getAvailableCharges("GBR")).to.eql([ response[0], response[1], ]); }); it("returns formatted pricing for all prices when countryCode is undefined but fulfilmentOption is given", () => { expect(offer.getAvailableCharges(null, "HD")).to.eql(response); }); it("throws an error when only fulfilmentOption is given", () => { expect(() => offer.getAvailableCharges("HD")).to.throw( "Pricing could not be found for country code: HD" ); }); }); context("getAllAvailableCharge", () => { it("returns all available charges only containing amount, currency and value", () => { expect(offer.getAllAvailableCharges()).to.eql(response); }); }); context("getAvailableChargesForCountry", () => { it("returns formatted charges based on country code", () => { expect(offer.getAvailableChargesForCountry("GBR")).to.eql([ response[0], response[1], ]); }); it("throws error pricing for country code could not be found", () => { const errorMessage = "Pricing could not be found for country code: ZZZ"; expect(() => offer.getAvailableChargesForCountry("ZZZ")).to.throw( errorMessage ); }); }); context("getAvailableChargesForCountryAndFulfilmentOption", () => { it("returns formatted charges based on country code and fulfilment details", () => { expect( offer.getAvailableChargesForCountryAndFulfilmentOption("GBR", "HD") ).to.eql([response[0], response[1]]); }); it("throws error when trying to get all available charges when fulfilmentOption could not be found", () => { expect(() => offer.getAvailableChargesForCountryAndFulfilmentOption() ).to.throw(); }); it("throws error when countryCode and fulfilmentOption could not be found", () => { expect(() => offer.getAvailableChargesForCountryAndFulfilmentOption( "fake", "fake" ) ).to.throw(); }); }); }); context("getSubscriptionTerm", () => { it("returns the subscriptionTerm for a price", () => { const response = { displayName: "Monthly", iso8601Duration: "P1M", autoRenewTerm: true, termType: "EVERGREEN", }; const price = offerData.pricing[0]; expect(offer.getSubscriptionTerm(price)).to.eql(response); }); it("throws an error when basis RECURRING cannot be found", () => { const pricing = { charges: [ { amount: { value: "1.00" }, basis: "ONE_TIME", subscriptionTerm: null, paymentDue: null, }, ], }; expect(() => offer.getSubscriptionTerm(pricing)).to.throw(); }); it("throws an error when there is an empty charge is not given", () => { expect(() => offer.getSubscriptionTerm({ charges: [] })).to.throw(); }); }); }); describe("trial offer", () => { context("isTrial", () => { it("returns TRUE if offer is a trial product", () => { offer.type = "TRIAL"; expect(offer.isTrial()).to.be.true; }); it("returns FALSE if offer is not a trial product", () => { offer.type = "rrp"; expect(offer.isTrial()).to.be.false; }); it("returns paymentDueAfter of P4W", () => { offer.type = "TRIAL"; const pricing = { charges: [ { basis: "RECURRING", subscriptionTerm: { displayName: "Monthly", iso8601Duration: "P1M", }, paymentDue: { after: "P4W" }, }, { basis: "ONE_TIME", subscriptionTerm: null, paymentDue: null, }, ], }; const response = { displayName: "Monthly", iso8601Duration: "P1M", paymentDueAfter: "P4W", }; expect(offer.getSubscriptionTerm(pricing)).to.eql(response); }); }); }); describe("getPrintProductCode", () => { it("should return a print product code of N5D when it is a print product", () => { offer.productCodes = ["N5D"]; expect(offer.getPrintProductCode()).to.equal("N5D"); }); it("should return a print product code of N5D when it is a bundle product", () => { offer.productCodes = ["P1", "N5D"]; expect(offer.getPrintProductCode()).to.equal("N5D"); }); it("should throw an error when the product is not print or bundle", () => { offer.productCodes = ["P1"]; expect(() => offer.getPrintProductCode()).to.throw(); }); it("should throw an error when the product is the Inside Politics (standard) niche email newsletter product", () => { offer.productCodes = ["NS1"]; expect(() => offer.getPrintProductCode()).to.throw(); }); it("should throw an error when the product is the Unhedged (premium) niche email newsletter product", () => { offer.productCodes = ["NP1"]; expect(() => offer.getPrintProductCode()).to.throw(); }); it("should throw an error when the product is the FT Newsletters trial product", () => { offer.productCodes = ["PNWU1"]; expect(() => offer.getPrintProductCode()).to.throw(); }); }); describe("getDigitalProductCode", () => { it("should return a digital product code of P1 when it is a digital product (P1)", () => { offer.productCodes = ["P1"]; expect(offer.getDigitalProductCode()).to.equal("P1"); }); it("should return a digital product code of P22 when it is a digital product (P2)", () => { offer.productCodes = ["P2"]; expect(offer.getDigitalProductCode()).to.equal("P2"); }); it("should return a digital product code of P22 when it is a digital product (P22)", () => { offer.productCodes = ["P22"]; expect(offer.getDigitalProductCode()).to.equal("P22"); }); it("should return a digital product code of P1 when it is a bundle product", () => { offer.productCodes = ["P1", "N5D"]; expect(offer.getDigitalProductCode()).to.equal("P1"); }); it("should return a digital product code of NS1 when it is the Inside Politics (standard) niche email newsletter product", () => { offer.productCodes = ["NS1"]; expect(offer.getDigitalProductCode()).to.equal("NS1"); }); it("should return a digital product code of NP1 when it is the Unhedged (premium) niche email newsletter product", () => { offer.productCodes = ["NP1"]; expect(offer.getDigitalProductCode()).to.equal("NP1"); }); it("should return a digital product code of PNWU1 when it is the FT Newsletters trial product", () => { offer.productCodes = ["PNWU1"]; expect(offer.getDigitalProductCode()).to.equal("PNWU1"); }); it("should throw an error when the product is not digital or bundle", () => { offer.productCodes = ["N5D"]; expect(() => offer.getDigitalProductCode()).to.throw(); }); }); describe("isEpaper", () => { it("returns TRUE if offer is an ePaper product", () => { offer.productType = "PRINT"; offer.productCode = "EP"; expect(offer.isEpaper()).to.be.true; }); it("returns FALSE if offer is not an ePaper product", () => { offer.productType = "BUNDLE"; expect(offer.isEpaper()).to.be.false; }); it("returns FALSE if offer is a print product", () => { offer.productType = "PRINT"; offer.productCode = "OTHER"; expect(offer.isEpaper()).to.be.false; }); }); });