From 2efa51347185552fcdb4003fe12a5052f892d388 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2023 14:49:54 -0500 Subject: [PATCH 01/10] proof of concept for automated tests for discord bot --- discord-bot/.env.test | 4 ++++ discord-bot/package.json | 7 +++++-- discord-bot/test/ping.test.js | 17 +++++++++++++++++ discord-bot/test/setup.js | 3 +++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 discord-bot/.env.test create mode 100644 discord-bot/test/ping.test.js create mode 100644 discord-bot/test/setup.js diff --git a/discord-bot/.env.test b/discord-bot/.env.test new file mode 100644 index 0000000..14e3f9a --- /dev/null +++ b/discord-bot/.env.test @@ -0,0 +1,4 @@ +STARGATE_JSON_API_URL=http://127.0.0.1:8181/v1/discordbot_test +STARGATE_JSON_USERNAME=cassandra +STARGATE_JSON_PASSWORD=cassandra +STARGATE_JSON_AUTH_URL=http://localhost:8081/v1/auth \ No newline at end of file diff --git a/discord-bot/package.json b/discord-bot/package.json index a2d2353..6d966cf 100644 --- a/discord-bot/package.json +++ b/discord-bot/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "lint": "eslint .", - "test": "echo \"Error: no test specified\" && exit 1", + "test": "mocha -r ./test/setup.js test/*.test.js", "start": "node ./index.js" }, "author": "", @@ -16,11 +16,14 @@ "dependencies": { "@discordjs/rest": "2.2.0", "@masteringjs/eslint-config": "0.0.1", - "@sapphire/framework": "4.8.2", "discord.js": "14.14.1", "dotenv": "16.3.1", "eslint": "8.54.0", "mongoose": "7.x", "stargate-mongoose": "0.3.0" + }, + "devDependencies": { + "mocha": "10.2.0", + "sinon": "17.0.1" } } diff --git a/discord-bot/test/ping.test.js b/discord-bot/test/ping.test.js new file mode 100644 index 0000000..b7d1917 --- /dev/null +++ b/discord-bot/test/ping.test.js @@ -0,0 +1,17 @@ +'use strict'; + +const assert = require('assert'); +const { describe, it } = require('mocha'); +const ping = require('../commands/ping'); +const sinon = require('sinon'); + +describe('ping', function() { + it('replies with "Pong!"', async function() { + const interaction = { + reply: sinon.stub() + }; + await ping.execute(interaction); + assert.ok(interaction.reply.calledOnce); + assert.deepEqual(interaction.reply.getCalls()[0].args, ['Pong!']); + }); +}); \ No newline at end of file diff --git a/discord-bot/test/setup.js b/discord-bot/test/setup.js new file mode 100644 index 0000000..ddc34ec --- /dev/null +++ b/discord-bot/test/setup.js @@ -0,0 +1,3 @@ +'use strict'; + +require('dotenv').config({ path: `${__dirname}/../.env.test` }); \ No newline at end of file From c1847b1c7b1fe389ad0e1f1023719336a4e35ce1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2023 17:34:17 -0500 Subject: [PATCH 02/10] test cases for discord bot --- .github/workflows/test.yml | 39 ++++++++++++++++++++++++ discord-bot/.env.test | 8 ++--- discord-bot/index.js | 1 - discord-bot/package.json | 2 +- discord-bot/test/countdocuments.test.js | 21 +++++++++++++ discord-bot/test/createdocument.test.js | 24 +++++++++++++++ discord-bot/test/setup.js | 20 +++++++++++- netlify-functions-ecommerce/package.json | 2 +- 8 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 discord-bot/test/countdocuments.test.js create mode 100644 discord-bot/test/createdocument.test.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 666f9e9..4e11185 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,6 +5,45 @@ permissions: contents: read jobs: + test-discord-bot: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + node: [16] + os: [ubuntu-20.04] + name: Discord Bot Sample App + steps: + ## Set up Stargate + - name: disable and stop mono-xsp4.service + run: | + sudo kill -9 $(sudo lsof -t -i:8084) + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + repository: stargate/stargate-mongoose + path: stargate-mongoose + ref: main + - name: Set up JSON API + run: | + chmod +x bin/start_json_api.sh + bin/start_json_api.sh -t v2.0.13 -j v1.0.0-ALPHA-9 + working-directory: stargate-mongoose + - name: Wait for services + run: | + while ! nc -z localhost 8080; do sleep 1; done + while ! nc -z localhost 8081; do sleep 1; done + working-directory: stargate-mongoose + ## Set up and run ecommerce sample app tests + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + - name: Setup node + uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3.1.1 + with: + node-version: ${{ matrix.node }} + + - run: npm install + working-directory: discord-bot + - run: npm test + working-directory: discord-bot test-ecommerce: runs-on: ${{ matrix.os }} strategy: diff --git a/discord-bot/.env.test b/discord-bot/.env.test index 14e3f9a..8990b89 100644 --- a/discord-bot/.env.test +++ b/discord-bot/.env.test @@ -1,4 +1,4 @@ -STARGATE_JSON_API_URL=http://127.0.0.1:8181/v1/discordbot_test -STARGATE_JSON_USERNAME=cassandra -STARGATE_JSON_PASSWORD=cassandra -STARGATE_JSON_AUTH_URL=http://localhost:8081/v1/auth \ No newline at end of file +JSON_API_URL=http://127.0.0.1:8181/v1/discordbot_test +JSON_API_AUTH_USERNAME=cassandra +JSON_API_AUTH_PASSWORD=cassandra +JSON_API_AUTH_URL=http://localhost:8081/v1/auth \ No newline at end of file diff --git a/discord-bot/index.js b/discord-bot/index.js index 6af01be..426a6e8 100644 --- a/discord-bot/index.js +++ b/discord-bot/index.js @@ -69,7 +69,6 @@ async function run() { authUrl: process.env.JSON_API_AUTH_URL }; } - await mongoose.connect(uri, jsonApiConnectOptions); console.log('Connecting to', uri); await mongoose.connect(uri, jsonApiConnectOptions); // Login to Discord with your client's token diff --git a/discord-bot/package.json b/discord-bot/package.json index 6d966cf..3753ff7 100644 --- a/discord-bot/package.json +++ b/discord-bot/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "lint": "eslint .", - "test": "mocha -r ./test/setup.js test/*.test.js", + "test": "mocha test/*.js", "start": "node ./index.js" }, "author": "", diff --git a/discord-bot/test/countdocuments.test.js b/discord-bot/test/countdocuments.test.js new file mode 100644 index 0000000..50d563a --- /dev/null +++ b/discord-bot/test/countdocuments.test.js @@ -0,0 +1,21 @@ +'use strict'; + +const Bot = require('../models/bot'); +const assert = require('assert'); +const { describe, it } = require('mocha'); +const countdocuments = require('../commands/countdocuments'); +const sinon = require('sinon'); + +describe('countdocuments', function() { + it('returns the number of bot documents', async function() { + await Bot.deleteMany({}); + await Bot.create({ name: 'test' }); + + const interaction = { + reply: sinon.stub() + }; + await countdocuments.execute(interaction); + assert.ok(interaction.reply.calledOnce); + assert.deepEqual(interaction.reply.getCalls()[0].args, [1]); + }); +}); \ No newline at end of file diff --git a/discord-bot/test/createdocument.test.js b/discord-bot/test/createdocument.test.js new file mode 100644 index 0000000..0f6d0d4 --- /dev/null +++ b/discord-bot/test/createdocument.test.js @@ -0,0 +1,24 @@ +'use strict'; + +const Bot = require('../models/bot'); +const assert = require('assert'); +const { describe, it } = require('mocha'); +const createdocument = require('../commands/createdocument'); +const sinon = require('sinon'); + +describe('createdocument', function() { + it('inserts a new document', async function() { + await Bot.deleteMany({}); + + const interaction = { + reply: sinon.stub() + }; + await createdocument.execute(interaction); + assert.ok(interaction.reply.calledOnce); + assert.deepEqual(interaction.reply.getCalls()[0].args, ['done!']); + + const docs = await Bot.find(); + assert.equal(docs.length, 1); + assert.equal(docs[0].name, 'I am a document'); + }); +}); \ No newline at end of file diff --git a/discord-bot/test/setup.js b/discord-bot/test/setup.js index ddc34ec..20f85a7 100644 --- a/discord-bot/test/setup.js +++ b/discord-bot/test/setup.js @@ -1,3 +1,21 @@ 'use strict'; -require('dotenv').config({ path: `${__dirname}/../.env.test` }); \ No newline at end of file +require('dotenv').config({ path: `${__dirname}/../.env.test` }); + +const Bot = require('../models/bot'); +const { before } = require('mocha'); +const mongoose = require('../mongoose'); + +const uri = process.env.JSON_API_URL; +const jsonApiConnectOptions = { + username: process.env.JSON_API_AUTH_USERNAME, + password: process.env.JSON_API_AUTH_PASSWORD, + authUrl: process.env.JSON_API_AUTH_URL +}; + +before(async function() { + console.log('Connecting to', uri); + await mongoose.connect(uri, jsonApiConnectOptions); + await Bot.db.dropCollection('bots').catch(() => {}); + await Bot.createCollection(); +}); \ No newline at end of file diff --git a/netlify-functions-ecommerce/package.json b/netlify-functions-ecommerce/package.json index e9535fe..c352751 100644 --- a/netlify-functions-ecommerce/package.json +++ b/netlify-functions-ecommerce/package.json @@ -6,7 +6,7 @@ "dotenv": "16.3.1", "mongoose": "7.x", "sinon": "16.1.0", - "stargate-mongoose": "0.2.0-ALPHA-8", + "stargate-mongoose": "file:../../stargate-mongoose/stargate-mongoose-0.3.0.tgz", "stripe": "13.9.0", "vanillatoasts": "1.6.0", "webpack": "5.x" From 17411b8d93235431481267cc5a80d9999284c7c3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2023 17:36:22 -0500 Subject: [PATCH 03/10] undo mistakenly committed changes --- netlify-functions-ecommerce/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netlify-functions-ecommerce/package.json b/netlify-functions-ecommerce/package.json index c352751..e9535fe 100644 --- a/netlify-functions-ecommerce/package.json +++ b/netlify-functions-ecommerce/package.json @@ -6,7 +6,7 @@ "dotenv": "16.3.1", "mongoose": "7.x", "sinon": "16.1.0", - "stargate-mongoose": "file:../../stargate-mongoose/stargate-mongoose-0.3.0.tgz", + "stargate-mongoose": "0.2.0-ALPHA-8", "stripe": "13.9.0", "vanillatoasts": "1.6.0", "webpack": "5.x" From 1beca39426aa9c711286df10dade96a2fbc6db7b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2023 17:37:39 -0500 Subject: [PATCH 04/10] run tests on pull request --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4e11185..97c1e63 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,7 @@ name: Test on: push: + pull_request: permissions: contents: read From 40da34ed25cd47953ae8451b756c1e111af2e123 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2023 21:01:30 -0500 Subject: [PATCH 05/10] make test.yml workflow consistent with stargate-mongoose --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 97c1e63..61a288c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,11 +27,11 @@ jobs: - name: Set up JSON API run: | chmod +x bin/start_json_api.sh - bin/start_json_api.sh -t v2.0.13 -j v1.0.0-ALPHA-9 + bin/start_json_api.sh working-directory: stargate-mongoose - name: Wait for services run: | - while ! nc -z localhost 8080; do sleep 1; done + while ! nc -z localhost 8181; do sleep 1; done while ! nc -z localhost 8081; do sleep 1; done working-directory: stargate-mongoose ## Set up and run ecommerce sample app tests From 73e5c7bc26dbe03887023ec0ebe54e3fa99b49a8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2023 21:02:46 -0500 Subject: [PATCH 06/10] bump stargate and json api versions --- api-compatibility.versions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api-compatibility.versions b/api-compatibility.versions index 7fb5f29..7fa1f61 100644 --- a/api-compatibility.versions +++ b/api-compatibility.versions @@ -1,2 +1,2 @@ -stargate_version=v2.1.0-ALPHA-6 -json_api_version=v1.0.0-ALPHA-12 \ No newline at end of file +stargate_version=v2.1.0-BETA-2 +json_api_version=v1.0.0-BETA-3 From ad4d5ca038a1307bbfe23b94792022d1e392df86 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2023 21:04:56 -0500 Subject: [PATCH 07/10] make ecommerce tests consistent with discord bot tests --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 61a288c..ab8de50 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,7 +34,7 @@ jobs: while ! nc -z localhost 8181; do sleep 1; done while ! nc -z localhost 8081; do sleep 1; done working-directory: stargate-mongoose - ## Set up and run ecommerce sample app tests + ## Set up and run discord bot sample app tests - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Setup node uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3.1.1 @@ -66,11 +66,11 @@ jobs: - name: Set up JSON API run: | chmod +x bin/start_json_api.sh - bin/start_json_api.sh -t v2.0.13 -j v1.0.0-ALPHA-9 + bin/start_json_api.sh working-directory: stargate-mongoose - name: Wait for services run: | - while ! nc -z localhost 8080; do sleep 1; done + while ! nc -z localhost 8181; do sleep 1; done while ! nc -z localhost 8081; do sleep 1; done working-directory: stargate-mongoose ## Set up and run ecommerce sample app tests From e6f2c8cf7f93e2bd2841bef510af6fa2391a6210 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2023 21:09:03 -0500 Subject: [PATCH 08/10] add local test env for ecommerce app --- netlify-functions-ecommerce/.env.test | 14 ++++++++++++++ netlify-functions-ecommerce/test/setup.test.js | 2 ++ 2 files changed, 16 insertions(+) create mode 100644 netlify-functions-ecommerce/.env.test diff --git a/netlify-functions-ecommerce/.env.test b/netlify-functions-ecommerce/.env.test new file mode 100644 index 0000000..c74b9a7 --- /dev/null +++ b/netlify-functions-ecommerce/.env.test @@ -0,0 +1,14 @@ +#Fill the Local JSON API related details only when NODE_ENV is set to 'jsonapi' +#Local JSON API URL for example: http://127.0.0.1:8181/v1/ecommerce_test where 'ecommerce_test' is the keyspace name +JSON_API_URL=http://127.0.0.1:8181/v1/ecommerce_test +#Auth URL for example: http://127.0.0.1:8081/v1/auth +JSON_API_AUTH_URL=http://127.0.0.1:8081/v1/auth +#Auth username and password +JSON_API_AUTH_USERNAME=cassandra +JSON_API_AUTH_PASSWORD=cassandra + +#Fill in Stripe related details if you want to see Stripe integration. +#Otherwise the sample app will bypass Stripe. +STRIPE_SECRET_KEY=test +STRIPE_SUCCESS_URL=http://127.0.0.1:8888/order-confirmation +STRIPE_CANCEL_URL=http://127.0.0.1:8888/cart \ No newline at end of file diff --git a/netlify-functions-ecommerce/test/setup.test.js b/netlify-functions-ecommerce/test/setup.test.js index 62de6ff..dbf24c0 100644 --- a/netlify-functions-ecommerce/test/setup.test.js +++ b/netlify-functions-ecommerce/test/setup.test.js @@ -1,5 +1,7 @@ 'use strict'; +require('dotenv').config({ path: `${__dirname}/../.env.test` }); + const { after } = require('mocha'); const connect = require('../connect'); const mongoose = require('../mongoose'); From 3278ff75219d5743b15e05458d2fca9795824437 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2023 21:16:31 -0500 Subject: [PATCH 09/10] quick fix so sinon stub actually runs --- netlify-functions-ecommerce/.env.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netlify-functions-ecommerce/.env.test b/netlify-functions-ecommerce/.env.test index c74b9a7..f8c2e0c 100644 --- a/netlify-functions-ecommerce/.env.test +++ b/netlify-functions-ecommerce/.env.test @@ -9,6 +9,6 @@ JSON_API_AUTH_PASSWORD=cassandra #Fill in Stripe related details if you want to see Stripe integration. #Otherwise the sample app will bypass Stripe. -STRIPE_SECRET_KEY=test +STRIPE_SECRET_KEY=test-key STRIPE_SUCCESS_URL=http://127.0.0.1:8888/order-confirmation STRIPE_CANCEL_URL=http://127.0.0.1:8888/cart \ No newline at end of file From 257f713ca8cbcc3dcdd0c6497963aa4946607411 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 24 Nov 2023 09:37:42 -0500 Subject: [PATCH 10/10] add ESLint for netlify-functions-ecommerce and run ESLint with tests --- .github/workflows/test.yml | 4 +++ netlify-functions-ecommerce/.eslintignore | 1 + netlify-functions-ecommerce/.eslintrc.js | 14 ++++++++++ netlify-functions-ecommerce/connect.js | 2 +- .../frontend/.eslintrc.js | 11 ++++++++ .../frontend/src/BaseComponent.js | 2 ++ .../frontend/src/cart/cart.js | 2 +- .../netlify/functions/checkout.js | 2 +- netlify-functions-ecommerce/package.json | 3 +++ netlify-functions-ecommerce/public/app.js | 27 ++++--------------- .../test/setup.test.js | 6 ++--- 11 files changed, 46 insertions(+), 28 deletions(-) create mode 100644 netlify-functions-ecommerce/.eslintignore create mode 100644 netlify-functions-ecommerce/.eslintrc.js create mode 100644 netlify-functions-ecommerce/frontend/.eslintrc.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ab8de50..f12ed04 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,6 +43,8 @@ jobs: - run: npm install working-directory: discord-bot + - run: npm run lint + working-directory: discord-bot - run: npm test working-directory: discord-bot test-ecommerce: @@ -82,5 +84,7 @@ jobs: - run: npm install working-directory: netlify-functions-ecommerce + - run: npm run lint + working-directory: netlify-functions-ecommerce - run: npm test working-directory: netlify-functions-ecommerce \ No newline at end of file diff --git a/netlify-functions-ecommerce/.eslintignore b/netlify-functions-ecommerce/.eslintignore new file mode 100644 index 0000000..d70ebaa --- /dev/null +++ b/netlify-functions-ecommerce/.eslintignore @@ -0,0 +1 @@ +public \ No newline at end of file diff --git a/netlify-functions-ecommerce/.eslintrc.js b/netlify-functions-ecommerce/.eslintrc.js new file mode 100644 index 0000000..b5d1028 --- /dev/null +++ b/netlify-functions-ecommerce/.eslintrc.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + extends: [ + '@masteringjs' + ], + parserOptions: { + ecmaVersion: 2020 + }, + env: { + node: true, + es6: true + } +}; \ No newline at end of file diff --git a/netlify-functions-ecommerce/connect.js b/netlify-functions-ecommerce/connect.js index db7ca79..a8b8588 100644 --- a/netlify-functions-ecommerce/connect.js +++ b/netlify-functions-ecommerce/connect.js @@ -5,7 +5,7 @@ require('dotenv').config(); const mongoose = require('./mongoose'); require('./models'); -const {createAstraUri} = require("stargate-mongoose"); +const { createAstraUri } = require('stargate-mongoose'); let conn = null; diff --git a/netlify-functions-ecommerce/frontend/.eslintrc.js b/netlify-functions-ecommerce/frontend/.eslintrc.js new file mode 100644 index 0000000..c386687 --- /dev/null +++ b/netlify-functions-ecommerce/frontend/.eslintrc.js @@ -0,0 +1,11 @@ +'use strict'; + +module.exports = { + env: { + browser: true + }, + globals: { + Vue: true, + VueRouter: true + } +}; \ No newline at end of file diff --git a/netlify-functions-ecommerce/frontend/src/BaseComponent.js b/netlify-functions-ecommerce/frontend/src/BaseComponent.js index 5c9270e..63a44a5 100644 --- a/netlify-functions-ecommerce/frontend/src/BaseComponent.js +++ b/netlify-functions-ecommerce/frontend/src/BaseComponent.js @@ -1,3 +1,5 @@ +'use strict'; + module.exports = (html, css) => { appendCSS(css); return { diff --git a/netlify-functions-ecommerce/frontend/src/cart/cart.js b/netlify-functions-ecommerce/frontend/src/cart/cart.js index 05fb51e..2366fdd 100644 --- a/netlify-functions-ecommerce/frontend/src/cart/cart.js +++ b/netlify-functions-ecommerce/frontend/src/cart/cart.js @@ -10,7 +10,7 @@ module.exports = app => app.component('cart', { computed: { cartTotal() { return '$' + this.state.cart.items.reduce((sum, item) => { - return sum + (+(item.quantity * this.product(item).price).toFixed(2)) + return sum + (+(item.quantity * this.product(item).price).toFixed(2)); }, 0).toFixed(2); } }, diff --git a/netlify-functions-ecommerce/netlify/functions/checkout.js b/netlify-functions-ecommerce/netlify/functions/checkout.js index a23e41f..4868105 100644 --- a/netlify-functions-ecommerce/netlify/functions/checkout.js +++ b/netlify-functions-ecommerce/netlify/functions/checkout.js @@ -39,7 +39,7 @@ const handler = async(event) => { return { statusCode: 200, body: JSON.stringify({ cart: cart, url: '/order-confirmation' }) - } + }; } const session = await stripe.checkout.sessions.create({ diff --git a/netlify-functions-ecommerce/package.json b/netlify-functions-ecommerce/package.json index bab77b6..805376f 100644 --- a/netlify-functions-ecommerce/package.json +++ b/netlify-functions-ecommerce/package.json @@ -12,7 +12,9 @@ "webpack": "5.x" }, "devDependencies": { + "@masteringjs/eslint-config": "0.0.1", "axios": "1.6.2", + "eslint": "8.54.0", "mocha": "10.2.0", "netlify-cli": "17.5.1" }, @@ -21,6 +23,7 @@ }, "scripts": { "build": "node ./frontend/build", + "lint": "eslint .", "seed": "node ./seed", "start": "netlify dev --dir public --functions netlify/functions", "test": "mocha ./test/*.test.js", diff --git a/netlify-functions-ecommerce/public/app.js b/netlify-functions-ecommerce/public/app.js index a95704d..921946f 100644 --- a/netlify-functions-ecommerce/public/app.js +++ b/netlify-functions-ecommerce/public/app.js @@ -1,4 +1,5 @@ /******/ (() => { // webpackBootstrap +/******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "./frontend/src/BaseComponent.js": @@ -7,6 +8,8 @@ \***************************************/ /***/ ((module) => { + + module.exports = (html, css) => { appendCSS(css); return { @@ -42,7 +45,6 @@ function appendCSS(css) { \***********************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { -"use strict"; const BaseComponent = __webpack_require__(/*! ../BaseComponent */ "./frontend/src/BaseComponent.js"); @@ -55,7 +57,7 @@ module.exports = app => app.component('cart', { computed: { cartTotal() { return '$' + this.state.cart.items.reduce((sum, item) => { - return sum + (+(item.quantity * this.product(item).price).toFixed(2)) + return sum + (+(item.quantity * this.product(item).price).toFixed(2)); }, 0).toFixed(2); } }, @@ -100,7 +102,6 @@ module.exports = app => app.component('cart', { \***********************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { -"use strict"; const BaseComponent = __webpack_require__(/*! ../BaseComponent */ "./frontend/src/BaseComponent.js"); @@ -148,7 +149,6 @@ module.exports = app => app.component('home', { \***************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { -"use strict"; const BaseComponent = __webpack_require__(/*! ../BaseComponent */ "./frontend/src/BaseComponent.js"); @@ -166,7 +166,6 @@ module.exports = app => app.component('navbar', { \***************************************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { -"use strict"; const BaseComponent = __webpack_require__(/*! ../BaseComponent */ "./frontend/src/BaseComponent.js"); @@ -207,7 +206,6 @@ module.exports = app => app.component('order-confirmation', { \*****************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { -"use strict"; const BaseComponent = __webpack_require__(/*! ../BaseComponent */ "./frontend/src/BaseComponent.js"); @@ -261,7 +259,6 @@ module.exports = app => app.component('product', { \*******************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { -"use strict"; const BaseComponent = __webpack_require__(/*! ../BaseComponent */ "./frontend/src/BaseComponent.js"); @@ -309,7 +306,6 @@ module.exports = app => app.component('products', { \********************************/ /***/ ((module) => { -"use strict"; module.exports = [ @@ -343,7 +339,6 @@ module.exports = [ \************************************/ /***/ ((module) => { -"use strict"; module.exports = ".cart .cart-item {\n display: flex;\n gap: 10px;\n width: 100%;\n margin-bottom: 1em;\n}\n\n.cart .cart-item .product-image {\n width: 80px;\n border: 1px solid #ddd;\n border-radius: 8px;\n padding: 5px;\n}\n\n.cart .cart-item .product-image img {\n width: 100%;\n height: auto;\n vertical-align: middle;\n}\n\n.cart .cart-item .item-description {\n flex-grow: 1;\n}\n\n.cart .cart-item .item-description .name {\n margin-bottom: 0.5em;\n font-weight: bold;\n}\n\n.cart .cart-item .subtotal {\n width: 120px;\n font-weight: bold;\n text-align: right;\n}\n\n.cart .total {\n width: 100%;\n font-weight: bold;\n border-top: 1px solid #ddd;\n padding-top: 1em;\n display: flex;\n}\n\n.cart .total .total-text {\n width: 50%;\n}\n\n.cart .total .total-price {\n text-align: right;\n width: 50%;\n}\n\n.cart .checkout {\n text-align: center;\n}\n\n.cart .checkout button {\n margin-top: 1em;\n font-size: 2em;\n background-color: white;\n border: 2px solid #43783E;\n color: #43783E;\n padding: 0.5em 1em;\n border-radius: 16px;\n}\n\n.cart .checkout button:hover {\n color: white;\n background-color: #43783E;\n}"; /***/ }), @@ -354,7 +349,6 @@ module.exports = ".cart .cart-item {\n display: flex;\n gap: 10px;\n width: 1 \*************************************/ /***/ ((module) => { -"use strict"; module.exports = "
\n

