first commit
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
'use strict'
|
||||
|
||||
const { expect } = require('chai')
|
||||
const HTTPStatus = require('http-status')
|
||||
|
||||
function expectStatus(err, expected) {
|
||||
const httpStatus = err.status || err.statusCode
|
||||
if (httpStatus === undefined) {
|
||||
throw err
|
||||
} else {
|
||||
expect(httpStatus).to.equal(expected)
|
||||
}
|
||||
}
|
||||
|
||||
async function expectHttpError(promise, expectedStatusCode) {
|
||||
try {
|
||||
await promise
|
||||
} catch (err) {
|
||||
const statusCode = err.status || err.statusCode
|
||||
if (statusCode === undefined) {
|
||||
throw err
|
||||
} else {
|
||||
expect(statusCode).to.equal(expectedStatusCode)
|
||||
return
|
||||
}
|
||||
}
|
||||
expect.fail('expected HTTP request to return with an error response')
|
||||
}
|
||||
|
||||
exports.expectHttpError = expectHttpError
|
||||
exports.notFound = function (err) {
|
||||
expectStatus(err, HTTPStatus.NOT_FOUND)
|
||||
}
|
||||
|
||||
exports.unprocessableEntity = function (err) {
|
||||
expectStatus(err, HTTPStatus.UNPROCESSABLE_ENTITY)
|
||||
}
|
||||
|
||||
exports.conflict = function (err) {
|
||||
expectStatus(err, HTTPStatus.CONFLICT)
|
||||
}
|
||||
|
||||
exports.unauthorized = function (err) {
|
||||
expectStatus(err, HTTPStatus.UNAUTHORIZED)
|
||||
}
|
||||
|
||||
exports.forbidden = function (err) {
|
||||
expectStatus(err, HTTPStatus.FORBIDDEN)
|
||||
}
|
||||
|
||||
exports.requestEntityTooLarge = function (err) {
|
||||
expectStatus(err, HTTPStatus.REQUEST_ENTITY_TOO_LARGE)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// @ts-check
|
||||
import config from 'config'
|
||||
import { startApp } from '../../../../../backup-deletion-app.mjs'
|
||||
|
||||
/** @type {import("http").Server} */
|
||||
let server
|
||||
|
||||
/**
|
||||
* @param {string} pathname
|
||||
* @return {string}
|
||||
*/
|
||||
function testUrl(pathname) {
|
||||
const url = new URL('http://127.0.0.1')
|
||||
const addr = server.address()
|
||||
if (addr && typeof addr === 'object') {
|
||||
url.port = addr.port.toString()
|
||||
}
|
||||
url.pathname = pathname
|
||||
return url.toString()
|
||||
}
|
||||
|
||||
const basicAuthHeader =
|
||||
'Basic ' +
|
||||
Buffer.from(`staging:${config.get('basicHttpAuth.password')}`).toString(
|
||||
'base64'
|
||||
)
|
||||
|
||||
async function listenOnRandomPort() {
|
||||
if (server) return // already running
|
||||
for (let i = 0; i < 10; i++) {
|
||||
try {
|
||||
server = await startApp(0)
|
||||
return
|
||||
} catch {}
|
||||
}
|
||||
server = await startApp(0)
|
||||
}
|
||||
|
||||
after('close server', function (done) {
|
||||
if (server) {
|
||||
server.close(done)
|
||||
} else {
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
||||
export default {
|
||||
testUrl,
|
||||
basicAuthHeader,
|
||||
listenOnRandomPort,
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// @ts-check
|
||||
import { startApp } from '../../../../../backup-verifier-app.mjs'
|
||||
|
||||
/** @type {import("http").Server} */
|
||||
let server
|
||||
|
||||
/**
|
||||
* @param {string} pathname
|
||||
* @return {string}
|
||||
*/
|
||||
function testUrl(pathname) {
|
||||
const url = new URL('http://127.0.0.1')
|
||||
const addr = server.address()
|
||||
if (addr && typeof addr === 'object') {
|
||||
url.port = addr.port.toString()
|
||||
}
|
||||
url.pathname = pathname
|
||||
return url.toString()
|
||||
}
|
||||
|
||||
async function listenOnRandomPort() {
|
||||
if (server) return // already running
|
||||
for (let i = 0; i < 10; i++) {
|
||||
try {
|
||||
server = await startApp(0)
|
||||
return
|
||||
} catch {}
|
||||
}
|
||||
server = await startApp(0, false)
|
||||
}
|
||||
|
||||
after('close server', function (done) {
|
||||
if (server) {
|
||||
server.close(done)
|
||||
} else {
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
||||
export default {
|
||||
testUrl,
|
||||
listenOnRandomPort,
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
const BPromise = require('bluebird')
|
||||
const { expect } = require('chai')
|
||||
const HTTPStatus = require('http-status')
|
||||
const assert = require('../../../../../storage/lib/assert')
|
||||
|
||||
const testServer = require('./test_server')
|
||||
|
||||
/**
|
||||
* Without a provided history id, a new one will get generated.
|
||||
* The history id could either be a mongo id, or a postgres id.
|
||||
*
|
||||
* @param {string} [existingHistoryId]
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
exports.createEmptyProject = function (existingHistoryId) {
|
||||
return BPromise.resolve(
|
||||
testServer.basicAuthClient.apis.Project.initializeProject({
|
||||
body: { projectId: existingHistoryId },
|
||||
})
|
||||
).then(response => {
|
||||
expect(response.status).to.equal(HTTPStatus.OK)
|
||||
const { projectId } = response.obj
|
||||
assert.projectId(projectId, 'bad projectId')
|
||||
return projectId
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* @file
|
||||
* Create a test server. For performance reasons, there is only one test server,
|
||||
* and it is shared between all of the tests.
|
||||
*
|
||||
* This uses the mocha's "root-level hooks" to start and clean up the server.
|
||||
*/
|
||||
|
||||
const BPromise = require('bluebird')
|
||||
const config = require('config')
|
||||
const http = require('node:http')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const Swagger = require('swagger-client')
|
||||
|
||||
const app = require('../../../../../app')
|
||||
|
||||
function testUrl(pathname, opts = {}) {
|
||||
const url = new URL('http://127.0.0.1')
|
||||
url.port = exports.server.address().port
|
||||
url.pathname = pathname
|
||||
if (opts.qs) {
|
||||
url.searchParams = new URLSearchParams(opts.qs)
|
||||
}
|
||||
return url.toString()
|
||||
}
|
||||
|
||||
exports.url = testUrl
|
||||
|
||||
function createClient(options) {
|
||||
// The Swagger client returns native Promises; we use Bluebird promises. Just
|
||||
// wrapping the client creation is enough in many (but not all) cases to
|
||||
// get Bluebird into the chain.
|
||||
return BPromise.resolve(new Swagger(testUrl('/api-docs'), options))
|
||||
}
|
||||
|
||||
function createTokenForProject(projectId, opts = {}) {
|
||||
const jwtKey = opts.jwtKey || config.get('jwtAuth.key')
|
||||
const jwtAlgorithm = config.get('jwtAuth.algorithm')
|
||||
return jwt.sign({ project_id: projectId }, jwtKey, {
|
||||
algorithm: jwtAlgorithm,
|
||||
})
|
||||
}
|
||||
|
||||
exports.createTokenForProject = createTokenForProject
|
||||
|
||||
function createClientForProject(projectId, opts = {}) {
|
||||
const token = createTokenForProject(projectId, opts)
|
||||
return createClient({ authorizations: { jwt: `Bearer ${token}` } })
|
||||
}
|
||||
|
||||
exports.createClientForProject = createClientForProject
|
||||
|
||||
function createClientForDownloadZip(projectId) {
|
||||
const token = createTokenForProject(projectId)
|
||||
return createClient({ authorizations: { token } })
|
||||
}
|
||||
|
||||
exports.createClientForDownloadZip = createClientForDownloadZip
|
||||
|
||||
function createBasicAuthClient() {
|
||||
return createClient({
|
||||
authorizations: {
|
||||
basic: {
|
||||
username: 'staging',
|
||||
password: config.get('basicHttpAuth.password'),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function createPseudoJwtBasicAuthClient() {
|
||||
// HACK: The history service will accept HTTP basic auth for any endpoint that
|
||||
// is expecting a JWT. If / when we fix that, we will need to fix this.
|
||||
const jwt =
|
||||
'Basic ' +
|
||||
Buffer.from(`staging:${config.get('basicHttpAuth.password')}`).toString(
|
||||
'base64'
|
||||
)
|
||||
return createClient({ authorizations: { jwt } })
|
||||
}
|
||||
|
||||
exports.basicAuthHeader =
|
||||
'Basic ' +
|
||||
Buffer.from(`staging:${config.get('basicHttpAuth.password')}`).toString(
|
||||
'base64'
|
||||
)
|
||||
|
||||
function createServer() {
|
||||
const server = http.createServer(app)
|
||||
return app.setup().then(() => {
|
||||
exports.server = server
|
||||
return server
|
||||
})
|
||||
}
|
||||
|
||||
function createDefaultUnauthenticatedClient() {
|
||||
return createClient().then(client => {
|
||||
exports.client = client
|
||||
})
|
||||
}
|
||||
|
||||
function createDefaultBasicAuthClient() {
|
||||
return createBasicAuthClient().then(client => {
|
||||
exports.basicAuthClient = client
|
||||
})
|
||||
}
|
||||
|
||||
function createDefaultPseudoJwtBasicAuthClient() {
|
||||
return createPseudoJwtBasicAuthClient().then(client => {
|
||||
exports.pseudoJwtBasicAuthClient = client
|
||||
})
|
||||
}
|
||||
|
||||
before(function () {
|
||||
function listenOnRandomPort(server) {
|
||||
const listen = BPromise.promisify(server.listen, { context: server })
|
||||
return listen(0).catch(err => {
|
||||
if (err.code !== 'EADDRINUSE' && err.code !== 'EACCES') throw err
|
||||
return listenOnRandomPort(server)
|
||||
})
|
||||
}
|
||||
|
||||
return createServer()
|
||||
.then(listenOnRandomPort)
|
||||
.then(createDefaultUnauthenticatedClient)
|
||||
.then(createDefaultBasicAuthClient)
|
||||
.then(createDefaultPseudoJwtBasicAuthClient)
|
||||
})
|
||||
|
||||
after(function () {
|
||||
exports.server.close()
|
||||
})
|
||||
Reference in New Issue
Block a user