diff --git a/compiled/jest_util.js b/compiled/jest_util.js new file mode 100644 index 00000000..1bdafcb1 --- /dev/null +++ b/compiled/jest_util.js @@ -0,0 +1,227 @@ +'use strict'; + +const accountTypes = require('../models/accountType'); +const guid = require('uuid/v1'); +const modelUtil = require('../models/_util'); +const orderPromises = require('../utilities').orderPromises; + +/* + ROUTES +*/ + +const route = route => `/api/${route}`; + +/* + TEST USER +*/ + +const user = { + email: 'trash@edwardtheapp.com', + password: 'thisismysecurepassword', + captchaResponse: 'token', + resetKey: '5cf197a4-1029-4250-91cc-6f0ef75bca77', + stripeId: 'cus_test', + verifyKey: '5cf197a4-1029-4250-91cc-6f0ef75bca77' +}; + +const alternateUser = {}; +Object.assign(alternateUser, user, { email: 'trash2@edwardtheapp.com' }); + +function getTestUserId(knex) { + return knex('users').where('email', user.email).first('id').then(({ id }) => id); +} + +function createTestUser(knex) { + return modelUtil.getHash(user.password).then(hash => { + return knex('users').insert(modelUtil.addTimestamps(knex, { + email: user.email, + password: hash, + 'account_type': accountTypes.LIMITED.name, + verified: true, + payment_period_end: knex.raw(`(SELECT 'now'::timestamp + '1 days'::interval)`) + })).returning(['id', 'email', 'account_type']).then(([user]) => user); + }); +} + +function createAlternateTestUser(knex) { + return modelUtil.getHash(alternateUser.password).then(hash => { + return knex('users').insert(modelUtil.addTimestamps(knex, { + email: alternateUser.email, + password: hash, + 'account_type': accountTypes.LIMITED.name, + verified: true, + payment_period_end: knex.raw(`(SELECT 'now'::timestamp + '1 days'::interval)`) + })).returning(['id', 'email', 'account_type']).then(([user]) => user); + }); +} + +function createTestDocument(knex, overrideEmail = null) { + const docGuid1 = guid(); + const docGuid2 = guid(); + + const userQuery = `(SELECT id FROM users WHERE email = '${overrideEmail || user.email}' LIMIT 1)`; + const userId = knex.raw(userQuery); + + return knex('documents').insert([{ + guid: docGuid1, + name: 'test', + 'user_id': userId + }, { + guid: docGuid2, + name: 'test2', + 'user_id': userId + }]).then(() => { + return knex('document_orders').insert({ + order: JSON.stringify([docGuid1, docGuid2]), + 'user_id': userId + }); + }).then(() => [docGuid1, docGuid2]); +} + +function createTestChapter(knex) { + const chapGuids = [guid(), guid(), guid()]; + + const userQuery = `(SELECT id FROM users WHERE email = '${user.email}' LIMIT 1)`; + const userId = knex.raw(userQuery); + const docId = knex.raw(`(SELECT id FROM documents WHERE user_id = ${userQuery} LIMIT 1)`); + + const chapter = index => ({ + archived: false, + content: { ops: [{ insert: 'test chapter content searchable' }] }, + guid: chapGuids[index - 1], + title: `test chapter ${index}`, + 'user_id': userId, + 'document_id': docId + }); + + return knex('chapters').insert([chapter(1), chapter(2), chapter(3)]).then(() => { + return knex('chapter_orders').insert({ + order: JSON.stringify(chapGuids), + 'document_id': docId, + 'user_id': userId + }); + }); +} + +function deleteTestUser(knex, email, deleteContentOnly = false) { + email = email || user.email; + + return knex('users').where('email', email).first('id').then(testUser => { + if (testUser === undefined) { + return; + } + + const testUserId = testUser.id; + + const tablesToDeleteFrom = ['section_orders', 'sections', 'plan_orders', 'plans', 'chapter_topics', 'master_topic_orders', 'master_topics', 'chapter_orders', 'chapters', 'document_orders', 'documents', 'workshop_content']; + + const deleteFns = tablesToDeleteFrom.map(table => () => { + return knex(table).where('user_id', testUserId).del(); + }); + + return orderPromises(deleteFns); + }).then(() => { + if (deleteContentOnly) { + return; + } + return knex('users').where('email', email).del(); + }); +} + +function getDocuments(knex, email) { + const userQuery = `(SELECT id FROM users WHERE email = '${email}' LIMIT 1)`; + const userId = knex.raw(userQuery); + + return knex('documents').where('user_id', userId).select(); +} + +function makeTestUserAdmin(knex) { + return knex('users').where('email', user.email).update({ + 'account_type': accountTypes.ADMIN.name + }); +} + +function makeTestUserDemo(knex) { + return knex('users').where('email', user.email).update({ + 'account_type': accountTypes.DEMO.name + }); +} + +function makeTestUserPremium(knex) { + return knex('users').where('email', user.email).update({ + 'account_type': accountTypes.PREMIUM.name, + 'payment_period_end': knex.raw(`(SELECT 'now'::timestamp + '1 month'::interval)`) + }); +} + +function setTestUserPaymentDueDate(knex, daysFromNow) { + return knex('users').where('email', user.email).update({ + 'payment_period_end': knex.raw(`(SELECT 'now'::timestamp + '${daysFromNow} days'::interval)`) + }); +} + +function setTestUserStripeId(knex) { + return knex('users').where('email', user.email).update({ + 'stripe_customer_id': user.stripeId + }); +} + +function setTestUserVerifyKey(knex) { + return knex('users').where('email', user.email).update({ + 'verify_key': user.verifyKey + }); +} + +function setTestUserResetKey(knex) { + return modelUtil.getHash(user.resetKey).then(hash => { + return knex('users').where('email', user.email).update({ + 'pass_reset_key': hash + }); + }); +} + +/* + EXTERNAL REQUEST STUBBING +*/ + +const request = require('request-promise-native'); + +function stubRecaptcha() { + beforeAll(() => { + const oldPost = request.post; + jest.spyOn(request, 'post').mockImplementation(body => { + if (body.uri === 'https://www.google.com/recaptcha/api/siteverify') { + return Promise.resolve({ success: true }); + } + return oldPost.apply([...arguments]); + }); + }); +} + +/* + GUIDS +*/ + +const workshopGuids = ['7f796320-3f2d-11e8-9fe0-af1b5e8b1c51', '7f796321-3f2d-11e8-9fe0-af1b5e8b1c51']; + +module.exports = { + user, + alternateUser, + createTestUser, + createAlternateTestUser, + createTestDocument, + createTestChapter, + deleteTestUser, + getDocuments, + getTestUserId, + makeTestUserAdmin, + makeTestUserDemo, + makeTestUserPremium, + route, + setTestUserPaymentDueDate, + setTestUserResetKey, + setTestUserStripeId, + setTestUserVerifyKey, + stubRecaptcha, + workshopGuids +}; diff --git a/compiled/test_util.js b/compiled/test_util.js new file mode 100644 index 00000000..b727bf58 --- /dev/null +++ b/compiled/test_util.js @@ -0,0 +1,228 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +const accountTypes = require('../models/accountType'); +const guid = require('uuid/v1'); +const modelUtil = require('../models/_util'); +const orderPromises = require('../utilities').orderPromises; + +/* + ROUTES +*/ + +const route = route => `/api/${route}`; + +/* + TEST USER +*/ + +const user = { + email: 'trash@edwardtheapp.com', + password: 'thisismysecurepassword', + captchaResponse: 'token', + resetKey: '5cf197a4-1029-4250-91cc-6f0ef75bca77', + stripeId: 'cus_test', + verifyKey: '5cf197a4-1029-4250-91cc-6f0ef75bca77' +}; + +const alternateUser = {}; +Object.assign(alternateUser, user, { email: 'trash2@edwardtheapp.com' }); + +function getTestUserId(knex) { + return knex('users').where('email', user.email).first('id').then(({ id }) => id); +} + +function createTestUser(knex) { + return modelUtil.getHash(user.password).then(hash => { + return knex('users').insert(modelUtil.addTimestamps(knex, { + email: user.email, + password: hash, + 'account_type': accountTypes.LIMITED.name, + verified: true, + payment_period_end: knex.raw(`(SELECT 'now'::timestamp + '1 days'::interval)`) + })).returning(['id', 'email', 'account_type']).then(([user]) => user); + }); +} + +function createAlternateTestUser(knex) { + return modelUtil.getHash(alternateUser.password).then(hash => { + return knex('users').insert(modelUtil.addTimestamps(knex, { + email: alternateUser.email, + password: hash, + 'account_type': accountTypes.LIMITED.name, + verified: true, + payment_period_end: knex.raw(`(SELECT 'now'::timestamp + '1 days'::interval)`) + })).returning(['id', 'email', 'account_type']).then(([user]) => user); + }); +} + +function createTestDocument(knex, overrideEmail = null) { + const docGuid1 = guid(); + const docGuid2 = guid(); + + const userQuery = `(SELECT id FROM users WHERE email = '${overrideEmail || user.email}' LIMIT 1)`; + const userId = knex.raw(userQuery); + + return knex('documents').insert([{ + guid: docGuid1, + name: 'test', + 'user_id': userId + }, { + guid: docGuid2, + name: 'test2', + 'user_id': userId + }]).then(() => { + return knex('document_orders').insert({ + order: JSON.stringify([docGuid1, docGuid2]), + 'user_id': userId + }); + }).then(() => [docGuid1, docGuid2]); +} + +function createTestChapter(knex) { + const chapGuids = [guid(), guid(), guid()]; + + const userQuery = `(SELECT id FROM users WHERE email = '${user.email}' LIMIT 1)`; + const userId = knex.raw(userQuery); + const docId = knex.raw(`(SELECT id FROM documents WHERE user_id = ${userQuery} LIMIT 1)`); + + const chapter = index => ({ + archived: false, + content: { ops: [{ insert: 'test chapter content searchable' }] }, + guid: chapGuids[index - 1], + title: `test chapter ${index}`, + 'user_id': userId, + 'document_id': docId + }); + + return knex('chapters').insert([chapter(1), chapter(2), chapter(3)]).then(() => { + return knex('chapter_orders').insert({ + order: JSON.stringify(chapGuids), + 'document_id': docId, + 'user_id': userId + }); + }); +} + +function deleteTestUser(knex, email, deleteContentOnly = false) { + email = email || user.email; + + return knex('users').where('email', email).first('id').then(testUser => { + if (testUser === undefined) { + return; + } + + const testUserId = testUser.id; + + const tablesToDeleteFrom = ['section_orders', 'sections', 'plan_orders', 'plans', 'chapter_topics', 'master_topic_orders', 'master_topics', 'chapter_orders', 'chapters', 'document_orders', 'documents', 'workshop_content']; + + const deleteFns = tablesToDeleteFrom.map(table => () => { + return knex(table).where('user_id', testUserId).del(); + }); + + return orderPromises(deleteFns); + }).then(() => { + if (deleteContentOnly) { + return; + } + return knex('users').where('email', email).del(); + }); +} + +function getDocuments(knex, email) { + const userQuery = `(SELECT id FROM users WHERE email = '${email}' LIMIT 1)`; + const userId = knex.raw(userQuery); + + return knex('documents').where('user_id', userId).select(); +} + +function makeTestUserAdmin(knex) { + return knex('users').where('email', user.email).update({ + 'account_type': accountTypes.ADMIN.name + }); +} + +function makeTestUserDemo(knex) { + return knex('users').where('email', user.email).update({ + 'account_type': accountTypes.DEMO.name + }); +} + +function makeTestUserPremium(knex) { + return knex('users').where('email', user.email).update({ + 'account_type': accountTypes.PREMIUM.name, + 'payment_period_end': knex.raw(`(SELECT 'now'::timestamp + '1 month'::interval)`) + }); +} + +function setTestUserPaymentDueDate(knex, daysFromNow) { + return knex('users').where('email', user.email).update({ + 'payment_period_end': knex.raw(`(SELECT 'now'::timestamp + '${daysFromNow} days'::interval)`) + }); +} + +function setTestUserStripeId(knex) { + return knex('users').where('email', user.email).update({ + 'stripe_customer_id': user.stripeId + }); +} + +function setTestUserVerifyKey(knex) { + return knex('users').where('email', user.email).update({ + 'verify_key': user.verifyKey + }); +} + +function setTestUserResetKey(knex) { + return modelUtil.getHash(user.resetKey).then(hash => { + return knex('users').where('email', user.email).update({ + 'pass_reset_key': hash + }); + }); +} + +/* + EXTERNAL REQUEST STUBBING +*/ + +const request = require('request-promise-native'); + +function stubRecaptcha() { + beforeAll(() => { + const oldPost = request.post; + jest.spyOn(request, 'post').mockImplementation(body => { + if (body.uri === 'https://www.google.com/recaptcha/api/siteverify') { + return Promise.resolve({ success: true }); + } + return oldPost.apply([...arguments]); + }); + }); +} + +/* + GUIDS +*/ + +const workshopGuids = ['7f796320-3f2d-11e8-9fe0-af1b5e8b1c51', '7f796321-3f2d-11e8-9fe0-af1b5e8b1c51']; + +exports.user = user; +exports.alternateUser = alternateUser; +exports.createTestUser = createTestUser; +exports.createAlternateTestUser = createAlternateTestUser; +exports.createTestDocument = createTestDocument; +exports.createTestChapter = createTestChapter; +exports.deleteTestUser = deleteTestUser; +exports.getDocuments = getDocuments; +exports.getTestUserId = getTestUserId; +exports.makeTestUserAdmin = makeTestUserAdmin; +exports.makeTestUserDemo = makeTestUserDemo; +exports.makeTestUserPremium = makeTestUserPremium; +exports.route = route; +exports.setTestUserPaymentDueDate = setTestUserPaymentDueDate; +exports.setTestUserResetKey = setTestUserResetKey; +exports.setTestUserStripeId = setTestUserStripeId; +exports.setTestUserVerifyKey = setTestUserVerifyKey; +exports.stubRecaptcha = stubRecaptcha; +exports.workshopGuids = workshopGuids; diff --git a/compiled/utilities.js b/compiled/utilities.js new file mode 100644 index 00000000..97036b3a --- /dev/null +++ b/compiled/utilities.js @@ -0,0 +1,144 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +// Complete an array of promises in order, each one waiting for the previous one to resolve +function orderPromises(promiseFns) { + if (!Array.isArray(promiseFns) || promiseFns.length && typeof promiseFns[0] !== 'function') { + throw new TypeError(`orderPromises expects an array of functions. Received: ${JSON.stringify(promiseFns)}`); + } + + if (!promiseFns.length) { + return Promise.resolve(); + } + + const promise = promiseFns[0](); + + if (!promise.then) { + throw new TypeError(`A function in the array passed to orderPromises did not return a promise. Returned: ${JSON.stringify(promise)}`); + } + + return promise.then(() => orderPromises(promiseFns.slice(1))); +} + +// getNewLine, getNewSegment, getStyles, getStyledArrayFromChapters: +// From an array of Edward chapters, produce an array of Line objects. +// Line { text: string | Segment[], style: string | string[], pageBreak: undefined | 'before' } +// Segment { text: string, style: string[] } +// Line style strings: h1|h2|h3|blockquote|ul|ol|chapterHeading +// Segment style strings: bold|italic|underline|strike + +function getNewLine() { + return { + text: [], + style: [] + }; +} + +function getNewSegment(text, style) { + return { + text: text || '', + style: style || [] + }; +} + +const listMap = { + bullet: 'ul', + ordered: 'ol' +}; +function getStyles(attributes) { + const styles = []; + const lineStyles = []; + + if (!attributes) { + return { styles, lineStyles }; + } + + for (const attr in attributes) { + if (['bold', 'italic', 'underline', 'strike'].includes(attr)) { + styles.push(attr); + continue; + } + + if (attr === 'header') { + lineStyles.push(`h${attributes[attr]}`); + continue; + } + + if (attr === 'blockquote') { + lineStyles.push('blockquote'); + continue; + } + + if (attr === 'list') { + lineStyles.push(listMap[attributes[attr]]); + continue; + } + } + + return { styles, lineStyles }; +} + +function getStyledArrayFromChapters(chapters) { + const splitContent = []; + + for (const chapter of chapters) { + splitContent.push({ + text: chapter.title, + style: 'chapterHeading', + pageBreak: 'before' + }); + + let currentLine = getNewLine(); + const ops = chapter.content && chapter.content.ops || []; + for (const op of ops) { + const insert = op.insert; + const { styles, lineStyles } = getStyles(op.attributes); + + if (lineStyles.length) { + currentLine.style.push(...lineStyles); + } + + if (insert === '\n') { + splitContent.push(currentLine); + currentLine = getNewLine(); + continue; + } + + if (insert.includes('\n')) { + const [first, ...lines] = insert.split('\n'); + if (first) { + const segment = getNewSegment(first, styles); + currentLine.text.push(segment); + } + + splitContent.push(currentLine); + currentLine = getNewLine(); + + for (let ix = 0; ix < lines.length - 1; ix++) { + const line = lines[ix]; + const segment = getNewSegment(line, styles); + currentLine.text.push(segment); + + splitContent.push(currentLine); + currentLine = getNewLine(); + } + + const last = lines[lines.length - 1]; + const segment = getNewSegment(last, styles); + currentLine.text.push(segment); + + continue; + } + + const segment = getNewSegment(insert, styles); + currentLine.text.push(segment); + } + } + + return splitContent; +} + +exports.orderPromises = orderPromises; +exports.getStyledArrayFromChapters = getStyledArrayFromChapters; diff --git a/jest.config.js b/jest.config.js index f7f2221d..729c9eea 100644 --- a/jest.config.js +++ b/jest.config.js @@ -136,8 +136,8 @@ module.exports = { // The glob patterns Jest uses to detect test files testMatch: [ - "/jest/**/*.js", - "!/jest/**/_*.js" + "/tests/jest/**/*.js", + "!/tests/jest/**/_*.js" ], // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped diff --git a/package-lock.json b/package-lock.json index 8400d737..dfb95bba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5562,6 +5562,75 @@ "is-buffer": "^1.1.5" } }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "chokidar": "^1.6.1", + "commander": "^2.11.0", + "convert-source-map": "^1.5.0", + "fs-readdir-recursive": "^1.0.0", + "glob": "^7.1.2", + "lodash": "^4.17.4", + "output-file-sync": "^1.1.2", + "path-is-absolute": "^1.0.1", + "slash": "^1.0.0", + "source-map": "^0.5.6", + "v8flags": "^2.1.1" + }, + "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "^1.1.1" + } + } + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -6406,6 +6475,25 @@ "esutils": "^2.0.2" } }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", @@ -12015,6 +12103,12 @@ "universalify": "^0.1.0" } }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -17672,6 +17766,17 @@ "os-tmpdir": "^1.0.0" } }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" + } + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -23231,6 +23336,12 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, "util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", diff --git a/package.json b/package.json index 865949a7..fa829b43 100644 --- a/package.json +++ b/package.json @@ -6,15 +6,16 @@ "author": "Isaac Lyman ", "scripts": { "build": "vue-cli-service build", - "test": "jest -i", - "lint": "vue-cli-service lint", - "cypress": "cypress open", "dev": "vue-cli-service serve", - "integration": "cypress run", "server": "node server.js", "server-dev": "nodemon server.js", "start": "npm run server", - "test:e2e": "vue-cli-service test:e2e" + "lint": "vue-cli-service lint", + "test": "jest -i", + "pretest": "node tests/pretest.js", + "cypress": "npm run pretest && cypress open", + "integration": "npm run pretest && cypress run", + "test:e2e": "npm run pretest && vue-cli-service test:e2e" }, "dependencies": { "autoprefixer": "7.1.2", @@ -85,6 +86,7 @@ "@vue/cli-plugin-pwa": "^3.0.4", "@vue/cli-service": "^3.0.4", "@vue/eslint-config-airbnb": "^3.0.4", + "babel-cli": "^6.26.0", "babel-core": "^6.26.3", "babel-jest": "^23.6.0", "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", diff --git a/jest/_imports.js b/tests/jest/_imports.js similarity index 94% rename from jest/_imports.js rename to tests/jest/_imports.js index 83dac6b0..810f0d7a 100644 --- a/jest/_imports.js +++ b/tests/jest/_imports.js @@ -1,5 +1,5 @@ -import accountTypes from '../models/accountType' -import { app as server, knex, serverReady } from '../server' +import accountTypes from '../../models/accountType' +import { app as server, knex, serverReady } from '../../server' import request from 'supertest' import { alternateUser, @@ -20,7 +20,7 @@ import { setTestUserVerifyKey, stubRecaptcha, user -} from './_util' +} from '../test_util' import uuid from 'uuid/v1' const app = request(server) diff --git a/jest/api/_chapter.helper.js b/tests/jest/api/_chapter.helper.js similarity index 100% rename from jest/api/_chapter.helper.js rename to tests/jest/api/_chapter.helper.js diff --git a/jest/api/_document.helper.js b/tests/jest/api/_document.helper.js similarity index 100% rename from jest/api/_document.helper.js rename to tests/jest/api/_document.helper.js diff --git a/jest/api/_plan.helper.js b/tests/jest/api/_plan.helper.js similarity index 100% rename from jest/api/_plan.helper.js rename to tests/jest/api/_plan.helper.js diff --git a/jest/api/_section.helper.js b/tests/jest/api/_section.helper.js similarity index 100% rename from jest/api/_section.helper.js rename to tests/jest/api/_section.helper.js diff --git a/jest/api/_topic.helper.js b/tests/jest/api/_topic.helper.js similarity index 100% rename from jest/api/_topic.helper.js rename to tests/jest/api/_topic.helper.js diff --git a/jest/api/_workshop.helper.js b/tests/jest/api/_workshop.helper.js similarity index 94% rename from jest/api/_workshop.helper.js rename to tests/jest/api/_workshop.helper.js index bc078d26..84a97e7b 100644 --- a/jest/api/_workshop.helper.js +++ b/tests/jest/api/_workshop.helper.js @@ -1,7 +1,7 @@ import { route } from '../_imports' -import writingWorkshops from '../../models/writingWorkshop' +import writingWorkshops from '../../../models/writingWorkshop' const guids = ['8104b1fb-c177-4ca1-b995-a75dcbe6911c', '2ae71a48-7873-4316-bf18-d9ee0e461799'] diff --git a/jest/api/admin.js b/tests/jest/api/admin.js similarity index 100% rename from jest/api/admin.js rename to tests/jest/api/admin.js diff --git a/jest/api/backup.js b/tests/jest/api/backup.js similarity index 99% rename from jest/api/backup.js rename to tests/jest/api/backup.js index ca2c7cf1..c6e6f309 100644 --- a/jest/api/backup.js +++ b/tests/jest/api/backup.js @@ -14,7 +14,7 @@ import { addTopic } from './_topic.helper' import { addPlan } from './_plan.helper' import { addSection } from './_section.helper' import { addWorkshops } from './_workshop.helper' -import writingWorkshops from '../../models/writingWorkshop' +import writingWorkshops from '../../../models/writingWorkshop' stubRecaptcha(test) diff --git a/jest/api/backup.upgrade.js b/tests/jest/api/backup.upgrade.js similarity index 99% rename from jest/api/backup.upgrade.js rename to tests/jest/api/backup.upgrade.js index 3f68f3ca..ad4bc961 100644 --- a/jest/api/backup.upgrade.js +++ b/tests/jest/api/backup.upgrade.js @@ -21,7 +21,7 @@ import localStorage from 'mock-local-storage' global.window = {} window.localStorage = global.localStorage -import Storage from '../../src/app/api/localStorage' +import Storage from '../../../src/app/api/localStorage' const storage = new Storage() stubRecaptcha(test) diff --git a/jest/api/chapter.js b/tests/jest/api/chapter.js similarity index 100% rename from jest/api/chapter.js rename to tests/jest/api/chapter.js diff --git a/jest/api/document.js b/tests/jest/api/document.js similarity index 100% rename from jest/api/document.js rename to tests/jest/api/document.js diff --git a/jest/api/document.saveAllContent.js b/tests/jest/api/document.saveAllContent.js similarity index 96% rename from jest/api/document.saveAllContent.js rename to tests/jest/api/document.saveAllContent.js index a2eddca6..050fa4cc 100644 --- a/jest/api/document.saveAllContent.js +++ b/tests/jest/api/document.saveAllContent.js @@ -13,8 +13,8 @@ import { checkChapters, compareChapters } from './_chapter.helper' import { checkTopics, compareTopics } from './_topic.helper' import { checkPlans, comparePlans } from './_plan.helper' import { compareSections } from './_section.helper' -import { checkWorkshops, workshops } from './_workshop.helper' -import writingWorkshops from '../../models/writingWorkshop' +import { checkWorkshops } from './_workshop.helper' +import writingWorkshops from '../../../models/writingWorkshop' stubRecaptcha(test) diff --git a/jest/api/email.js b/tests/jest/api/email.js similarity index 91% rename from jest/api/email.js rename to tests/jest/api/email.js index f3833dac..5b669559 100644 --- a/jest/api/email.js +++ b/tests/jest/api/email.js @@ -1,5 +1,5 @@ import { serverReady } from '../_imports' -import Email from '../../api/email.helper' +import Email from '../../../api/email.helper' test('An email can be sent', async done => { await serverReady diff --git a/jest/api/login.js b/tests/jest/api/login.js similarity index 100% rename from jest/api/login.js rename to tests/jest/api/login.js diff --git a/jest/api/payments.js b/tests/jest/api/payments.js similarity index 94% rename from jest/api/payments.js rename to tests/jest/api/payments.js index d71f9672..df0b0411 100644 --- a/jest/api/payments.js +++ b/tests/jest/api/payments.js @@ -1,5 +1,5 @@ import { knex, serverReady, user } from '../_imports' -import payments from '../../api/payments.helper' +import payments from '../../../api/payments.helper' function token (id = 'tok_visa') { return { id, object: 'token' } diff --git a/jest/api/plan.js b/tests/jest/api/plan.js similarity index 100% rename from jest/api/plan.js rename to tests/jest/api/plan.js diff --git a/jest/api/section.js b/tests/jest/api/section.js similarity index 100% rename from jest/api/section.js rename to tests/jest/api/section.js diff --git a/jest/api/space-used.helper.js b/tests/jest/api/space-used.helper.js similarity index 88% rename from jest/api/space-used.helper.js rename to tests/jest/api/space-used.helper.js index c65f7118..7693b022 100644 --- a/jest/api/space-used.helper.js +++ b/tests/jest/api/space-used.helper.js @@ -7,7 +7,7 @@ import { makeTestUserPremium, stubRecaptcha } from '../_imports' -import { getUsersOverLimit } from '../../api/space-used.helper' +import { getUsersOverLimit } from '../../../api/space-used.helper' stubRecaptcha(test) diff --git a/jest/api/topic.js b/tests/jest/api/topic.js similarity index 100% rename from jest/api/topic.js rename to tests/jest/api/topic.js diff --git a/jest/api/user-premium.js b/tests/jest/api/user-premium.js similarity index 100% rename from jest/api/user-premium.js rename to tests/jest/api/user-premium.js diff --git a/jest/api/user-recaptcha-fail.js b/tests/jest/api/user-recaptcha-fail.js similarity index 100% rename from jest/api/user-recaptcha-fail.js rename to tests/jest/api/user-recaptcha-fail.js diff --git a/jest/api/user.demo.js b/tests/jest/api/user.demo.js similarity index 100% rename from jest/api/user.demo.js rename to tests/jest/api/user.demo.js diff --git a/jest/api/user.js b/tests/jest/api/user.js similarity index 99% rename from jest/api/user.js rename to tests/jest/api/user.js index d1f88d56..4cc2af43 100644 --- a/jest/api/user.js +++ b/tests/jest/api/user.js @@ -17,7 +17,7 @@ import { stubRecaptcha, user } from '../_imports' -import { paymentSucceeded } from '../../api/payments.events' +import { paymentSucceeded } from '../../../api/payments.events' stubRecaptcha(test) diff --git a/jest/api/utilities.js b/tests/jest/api/utilities.js similarity index 94% rename from jest/api/utilities.js rename to tests/jest/api/utilities.js index 1da93425..10ca6c44 100644 --- a/jest/api/utilities.js +++ b/tests/jest/api/utilities.js @@ -1,4 +1,4 @@ -import utilities from '../../api/utilities' +import utilities from '../../../api/utilities' test('containSameElements is true when it should be', () => { const arr1 = ['bob', 3, undefined, 'foo'] diff --git a/jest/api/word.export.js b/tests/jest/api/word.export.js similarity index 100% rename from jest/api/word.export.js rename to tests/jest/api/word.export.js diff --git a/jest/api/workshops.js b/tests/jest/api/workshops.js similarity index 98% rename from jest/api/workshops.js rename to tests/jest/api/workshops.js index a5025e52..5c922a63 100644 --- a/jest/api/workshops.js +++ b/tests/jest/api/workshops.js @@ -8,7 +8,7 @@ import { stubRecaptcha } from '../_imports' import { addDocument } from './_document.helper' -import writingWorkshops from '../../models/writingWorkshop' +import writingWorkshops from '../../../models/writingWorkshop' import { workshops, addWorkshops } from './_workshop.helper' stubRecaptcha(test) diff --git a/jest/app/backup.local.js b/tests/jest/app/backup.local.js similarity index 98% rename from jest/app/backup.local.js rename to tests/jest/app/backup.local.js index 9b39e482..fea15b4d 100644 --- a/jest/app/backup.local.js +++ b/tests/jest/app/backup.local.js @@ -12,7 +12,7 @@ import localStorage from 'mock-local-storage' global.window = {} window.localStorage = global.localStorage -import Storage from '../../src/app/api/localStorage' +import Storage from '../../../src/app/api/localStorage' const storage = new Storage() stubRecaptcha(test) diff --git a/jest/app/localStorage.chapter.js b/tests/jest/app/localStorage.chapter.js similarity index 99% rename from jest/app/localStorage.chapter.js rename to tests/jest/app/localStorage.chapter.js index d21025c5..95457c06 100644 --- a/jest/app/localStorage.chapter.js +++ b/tests/jest/app/localStorage.chapter.js @@ -5,7 +5,7 @@ import localStorage from 'mock-local-storage' global.window = {} window.localStorage = global.localStorage -import LocalStorageApi from '../../src/app/api/localStorage' +import LocalStorageApi from '../../../src/app/api/localStorage' const lsa = new LocalStorageApi() let doc diff --git a/jest/app/localStorage.document.js b/tests/jest/app/localStorage.document.js similarity index 97% rename from jest/app/localStorage.document.js rename to tests/jest/app/localStorage.document.js index fb5ea2ef..4fcc8ba1 100644 --- a/jest/app/localStorage.document.js +++ b/tests/jest/app/localStorage.document.js @@ -5,7 +5,7 @@ import localStorage from 'mock-local-storage' global.window = {} window.localStorage = global.localStorage -import LocalStorageApi from '../../src/app/api/localStorage' +import LocalStorageApi from '../../../src/app/api/localStorage' const lsa = new LocalStorageApi() beforeEach(async () => { diff --git a/jest/app/localStorage.js b/tests/jest/app/localStorage.js similarity index 89% rename from jest/app/localStorage.js rename to tests/jest/app/localStorage.js index c0173d61..0318d9f4 100644 --- a/jest/app/localStorage.js +++ b/tests/jest/app/localStorage.js @@ -5,7 +5,7 @@ import localStorage from 'mock-local-storage' global.window = {} window.localStorage = global.localStorage -import LocalStorageApi from '../../src/app/api/localStorage' +import LocalStorageApi from '../../../src/app/api/localStorage' const lsa = new LocalStorageApi() beforeEach(async () => { diff --git a/jest/app/localStorage.plan.js b/tests/jest/app/localStorage.plan.js similarity index 97% rename from jest/app/localStorage.plan.js rename to tests/jest/app/localStorage.plan.js index 7ca9d67d..e6f5c8fc 100644 --- a/jest/app/localStorage.plan.js +++ b/tests/jest/app/localStorage.plan.js @@ -5,7 +5,7 @@ import localStorage from 'mock-local-storage' global.window = {} window.localStorage = global.localStorage -import LocalStorageApi from '../../src/app/api/localStorage' +import LocalStorageApi from '../../../src/app/api/localStorage' const lsa = new LocalStorageApi() let doc diff --git a/jest/app/localStorage.section.js b/tests/jest/app/localStorage.section.js similarity index 97% rename from jest/app/localStorage.section.js rename to tests/jest/app/localStorage.section.js index 8ef7b8dd..ef7a67d7 100644 --- a/jest/app/localStorage.section.js +++ b/tests/jest/app/localStorage.section.js @@ -5,7 +5,7 @@ import localStorage from 'mock-local-storage' global.window = {} window.localStorage = global.localStorage -import LocalStorageApi from '../../src/app/api/localStorage' +import LocalStorageApi from '../../../src/app/api/localStorage' const lsa = new LocalStorageApi() let doc, plan diff --git a/jest/app/localStorage.topic.js b/tests/jest/app/localStorage.topic.js similarity index 97% rename from jest/app/localStorage.topic.js rename to tests/jest/app/localStorage.topic.js index 5db2e084..52a8096d 100644 --- a/jest/app/localStorage.topic.js +++ b/tests/jest/app/localStorage.topic.js @@ -5,7 +5,7 @@ import localStorage from 'mock-local-storage' global.window = {} window.localStorage = global.localStorage -import LocalStorageApi from '../../src/app/api/localStorage' +import LocalStorageApi from '../../../src/app/api/localStorage' const lsa = new LocalStorageApi() let doc diff --git a/jest/app/versionResolver.js b/tests/jest/app/versionResolver.js similarity index 98% rename from jest/app/versionResolver.js rename to tests/jest/app/versionResolver.js index 759776a3..e108f39b 100644 --- a/jest/app/versionResolver.js +++ b/tests/jest/app/versionResolver.js @@ -1,5 +1,5 @@ import clone from 'lodash/clone' -import VersionResolver from '../../src/app/shared/versionResolver' +import VersionResolver from '../../../src/app/shared/versionResolver' const wait = async () => await new Promise(resolve => setTimeout(resolve, 50)) diff --git a/jest/index.js b/tests/jest/index.js similarity index 100% rename from jest/index.js rename to tests/jest/index.js diff --git a/jest/models/util.js b/tests/jest/models/util.js similarity index 100% rename from jest/models/util.js rename to tests/jest/models/util.js diff --git a/jest/server.js b/tests/jest/server.js similarity index 100% rename from jest/server.js rename to tests/jest/server.js diff --git a/jest/util_tests.js b/tests/jest/util_tests.js similarity index 98% rename from jest/util_tests.js rename to tests/jest/util_tests.js index a21c4b40..22f2d2cc 100644 --- a/jest/util_tests.js +++ b/tests/jest/util_tests.js @@ -8,7 +8,7 @@ import { createTestUser, deleteTestUser, makeTestUserPremium -} from './_util' +} from '../test_util' stubRecaptcha(test) diff --git a/jest/utilities.js b/tests/jest/utilities.js similarity index 98% rename from jest/utilities.js rename to tests/jest/utilities.js index 41bf6430..6ea34bfa 100644 --- a/jest/utilities.js +++ b/tests/jest/utilities.js @@ -1,4 +1,4 @@ -import { orderPromises } from '../utilities' +import { orderPromises } from '../../utilities' import { setTimeout } from 'timers'; const getPromiseFn = (callback, timeout) => diff --git a/tests/pretest.js b/tests/pretest.js new file mode 100644 index 00000000..bd8fe3b3 --- /dev/null +++ b/tests/pretest.js @@ -0,0 +1,8 @@ +const { execSync } = require('child_process') + +process.env['NODE_ENV'] = 'test'; + +execSync('npx babel utilities.js --out-file compiled/utilities.js') +execSync('npx babel tests/test_util.js --out-file compiled/test_util.js') + +process.exit() \ No newline at end of file diff --git a/jest/_util.js b/tests/test_util.js similarity index 99% rename from jest/_util.js rename to tests/test_util.js index d0eb8fa1..32fe201d 100644 --- a/jest/_util.js +++ b/tests/test_util.js @@ -225,7 +225,7 @@ function stubRecaptcha() { const workshopGuids = ['7f796320-3f2d-11e8-9fe0-af1b5e8b1c51', '7f796321-3f2d-11e8-9fe0-af1b5e8b1c51'] -module.exports = { +export { user, alternateUser, createTestUser, diff --git a/utilities.js b/utilities.js index fcd00111..6e58553b 100644 --- a/utilities.js +++ b/utilities.js @@ -135,17 +135,7 @@ function getStyledArrayFromChapters(chapters) { return splitContent } -(function (root, factory) { - if (typeof define === 'function' && define.amd) { // eslint-disable-line - define([], factory) // eslint-disable-line - } else if (typeof module === 'object' && module.exports) { - module.exports = factory() - } else { - root.returnExports = factory() -} -}(typeof self !== 'undefined' ? self : this, function () { - return { - getStyledArrayFromChapters, - orderPromises, - } -})) +export { + orderPromises, + getStyledArrayFromChapters +} \ No newline at end of file