My Cart

\n
\n
\n
\n \n
\n
\n
\n {{product(item).name}}\n
\n
\n x{{item.quantity}}\n
\n
\n
\n {{formatTotal(item, product(item))}}\n
\n
\n
\n
\n Total\n
\n
\n {{cartTotal}}\n
\n
\n\n
\n \n
\n
\n
"; /***/ }), @@ -365,7 +359,6 @@ module.exports = "
\n

My Cart

\n
{ -"use strict"; module.exports = ".home {\n margin-bottom: 80px;\n}\n\n.home .hero {\n background-color: #CFFC7B;\n padding: 50px;\n position: relative;\n overflow: hidden;\n}\n\n.home .hero h1 {\n line-height: 1.25em;\n}\n\n.home .hero button {\n padding: 10px 15px;\n border-radius: 8px;\n color: white;\n background-color: #43783E;\n border: 0px;\n font-size: 1.5em;\n margin-top: 10px;\n}\n\n.home .hero img {\n width: 33%;\n position: absolute;\n right: 15px;\n top: -10px;\n}\n\n.home .iphone {\n width: 25%;\n}\n\n.home .iphone .image-wrapper {\n background-color: #ddd;\n padding-top: 10px;\n padding-bottom: 10px;\n}\n\n.home .iphone img {\n width: 100%;\n}\n\n.home .iphone-container {\n display: flex;\n gap: 15px;\n}\n\n.home .iphone .info-wrapper {\n font-weight: bold;\n display: flex;\n margin-top: 0.5em;\n}\n\n.home .iphone .info-wrapper .price {\n text-align: right;\n flex-grow: 1;\n}"; /***/ }), @@ -376,7 +369,6 @@ module.exports = ".home {\n margin-bottom: 80px;\n}\n\n.home .hero {\n backgro \*************************************/ /***/ ((module) => { -"use strict"; module.exports = "
\n
\n
\n \n
\n

