From 30b113cc84eea1e49a7f721e90fc90717636034a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Fri, 14 Jul 2023 10:52:17 +0200 Subject: [PATCH] chore: running paid subscription e2e tests on both self-hosted and home-server setup (#2355) * chore: add activating paid subscription in e2e on both self-hosted and home-server setup * chore: fix activating premium features on e2e test suites * chore: remove unnecessary sleep duplication * chore: add defining the subscription expires at date in e2e --- packages/snjs/mocha/files.test.js | 36 ++++-------- packages/snjs/mocha/lib/AppContext.js | 53 +++++++++++------ packages/snjs/mocha/lib/Events.js | 6 +- packages/snjs/mocha/lib/HomeServer.js | 16 +++++ packages/snjs/mocha/settings.test.js | 72 +++-------------------- packages/snjs/mocha/subscriptions.test.js | 25 ++------ packages/snjs/mocha/test.html | 6 +- packages/snjs/mocha/vaults/files.test.js | 2 +- 8 files changed, 79 insertions(+), 137 deletions(-) create mode 100644 packages/snjs/mocha/lib/HomeServer.js diff --git a/packages/snjs/mocha/files.test.js b/packages/snjs/mocha/files.test.js index 622453dc9..d80ab012a 100644 --- a/packages/snjs/mocha/files.test.js +++ b/packages/snjs/mocha/files.test.js @@ -1,5 +1,4 @@ import * as Factory from './lib/factory.js' -import * as Events from './lib/Events.js' import * as Utils from './lib/Utils.js' import * as Files from './lib/Files.js' @@ -39,7 +38,7 @@ describe('files', function () { }) if (subscription) { - await context.publicMockSubscriptionPurchaseEvent() + await context.activatePaidSubscriptionForUser() } } @@ -48,7 +47,7 @@ describe('files', function () { localStorage.clear() }) - it('should create valet token from server - @paidfeature', async function () { + it('should create valet token from server', async function () { await setup({ fakeCrypto: true, subscription: true }) const remoteIdentifier = Utils.generateUuid() @@ -66,26 +65,15 @@ describe('files', function () { expect(isClientDisplayableError(tokenOrError)).to.equal(true) }) - it('should not create valet token from server when user has an expired subscription - @paidfeature', async function () { + it('should not create valet token from server when user has an expired subscription', async function () { await setup({ fakeCrypto: true, subscription: false }) - await Events.publishMockedEvent('SUBSCRIPTION_PURCHASED', { - userEmail: context.email, - subscriptionId: subscriptionId++, - subscriptionName: 'PLUS_PLAN', - subscriptionExpiresAt: (new Date().getTime() - 3_600_000) * 1_000, - timestamp: Date.now(), - offline: false, - discountCode: null, - limitedDiscountPurchased: false, - newSubscriber: true, - totalActiveSubscriptionsCount: 1, - userRegisteredAt: 1, - billingFrequency: 12, - payAmount: 59.0, - }) + const dateAnHourBefore = new Date() + dateAnHourBefore.setHours(dateAnHourBefore.getHours() - 1) - await Factory.sleep(2) + await context.activatePaidSubscriptionForUser({ + expiresAt: dateAnHourBefore, + }) const remoteIdentifier = Utils.generateUuid() const tokenOrError = await application.apiService.createUserFileValetToken(remoteIdentifier, 'write') @@ -93,7 +81,7 @@ describe('files', function () { expect(isClientDisplayableError(tokenOrError)).to.equal(true) }) - it('creating two upload sessions successively should succeed - @paidfeature', async function () { + it('creating two upload sessions successively should succeed', async function () { await setup({ fakeCrypto: true, subscription: true }) const firstToken = await application.apiService.createUserFileValetToken(Utils.generateUuid(), 'write') @@ -107,7 +95,7 @@ describe('files', function () { expect(secondSession.uploadId).to.be.ok }) - it('should encrypt and upload small file - @paidfeature', async function () { + it('should encrypt and upload small file', async function () { await setup({ fakeCrypto: false, subscription: true }) const response = await fetch('/packages/snjs/mocha/assets/small_file.md') @@ -120,7 +108,7 @@ describe('files', function () { expect(downloadedBytes).to.eql(buffer) }) - it('should encrypt and upload big file - @paidfeature', async function () { + it('should encrypt and upload big file', async function () { await setup({ fakeCrypto: false, subscription: true }) const response = await fetch('/packages/snjs/mocha/assets/two_mb_file.md') @@ -133,7 +121,7 @@ describe('files', function () { expect(downloadedBytes).to.eql(buffer) }) - it('should delete file - @paidfeature', async function () { + it('should delete file', async function () { await setup({ fakeCrypto: false, subscription: true }) const response = await fetch('/packages/snjs/mocha/assets/small_file.md') diff --git a/packages/snjs/mocha/lib/AppContext.js b/packages/snjs/mocha/lib/AppContext.js index 4d19d3f64..231f5d783 100644 --- a/packages/snjs/mocha/lib/AppContext.js +++ b/packages/snjs/mocha/lib/AppContext.js @@ -3,6 +3,7 @@ import * as Applications from './Applications.js' import * as Utils from './Utils.js' import * as Defaults from './Defaults.js' import * as Events from './Events.js' +import * as HomeServer from './HomeServer.js' import { createNotePayload } from './Items.js' UuidGenerator.SetGenerator(new FakeWebCrypto().generateUUID) @@ -597,23 +598,41 @@ export class AppContext { console.warn('Anticipating a console error with message:', message) } - async publicMockSubscriptionPurchaseEvent() { - await Events.publishMockedEvent('SUBSCRIPTION_PURCHASED', { - userEmail: this.email, - subscriptionId: GlobalSubscriptionIdCounter++, - subscriptionName: 'PRO_PLAN', - subscriptionExpiresAt: (new Date().getTime() + 3_600_000) * 1_000, - timestamp: Date.now(), - offline: false, - discountCode: null, - limitedDiscountPurchased: false, - newSubscriber: true, - totalActiveSubscriptionsCount: 1, - userRegisteredAt: 1, - billingFrequency: 12, - payAmount: 59.0, - }) + async activatePaidSubscriptionForUser(options = {}) { + const dateInAnHour = new Date() + dateInAnHour.setHours(dateInAnHour.getHours() + 1) - await Utils.sleep(2) + options.expiresAt = options.expiresAt || dateInAnHour + options.subscriptionPlanName = options.subscriptionPlanName || 'PRO_PLAN' + + try { + await Events.publishMockedEvent('SUBSCRIPTION_PURCHASED', { + userEmail: this.email, + subscriptionId: GlobalSubscriptionIdCounter++, + subscriptionName: options.subscriptionPlanName, + subscriptionExpiresAt: options.expiresAt.getTime() * 1_000, + timestamp: Date.now(), + offline: false, + discountCode: null, + limitedDiscountPurchased: false, + newSubscriber: true, + totalActiveSubscriptionsCount: 1, + userRegisteredAt: 1, + billingFrequency: 12, + payAmount: 59.0, + }) + + await Utils.sleep(2) + } catch (error) { + console.warn(`Mock events service not available. You are probalby running a test suite for home server: ${error.message}`) + } + + try { + await HomeServer.activatePremiumFeatures(this.email, options.subscriptionPlanName, options.expiresAt) + + await Utils.sleep(1) + } catch (error) { + console.warn(`Home server not available. You are probalby running a test suite for self hosted setup: ${error.message}`) + } } } diff --git a/packages/snjs/mocha/lib/Events.js b/packages/snjs/mocha/lib/Events.js index 7deba7546..42a6323a8 100644 --- a/packages/snjs/mocha/lib/Events.js +++ b/packages/snjs/mocha/lib/Events.js @@ -1,7 +1,7 @@ import * as Defaults from './Defaults.js' export async function publishMockedEvent(eventType, eventPayload) { - const response = await fetch(`${Defaults.getDefaultMockedEventServiceUrl()}/events`, { + await fetch(`${Defaults.getDefaultMockedEventServiceUrl()}/events`, { method: 'POST', headers: { Accept: 'application/json', @@ -12,8 +12,4 @@ export async function publishMockedEvent(eventType, eventPayload) { eventPayload, }), }) - - if (!response.ok) { - console.error(`Failed to publish mocked event: ${response.status} ${response.statusText}`) - } } diff --git a/packages/snjs/mocha/lib/HomeServer.js b/packages/snjs/mocha/lib/HomeServer.js new file mode 100644 index 000000000..220138031 --- /dev/null +++ b/packages/snjs/mocha/lib/HomeServer.js @@ -0,0 +1,16 @@ +import * as Defaults from './Defaults.js' + +export async function activatePremiumFeatures(username, subscriptionPlanName, endsAt) { + await fetch(`${Defaults.getDefaultHost()}/e2e/activate-premium`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + username, + subscriptionPlanName, + endsAt, + }), + }) +} diff --git a/packages/snjs/mocha/settings.test.js b/packages/snjs/mocha/settings.test.js index 6e1f89880..0fd22ec4a 100644 --- a/packages/snjs/mocha/settings.test.js +++ b/packages/snjs/mocha/settings.test.js @@ -134,50 +134,19 @@ describe('settings service', function () { expect(settings.getSettingValue(SettingName.create(SettingName.NAMES.MfaSecret).getValue())).to.not.be.ok }) - it('reads a subscription setting - @paidfeature', async () => { - await Events.publishMockedEvent('SUBSCRIPTION_PURCHASED', { - userEmail: context.email, - subscriptionId: subscriptionId++, - subscriptionName: 'PRO_PLAN', - subscriptionExpiresAt: (new Date().getTime() + 3_600_000) * 1_000, - timestamp: Date.now(), - offline: false, - discountCode: null, - limitedDiscountPurchased: false, - newSubscriber: true, - totalActiveSubscriptionsCount: 1, - userRegisteredAt: 1, - billingFrequency: 12, - payAmount: 59.0, - }) - - await Factory.sleep(2) + it('reads a subscription setting', async () => { + await context.activatePaidSubscriptionForUser() const setting = await application.settings.getSubscriptionSetting( - SettingName.create(SettingName.NAMES.FileUploadBytesLimit).getValue(), + SettingName.create(SettingName.NAMES.FileUploadBytesUsed).getValue(), ) expect(setting).to.be.a('string') }) - it('persist irreplaceable subscription settings between subsequent subscriptions - @paidfeature', async () => { + it('persist irreplaceable subscription settings between subsequent subscriptions', async () => { await reInitializeApplicationWithRealCrypto() - await Events.publishMockedEvent('SUBSCRIPTION_PURCHASED', { - userEmail: context.email, - subscriptionId: subscriptionId, - subscriptionName: 'PRO_PLAN', - subscriptionExpiresAt: (new Date().getTime() + 3_600_000) * 1_000, - timestamp: Date.now(), - offline: false, - discountCode: null, - limitedDiscountPurchased: false, - newSubscriber: true, - totalActiveSubscriptionsCount: 1, - userRegisteredAt: 1, - billingFrequency: 12, - payAmount: 59.0, - }) - await Factory.sleep(1) + await context.activatePaidSubscriptionForUser() const response = await fetch('/packages/snjs/mocha/assets/small_file.md') const buffer = new Uint8Array(await response.arrayBuffer()) @@ -189,42 +158,15 @@ describe('settings service', function () { const limitSettingBefore = await application.settings.getSubscriptionSetting( SettingName.create(SettingName.NAMES.FileUploadBytesLimit).getValue(), ) - expect(limitSettingBefore).to.equal('107374182400') const usedSettingBefore = await application.settings.getSubscriptionSetting( SettingName.create(SettingName.NAMES.FileUploadBytesUsed).getValue(), ) expect(usedSettingBefore).to.equal('196') - await Events.publishMockedEvent('SUBSCRIPTION_EXPIRED', { - userEmail: context.email, - subscriptionId: subscriptionId++, - subscriptionName: 'PRO_PLAN', - timestamp: Date.now(), - offline: false, - totalActiveSubscriptionsCount: 1, - userExistingSubscriptionsCount: 1, - billingFrequency: 12, - payAmount: 59.0, - }) - await Factory.sleep(1) + await context.activatePaidSubscriptionForUser() - await Events.publishMockedEvent('SUBSCRIPTION_PURCHASED', { - userEmail: context.email, - subscriptionId: subscriptionId++, - subscriptionName: 'PRO_PLAN', - subscriptionExpiresAt: (new Date().getTime() + 3_600_000) * 1_000, - timestamp: Date.now(), - offline: false, - discountCode: null, - limitedDiscountPurchased: false, - newSubscriber: false, - totalActiveSubscriptionsCount: 2, - userRegisteredAt: 1, - billingFrequency: 12, - payAmount: 59.0, - }) - await Factory.sleep(1) + await context.activatePaidSubscriptionForUser() const limitSettingAfter = await application.settings.getSubscriptionSetting( SettingName.create(SettingName.NAMES.FileUploadBytesLimit).getValue(), diff --git a/packages/snjs/mocha/subscriptions.test.js b/packages/snjs/mocha/subscriptions.test.js index bf3cf396d..e88cf7cbf 100644 --- a/packages/snjs/mocha/subscriptions.test.js +++ b/packages/snjs/mocha/subscriptions.test.js @@ -32,25 +32,10 @@ describe('subscriptions', function () { password: context.password, }) - await Events.publishMockedEvent('SUBSCRIPTION_PURCHASED', { - userEmail: context.email, - subscriptionId: subscriptionId++, - subscriptionName: 'PRO_PLAN', - subscriptionExpiresAt: (new Date().getTime() + 3_600_000) * 1_000, - timestamp: Date.now(), - offline: false, - discountCode: null, - limitedDiscountPurchased: false, - newSubscriber: true, - totalActiveSubscriptionsCount: 1, - userRegisteredAt: 1, - billingFrequency: 12, - payAmount: 59.00 - }) - await Factory.sleep(2) + await context.activatePaidSubscriptionForUser() }) - it('should invite a user by email to a shared subscription - @paidfeature', async () => { + it('should invite a user by email to a shared subscription', async () => { await subscriptionManager.inviteToSubscription('test@test.te') const existingInvites = await subscriptionManager.listSubscriptionInvitations() @@ -60,7 +45,7 @@ describe('subscriptions', function () { expect(newlyCreatedInvite.status).to.equal('sent') }) - it('should not invite a user by email if the limit of shared subscription is breached - @paidfeature', async () => { + it('should not invite a user by email if the limit of shared subscription is breached', async () => { await subscriptionManager.inviteToSubscription('test1@test.te') await subscriptionManager.inviteToSubscription('test2@test.te') await subscriptionManager.inviteToSubscription('test3@test.te') @@ -78,7 +63,7 @@ describe('subscriptions', function () { expect(existingInvites.length).to.equal(5) }) - it('should cancel a user invitation to a shared subscription - @paidfeature', async () => { + it('should cancel a user invitation to a shared subscription', async () => { await subscriptionManager.inviteToSubscription('test@test.te') await subscriptionManager.inviteToSubscription('test2@test.te') @@ -97,7 +82,7 @@ describe('subscriptions', function () { expect(existingInvites.filter(invite => invite.status === 'canceled').length).to.equal(1) }) - it('should invite a user by email if the limit of shared subscription is restored - @paidfeature', async () => { + it('should invite a user by email if the limit of shared subscription is restored', async () => { await subscriptionManager.inviteToSubscription('test1@test.te') await subscriptionManager.inviteToSubscription('test2@test.te') await subscriptionManager.inviteToSubscription('test3@test.te') diff --git a/packages/snjs/mocha/test.html b/packages/snjs/mocha/test.html index e722ea517..aa8afdc5b 100644 --- a/packages/snjs/mocha/test.html +++ b/packages/snjs/mocha/test.html @@ -27,16 +27,12 @@ const urlParams = new URLSearchParams(window.location.search); const bail = urlParams.get('bail') === 'false' ? false : true; - const skipPaidFeatures = urlParams.get('skip_paid_features') === 'true' ? true : false; mocha.setup({ ui: 'bdd', timeout: 5000, bail: bail, }); - if (skipPaidFeatures) { - mocha.grep('@paidfeature').invert(); - }