Skip to content
This repository has been archived by the owner on Mar 12, 2020. It is now read-only.

Commit

Permalink
Merge pull request #203 from Financial-Times/teaserTesting
Browse files Browse the repository at this point in the history
Teaser testing
  • Loading branch information
saldixon authored Jan 18, 2019
2 parents 3fc34a1 + 969ce81 commit 1b7431b
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 11 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"mocha": "^5.2.0",
"node-sass": "^4.0.0",
"npm-prepublish": "^1.2.1",
"pa11y-ci": "^2.1.1"
"pa11y-ci": "^2.1.1",
"sinon": "^6.0.1"
},
"config": {},
"scripts": {
Expand Down
60 changes: 52 additions & 8 deletions src/presenters/teaser-presenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,16 +310,20 @@ class TeaserPresenter {
// returns title either standard or promotional based on flag
get displayTitle () {
const altTitles = this.data.alternativeTitles;

if (this.isTeaserTestActive && this.teaserTestVariant === 'variant2') {
return this.teaserTestVariantText;
}

// Support the old 'headlineTesting' mechanism of identifying a test until article-specific testing is available end-to-end.
if (this.data.flags && this.data.flags.headlineTesting && this.data.flags.headlineTesting === 'variant2' && altTitles && (altTitles.promotionalTitleVariant || altTitles.contentPackageTitle)) {
return altTitles.promotionalTitleVariant ? altTitles.promotionalTitleVariant : altTitles.contentPackageTitle;
} else if (this.data.flags && this.data.flags.teaserUsePromotionalTitle) {
if (this.data.promotionalTitle) {
return this.data.promotionalTitle;
}
if (this.data.alternativeTitles && this.data.alternativeTitles.promotionalTitle) {
return this.data.alternativeTitles.promotionalTitle;
}
return altTitles.promotionalTitleVariant ? altTitles.promotionalTitleVariant: altTitles.contentPackageTitle ;
}

if (this.isTeaserPromoActive) {
return this.teaserPromoTitleText;
}

return this.data.title;
}

Expand All @@ -342,6 +346,46 @@ class TeaserPresenter {
return null;
}

// returns true if there the teaser promo flag is enabled AND teaser promo text has been configured
get isTeaserPromoActive () {
return (this.data.flags && this.data.flags.teaserUsePromotionalTitle && this.teaserPromoTitleText) ? true : false;
}

// returns the text configured for a teaserPromo
get teaserPromoTitleText () {
if (this.data.promotionalTitle) {
return this.data.promotionalTitle;
}
if (this.data.alternativeTitles && this.data.alternativeTitles.promotionalTitle) {
return this.data.alternativeTitles.promotionalTitle ;
}
return null;
}

// returns true if there is a active teaser testing flag created for this story AND a variant headline has been configured
get isTeaserTestActive () {
return (this.teaserTestVariant && this.teaserTestVariantText) ? true : false;
}

// returns the variant name specified by this teaser's flag
get teaserTestVariant () {
const teaserTestFlagName = 'teaser-test-' + this.data.id;
if (this.data.flags && this.data.flags[teaserTestFlagName]) {
return this.data.flags[teaserTestFlagName]
}
return null;
}

// the text configured for a teaser VARIANT
get teaserTestVariantText () {
const altTitles = this.data.alternativeTitles;
if (altTitles && (altTitles.promotionalTitleVariant || altTitles.contentPackageTitle)) {
return altTitles.promotionalTitleVariant ? altTitles.promotionalTitleVariant: altTitles.contentPackageTitle ;
}
return null;
}


get isPlayableVideo () {
const isTopStory = this.data.template === 'top-story-heavy';
const isBigStory = modsDoesInclude('big-story', this.data.mods);
Expand Down
6 changes: 5 additions & 1 deletion templates/partials/title.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
data-trackable="main-link"
{{#ifEquals type 'promoted-content'}}target="_blank"{{/ifEquals}}
{{#if @nTeaserPresenter.headlineTestingVariant}}data-trackable-context-headline-variant="{{{@nTeaserPresenter.headlineTestingVariant}}}"{{/if}}

{{#if @nTeaserPresenter.isTeaserTestActive}}
data-trackable-context-teaser-variant="{{{@nTeaserPresenter.teaserTestVariant}}}"
{{/if}}
>
{{@nTeaserPresenter.displayTitle}}
</a>
{{#if isPremium}}
<span class="o-labels o-labels--premium" aria-label="Premium content">Premium</span>
{{/if}}
</div>
</div>
154 changes: 153 additions & 1 deletion tests/presenters/teaser-presenter.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const expect = require('chai').expect;
const sinon = require('sinon');
const Presenter = require('../../src/presenters/teaser-presenter');
const articleBrandFixture = require('../fixtures/article-brand-fixture');
const articleOpinionAuthorFixture = require('../fixtures/article-opinion-author-fixture');
Expand Down Expand Up @@ -650,7 +651,8 @@ describe('Teaser Presenter', () => {

});

describe('displayTitle', () => {
// todo rip this out when headline testing has been replaced with teaserTesting
describe('displayTitle_headlineTesting', () => {

const promotionalTitle = { promotionalTitle: 'promotional' };
const headlineTestingVariants = { alternativeTitles: { contentPackageTitle: 'contentTitle', promotionalTitleVariant: 'variantHeadline' }};
Expand Down Expand Up @@ -747,6 +749,156 @@ describe('Teaser Presenter', () => {
});
});


describe('displayTitle', () => {
const title = { title: 'title'};
const promotionalTitle = { promotionalTitle: 'promotional' };
const alternativeTitles = { alternativeTitles: { contentPackageTitle: 'contentTitle', promotionalTitleVariant: 'variantHeadline' }};
const allTitles = Object.assign({}, title, promotionalTitle, alternativeTitles);

it('Returns the title if teaserTest inactive and teaserPromo inactive', () => {
const content = Object.assign({}, allTitles);
subject = new Presenter(content);
sinon.stub(subject, 'isTeaserTestActive').get(() => false);
sinon.stub(subject, 'isTeaserPromoActive').get(() => false);
expect(subject.displayTitle).to.equal('title');
});

it('Returns the relevant teaser promoTitle if teaserTest inactive, teaserPromo active', () => {
subject = new Presenter( {} );
sinon.stub(subject, 'isTeaserTestActive').get(() => false);
sinon.stub(subject, 'isTeaserPromoActive').get(() => true);
sinon.stub(subject, 'teaserPromoTitleText').get(() => 'a promo title');
expect(subject.displayTitle).to.equal('a promo title');
});

it('Returns the teaser variant if teaserTest active AND teaser variant is variant2', () => {
subject = new Presenter( {} );
sinon.stub(subject, 'isTeaserTestActive').get(() => true);
sinon.stub(subject, 'teaserTestVariant').get(() => 'variant2');
sinon.stub(subject, 'teaserTestVariantText').get(() => 'teaser variant headline');
expect(subject.displayTitle).to.equal('teaser variant headline');
});

it('Returns title if teaserTest active but teaser variant is NOT variant2', () => {
subject = new Presenter( Object.assign({}, allTitles ));
sinon.stub(subject, 'isTeaserTestActive').get(() => true);
sinon.stub(subject, 'teaserTestVariant').get(() => 'variant1');
sinon.stub(subject, 'teaserTestVariantText').get(() => 'teaser variant headline');
expect(subject.displayTitle).to.equal('title');
});

it('Gives precendence to Teaser testing over teaserPromo display', () => {
subject = new Presenter( {} );
sinon.stub(subject, 'isTeaserPromoActive').get(() => true);
sinon.stub(subject, 'teaserPromoTitleText').get(() => 'a promo title');
sinon.stub(subject, 'isTeaserTestActive').get(() => true);
sinon.stub(subject, 'teaserTestVariant').get(() => 'variant2');
sinon.stub(subject, 'teaserTestVariantText').get(() => 'teaser variant headline');
expect(subject.displayTitle).to.equal('teaser variant headline');
});

});

describe('get isTeaserPromoActive', () => {
const flagOn = { teaserUsePromotionalTitle: true };

it('returns true if promo title configured AND flag is on', () => {
const flags = Object.assign({}, flagOn);
subject = new Presenter( Object.assign({}, {flags} ) );
sinon.stub(subject, 'teaserPromoTitleText').get(() => 'somePromoText');
expect(subject.isTeaserPromoActive).to.equal(true);
});
it('returns false if flag is on but no promo title configured', () => {
const flags = Object.assign({}, flagOn);
subject = new Presenter(Object.assign({}, {flags} ));
sinon.stub(subject, 'teaserPromoTitleText').get(() => null);
expect(subject.isTeaserPromoActive).to.equal(false);
});
it('returns false if promo title configured but flag is OFF', () => {
subject = new Presenter( {} );
sinon.stub(subject, 'teaserPromoTitleText').get(() => 'somePromoText');
expect(subject.isTeaserPromoActive).to.equal(false);
});

});

describe('get teaserPromoTitleText', () => {
const title = { title: 'title'};
const promotionalTitle = { promotionalTitle: 'promotional' };
const alternativeTitles = { alternativeTitles: { contentPackageTitle: 'contentTitle', promotionalTitleVariant: 'variantHeadline', promotionalTitle: 'altPromotional' } };
const allTitles = Object.assign({}, title, promotionalTitle, alternativeTitles);

it('uses promotionalTitle if present', () => {
const content = Object.assign({}, allTitles );
subject = new Presenter(Object.assign({}, content ));
expect(subject.teaserPromoTitleText).to.equal('promotional');
});

it('uses alternativeTitles.promotionalTitle if promotionalTitle not present', () => {
const content = Object.assign({}, alternativeTitles, title );
subject = new Presenter(Object.assign({}, content ));
expect(subject.teaserPromoTitleText).to.equal('altPromotional');
});

it('returns null if neither promoTitle found', () => {
const content = Object.assign({}, { title: 'the-title', alternativeTitles: { promotionalTitleVariant: 'variantHeadline' } } );
subject = new Presenter(Object.assign({}, content ));
expect(subject.teaserPromoTitleText).to.equal(null);
});
});

describe('get teaserTestVariant', () => {
it('inspects the right flag to see what variant specified for this particular teaser', () => {
const flags = {'teaser-test-content-uuid-1': 'variant1', 'teaser-test-content-uuid-2': 'variant2'};
subject1 = new Presenter(Object.assign({}, {id: 'content-uuid-1'}, {flags} ));
subject2 = new Presenter(Object.assign({}, {id: 'content-uuid-2'}, {flags} ));
subject3 = new Presenter(Object.assign({}, {id: 'content-uuid-3'}, {flags} )); // no flag at all for this teaser
expect(subject1.teaserTestVariant).to.equal('variant1');
expect(subject2.teaserTestVariant).to.equal('variant2');
expect(subject3.teaserTestVariant).to.equal(null);
});
});

describe('isTeaserTestActive', () => {
it('returns true if flag is set for that teaser AND variant headlines are configured for that teaser', () => {
const flags = {'teaser-test-content-uuid-1': 'some-variant'};
const content = Object.assign({}, { id: 'content-uuid-1'}, { alternativeTitles: { promotionalTitleVariant: 'the-promotional-title-variant' }} );
subject = new Presenter(Object.assign( {}, content, {flags} ));
expect(subject.isTeaserTestActive).to.equal(true);
});
it('returns false if flag not set for that teaser', () => {
const content = Object.assign({}, { id: 'content-uuid-1'}, { alternativeTitles: { promotionalTitleVariant: 'the-promotional-title-variant' }} );
subject = new Presenter(Object.assign( {}, content ));
expect(subject.isTeaserTestActive).to.equal(false);
});
it('returns false if no alt titles configured for that teaser', () => {
const content = Object.assign({}, { id: 'content-uuid-1'}, { title: 'the-title' } );
subject = new Presenter(Object.assign( {}, content ));
expect(subject.isTeaserTestActive).to.equal(false);
});
});

describe('get teaserTestVariantText', () => {
it('uses promotionalTitleVariant if present', () => {
const content = Object.assign({}, { alternativeTitles: { promotionalTitleVariant: 'the-promotional-title-variant', contentPackageTitle: 'the-content-package-title'}, title: 'the-title' } );
subject = new Presenter(Object.assign({}, content ));
expect(subject.teaserTestVariantText).to.equal('the-promotional-title-variant');
});

it('uses contentPackageTitle if promotionalTitleVariant not present', () => {
const content = Object.assign({}, { alternativeTitles: { promotionalTitleVariant: null, contentPackageTitle: 'the-content-package-title'}, title: 'the-title' } );
subject = new Presenter(Object.assign({}, content ));
expect(subject.teaserTestVariantText).to.equal('the-content-package-title');
});

it('returns null if neither alternativeTitle found', () => {
const content = Object.assign({}, { title: 'the-title' } );
subject = new Presenter(Object.assign({}, content ));
expect(subject.teaserTestVariantText).to.equal(null);
});
});

describe('display standfirst', () => {
const standfirst = { standfirst: 'This is the standfirst' };
const promotionalStandfirst = { promotionalStandfirst: 'This is promotional' };
Expand Down

0 comments on commit 1b7431b

Please sign in to comment.