Skip to content

Commit

Permalink
add test workflow & other improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
stepanjakl committed May 17, 2024
1 parent b17b869 commit 4510044
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 60 deletions.
53 changes: 53 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: lint-and-test
run-name: lint and test

on:
push:
branches: ["main"]
pull_request:
branches: ["*"]

jobs:
lint-and-test:
name: Lint and Test
runs-on: ubuntu-latest

steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22.x

- name: Set up MongoDB
uses: supercharge/mongodb-github-action@v1
with:
mongodb-version: 7.0

- name: Install Dependencies
run: |
sudo apt update
sudo apt install net-tools -y
mkdir -p tmp
ls
curl -s https://api.github.com/repos/stripe/stripe-mock/releases/latest | jq -r '.assets[] | select(.name | contains("linux_amd64") and endswith(".tar.gz")) | .browser_download_url' | xargs -I{} sh -c 'echo "Downloading {}" && curl -L {} -o tmp/stripe-mock.tar.gz'
tar -xvf tmp/stripe-mock.tar.gz -C tmp
mv tmp/stripe-mock /usr/local/bin/
chmod -R 755 /usr/local/bin/stripe-mock
rm tmp/stripe-mock.tar.gz
npm install
npm install pm2 -g
- name: Start stripe-mock
run: pm2 start --name stripe-mock stripe-mock -- -http-addr 127.0.0.1:12111 -https-addr 127.0.0.1:12112

- name: Display active connections
run: sleep 5 && netstat -tuln

- name: Run ESLint
run: npm run eslint

- name: Run Mocha Tests
run: npm run mocha
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
<img alt="License"
src="https://img.shields.io/static/v1?style=for-the-badge&labelColor=000000&label=License&message=MIT&color=3DA639">
</a>
<br>
<br>
<a aria-label="Unit Tests"
href="https://github.com/stepanjakl/apostrophe-stripe-checkout/actions/workflows/tests.yml">
<img alt="Unit Tests"
src="https://github.com/stepanjakl/apostrophe-stripe-checkout/actions/workflows/tests.yml/badge.svg?branch=main">
</a>
</p>
</div>

Expand All @@ -42,7 +49,7 @@ This module adds a custom route to initiate a Stripe Checkout instance and anoth

## Installation

Use your preferred package manager to install the module. You'll also need to install the [read-only-field](https://github.com/) package alongside it:
Use your preferred package manager to install the module. You'll also need to install the [read-only-field](https://github.com/stepanjakl/apostrophe-read-only-field) package alongside it:

