2023-06-21 11:56:59 +03:00
|
|
|
const assert = require('assert/strict');
|
2022-10-18 13:48:45 +03:00
|
|
|
const ObjectID = require('bson-objectid');
|
|
|
|
const Tier = require('../lib/Tier');
|
2022-10-20 13:25:19 +03:00
|
|
|
const TierActivatedEvent = require('../lib/TierActivatedEvent');
|
|
|
|
const TierArchivedEvent = require('../lib/TierArchivedEvent');
|
|
|
|
const TierNameChangeEvent = require('../lib/TierNameChangeEvent');
|
|
|
|
const TierPriceChangeEvent = require('../lib/TierPriceChangeEvent');
|
2022-10-18 13:48:45 +03:00
|
|
|
|
|
|
|
async function assertError(fn, checkError) {
|
|
|
|
let error;
|
|
|
|
try {
|
|
|
|
await fn();
|
|
|
|
error = false;
|
|
|
|
} catch (err) {
|
|
|
|
error = err;
|
|
|
|
} finally {
|
|
|
|
assert(error);
|
|
|
|
if (checkError) {
|
|
|
|
checkError(error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const validInput = {
|
|
|
|
name: 'Tier Name',
|
|
|
|
slug: 'tier-name',
|
|
|
|
description: 'My First Tier',
|
2022-10-20 07:46:28 +03:00
|
|
|
welcomePageURL: null,
|
2022-10-18 13:48:45 +03:00
|
|
|
status: 'active',
|
|
|
|
visibility: 'public',
|
|
|
|
type: 'paid',
|
2022-10-20 07:46:28 +03:00
|
|
|
trialDays: 10,
|
2022-10-18 13:48:45 +03:00
|
|
|
currency: 'usd',
|
2022-10-20 07:46:28 +03:00
|
|
|
monthlyPrice: 5000,
|
|
|
|
yearlyPrice: 50000,
|
2022-10-18 13:48:45 +03:00
|
|
|
benefits: []
|
|
|
|
};
|
|
|
|
|
|
|
|
const invalidInputs = [
|
|
|
|
{id: [100]},
|
|
|
|
{name: 100},
|
|
|
|
{name: ('a').repeat(200)},
|
2022-10-20 07:39:32 +03:00
|
|
|
{slug: ('slug').repeat(50)},
|
2022-10-18 13:48:45 +03:00
|
|
|
{description: ['whatever?']},
|
|
|
|
{description: ('b').repeat(200)},
|
2022-10-20 07:46:28 +03:00
|
|
|
{welcomePageURL: {cool: 'beans'}},
|
2022-10-18 13:48:45 +03:00
|
|
|
{status: 'something random'},
|
|
|
|
{visibility: 'highly visible'},
|
|
|
|
{type: 'comped'},
|
2022-10-20 07:46:28 +03:00
|
|
|
{trialDays: -10},
|
|
|
|
{trialDays: 10, type: 'free', currency: null, monthlyPrice: null, yearlyPrice: null},
|
2022-10-18 13:48:45 +03:00
|
|
|
{currency: 'dollar bills'},
|
|
|
|
{currency: 25},
|
|
|
|
{currency: 'USD', type: 'free'},
|
2022-10-20 07:46:28 +03:00
|
|
|
{monthlyPrice: 2000, type: 'free', trialDays: null, currency: null, yearlyPrice: null},
|
|
|
|
{monthlyPrice: -20},
|
|
|
|
{monthlyPrice: 10000000000},
|
|
|
|
{yearlyPrice: 2000, type: 'free', trialDays: null, monthlyPrice: null, currency: null},
|
|
|
|
{yearlyPrice: -20},
|
|
|
|
{yearlyPrice: 10000000000},
|
|
|
|
{createdAt: 'Today'},
|
|
|
|
{updatedAt: 'Tomorrow'}
|
2022-10-18 13:48:45 +03:00
|
|
|
];
|
|
|
|
|
|
|
|
const validInputs = [
|
2022-10-20 07:46:28 +03:00
|
|
|
{welcomePageURL: 'https://google.com'},
|
2022-10-18 13:48:45 +03:00
|
|
|
{id: (new ObjectID()).toHexString()},
|
|
|
|
{id: new ObjectID()},
|
2022-10-20 07:46:28 +03:00
|
|
|
{type: 'free', currency: null, monthlyPrice: null, yearlyPrice: null, trialDays: null},
|
|
|
|
{createdAt: new Date()},
|
|
|
|
{updatedAt: new Date()},
|
2022-10-18 13:48:45 +03:00
|
|
|
{status: undefined},
|
|
|
|
{type: undefined},
|
|
|
|
{visibility: undefined}
|
|
|
|
];
|
|
|
|
|
|
|
|
describe('Tier', function () {
|
|
|
|
describe('create', function () {
|
|
|
|
it('Errors if passed an invalid input', async function () {
|
|
|
|
for (const invalidInput of invalidInputs) {
|
|
|
|
let input = {};
|
|
|
|
Object.assign(input, validInput, invalidInput);
|
|
|
|
await assertError(async function () {
|
2022-10-20 07:39:32 +03:00
|
|
|
await Tier.create(input);
|
2022-10-18 13:48:45 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-12-07 18:02:37 +03:00
|
|
|
it('Uses default monthly and yearly price if they are set to 0', async function () {
|
|
|
|
const tier = await Tier.create({
|
|
|
|
...validInput,
|
|
|
|
monthlyPrice: 0,
|
|
|
|
yearlyPrice: 0
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(tier.getPrice('month'), 500);
|
|
|
|
assert.equal(tier.getPrice('year'), 5000);
|
|
|
|
});
|
|
|
|
|
2022-10-18 13:48:45 +03:00
|
|
|
it('Does not error for valid inputs', async function () {
|
|
|
|
for (const validInputItem of validInputs) {
|
|
|
|
let input = {};
|
|
|
|
Object.assign(input, validInput, validInputItem);
|
2022-10-20 07:39:32 +03:00
|
|
|
await Tier.create(input);
|
2022-10-18 13:48:45 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Can create a Tier with valid input', async function () {
|
2022-10-20 07:39:32 +03:00
|
|
|
const tier = await Tier.create(validInput);
|
2022-10-18 13:48:45 +03:00
|
|
|
|
|
|
|
const expectedProps = [
|
|
|
|
'slug',
|
|
|
|
'name',
|
|
|
|
'description',
|
2022-10-20 07:46:28 +03:00
|
|
|
'welcomePageURL',
|
2022-10-18 13:48:45 +03:00
|
|
|
'status',
|
|
|
|
'visibility',
|
|
|
|
'type',
|
2022-10-20 07:46:28 +03:00
|
|
|
'trialDays',
|
2022-10-18 13:48:45 +03:00
|
|
|
'currency',
|
2022-10-20 07:46:28 +03:00
|
|
|
'monthlyPrice',
|
|
|
|
'yearlyPrice',
|
|
|
|
'createdAt',
|
|
|
|
'updatedAt',
|
2022-10-18 13:48:45 +03:00
|
|
|
'benefits'
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const prop of expectedProps) {
|
|
|
|
assert(tier[prop] === tier.toJSON()[prop]);
|
|
|
|
}
|
2022-10-24 07:49:24 +03:00
|
|
|
assert(tier.id.toHexString() === tier.toJSON().id);
|
2022-10-18 13:48:45 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
it('Errors when attempting to set invalid properties', async function () {
|
2022-10-20 07:39:32 +03:00
|
|
|
const tier = await Tier.create(validInput);
|
2022-10-18 13:48:45 +03:00
|
|
|
|
|
|
|
assertError(() => {
|
|
|
|
tier.name = 20;
|
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
|
|
|
tier.benefits = 20;
|
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
|
|
|
tier.description = 20;
|
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
2022-10-20 07:46:28 +03:00
|
|
|
tier.welcomePageURL = 20;
|
2022-10-18 13:48:45 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
|
|
|
tier.status = 20;
|
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
|
|
|
tier.visibility = 20;
|
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
2022-10-20 07:46:28 +03:00
|
|
|
tier.trialDays = 'one hundred';
|
2022-10-18 13:48:45 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
|
|
|
tier.currency = 'one hundred';
|
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
2022-10-20 07:46:28 +03:00
|
|
|
tier.monthlyPrice = 'one hundred';
|
2022-10-18 13:48:45 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
2022-10-20 07:46:28 +03:00
|
|
|
tier.yearlyPrice = 'one hundred';
|
2022-10-18 13:48:45 +03:00
|
|
|
});
|
|
|
|
});
|
2022-10-20 13:25:19 +03:00
|
|
|
|
|
|
|
it('Can change name and adds an event', async function () {
|
|
|
|
const tier = await Tier.create(validInput);
|
|
|
|
|
|
|
|
tier.name = 'New name';
|
|
|
|
|
|
|
|
assert(tier.events.find((event) => {
|
|
|
|
return event instanceof TierNameChangeEvent;
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Can update pricing information and adds an event', async function () {
|
|
|
|
const tier = await Tier.create(validInput);
|
|
|
|
|
|
|
|
tier.updatePricing({
|
|
|
|
currency: 'eur',
|
|
|
|
monthlyPrice: 1000,
|
|
|
|
yearlyPrice: 6000
|
|
|
|
});
|
|
|
|
|
|
|
|
assert(tier.currency === 'EUR');
|
|
|
|
assert(tier.monthlyPrice === 1000);
|
|
|
|
assert(tier.yearlyPrice === 6000);
|
|
|
|
assert(tier.events.find((event) => {
|
|
|
|
return event instanceof TierPriceChangeEvent;
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Can archive tier and adds an event', async function () {
|
|
|
|
const tier = await Tier.create(validInput);
|
|
|
|
|
|
|
|
tier.status = 'archived';
|
|
|
|
assert(tier.events.find((event) => {
|
|
|
|
return event instanceof TierArchivedEvent;
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Can activate tier and adds an event', async function () {
|
|
|
|
const tier = await Tier.create({...validInput, status: 'archived'});
|
|
|
|
|
|
|
|
tier.status = 'active';
|
|
|
|
assert(tier.events.find((event) => {
|
|
|
|
return event instanceof TierActivatedEvent;
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Does not add event if values not changed', async function () {
|
|
|
|
const tier = await Tier.create(validInput);
|
|
|
|
|
|
|
|
tier.status = 'active';
|
|
|
|
assert(!tier.events.find((event) => {
|
|
|
|
return event instanceof TierActivatedEvent;
|
|
|
|
}));
|
|
|
|
|
|
|
|
tier.name = 'Tier Name';
|
|
|
|
assert(!tier.events.find((event) => {
|
|
|
|
return event instanceof TierNameChangeEvent;
|
|
|
|
}));
|
|
|
|
|
|
|
|
tier.updatePricing({
|
|
|
|
currency: tier.currency,
|
|
|
|
monthlyPrice: tier.monthlyPrice,
|
|
|
|
yearlyPrice: tier.yearlyPrice
|
|
|
|
});
|
|
|
|
assert(!tier.events.find((event) => {
|
|
|
|
return event instanceof TierPriceChangeEvent;
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Cannot set pricing data on a free tier', async function () {
|
|
|
|
const tier = await Tier.create({
|
|
|
|
...validInput,
|
|
|
|
type: 'free',
|
|
|
|
currency: null,
|
|
|
|
monthlyPrice: null,
|
|
|
|
yearlyPrice: null,
|
|
|
|
trialDays: null
|
|
|
|
});
|
|
|
|
|
|
|
|
assertError(() => {
|
|
|
|
tier.updatePricing({
|
|
|
|
currency: 'usd',
|
|
|
|
monthlyPrice: 1000,
|
|
|
|
yearlyPrice: 10000
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2022-11-01 12:25:55 +03:00
|
|
|
|
|
|
|
it('Can set the description of a Tier', async function () {
|
|
|
|
const tier = await Tier.create(validInput);
|
|
|
|
|
|
|
|
tier.description = 'Updated description';
|
|
|
|
|
2023-06-21 11:56:59 +03:00
|
|
|
assert.equal('Updated description', tier.description);
|
2022-11-01 12:25:55 +03:00
|
|
|
});
|
2022-10-18 13:48:45 +03:00
|
|
|
});
|
|
|
|
});
|