const assert = require('assert'); const should = require('should'); const sinon = require('sinon'); const supertest = require('supertest'); const moment = require('moment'); const testUtils = require('../utils'); const configUtils = require('../utils/configUtils'); const settingsCache = require('../../core/shared/settings-cache'); const DomainEvents = require('@tryghost/domain-events'); const {MemberPageViewEvent} = require('@tryghost/member-events'); const models = require('../../core/server/models'); const {mockManager} = require('../utils/e2e-framework'); const DataGenerator = require('../utils/fixtures/data-generator'); function assertContentIsPresent(res) { res.text.should.containEql('
Free content
Members content
', published_at: moment().add(5, 'seconds').toDate() }); labelPost = testUtils.DataGenerator.forKnex.createPost({ slug: 'thou-must-be-labelled-vip', visibility: 'label:vip', published_at: moment().toDate() }); productPost = testUtils.DataGenerator.forKnex.createPost({ slug: 'thou-must-have-default-product', visibility: 'product:default-product', published_at: moment().toDate() }); return testUtils.fixtures.insertPosts([ publicPost, membersPost, paidPost, membersPostWithPaywallCard, labelPost, productPost ]); }); describe('as non-member', function () { it('can read public post content', async function () { await request .get('/free-to-see/') .expect(200) .expect(assertContentIsPresent); }); it('cannot read members post content', async function () { await request .get('/thou-shalt-not-be-seen/') .expect(200) .expect(assertContentIsAbsent); }); it('cannot read paid post content', async function () { await request .get('/thou-shalt-be-paid-for/') .expect(200) .expect(assertContentIsAbsent); }); it('cannot read label-only post content', async function () { await request .get('/thou-must-be-labelled-vip/') .expect(200) .expect(assertContentIsAbsent); }); it('cannot read product-only post content', async function () { await request .get('/thou-must-have-default-product/') .expect(200) .expect(assertContentIsAbsent); }); it('doesn\'t generate a MemberPageView event', async function () { const spy = sinon.spy(); DomainEvents.subscribe(MemberPageViewEvent, spy); await request .get('/free-to-see/') .expect(200) .expect(assertContentIsPresent); assert(spy.notCalled, 'A page view from a non-member shouldn\'t generate a MemberPageViewEvent event'); }); }); describe('as free member', function () { before(async function () { await loginAsMember('member1@test.com'); }); it('can read public post content', async function () { await request .get('/free-to-see/') .expect(200) .expect(assertContentIsPresent); }); it('can read members post content', async function () { await request .get('/thou-shalt-not-be-seen/') .expect(200) .expect(assertContentIsPresent); }); it('cannot read paid post content', async function () { await request .get('/thou-shalt-be-paid-for/') .expect(200) .expect(assertContentIsAbsent); }); it('cannot read label-only post content', async function () { await request .get('/thou-must-be-labelled-vip/') .expect(200) .expect(assertContentIsAbsent); }); it('cannot read product-only post content', async function () { await request .get('/thou-must-have-default-product/') .expect(200) .expect(assertContentIsAbsent); }); }); describe('as free member with vip label', function () { const email = 'vip@test.com'; before(async function () { await loginAsMember(email); }); it('generates a MemberPageView event', async function () { const spy = sinon.spy(); DomainEvents.subscribe(MemberPageViewEvent, spy); // Reset last_seen_at property let member = await models.Member.findOne({email}); await models.Member.edit({last_seen_at: null}, {id: member.get('id')}); member = await models.Member.findOne({email}); assert.equal(member.get('last_seen_at'), null, 'The member shouldn\'t have a `last_seen_at` property set before this test.'); await request .get('/free-to-see/') .expect(200) .expect(assertContentIsPresent); assert(spy.calledOnce, 'A page view from a member should generate a MemberPageViewEvent event'); member = await models.Member.findOne({email}); assert.notEqual(member.get('last_seen_at'), null, 'The member should have a `last_seen_at` property after having visited a page while logged-in.'); }); }); describe('as paid member', function () { const email = 'paid@test.com'; before(async function () { // membersService needs to be required after Ghost start so that settings // are pre-populated with defaults const membersService = require('../../core/server/services/members'); const signinLink = await membersService.api.getMagicLink(email); const signinURL = new URL(signinLink); // request needs a relative path rather than full url with host const signinPath = `${signinURL.pathname}${signinURL.search}`; // perform a sign-in request to set members cookies on superagent await request.get(signinPath) .expect(302) .then((res) => { const redirectUrl = new URL(res.headers.location, testUtils.API.getURL()); should.exist(redirectUrl.searchParams.get('success')); redirectUrl.searchParams.get('success').should.eql('true'); }); }); it('can read public post content', async function () { await request .get('/free-to-see/') .expect(200) .expect(assertContentIsPresent); }); it('can read members post content', async function () { await request .get('/thou-shalt-not-be-seen/') .expect(200) .expect(assertContentIsPresent); }); it('can read paid post content', async function () { await request .get('/thou-shalt-be-paid-for/') .expect(200) .expect(assertContentIsPresent); }); it('cannot read label-only post content', async function () { await request .get('/thou-must-be-labelled-vip/') .expect(200) .expect(assertContentIsAbsent); }); it('can read product-only post content', async function () { await request .get('/thou-must-have-default-product/') .expect(200) .expect(assertContentIsPresent); }); it('generates a MemberPageView event', async function () { const spy = sinon.spy(); DomainEvents.subscribe(MemberPageViewEvent, spy); // Reset last_seen_at property let member = await models.Member.findOne({email}); await models.Member.edit({last_seen_at: null}, {id: member.get('id')}); member = await models.Member.findOne({email}); assert.equal(member.get('last_seen_at'), null, 'The member shouldn\'t have a `last_seen_at` property set before this test.'); await request .get('/free-to-see/') .expect(200) .expect(assertContentIsPresent); assert(spy.calledOnce, 'A page view from a member should generate a MemberPageViewEvent event'); member = await models.Member.findOne({email}); assert.notEqual(member.get('last_seen_at'), null, 'The member should have a `last_seen_at` property after having visited a page while logged-in.'); }); }); describe('as comped member', function () { before(async function () { await loginAsMember('comped@test.com'); }); it('can read public post content', async function () { await request .get('/free-to-see/') .expect(200) .expect(assertContentIsPresent); }); it('can read members post content', async function () { await request .get('/thou-shalt-not-be-seen/') .expect(200) .expect(assertContentIsPresent); }); it('can read paid post content', async function () { await request .get('/thou-shalt-be-paid-for/') .expect(200) .expect(assertContentIsPresent); }); it('cannot read label-only post content', async function () { await request .get('/thou-must-be-labelled-vip/') .expect(200) .expect(assertContentIsAbsent); }); it('can read product-only post content', async function () { await request .get('/thou-must-have-default-product/') .expect(200) .expect(assertContentIsPresent); }); }); describe('as member with product', function () { before(async function () { await loginAsMember('with-product@test.com'); }); it('can read product-only post content', async function () { await request .get('/thou-must-have-default-product/') .expect(200) .expect(assertContentIsPresent); }); }); }); });