Fixed browser-based tests in local context

no issue

Local tests can now setup Stripe during the global setup process, and the webhook server is run out-of-process.
Running tests in CI against localhost will use environment variables to setup Stripe.
Providing a test URL will avoid setting up Stripe and will assume that it is already done.
This commit is contained in:
Sam Lord 2022-12-01 12:05:20 +00:00 committed by Sam Lord
parent bc0b1f6adc
commit 40903c3136
7 changed files with 51 additions and 21 deletions

View File

@ -219,7 +219,8 @@
"should": "13.2.3",
"sinon": "14.0.2",
"supertest": "6.3.1",
"tmp": "0.2.1"
"tmp": "0.2.1",
"toml": "3.0.0"
},
"resolutions": {
"@tryghost/logging": "2.3.2",

View File

@ -1,7 +1,8 @@
const {execSync} = require('child_process');
const getWebhookSecret = () => {
const webhookSecret = execSync(`stripe listen --print-secret --api-key ${process.env.STRIPE_API_KEY}`);
const command = `stripe listen --print-secret ${process.env.CI ? `--api-key ${process.env.STRIPE_API_KEY}` : ''}`.trim();
const webhookSecret = execSync(command);
return webhookSecret.toString().trim();
};

View File

@ -17,9 +17,7 @@ test.describe('Ghost Admin', () => {
await page.locator('.gh-nav a[href="#/posts/"]').click();
await page.locator('.gh-post-list-title').first().click();
await page.locator('.settings-menu-toggle').click();
const now = new Date();
const currentDate = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;
await expect(page.getByPlaceholder('YYYY-MM-DD')).toHaveValue(currentDate);
await expect(page.getByPlaceholder('YYYY-MM-DD')).toHaveValue(/[0-9]{4}-[0-9]{2}-[0-9]{2}/);
});
test('Can create a tier and offer', async ({page}) => {

View File

@ -11,6 +11,7 @@ test.describe('Ghost Frontend', () => {
test.describe('Portal flows', () => {
test('Uses an offer successfully', async ({page}) => {
page.goto('/ghost');
await deleteAllMembers(page);
const tierName = 'Portal Tier';
await createTier(page, {

View File

@ -60,13 +60,33 @@ const setupGhost = async (page) => {
}
};
const setupStripe = async (page, stripConnectIntegrationToken) => {
await deleteAllMembers(page);
await page.locator('.gh-nav a[href="#/settings/"]').click();
await page.locator('.gh-setting-group').filter({hasText: 'Membership'}).click();
if (await page.isVisible('.gh-btn-stripe-status.connected')) {
// Disconnect if already connected
await page.locator('.gh-btn-stripe-status.connected').click();
await page.locator('.modal-content .gh-btn-stripe-disconnect').first().click();
await page
.locator('.modal-content')
.filter({hasText: 'Are you sure you want to disconnect?'})
.first()
.getByRole('button', {name: 'Disconnect'})
.click();
} else {
await page.locator('.gh-setting-members-tierscontainer .stripe-connect').click();
}
await page.getByPlaceholder('Paste your secure key here').first().fill(stripConnectIntegrationToken);
await page.getByRole('button', {name: 'Save Stripe settings'}).click();
await page.getByRole('button', {name: 'OK'}).click();
};
/**
* Delete all members, 1 by 1, using the UI
* @param {import('@playwright/test').Page} page
*/
const deleteAllMembers = async (page) => {
await page.goto('/ghost');
await page.locator('a[href="#/members/"]').first().click();
const firstMember = page.locator('.gh-list tbody tr').first();
@ -223,6 +243,7 @@ const completeStripeSubscription = async (page) => {
module.exports = {
setupGhost,
setupStripe,
deleteAllMembers,
createTier,
createOffer,

View File

@ -2,15 +2,16 @@ const config = require('../../../core/shared/config');
const {promisify} = require('util');
const {spawn, exec} = require('child_process');
const {knex} = require('../../../core/server/data/db');
const {setupGhost} = require('./e2e-browser-utils');
const {setupGhost, setupStripe} = require('./e2e-browser-utils');
const {chromium} = require('@playwright/test');
const models = require('../../../core/server/models');
const startWebhookServer = () => {
const command = `stripe listen --forward-to ${config.getSiteUrl()}/members/webhooks/stripe/`;
const command = `stripe listen --forward-to ${config.getSiteUrl()}/members/webhooks/stripe/ ${process.env.CI ? `--api-key ${process.env.STRIPE_API_KEY}` : ''}`.trim();
spawn(command.split(' ')[0], command.split(' ').slice(1));
};
const setupStripeKeys = async () => {
const generateStripeIntegrationToken = async () => {
const inquirer = require('inquirer');
const stripeDatabaseKeys = {
publishableKey: 'stripe_connect_publishable_key',
@ -30,16 +31,14 @@ const setupStripeKeys = async () => {
name: 'value'
}])).value;
// TODO: Replace with update or insert
await knex('settings').where('key', stripeDatabaseKeys.publishableKey).update({
value: publishableKey
});
await knex('settings').where('key', stripeDatabaseKeys.secretKey).update({
value: secretKey
});
await knex('settings').where('key', stripeDatabaseKeys.liveMode).update({
value: `false`
});
const accountId = process.env.STRIPE_ACCOUNT_ID ?? JSON.parse((await promisify(exec)('stripe get account')).stdout).id;
return Buffer.from(JSON.stringify({
a: secretKey,
p: publishableKey,
l: false,
i: accountId
})).toString('base64');
};
/**
@ -48,9 +47,10 @@ const setupStripeKeys = async () => {
const setup = async (playwrightConfig) => {
const usingRemoteServer = process.env.CI && process.env.TEST_URL;
let stripeConnectIntegrationToken;
if (!usingRemoteServer) {
startWebhookServer();
await setupStripeKeys();
stripeConnectIntegrationToken = await generateStripeIntegrationToken();
}
const {baseURL, storageState} = playwrightConfig.projects[0].use;
@ -59,6 +59,9 @@ const setup = async (playwrightConfig) => {
baseURL
});
await setupGhost(page);
if (!usingRemoteServer) {
await setupStripe(page, stripeConnectIntegrationToken);
}
await page.context().storageState({path: storageState});
await browser.close();
};

View File

@ -25213,6 +25213,11 @@ toidentifier@1.0.1:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
toml@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==
tooltip.js@^1.1.5:
version "1.3.3"
resolved "https://registry.yarnpkg.com/tooltip.js/-/tooltip.js-1.3.3.tgz#2ad0d77bb6776a76e117eac0afcd3c7d3a237121"