From 178143dfb764fc91e3f05313c1e89b5227b50eb1 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Fri, 17 Jan 2020 00:51:33 +0100 Subject: [PATCH] refactor(modules): Various import fixes * DRY schema stitching code * Use same `.env` configuration file for cypress tests That last part I couldn't improve a lot. I thought it might be possible with cypress to import all files from a folder. But since it must be browser compatible and our backend is not using webpack or anything, it remains a goal unreached. close #2773 close #2774 --- backend/package.json | 2 +- backend/src/config/index.js | 16 +++++++-- backend/src/models/Badge.js | 2 +- backend/src/models/Category.js | 2 +- backend/src/models/Comment.js | 2 +- backend/src/models/Donations.js | 2 +- backend/src/models/EmailAddress.js | 2 +- backend/src/models/InvitationCode.js | 2 +- backend/src/models/Location.js | 2 +- backend/src/models/Post.js | 2 +- backend/src/models/Report.js | 2 +- backend/src/models/SocialMedia.js | 2 +- backend/src/models/Tag.js | 2 +- backend/src/models/UnverifiedEmailAddress.js | 2 +- backend/src/models/User.js | 2 +- backend/src/models/index.js | 24 ++++++------- backend/src/schema/types/index.js | 29 ++------------- backend/src/seed/factories/index.js | 38 +++++++------------- backend/src/server.js | 10 +----- cypress/plugins/index.js | 11 +++++- cypress/support/factories.js | 10 ++++-- 21 files changed, 72 insertions(+), 94 deletions(-) diff --git a/backend/package.json b/backend/package.json index 7ca301c14..ab9bfd5a4 100644 --- a/backend/package.json +++ b/backend/package.json @@ -7,7 +7,7 @@ "build": "babel src/ -d dist/ --copy-files", "start": "node dist/", "dev": "nodemon --exec babel-node src/ -e js,gql", - "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/index.js -e js,gql", + "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql", "lint": "eslint src --config .eslintrc.js", "test": "jest --forceExit --detectOpenHandles --runInBand", "db:reset": "babel-node src/seed/reset-db.js", diff --git a/backend/src/config/index.js b/backend/src/config/index.js index 80573e180..2f8d0ed22 100644 --- a/backend/src/config/index.js +++ b/backend/src/config/index.js @@ -1,7 +1,8 @@ import dotenv from 'dotenv' -import path from 'path' - -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +if (require.resolve) { + // are we in a nodejs environment? + dotenv.config({ path: require.resolve('../../.env') }) +} const { MAPBOX_TOKEN, @@ -27,6 +28,15 @@ export const requiredConfigs = { PRIVATE_KEY_PASSPHRASE, } +if (require.resolve) { + // are we in a nodejs environment? + Object.entries(requiredConfigs).map(entry => { + if (!entry[1]) { + throw new Error(`ERROR: "${entry[0]}" env variable is missing.`) + } + }) +} + export const smtpConfigs = { SMTP_HOST, SMTP_PORT, diff --git a/backend/src/models/Badge.js b/backend/src/models/Badge.js index 6968a056b..9c4831041 100644 --- a/backend/src/models/Badge.js +++ b/backend/src/models/Badge.js @@ -1,4 +1,4 @@ -module.exports = { +export default { id: { type: 'string', primary: true, lowercase: true }, status: { type: 'string', valid: ['permanent', 'temporary'] }, type: { type: 'string', valid: ['role', 'crowdfunding'] }, diff --git a/backend/src/models/Category.js b/backend/src/models/Category.js index d8f1bff6f..faf5f189f 100644 --- a/backend/src/models/Category.js +++ b/backend/src/models/Category.js @@ -1,6 +1,6 @@ import uuid from 'uuid/v4' -module.exports = { +export default { id: { type: 'string', primary: true, default: uuid }, name: { type: 'string', required: true, default: false }, slug: { type: 'string' }, diff --git a/backend/src/models/Comment.js b/backend/src/models/Comment.js index 54cbda675..773152541 100644 --- a/backend/src/models/Comment.js +++ b/backend/src/models/Comment.js @@ -1,6 +1,6 @@ import uuid from 'uuid/v4' -module.exports = { +export default { id: { type: 'string', primary: true, default: uuid }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, updatedAt: { diff --git a/backend/src/models/Donations.js b/backend/src/models/Donations.js index 45e06e1d4..45d737f85 100644 --- a/backend/src/models/Donations.js +++ b/backend/src/models/Donations.js @@ -1,6 +1,6 @@ import uuid from 'uuid/v4' -module.exports = { +export default { id: { type: 'string', primary: true, default: uuid }, goal: { type: 'number' }, progress: { type: 'number' }, diff --git a/backend/src/models/EmailAddress.js b/backend/src/models/EmailAddress.js index 6afccd1ed..fa2aa0b27 100644 --- a/backend/src/models/EmailAddress.js +++ b/backend/src/models/EmailAddress.js @@ -1,4 +1,4 @@ -module.exports = { +export default { email: { type: 'string', primary: true, lowercase: true, email: true }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, verifiedAt: { type: 'string', isoDate: true }, diff --git a/backend/src/models/InvitationCode.js b/backend/src/models/InvitationCode.js index f137f6c15..138289faf 100644 --- a/backend/src/models/InvitationCode.js +++ b/backend/src/models/InvitationCode.js @@ -1,4 +1,4 @@ -module.exports = { +export default { createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, token: { type: 'string', primary: true, token: true }, generatedBy: { diff --git a/backend/src/models/Location.js b/backend/src/models/Location.js index 2c62877f7..d33186da4 100644 --- a/backend/src/models/Location.js +++ b/backend/src/models/Location.js @@ -1,4 +1,4 @@ -module.exports = { +export default { id: { type: 'string', primary: true }, lat: { type: 'number' }, lng: { type: 'number' }, diff --git a/backend/src/models/Post.js b/backend/src/models/Post.js index bd6eda2e4..fd1e5b2ac 100644 --- a/backend/src/models/Post.js +++ b/backend/src/models/Post.js @@ -1,6 +1,6 @@ import uuid from 'uuid/v4' -module.exports = { +export default { id: { type: 'string', primary: true, default: uuid }, activityId: { type: 'string', allow: [null] }, objectId: { type: 'string', allow: [null] }, diff --git a/backend/src/models/Report.js b/backend/src/models/Report.js index 2ace4ea73..93876f404 100644 --- a/backend/src/models/Report.js +++ b/backend/src/models/Report.js @@ -1,6 +1,6 @@ import uuid from 'uuid/v4' -module.exports = { +export default { id: { type: 'string', primary: true, default: uuid }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, updatedAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, diff --git a/backend/src/models/SocialMedia.js b/backend/src/models/SocialMedia.js index 42d2da30e..abdb12b02 100644 --- a/backend/src/models/SocialMedia.js +++ b/backend/src/models/SocialMedia.js @@ -1,6 +1,6 @@ import uuid from 'uuid/v4' -module.exports = { +export default { id: { type: 'string', primary: true, default: uuid }, url: { type: 'string', uri: true, required: true }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, diff --git a/backend/src/models/Tag.js b/backend/src/models/Tag.js index 90b5f8772..8df60c761 100644 --- a/backend/src/models/Tag.js +++ b/backend/src/models/Tag.js @@ -1,4 +1,4 @@ -module.exports = { +export default { id: { type: 'string', primary: true }, deleted: { type: 'boolean', default: false }, disabled: { type: 'boolean', default: false }, diff --git a/backend/src/models/UnverifiedEmailAddress.js b/backend/src/models/UnverifiedEmailAddress.js index 7b37b9a39..489e8517a 100644 --- a/backend/src/models/UnverifiedEmailAddress.js +++ b/backend/src/models/UnverifiedEmailAddress.js @@ -1,4 +1,4 @@ -module.exports = { +export default { email: { type: 'string', primary: true, lowercase: true, email: true }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, nonce: { type: 'string', token: true }, diff --git a/backend/src/models/User.js b/backend/src/models/User.js index 32f053e2b..fc352dccc 100644 --- a/backend/src/models/User.js +++ b/backend/src/models/User.js @@ -1,6 +1,6 @@ import uuid from 'uuid/v4' -module.exports = { +export default { id: { type: 'string', primary: true, default: uuid }, // TODO: should be type: 'uuid' but simplified for our tests actorId: { type: 'string', allow: [null] }, name: { type: 'string', disallow: [null], min: 3 }, diff --git a/backend/src/models/index.js b/backend/src/models/index.js index 0b9378162..047ace67c 100644 --- a/backend/src/models/index.js +++ b/backend/src/models/index.js @@ -1,16 +1,16 @@ // NOTE: We cannot use `fs` here to clean up the code. Cypress breaks on any npm // module that is not browser-compatible. Node's `fs` module is server-side only export default { - Badge: require('./Badge.js'), - User: require('./User.js'), - EmailAddress: require('./EmailAddress.js'), - UnverifiedEmailAddress: require('./UnverifiedEmailAddress.js'), - SocialMedia: require('./SocialMedia.js'), - Post: require('./Post.js'), - Comment: require('./Comment.js'), - Category: require('./Category.js'), - Tag: require('./Tag.js'), - Location: require('./Location.js'), - Donations: require('./Donations.js'), - Report: require('./Report.js'), + Badge: require('./Badge.js').default, + User: require('./User.js').default, + EmailAddress: require('./EmailAddress.js').default, + UnverifiedEmailAddress: require('./UnverifiedEmailAddress.js').default, + SocialMedia: require('./SocialMedia.js').default, + Post: require('./Post.js').default, + Comment: require('./Comment.js').default, + Category: require('./Category.js').default, + Tag: require('./Tag.js').default, + Location: require('./Location.js').default, + Donations: require('./Donations.js').default, + Report: require('./Report.js').default, } diff --git a/backend/src/schema/types/index.js b/backend/src/schema/types/index.js index 068af64da..d49becffc 100644 --- a/backend/src/schema/types/index.js +++ b/backend/src/schema/types/index.js @@ -1,30 +1,5 @@ -import fs from 'fs' import path from 'path' -import { mergeTypes } from 'merge-graphql-schemas' - -const findGqlFiles = dir => { - var results = [] - var list = fs.readdirSync(dir) - list.forEach(file => { - file = path.join(dir, file).toString('utf-8') - var stat = fs.statSync(file) - if (stat && stat.isDirectory()) { - // Recurse into a subdirectory - results = results.concat(findGqlFiles(file)) - } else { - if (path.extname(file) === '.gql') { - // Is a gql file - results.push(file) - } - } - }) - return results -} - -const typeDefs = [] - -findGqlFiles(__dirname).forEach(file => { - typeDefs.push(fs.readFileSync(file).toString('utf-8')) -}) +import { mergeTypes, fileLoader } from 'merge-graphql-schemas' +const typeDefs = fileLoader(path.join(__dirname, './**/*.gql')) export default mergeTypes(typeDefs, { all: true }) diff --git a/backend/src/seed/factories/index.js b/backend/src/seed/factories/index.js index 8b80a4b4f..ff6a52a76 100644 --- a/backend/src/seed/factories/index.js +++ b/backend/src/seed/factories/index.js @@ -1,30 +1,18 @@ import { getDriver, getNeode } from '../../bootstrap/neo4j' -import createBadge from './badges.js' -import createUser from './users.js' -import createPost from './posts.js' -import createComment from './comments.js' -import createCategory from './categories.js' -import createTag from './tags.js' -import createSocialMedia from './socialMedia.js' -import createLocation from './locations.js' -import createEmailAddress from './emailAddresses.js' -import createDonations from './donations.js' -import createUnverifiedEmailAddresss from './unverifiedEmailAddresses.js' -import createReport from './reports.js' const factories = { - Badge: createBadge, - User: createUser, - Post: createPost, - Comment: createComment, - Category: createCategory, - Tag: createTag, - SocialMedia: createSocialMedia, - Location: createLocation, - EmailAddress: createEmailAddress, - UnverifiedEmailAddress: createUnverifiedEmailAddresss, - Donations: createDonations, - Report: createReport, + Badge: require('./badges.js').default, + User: require('./users.js').default, + Post: require('./posts.js').default, + Comment: require('./comments.js').default, + Category: require('./categories.js').default, + Tag: require('./tags.js').default, + SocialMedia: require('./socialMedia.js').default, + Location: require('./locations.js').default, + EmailAddress: require('./emailAddresses.js').default, + UnverifiedEmailAddress: require('./unverifiedEmailAddresses.js').default, + Donations: require('./donations.js').default, + Report: require('./reports.js').default, } export const cleanDatabase = async (options = {}) => { @@ -34,7 +22,7 @@ export const cleanDatabase = async (options = {}) => { await session.writeTransaction(transaction => { return transaction.run( ` - MATCH (everything) + MATCH (everything) DETACH DELETE everything `, ) diff --git a/backend/src/server.js b/backend/src/server.js index 122f23683..bd9973a39 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -1,21 +1,13 @@ import express from 'express' import helmet from 'helmet' import { ApolloServer } from 'apollo-server-express' -import CONFIG, { requiredConfigs } from './config' +import CONFIG from './config' import middleware from './middleware' import { getNeode, getDriver } from './bootstrap/neo4j' import decode from './jwt/decode' import schema from './schema' import webfinger from './activitypub/routes/webfinger' -// check required configs and throw error -// TODO check this directly in config file - currently not possible due to testsetup -Object.entries(requiredConfigs).map(entry => { - if (!entry[1]) { - throw new Error(`ERROR: "${entry[0]}" env variable is missing.`) - } -}) - const driver = getDriver() const neode = getNeode() diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index 4ec4addb3..893b99f4f 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -11,10 +11,19 @@ // This function is called when a project is opened or re-opened (e.g. due to // the project's config changing) + const cucumber = require('cypress-cucumber-preprocessor').default -module.exports = on => { +const dotenv = require('dotenv') + +module.exports = (on, config) => { // (on, config) => { // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress config + const { parsed } = dotenv.config({ path: require.resolve('../../backend/.env') }) + config.env.NEO4J_URI = parsed.NEO4J_URI + config.env.NEO4J_USERNAME = parsed.NEO4J_USERNAME + config.env.NEO4J_PASSWORD = parsed.NEO4J_PASSWORD + on('file:preprocessor', cucumber()) + return config } diff --git a/cypress/support/factories.js b/cypress/support/factories.js index 234584e09..e0b6210d8 100644 --- a/cypress/support/factories.js +++ b/cypress/support/factories.js @@ -1,9 +1,13 @@ import Factory from '../../backend/src/seed/factories' import { getDriver, getNeode } from '../../backend/src/bootstrap/neo4j' -import neode from 'neode' -const neo4jDriver = getDriver() -const neodeInstance = getNeode() +const neo4jConfigs = { + uri: Cypress.env('NEO4J_URI'), + username: Cypress.env('NEO4J_USERNAME'), + password: Cypress.env('NEO4J_PASSWORD') +} +const neo4jDriver = getDriver(neo4jConfigs) +const neodeInstance = getNeode(neo4jConfigs) const factoryOptions = { neo4jDriver, neodeInstance } const factory = Factory(factoryOptions)