\n Get the Latest iPhones
at the Best Prices \n

\n \n \n \n
\n
\n

iPhones For You

\n\n
\n
\n
\n \n \n \n
\n
\n \n {{product.name}}\n \n
\n {{formatPrice(product.price)}}\n
\n
\n
\n \n
\n
\n
\n
\n
"; /***/ }), @@ -387,7 +379,6 @@ module.exports = "
\n
\n
{ -"use strict"; module.exports = ".navbar {\n max-width: 1000px;\n display: flex;\n margin-left: auto;\n margin-right: auto;\n margin-bottom: 25px;\n margin-top: 10px;\n}\n\n.navbar img {\n vertical-align: middle;\n}\n\n.navbar .logo {\n flex-grow: 0;\n font-size: 2em;\n}\n\n.navbar .logo img {\n height: 45px;\n}\n\n.navbar .nav-center {\n flex-grow: 1;\n}\n\n.navbar .right {\n padding-top: 11px;\n position: relative;\n}\n\n.navbar .right img {\n height: 1.5em;\n margin-right: 0.5em;\n}\n\n.navbar .right .cart-indicator {\n position: absolute;\n background-color: #43783E;\n color: white;\n border-radius: 50%;\n height: 1.75em;\n width: 1.75em;\n font-size: 0.7em;\n left: 1.25em;\n top: 0.25em;\n text-align: center;\n line-height: 1.75em;\n}"; /***/ }), @@ -398,7 +389,6 @@ module.exports = ".navbar {\n max-width: 1000px;\n display: flex;\n margin-le \*****************************************/ /***/ ((module) => { -"use strict"; module.exports = "
\n
\n \n \n iPhoneMarket\n \n
\n
 