```zsh
npm install stripe-checkout@npm:@stepanjakl/apostrophe-stripe-checkout
Expand Down Expand Up @@ -175,6 +182,4 @@ pm2 start --name stripe-listener "stripe listen --events checkout.session.comple

## TODOs (Limitations)

- Option for one-time and recurring payments
- Enable checkout session with more than 99 items
- Add other extra checkout session options (e.g. custom styles)
22 changes: 8 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ const path = require('path');
const Stripe = require('stripe'); // Importing the Stripe SDK
let stripe = null;

if (process.env.STRIPE_TEST_MODE === 'false') {
// Using Stripe production mode settings with the API key
stripe = Stripe(process.env.STRIPE_KEY);
} else {
// Using Stripe test mode settings
if (process.env.STRIPE_MOCK_TEST_MODE === 'true') {
// Using Stripe mock test mode settings
stripe = new Stripe('sk_test_xyz', {
host: 'localhost',
host: '127.0.0.1',
protocol: 'http',
port: 12111
});
} else {
// Using Stripe production mode settings with the API key
stripe = Stripe(process.env.STRIPE_KEY);
}

const bodyParser = require('body-parser'); // Importing the body-parser middleware
Expand Down Expand Up @@ -149,15 +149,9 @@ module.exports = {
'/api/v1/stripe/checkout/sessions/create': async function (req) {
try {
// Create a new checkout session with the provided parameters
const checkoutSession = await stripe.checkout.sessions.create({
line_items: req.body.line_items,
locale: 'en',
mode: 'payment',
success_url: req.body.success_url,
cancel_url: req.body.cancel_url
});
const checkoutSession = await stripe.checkout.sessions.create(req.body);
// Return the URL of the created checkout session
return checkoutSession.url;
return checkoutSession;
} catch (error) {
req.res.status(500).send(error);
}
Expand Down
14 changes: 0 additions & 14 deletions modules/stripe-checkout/session/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,18 +179,4 @@ module.exports = {
filters: {
remove: [ 'visibility' ]
}
/* init(self) {
self.addReadOnlyFieldType()
},
methods(self) {
return {
addReadOnlyFieldType() {
self.apos.schema.addFieldType({
name: 'readOnly',
convert: self.convertInput,
vueComponent: 'InputReadOnly'
})
}
}
} */
};
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
"eslint-plugin-mocha": "^10.4.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-vue": "^9.25.0",
"eslint-plugin-vue": "^9.26.0",
"mocha": "^10.4.0",
"read-only-field": "npm:@stepanjakl/apostrophe-read-only-field@latest",
"stripe": "^15.3.0",
"stylelint": "^15.x.x",
"stylelint-config-apostrophe": "^3.0.2"
"stripe": "^15.7.0",
"stylelint": "^16.x.x",
"stylelint-config-apostrophe": "^4.x.x"
},
"publishConfig": {
"access": "public"
Expand Down
70 changes: 45 additions & 25 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const assert = require('assert');
const t = require('apostrophe/test-lib/test');

process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET = 'whsec_xyz';
process.env.STRIPE_TEST_MODE = 'true';
process.env.STRIPE_MOCK_TEST_MODE = 'true';

describe('Apostrophe - Stripe Checkout Integration Tests', function () {
let apos;
Expand Down Expand Up @@ -34,12 +34,34 @@ describe('Apostrophe - Stripe Checkout Integration Tests', function () {
});

it('should properly instantiate the read-only field module', function () {
assert(apos.readOnlyField);
assert(apos.modules['read-only-field'], 'Read-only field module should be instantiated');
});

it('should properly instantiate the checkout and checkout session modules', function () {
assert(apos.stripeCheckout);
assert(apos.stripeCheckoutSession);
assert(apos.modules['stripe-checkout'], 'Stripe checkout module should be instantiated');
assert(apos.modules['stripe-checkout/session'], 'Stripe checkout session module should be instantiated');
});

it('should connect to Stripe API', async function() {
const Stripe = require('stripe');
const stripe = new Stripe('sk_test_xyz', {
host: '127.0.0.1',
protocol: 'http',
port: 12111,
maxNetworkRetries: 3,
timeout: 10 * 1000
});

try {
const paymentMethods = await stripe.paymentMethods.list({ limit: 1 });
assert.strictEqual(paymentMethods.data.length > 0, true, 'Should connect to Stripe API successfully');
} catch (error) {
console.error('Error connecting to Stripe API:', error);
if (error.detail?.errors?.length > 0) {
console.error('Error detail:', ...error.detail.errors);
}
throw error;
}
});

it('should create a test checkout session and return a valid URL', async function () {
Expand All @@ -51,7 +73,7 @@ describe('Apostrophe - Stripe Checkout Integration Tests', function () {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: {
body: JSON.stringify({
line_items: [
{
price: 'price_test_abc',
Expand All @@ -64,41 +86,39 @@ describe('Apostrophe - Stripe Checkout Integration Tests', function () {
],
success_url: apos.baseUrl,
cancel_url: apos.baseUrl
}
})
});
} catch (error) {
console.error('An error occurred:', error);
throw error;
}

function isURL(string) {
const urlRegex = /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/i;
return urlRegex.test(string);
}

assert.strictEqual(isURL(response), true);
assert.strictEqual(typeof response, 'object', 'Response should be an object');
assert(response.id, 'Response should contain an "id" parameter');
});

it('should send request to webhook endpoint and save the completed checkout session to the database', async function () {

await apos.http.post('/api/v1/stripe/checkout/webhook', {
headers: {
'stripe-signature': 't=1711059559,v1=9dd216ac7ffc2d07d3edd4b4de4a67200705c52f435e92bc3b21a605f3af91af,v0=4251a0f2bbd73dd1622bb01aedb334cab148be2a84bb3b1daea4af931e0172e2'
},
body: {
id: 'evt_xyz',
object: 'event'
}
}).catch(error => {
try {
await apos.http.post('/api/v1/stripe/checkout/webhook', {
headers: {
'stripe-signature': 't=1711059559,v1=9dd216ac7ffc2d07d3edd4b4de4a67200705c52f435e92bc3b21a605f3af91af,v0=4251a0f2bbd73dd1622bb01aedb334cab148be2a84bb3b1daea4af931e0172e2'
},
body: JSON.stringify({
id: 'evt_xyz',
object: 'event'
})
});
} catch (error) {
console.error('An error occurred:', error);
throw error;
});
}

const sessionDoc = await apos.stripeCheckoutSession.find(apos.task.getReq(), {
const sessionDoc = await apos.modules['stripe-checkout/session'].find(apos.task.getReq(), {
slug: 'cs_xyz',
aposMode: 'published'
}).toObject();

assert(sessionDoc);
assert(sessionDoc, 'The session document should be saved in the database');
assert.strictEqual(sessionDoc.slug, 'cs_xyz', 'Session document should have the correct slug');
});
});

0 comments on commit 4510044

Please sign in to comment.