Updating testing system across the board after playing around with it, having the worker tests run when top level test is ran, fixing environment in worker when testing, removing the use of redis (replacing with ioredis-mock) when in test.
This commit is contained in:
parent
48236b2c2f
commit
2ee4fd21e4
|
@ -15,5 +15,8 @@
|
|||
"passport-jwt": "^4.0.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ioredis-mock": "^5.5.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
function isTest() {
|
||||
return (
|
||||
process.env.NODE_ENV === "jest" ||
|
||||
process.env.NODE_ENV === "cypress" ||
|
||||
process.env.JEST_WORKER_ID != null
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
JWT_SECRET: process.env.JWT_SECRET,
|
||||
COUCH_DB_URL: process.env.COUCH_DB_URL,
|
||||
SALT_ROUNDS: process.env.SALT_ROUNDS,
|
||||
REDIS_URL: process.env.REDIS_URL,
|
||||
REDIS_PASSWORD: process.env.REDIS_PASSWORD,
|
||||
isTest,
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
const Redis = require("ioredis")
|
||||
const env = require("../environment")
|
||||
// ioredis mock is all in memory
|
||||
const Redis = env.isTest() ? require("ioredis-mock") : require("ioredis")
|
||||
const { addDbPrefix, removeDbPrefix, getRedisOptions } = require("./utils")
|
||||
|
||||
const CLUSTERED = false
|
||||
|
||||
let CLIENT
|
||||
// for testing just generate the client once
|
||||
let CLIENT = env.isTest() ? new Redis(getRedisOptions()) : null
|
||||
|
||||
/**
|
||||
* Inits the system, will error if unable to connect to redis cluster (may take up to 10 seconds) otherwise
|
||||
|
@ -12,6 +15,10 @@ let CLIENT
|
|||
*/
|
||||
function init() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// testing uses a single in memory client
|
||||
if (env.isTest()) {
|
||||
return resolve(CLIENT)
|
||||
}
|
||||
// if a connection existed, close it and re-create it
|
||||
if (CLIENT) {
|
||||
CLIENT.disconnect()
|
||||
|
@ -108,7 +115,12 @@ class RedisWrapper {
|
|||
if (response != null && response.key) {
|
||||
response.key = key
|
||||
}
|
||||
// if its not an object just return the response
|
||||
try {
|
||||
return JSON.parse(response)
|
||||
} catch (err) {
|
||||
return response
|
||||
}
|
||||
}
|
||||
|
||||
async store(key, value, expirySeconds = null) {
|
||||
|
|
|
@ -3,6 +3,8 @@ const env = require("../environment")
|
|||
const SLOT_REFRESH_MS = 2000
|
||||
const CONNECT_TIMEOUT_MS = 10000
|
||||
const SEPARATOR = "-"
|
||||
const REDIS_URL = !env.REDIS_URL ? "localhost:6379" : env.REDIS_URL
|
||||
const REDIS_PASSWORD = !env.REDIS_PASSWORD ? "budibase" : env.REDIS_PASSWORD
|
||||
|
||||
exports.Databases = {
|
||||
PW_RESETS: "pwReset",
|
||||
|
@ -10,20 +12,20 @@ exports.Databases = {
|
|||
}
|
||||
|
||||
exports.getRedisOptions = (clustered = false) => {
|
||||
const [host, port] = env.REDIS_URL.split(":")
|
||||
const [host, port] = REDIS_URL.split(":")
|
||||
const opts = {
|
||||
connectTimeout: CONNECT_TIMEOUT_MS,
|
||||
}
|
||||
if (clustered) {
|
||||
opts.redisOptions = {}
|
||||
opts.redisOptions.tls = {}
|
||||
opts.redisOptions.password = env.REDIS_PASSWORD
|
||||
opts.redisOptions.password = REDIS_PASSWORD
|
||||
opts.slotsRefreshTimeout = SLOT_REFRESH_MS
|
||||
opts.dnsLookup = (address, callback) => callback(null, address)
|
||||
} else {
|
||||
opts.host = host
|
||||
opts.port = port
|
||||
opts.password = env.REDIS_PASSWORD
|
||||
opts.password = REDIS_PASSWORD
|
||||
}
|
||||
return { opts, host, port }
|
||||
}
|
||||
|
|
|
@ -46,6 +46,11 @@ aws4@^1.8.0:
|
|||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
||||
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
base64url@3.x.x:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
|
||||
|
@ -63,6 +68,14 @@ bcryptjs@^2.4.3:
|
|||
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
|
||||
integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||
|
@ -85,6 +98,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
|
|||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
core-util-is@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
|
@ -154,6 +172,20 @@ fast-json-stable-stringify@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||
|
||||
fengari-interop@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/fengari-interop/-/fengari-interop-0.1.2.tgz#f7731dcdd2ff4449073fb7ac3c451a8841ce1e87"
|
||||
integrity sha512-8iTvaByZVoi+lQJhHH9vC+c/Yaok9CwOqNQZN6JrVpjmWwW4dDkeblBXhnHC+BoI6eF4Cy5NKW3z6ICEjvgywQ==
|
||||
|
||||
fengari@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/fengari/-/fengari-0.1.4.tgz#72416693cd9e43bd7d809d7829ddc0578b78b0bb"
|
||||
integrity sha512-6ujqUuiIYmcgkGz8MGAdERU57EIluGGPSUgGPTsco657EHa+srq0S3/YUl/r9kx1+D+d4rGfYObd+m8K22gB1g==
|
||||
dependencies:
|
||||
readline-sync "^1.4.9"
|
||||
sprintf-js "^1.1.1"
|
||||
tmp "^0.0.33"
|
||||
|
||||
forever-agent@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||
|
@ -233,6 +265,17 @@ http-signature@~1.2.0:
|
|||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
|
||||
ioredis-mock@^5.5.5:
|
||||
version "5.5.5"
|
||||
resolved "https://registry.yarnpkg.com/ioredis-mock/-/ioredis-mock-5.5.5.tgz#dec9fedd238c6ab9f56c026fc366533144f8a256"
|
||||
integrity sha512-7SxCAwNtDLC8IFDptqIhOC7ajp3fciVtCrXOEOkpyjPboAGRQkJbnpNPy1NYORoWi+0/iOtUPUQckSKtSQj4DA==
|
||||
dependencies:
|
||||
fengari "^0.1.4"
|
||||
fengari-interop "^0.1.2"
|
||||
lodash "^4.17.21"
|
||||
minimatch "^3.0.4"
|
||||
standard-as-callback "^2.1.0"
|
||||
|
||||
ioredis@^4.27.1:
|
||||
version "4.27.1"
|
||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.27.1.tgz#4ef947b455a1b995baa4b0d7e2c4e4f75f746421"
|
||||
|
@ -379,7 +422,7 @@ lodash.once@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
|
||||
|
||||
lodash@^4.14.0:
|
||||
lodash@^4.14.0, lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
@ -401,6 +444,13 @@ mime@^1.4.1:
|
|||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
|
@ -426,6 +476,11 @@ oauth@0.9.x:
|
|||
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
||||
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
|
||||
|
||||
os-tmpdir@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||
|
||||
p-map@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
|
||||
|
@ -534,6 +589,11 @@ qs@~6.5.2:
|
|||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||
|
||||
readline-sync@^1.4.9:
|
||||
version "1.4.10"
|
||||
resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b"
|
||||
integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==
|
||||
|
||||
redis-commands@1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89"
|
||||
|
@ -592,6 +652,11 @@ semver@^5.6.0:
|
|||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
sprintf-js@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
|
||||
integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
||||
|
@ -617,6 +682,13 @@ string-template@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96"
|
||||
integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y=
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
|
||||
dependencies:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
tough-cookie@~2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
||||
|
|
|
@ -5,13 +5,16 @@ const compress = require("koa-compress")
|
|||
const zlib = require("zlib")
|
||||
const { mainRoutes, staticRoutes } = require("./routes")
|
||||
const pkg = require("../../package.json")
|
||||
const bullboard = require("bull-board")
|
||||
const expressApp = require("express")()
|
||||
const env = require("../environment")
|
||||
|
||||
expressApp.use("/bulladmin", bullboard.router)
|
||||
if (!env.isTest()) {
|
||||
const bullboard = require("bull-board")
|
||||
const expressApp = require("express")()
|
||||
|
||||
expressApp.use("/bulladmin", bullboard.router)
|
||||
}
|
||||
|
||||
const router = new Router()
|
||||
const env = require("../environment")
|
||||
|
||||
router
|
||||
.use(
|
||||
|
|
|
@ -402,14 +402,16 @@ describe("/rows", () => {
|
|||
name: "test",
|
||||
description: "test",
|
||||
attachment: [{
|
||||
url: "/test/thing",
|
||||
key: `/assets/${config.getAppId()}/attachment/test/thing.csv`,
|
||||
}],
|
||||
tableId: table._id,
|
||||
})
|
||||
// the environment needs configured for this
|
||||
await setup.switchToSelfHosted(async () => {
|
||||
const enriched = await outputProcessing(config.getAppId(), table, [row])
|
||||
expect(enriched[0].attachment[0].url).toBe(`/app-assets/assets/${config.getAppId()}/test/thing`)
|
||||
expect(enriched[0].attachment[0].url).toBe(
|
||||
`/prod-budi-app-assets/assets/${config.getAppId()}/attachment/test/thing.csv`
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const CouchDB = require("../db")
|
||||
const emitter = require("../events/index")
|
||||
const Queue = require("bull")
|
||||
const env = require("../environment")
|
||||
const Queue = env.isTest() ? require("../utilities/queue/inMemoryQueue") : require("bull")
|
||||
const { setQueues, BullAdapter } = require("bull-board")
|
||||
const { getAutomationParams } = require("../db/utils")
|
||||
const { coerce } = require("../utilities/rowProcessor")
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
"scripts": {
|
||||
"run:docker": "node src/index.js",
|
||||
"dev:stack:init": "node ./scripts/dev/manage.js init",
|
||||
"dev:builder": "npm run dev:stack:init && nodemon src/index.js"
|
||||
"dev:builder": "npm run dev:stack:init && nodemon src/index.js",
|
||||
"test": "jest --runInBand"
|
||||
},
|
||||
"author": "Budibase",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
|
@ -50,5 +51,11 @@
|
|||
"nodemon": "^2.0.7",
|
||||
"pouchdb-adapter-memory": "^7.2.2",
|
||||
"supertest": "^6.1.3"
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "node",
|
||||
"setupFiles": [
|
||||
"./scripts/jestSetup.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
const env = require("../src/environment")
|
||||
|
||||
env._set("NODE_ENV", "jest")
|
||||
env._set("JWT_SECRET", "test-jwtsecret")
|
||||
env._set("LOG_LEVEL", "silent")
|
|
@ -1,8 +1,17 @@
|
|||
const { sendEmail } = require("../../../utilities/email")
|
||||
const CouchDB = require("../../../db")
|
||||
const authPkg = require("@budibase/auth")
|
||||
|
||||
const GLOBAL_DB = authPkg.StaticDatabases.GLOBAL.name
|
||||
|
||||
exports.sendEmail = async ctx => {
|
||||
const { groupId, email, userId, purpose } = ctx.request.body
|
||||
const response = await sendEmail(email, purpose, { groupId, userId })
|
||||
let user
|
||||
if (userId) {
|
||||
const db = new CouchDB(GLOBAL_DB)
|
||||
user = await db.get(userId)
|
||||
}
|
||||
const response = await sendEmail(email, purpose, { groupId, user })
|
||||
ctx.body = {
|
||||
...response,
|
||||
message: `Email sent to ${email}.`,
|
||||
|
|
|
@ -126,7 +126,7 @@ exports.find = async ctx => {
|
|||
|
||||
exports.invite = async ctx => {
|
||||
const { email } = ctx.request.body
|
||||
const existing = await getGlobalUserByEmail(FIRST_USER_EMAIL)
|
||||
const existing = await getGlobalUserByEmail(email)
|
||||
if (existing) {
|
||||
ctx.throw(400, "Email address already in use.")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
const setup = require("./utilities")
|
||||
|
||||
jest.mock("nodemailer")
|
||||
const sendMailMock = setup.emailMock()
|
||||
|
||||
describe("/api/admin/auth", () => {
|
||||
let request = setup.getRequest()
|
||||
let config = setup.getConfig()
|
||||
let code
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.init()
|
||||
})
|
||||
|
||||
afterAll(setup.afterAll)
|
||||
|
||||
it("should be able to generate password reset email", async () => {
|
||||
// initially configure settings
|
||||
await config.saveSmtpConfig()
|
||||
await config.saveSettingsConfig()
|
||||
await config.createUser("test@test.com")
|
||||
const res = await request
|
||||
.post(`/api/admin/auth/reset`)
|
||||
.send({
|
||||
email: "test@test.com",
|
||||
})
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body).toEqual({ message: "Please check your email for a reset link." })
|
||||
expect(sendMailMock).toHaveBeenCalled()
|
||||
const emailCall = sendMailMock.mock.calls[0][0]
|
||||
// after this URL there should be a code
|
||||
const parts = emailCall.html.split("http://localhost:10000/reset/")
|
||||
code = parts[1].split("\"")[0]
|
||||
expect(code).toBeDefined()
|
||||
})
|
||||
|
||||
it("should allow resetting user password with code", async () => {
|
||||
const res = await request
|
||||
.post(`/api/admin/auth/reset/update`)
|
||||
.send({
|
||||
password: "newpassword",
|
||||
resetCode: code,
|
||||
})
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body).toEqual({ message: "password reset successfully." })
|
||||
})
|
||||
})
|
|
@ -2,13 +2,8 @@ const setup = require("./utilities")
|
|||
const { EmailTemplatePurpose } = require("../../../constants")
|
||||
|
||||
// mock the email system
|
||||
const sendMailMock = jest.fn()
|
||||
jest.mock("nodemailer")
|
||||
const nodemailer = require("nodemailer")
|
||||
nodemailer.createTransport.mockReturnValue({
|
||||
sendMail: sendMailMock,
|
||||
verify: jest.fn()
|
||||
})
|
||||
const sendMailMock = setup.emailMock()
|
||||
|
||||
describe("/api/admin/email", () => {
|
||||
let request = setup.getRequest()
|
||||
|
|
|
@ -16,11 +16,13 @@ describe("/api/admin/email", () => {
|
|||
async function sendRealEmail(purpose) {
|
||||
await config.saveEtherealSmtpConfig()
|
||||
await config.saveSettingsConfig()
|
||||
const user = await config.getUser("test@test.com")
|
||||
const res = await request
|
||||
.post(`/api/admin/email/send`)
|
||||
.send({
|
||||
email: "test@test.com",
|
||||
purpose,
|
||||
userId: user._id,
|
||||
})
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
|
@ -55,6 +57,6 @@ describe("/api/admin/email", () => {
|
|||
})
|
||||
|
||||
it("should be able to send a password recovery email", async () => {
|
||||
const res = await sendRealEmail(EmailTemplatePurpose.PASSWORD_RECOVERY)
|
||||
await sendRealEmail(EmailTemplatePurpose.PASSWORD_RECOVERY)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,52 @@
|
|||
const setup = require("./utilities")
|
||||
|
||||
jest.mock("nodemailer")
|
||||
const sendMailMock = setup.emailMock()
|
||||
|
||||
describe("/api/admin/users", () => {
|
||||
let request = setup.getRequest()
|
||||
let config = setup.getConfig()
|
||||
let code
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.init()
|
||||
})
|
||||
|
||||
afterAll(setup.afterAll)
|
||||
|
||||
it("should be able to generate an invitation", async () => {
|
||||
// initially configure settings
|
||||
await config.saveSmtpConfig()
|
||||
await config.saveSettingsConfig()
|
||||
const res = await request
|
||||
.post(`/api/admin/users/invite`)
|
||||
.send({
|
||||
email: "invite@test.com",
|
||||
})
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body).toEqual({ message: "Invitation has been sent." })
|
||||
expect(sendMailMock).toHaveBeenCalled()
|
||||
const emailCall = sendMailMock.mock.calls[0][0]
|
||||
// after this URL there should be a code
|
||||
const parts = emailCall.html.split("http://localhost:10000/invite/")
|
||||
code = parts[1].split("\"")[0]
|
||||
expect(code).toBeDefined()
|
||||
})
|
||||
|
||||
it("should be able to create new user from invite", async () => {
|
||||
const res = await request
|
||||
.post(`/api/admin/users/invite/accept`)
|
||||
.send({
|
||||
password: "newpassword",
|
||||
inviteCode: code,
|
||||
})
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body._id).toBeDefined()
|
||||
const user = await config.getUser("invite@test.com")
|
||||
expect(user).toBeDefined()
|
||||
expect(user._id).toEqual(res.body._id)
|
||||
})
|
||||
})
|
|
@ -4,6 +4,7 @@ const supertest = require("supertest")
|
|||
const { jwt } = require("@budibase/auth").auth
|
||||
const { Cookies } = require("@budibase/auth").constants
|
||||
const { Configs, LOGO_URL } = require("../../../../constants")
|
||||
const { getGlobalUserByEmail } = require("@budibase/auth").utils
|
||||
|
||||
class TestConfiguration {
|
||||
constructor(openServer = true) {
|
||||
|
@ -53,6 +54,12 @@ class TestConfiguration {
|
|||
)
|
||||
}
|
||||
|
||||
async end() {
|
||||
if (this.server) {
|
||||
await this.server.close()
|
||||
}
|
||||
}
|
||||
|
||||
defaultHeaders() {
|
||||
const user = {
|
||||
_id: "us_uuid1",
|
||||
|
@ -65,6 +72,25 @@ class TestConfiguration {
|
|||
}
|
||||
}
|
||||
|
||||
async getUser(email) {
|
||||
return getGlobalUserByEmail(email)
|
||||
}
|
||||
|
||||
async createUser(email = "test@test.com", password = "test") {
|
||||
const user = await this.getUser(email)
|
||||
if (user) {
|
||||
return user
|
||||
}
|
||||
await this._req(
|
||||
{
|
||||
email,
|
||||
password,
|
||||
},
|
||||
null,
|
||||
controllers.users.save
|
||||
)
|
||||
}
|
||||
|
||||
async deleteConfig(type) {
|
||||
try {
|
||||
const cfg = await this._req(
|
||||
|
|
|
@ -7,9 +7,9 @@ exports.beforeAll = () => {
|
|||
request = config.getRequest()
|
||||
}
|
||||
|
||||
exports.afterAll = () => {
|
||||
exports.afterAll = async () => {
|
||||
if (config) {
|
||||
config.end()
|
||||
await config.end()
|
||||
}
|
||||
request = null
|
||||
config = null
|
||||
|
@ -28,3 +28,14 @@ exports.getConfig = () => {
|
|||
}
|
||||
return config
|
||||
}
|
||||
|
||||
exports.emailMock = () => {
|
||||
// mock the email system
|
||||
const sendMailMock = jest.fn()
|
||||
const nodemailer = require("nodemailer")
|
||||
nodemailer.createTransport.mockReturnValue({
|
||||
sendMail: sendMailMock,
|
||||
verify: jest.fn()
|
||||
})
|
||||
return sendMailMock
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ function isTest() {
|
|||
}
|
||||
|
||||
let LOADED = false
|
||||
if (!LOADED && isDev()) {
|
||||
if (!LOADED && isDev() && !isTest()) {
|
||||
require("dotenv").config()
|
||||
LOADED = true
|
||||
}
|
||||
|
|
|
@ -12,10 +12,6 @@ const api = require("./api")
|
|||
|
||||
const app = new Koa()
|
||||
|
||||
if (!env.SELF_HOSTED) {
|
||||
throw "Currently this service only supports use in self hosting"
|
||||
}
|
||||
|
||||
// set up top level koa middleware
|
||||
app.use(koaBody({ multipart: true }))
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ exports.getSettingsTemplateContext = async (purpose, code = null) => {
|
|||
case EmailTemplatePurpose.INVITATION:
|
||||
context[TemplateBindings.INVITE_CODE] = code
|
||||
context[TemplateBindings.REGISTRATION_URL] = checkSlashesInUrl(
|
||||
`${URL}/registration/${code}`
|
||||
`${URL}/invite/${code}`
|
||||
)
|
||||
break
|
||||
}
|
||||
|
|
|
@ -287,7 +287,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/auth@0.0.1":
|
||||
"@budibase/auth@^0.18.6":
|
||||
version "0.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.18.6.tgz#d893005962afd9425f10e2ac8d1d495047d0d44e"
|
||||
integrity sha512-pdyqR8G240lToMe2OZNpw2YzuRwOlOT+cAfVHPMBxJJKF0VvZ0K500NoSUINEQPr4IfWpPSu6CQhq+ROf4pMXA==
|
||||
|
@ -2505,6 +2505,20 @@ fb-watchman@^2.0.0:
|
|||
dependencies:
|
||||
bser "2.1.1"
|
||||
|
||||
fengari-interop@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/fengari-interop/-/fengari-interop-0.1.2.tgz#f7731dcdd2ff4449073fb7ac3c451a8841ce1e87"
|
||||
integrity sha512-8iTvaByZVoi+lQJhHH9vC+c/Yaok9CwOqNQZN6JrVpjmWwW4dDkeblBXhnHC+BoI6eF4Cy5NKW3z6ICEjvgywQ==
|
||||
|
||||
fengari@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/fengari/-/fengari-0.1.4.tgz#72416693cd9e43bd7d809d7829ddc0578b78b0bb"
|
||||
integrity sha512-6ujqUuiIYmcgkGz8MGAdERU57EIluGGPSUgGPTsco657EHa+srq0S3/YUl/r9kx1+D+d4rGfYObd+m8K22gB1g==
|
||||
dependencies:
|
||||
readline-sync "^1.4.9"
|
||||
sprintf-js "^1.1.1"
|
||||
tmp "^0.0.33"
|
||||
|
||||
fetch-cookie@0.10.1:
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-0.10.1.tgz#5ea88f3d36950543c87997c27ae2aeafb4b5c4d4"
|
||||
|
@ -3130,6 +3144,17 @@ inline-process-browser@^1.0.0:
|
|||
falafel "^1.0.1"
|
||||
through2 "^0.6.5"
|
||||
|
||||
ioredis-mock@^5.5.5:
|
||||
version "5.5.5"
|
||||
resolved "https://registry.yarnpkg.com/ioredis-mock/-/ioredis-mock-5.5.5.tgz#dec9fedd238c6ab9f56c026fc366533144f8a256"
|
||||
integrity sha512-7SxCAwNtDLC8IFDptqIhOC7ajp3fciVtCrXOEOkpyjPboAGRQkJbnpNPy1NYORoWi+0/iOtUPUQckSKtSQj4DA==
|
||||
dependencies:
|
||||
fengari "^0.1.4"
|
||||
fengari-interop "^0.1.2"
|
||||
lodash "^4.17.21"
|
||||
minimatch "^3.0.4"
|
||||
standard-as-callback "^2.1.0"
|
||||
|
||||
ioredis@^4.27.1:
|
||||
version "4.27.1"
|
||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.27.1.tgz#4ef947b455a1b995baa4b0d7e2c4e4f75f746421"
|
||||
|
@ -3146,6 +3171,22 @@ ioredis@^4.27.1:
|
|||
redis-parser "^3.0.0"
|
||||
standard-as-callback "^2.1.0"
|
||||
|
||||
ioredis@^4.27.2:
|
||||
version "4.27.2"
|
||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.27.2.tgz#6a79bca05164482da796f8fa010bccefd3bf4811"
|
||||
integrity sha512-7OpYymIthonkC2Jne5uGWXswdhlua1S1rWGAERaotn0hGJWTSURvxdHA9G6wNbT/qKCloCja/FHsfKXW8lpTmg==
|
||||
dependencies:
|
||||
cluster-key-slot "^1.1.0"
|
||||
debug "^4.3.1"
|
||||
denque "^1.1.0"
|
||||
lodash.defaults "^4.2.0"
|
||||
lodash.flatten "^4.4.0"
|
||||
p-map "^2.1.0"
|
||||
redis-commands "1.7.0"
|
||||
redis-errors "^1.2.0"
|
||||
redis-parser "^3.0.0"
|
||||
standard-as-callback "^2.1.0"
|
||||
|
||||
is-accessor-descriptor@^0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
|
||||
|
@ -4403,7 +4444,7 @@ lodash.templatesettings@^4.0.0:
|
|||
dependencies:
|
||||
lodash._reinterpolate "^3.0.0"
|
||||
|
||||
lodash@^4.14.0, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.7.0:
|
||||
lodash@^4.14.0, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
@ -4894,6 +4935,11 @@ optionator@^0.8.1:
|
|||
type-check "~0.3.2"
|
||||
word-wrap "~1.2.3"
|
||||
|
||||
os-tmpdir@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||
|
||||
p-cancelable@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
|
||||
|
@ -5521,6 +5567,11 @@ readdirp@~3.5.0:
|
|||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
readline-sync@^1.4.9:
|
||||
version "1.4.10"
|
||||
resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b"
|
||||
integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==
|
||||
|
||||
recast@^0.10.1:
|
||||
version "0.10.43"
|
||||
resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.43.tgz#b95d50f6d60761a5f6252e15d80678168491ce7f"
|
||||
|
@ -6045,6 +6096,11 @@ split2@^3.1.1:
|
|||
dependencies:
|
||||
readable-stream "^3.0.0"
|
||||
|
||||
sprintf-js@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
|
||||
integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
|
@ -6327,6 +6383,13 @@ tiny-queue@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046"
|
||||
integrity sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY=
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
|
||||
dependencies:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
tmpl@1.0.x:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
|
||||
|
|
Loading…
Reference in New Issue