\n
\n \n \n Cart\n \n {{state.cart.numItems}}\n
\n \n
\n
"; /***/ }), @@ -409,7 +399,6 @@ module.exports = "
\n
\n { -"use strict"; module.exports = ".order-confirmation .order-info {\n display: flex;\n}\n\n.order-confirmation .order-info .order-detail {\n flex-grow: 1;\n}\n\n.order-confirmation .order-info .order-detail .subheader {\n font-weight: bold;\n}\n\n.order-confirmation button {\n background-color: white;\n border: 2px solid #43783E;\n color: #43783E;\n padding: 0.5em 1em;\n border-radius: 16px;\n margin-top: 1em;\n}\n\n.order-confirmation button:hover {\n background-color: #43783E;\n border: 2px solid #43783E;\n color: white;\n}"; /***/ }), @@ -420,7 +409,6 @@ module.exports = ".order-confirmation .order-info {\n display: flex;\n}\n\n.ord \*****************************************************************/ /***/ ((module) => { -"use strict"; module.exports = "
\n
\n

Your Order is Confirmed

\n
\n
\n
\n Total\n
\n
\n ${{order.total.toFixed(2)}}\n
\n
\n
\n
\n Payment Method\n
\n
\n {{order.paymentMethod.brand}} ending in {{order.paymentMethod.last4}}\n
\n
\n
\n\n
\n \n \n \n
\n
\n
"; /***/ }), @@ -431,7 +419,6 @@ module.exports = "
\n
\n \******************************************/ /***/ ((module) => { -"use strict"; module.exports = ".product .product-wrapper {\n display: flex;\n gap: 20px;\n}\n\n.product .breadcrumbs {\n font-size: 0.9em;\n color: #666;\n margin-bottom: 1em;\n}\n\n.product .breadcrumbs a {\n color: #666;\n}\n\n.product .product-wrapper .product-image {\n width: 50%;\n background-color: #ddd;\n}\n\n.product .product-wrapper .product-image img {\n width: 100%;\n}\n\n.product .product-wrapper .product-description {\n width: 50%;\n}\n\n.product .product-description .name {\n font-size: 1.5em;\n font-weight: bold;\n margin-bottom: 0.5em;\n}\n\n.product .product-description .price {\n margin-bottom: 1em;\n font-weight: bold;\n}\n\n.product .product-description .description {\n line-height: 1.5em;\n margin-bottom: 1em;\n}\n\n.product .product-description button {\n font-size: 1.5em;\n}"; /***/ }), @@ -442,7 +429,6 @@ module.exports = ".product .product-wrapper {\n display: flex;\n gap: 20px;\n} \*******************************************/ /***/ ((module) => { -"use strict"; module.exports = "
\n
\n All Products\n /\n {{product.name}}\n
\n
\n
\n \n
\n
\n
\n {{product.name}}\n
\n
\n {{formatPrice(product.price)}}\n
\n
\n {{product.description}}\n
\n \n
\n \n
\n
\n
\n
"; /***/ }), @@ -453,7 +439,6 @@ module.exports = "
\n
{ -"use strict"; module.exports = ".products .iphone {\n width: 25%;\n}\n\n.products .iphone .image-wrapper {\n background-color: #ddd;\n padding-top: 10px;\n padding-bottom: 10px;\n}\n\n.products .iphone img {\n width: 100%;\n}\n\n.products .iphone-container {\n display: flex;\n gap: 15px;\n}\n\n.products .iphone .info-wrapper {\n font-weight: bold;\n display: flex;\n margin-top: 0.5em;\n}\n\n.products .iphone .info-wrapper .price {\n text-align: right;\n flex-grow: 1;\n}"; /***/ }), @@ -464,7 +449,6 @@ module.exports = ".products .iphone {\n width: 25%;\n}\n\n.products .iphone .im \*********************************************/ /***/ ((module) => { -"use strict"; module.exports = "
\n

All Products

\n
\n
\n
\n \n \n \n
\n
\n
\n \n {{product.name}}\n \n
\n
\n {{formatPrice(product.price)}}\n
\n
\n
\n \n
\n
\n
\n
"; /***/ }) @@ -497,9 +481,8 @@ module.exports = "
\n

All Products

\n
{ -"use strict"; /*!*******************************!*\ !*** ./frontend/src/index.js ***! \*******************************/ diff --git a/netlify-functions-ecommerce/test/setup.test.js b/netlify-functions-ecommerce/test/setup.test.js index dbf24c0..6d48006 100644 --- a/netlify-functions-ecommerce/test/setup.test.js +++ b/netlify-functions-ecommerce/test/setup.test.js @@ -2,12 +2,12 @@ require('dotenv').config({ path: `${__dirname}/../.env.test` }); -const { after } = require('mocha'); +const { after, before } = require('mocha'); const connect = require('../connect'); const mongoose = require('../mongoose'); before(async function() { - this.timeout(30_000); + this.timeout(30000); await connect(); await Promise.all(Object.values(mongoose.connection.models).map(Model => Model.createCollection())); @@ -15,7 +15,7 @@ before(async function() { }); after(async function() { - this.timeout(30_000); + this.timeout(30000); await Promise.all(Object.values(mongoose.connection.models).map(async Model => { await mongoose.connection.dropCollection(Model.collection.collectionName); }));