Many test, many refactoring, only core, lib and runner left to test and fix
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
This commit is contained in:
parent
04747bc1c6
commit
17830d7f8d
7 changed files with 435 additions and 191 deletions
|
@ -33,6 +33,8 @@ export function request(config, path, filePath = null, redirects, fastRaw = fals
|
||||||
h = https
|
h = https
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let req = null
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (!path) {
|
if (!path) {
|
||||||
return reject(new Error('Request path was empty'))
|
return reject(new Error('Request path was empty'))
|
||||||
|
@ -46,8 +48,6 @@ export function request(config, path, filePath = null, redirects, fastRaw = fals
|
||||||
}
|
}
|
||||||
let timeout = fastRaw ? 5000 : config.timeout || 10000
|
let timeout = fastRaw ? 5000 : config.timeout || 10000
|
||||||
|
|
||||||
let req = null
|
|
||||||
|
|
||||||
let timedout = false
|
let timedout = false
|
||||||
let timer = setTimeout(function() {
|
let timer = setTimeout(function() {
|
||||||
timedout = true
|
timedout = true
|
||||||
|
@ -103,7 +103,9 @@ export function request(config, path, filePath = null, redirects, fastRaw = fals
|
||||||
|
|
||||||
req.on('error', function(err) {
|
req.on('error', function(err) {
|
||||||
if (timedout) return
|
if (timedout) return
|
||||||
reject(new Error(`Error during request ${path}: ${err.message}`))
|
let wrapped = new Error(`Error during request ${path}: ${err.message}`)
|
||||||
|
wrapped.code = err.code
|
||||||
|
reject(wrapped)
|
||||||
})
|
})
|
||||||
req.on('timeout', function(err) {
|
req.on('timeout', function(err) {
|
||||||
if (timedout) return
|
if (timedout) return
|
||||||
|
@ -112,6 +114,9 @@ export function request(config, path, filePath = null, redirects, fastRaw = fals
|
||||||
|
|
||||||
req.end()
|
req.end()
|
||||||
}).then(function(res) {
|
}).then(function(res) {
|
||||||
|
if (req) {
|
||||||
|
req.destroy()
|
||||||
|
}
|
||||||
if (!filePath && !fastRaw) {
|
if (!filePath && !fastRaw) {
|
||||||
if (typeof(res.body) === 'string') {
|
if (typeof(res.body) === 'string') {
|
||||||
try {
|
try {
|
||||||
|
|
228
core/db.mjs
228
core/db.mjs
|
@ -1,143 +1,104 @@
|
||||||
import lowdb from 'lowdb'
|
import { Low, JSONFile } from 'lowdb'
|
||||||
import FileAsync from 'lowdb/adapters/FileAsync.js'
|
import { type } from 'os'
|
||||||
|
|
||||||
let lastId = -1
|
export default function GetDB(util, log, filename = 'db.json') {
|
||||||
|
let fullpath = util.getPathFromRoot('./' + filename)
|
||||||
|
const adapter = new JSONFile(fullpath)
|
||||||
|
const db = new Low(adapter)
|
||||||
|
|
||||||
// Take from https://github.com/typicode/lodash-id/blob/master/src/index.js
|
db.id = 'id'
|
||||||
// from package lodash-id
|
|
||||||
const lodashId = {
|
db.createId = function(collection) {
|
||||||
// Empties properties
|
if (collection.length) {
|
||||||
__empty: function (doc) {
|
return (collection[collection.length - 1].id || 0) + 1
|
||||||
this.forEach(doc, function (value, key) {
|
}
|
||||||
delete doc[key]
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
db.get = function(collection, id, returnIndex = false) {
|
||||||
|
let col = db.getCollection(collection)
|
||||||
|
for (let i = col.length - 1; i >= 0; i--) {
|
||||||
|
if (col[i][db.id] === id) {
|
||||||
|
if (returnIndex) return i
|
||||||
|
return col[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
db.getCollection = function(collection) {
|
||||||
|
if (typeof(collection) === 'string') {
|
||||||
|
return db.data[collection]
|
||||||
|
}
|
||||||
|
return collection
|
||||||
|
}
|
||||||
|
|
||||||
|
db.upsert = function(collection, item) {
|
||||||
|
let col = db.getCollection(collection)
|
||||||
|
if (item[db.id]) {
|
||||||
|
let i = db.get(col, item[db.id], true)
|
||||||
|
if (i !== null) {
|
||||||
|
col[i] = item
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item[db.id] = db.createId(col)
|
||||||
|
col.push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
db.remove = function(collection, itemOrId) {
|
||||||
|
let col = db.getCollection(collection)
|
||||||
|
let id = itemOrId
|
||||||
|
if (typeof(id) === 'object') {
|
||||||
|
id = id[db.id]
|
||||||
|
}
|
||||||
|
for (let i = col.length - 1; i >= 0; i--) {
|
||||||
|
if (col[i][db.id] === id) {
|
||||||
|
col.splice(i, 1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.read()
|
||||||
|
.then(function() {
|
||||||
|
db.data ||= {
|
||||||
|
core: {
|
||||||
|
app: {
|
||||||
|
active: null,
|
||||||
|
latestInstalled: null,
|
||||||
|
latestVersion: null,
|
||||||
|
versions: [],
|
||||||
|
},
|
||||||
|
manager: {
|
||||||
|
active: null,
|
||||||
|
latestInstalled: null,
|
||||||
|
latestVersion: null,
|
||||||
|
versions: [],
|
||||||
|
},
|
||||||
|
version: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.write()
|
||||||
})
|
})
|
||||||
},
|
.then(
|
||||||
|
function() { return db },
|
||||||
// Copies properties from an object to another
|
function(err) {
|
||||||
__update: function (dest, src) {
|
let wrapped = new Error(`Error writing to ${fullpath}: ${err.code}`)
|
||||||
this.forEach(src, function (value, key) {
|
wrapped.code = err.code
|
||||||
dest[key] = value
|
throw wrapped
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// Removes an item from an array
|
|
||||||
__remove: function (array, item) {
|
|
||||||
var index = this.indexOf(array, item)
|
|
||||||
if (index !== -1) array.splice(index, 1)
|
|
||||||
},
|
|
||||||
|
|
||||||
__id: function () {
|
|
||||||
var id = this.id || 'id'
|
|
||||||
return id
|
|
||||||
},
|
|
||||||
|
|
||||||
getById: function (collection, id) {
|
|
||||||
var self = this
|
|
||||||
return this.find(collection, function (doc) {
|
|
||||||
if (self.has(doc, self.__id())) {
|
|
||||||
return doc[self.__id()] === id
|
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
},
|
|
||||||
|
|
||||||
createId: function (collection, doc) {
|
/*
|
||||||
let next = new Date().getTime()
|
const adapter = new FileAsync(util.getPathFromRoot('./' + filename))
|
||||||
if (next <= lastId) {
|
|
||||||
next = lastId + 1
|
|
||||||
}
|
|
||||||
lastId = next
|
|
||||||
return next
|
|
||||||
},
|
|
||||||
|
|
||||||
insert: function (collection, doc) {
|
|
||||||
doc[this.__id()] = doc[this.__id()] || this.createId(collection, doc)
|
|
||||||
var d = this.getById(collection, doc[this.__id()])
|
|
||||||
if (d) throw new Error('Insert failed, duplicate id')
|
|
||||||
collection.push(doc)
|
|
||||||
return doc
|
|
||||||
},
|
|
||||||
|
|
||||||
upsert: function (collection, doc) {
|
|
||||||
if (doc[this.__id()]) {
|
|
||||||
// id is set
|
|
||||||
var d = this.getById(collection, doc[this.__id()])
|
|
||||||
if (d) {
|
|
||||||
// replace properties of existing object
|
|
||||||
this.__empty(d)
|
|
||||||
this.assign(d, doc)
|
|
||||||
} else {
|
|
||||||
// push new object
|
|
||||||
collection.push(doc)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// create id and push new object
|
|
||||||
doc[this.__id()] = this.createId(collection, doc)
|
|
||||||
collection.push(doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return doc
|
|
||||||
},
|
|
||||||
|
|
||||||
updateById: function (collection, id, attrs) {
|
|
||||||
var doc = this.getById(collection, id)
|
|
||||||
|
|
||||||
if (doc) {
|
|
||||||
this.assign(doc, attrs, {id: doc.id})
|
|
||||||
}
|
|
||||||
|
|
||||||
return doc
|
|
||||||
},
|
|
||||||
|
|
||||||
updateWhere: function (collection, predicate, attrs) {
|
|
||||||
var self = this
|
|
||||||
var docs = this.filter(collection, predicate)
|
|
||||||
|
|
||||||
docs.forEach(function (doc) {
|
|
||||||
self.assign(doc, attrs, {id: doc.id})
|
|
||||||
})
|
|
||||||
|
|
||||||
return docs
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceById: function (collection, id, attrs) {
|
|
||||||
var doc = this.getById(collection, id)
|
|
||||||
|
|
||||||
if (doc) {
|
|
||||||
var docId = doc.id
|
|
||||||
this.__empty(doc)
|
|
||||||
this.assign(doc, attrs, {id: docId})
|
|
||||||
}
|
|
||||||
|
|
||||||
return doc
|
|
||||||
},
|
|
||||||
|
|
||||||
removeById: function (collection, id) {
|
|
||||||
var doc = this.getById(collection, id)
|
|
||||||
|
|
||||||
this.__remove(collection, doc)
|
|
||||||
|
|
||||||
return doc
|
|
||||||
},
|
|
||||||
|
|
||||||
removeWhere: function (collection, predicate) {
|
|
||||||
var self = this
|
|
||||||
var docs = this.filter(collection, predicate)
|
|
||||||
|
|
||||||
docs.forEach(function (doc) {
|
|
||||||
self.__remove(collection, doc)
|
|
||||||
})
|
|
||||||
|
|
||||||
return docs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function GetDB(util, log) {
|
|
||||||
const adapter = new FileAsync(util.getPathFromRoot('./db.json'))
|
|
||||||
|
|
||||||
return lowdb(adapter)
|
return lowdb(adapter)
|
||||||
.then(function(db) {
|
.then(function(db) {
|
||||||
db._.mixin(lodashId)
|
db._.mixin(lodashId)
|
||||||
db.adapterFilePath = util.getPathFromRoot('./db.json')
|
db.adapterFilePath = util.getPathFromRoot('./' + filename)
|
||||||
|
|
||||||
return db.defaults({
|
return db.defaults({
|
||||||
core: {
|
core: {
|
||||||
|
@ -154,8 +115,9 @@ export default function GetDB(util, log) {
|
||||||
})
|
})
|
||||||
.write()
|
.write()
|
||||||
.then(
|
.then(
|
||||||
function() { db },
|
function() { return db },
|
||||||
function(e) { log.error(e, 'Error writing defaults to lowdb') }
|
function() { throw new Error('Error writing defaults to lowdb'); }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,73 +1,49 @@
|
||||||
import http from 'http'
|
import http from 'http'
|
||||||
|
import https from 'https'
|
||||||
|
|
||||||
export default class HttpServer {
|
export default class HttpServer {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
this.active = {
|
this.ishttps = false
|
||||||
app: false,
|
this.active = null
|
||||||
manage: false,
|
this.sockets = new Set()
|
||||||
dev: false,
|
this.creator = http
|
||||||
|
if (config && config.https) {
|
||||||
|
this.creator = https
|
||||||
|
this.ishttps = true
|
||||||
}
|
}
|
||||||
this.sockets = {
|
|
||||||
app: new Set(),
|
|
||||||
manage: new Set(),
|
|
||||||
dev: new Set(),
|
|
||||||
}
|
|
||||||
this._context = 'dev'
|
|
||||||
}
|
|
||||||
|
|
||||||
setContext(name) {
|
|
||||||
if (name !== 'app' && name !== 'manage' && name !== 'dev') {
|
|
||||||
throw new Error('Cannot call setContext with values other than app or manage')
|
|
||||||
}
|
|
||||||
this._context = name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createServer(opts, listener) {
|
createServer(opts, listener) {
|
||||||
return this._createServer(this._context, opts, listener)
|
let server = this.creator.createServer(opts, listener)
|
||||||
}
|
|
||||||
|
|
||||||
_createServer(name, opts, listener) {
|
|
||||||
let server = http.createServer(opts, listener)
|
|
||||||
|
|
||||||
server.on('connection', (socket) => {
|
server.on('connection', (socket) => {
|
||||||
this.sockets[name].add(socket)
|
this.sockets.add(socket)
|
||||||
|
|
||||||
socket.once('close', () => {
|
socket.once('close', () => {
|
||||||
this.sockets[name].delete(socket)
|
this.sockets.delete(socket)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.active[name] = server
|
this.active = server
|
||||||
return server
|
return server
|
||||||
}
|
}
|
||||||
|
|
||||||
getServer(name) {
|
closeServer() {
|
||||||
return this.active[name]
|
if (!this.active) return Promise.resolve()
|
||||||
}
|
|
||||||
|
|
||||||
async closeServer(name) {
|
return new Promise((res, rej) => {
|
||||||
if (!this.active[name]) return false
|
this.sockets.forEach(function(socket) {
|
||||||
|
|
||||||
try {
|
|
||||||
return await new Promise((res, rej) => {
|
|
||||||
this.sockets[name].forEach(function(socket) {
|
|
||||||
socket.destroy()
|
socket.destroy()
|
||||||
})
|
})
|
||||||
this.sockets[name].clear()
|
this.sockets.clear()
|
||||||
|
|
||||||
this.active[name].close(function(err) {
|
this.active.close(err => {
|
||||||
if (err) return rej(err)
|
if (err) return rej(err)
|
||||||
|
this.active = null
|
||||||
|
|
||||||
// Waiting 1 second for it to close down
|
// Waiting 1 second for it to close down
|
||||||
setTimeout(function() { res(true) }, 1000)
|
setTimeout(function() {res() }, 1000)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} catch (err) {
|
|
||||||
throw new Error(`Error closing ${name}: ${err.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCurrentServer() {
|
|
||||||
return this.active[this._context]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bunyan-lite": "^1.0.1",
|
"bunyan-lite": "^1.0.1",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
"lowdb": "^1.0.0"
|
"lowdb": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eltro": "^1.3.0"
|
"eltro": "^1.3.0"
|
||||||
|
|
174
test/db.test.mjs
174
test/db.test.mjs
|
@ -1,2 +1,174 @@
|
||||||
import { Eltro as t, assert} from 'eltro'
|
import { Eltro as t, assert, stub } from 'eltro'
|
||||||
|
import fs from 'fs/promises'
|
||||||
import lowdb from '../core/db.mjs'
|
import lowdb from '../core/db.mjs'
|
||||||
|
import Util from '../core/util.mjs'
|
||||||
|
|
||||||
|
var util = new Util(import.meta.url)
|
||||||
|
var logger = {
|
||||||
|
info: stub(),
|
||||||
|
error: stub(),
|
||||||
|
}
|
||||||
|
|
||||||
|
t.before(function() {
|
||||||
|
return fs.rm('./test/db_test.json')
|
||||||
|
.catch(function() {})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.afterEach(function() {
|
||||||
|
return fs.rm('./test/db_test.json')
|
||||||
|
.catch(function() { })
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Should auto create file with some defaults', async function() {
|
||||||
|
await assert.isRejected(fs.stat('./test/db_test.json'))
|
||||||
|
|
||||||
|
let db = await lowdb(util, logger, 'db_test.json')
|
||||||
|
|
||||||
|
let stat = await fs.stat('./test/db_test.json')
|
||||||
|
assert.ok(stat.size > 0)
|
||||||
|
|
||||||
|
assert.ok(db.data.core)
|
||||||
|
assert.ok(db.data.core.app)
|
||||||
|
assert.ok(db.data.core.app.versions)
|
||||||
|
assert.ok(db.data.core.manager)
|
||||||
|
assert.ok(db.data.core.manager.versions)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Should support reading from db', async function() {
|
||||||
|
const assertValue = { a: 1 }
|
||||||
|
await assert.isRejected(fs.stat('./test/db_test.json'))
|
||||||
|
|
||||||
|
let db = await lowdb(util, logger, 'db_test.json')
|
||||||
|
|
||||||
|
|
||||||
|
db.data.test = assertValue
|
||||||
|
await db.write()
|
||||||
|
|
||||||
|
assert.strictEqual(db.data.test, assertValue)
|
||||||
|
|
||||||
|
let dbSecondary = await lowdb(util, logger, 'db_test.json')
|
||||||
|
assert.notStrictEqual(dbSecondary.data.test, assertValue)
|
||||||
|
assert.deepStrictEqual(dbSecondary.data.test, assertValue)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('should throw if unable to write to file', function() {
|
||||||
|
return assert.isRejected(lowdb(util, logger, '../test'))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('should have basic database-like functions defined', async function() {
|
||||||
|
const assertItem1 = { a: 1 }
|
||||||
|
const assertItem2 = { a: 2 }
|
||||||
|
const assertItem3 = { a: 3 }
|
||||||
|
let db = await lowdb(util, logger, 'db_test.json')
|
||||||
|
assert.strictEqual(db.id, 'id')
|
||||||
|
|
||||||
|
db.data.myarr = []
|
||||||
|
db.upsert(db.data.myarr, assertItem1)
|
||||||
|
db.upsert(db.data.myarr, assertItem2)
|
||||||
|
|
||||||
|
assert.strictEqual(db.data.myarr.length, 2)
|
||||||
|
assert.ok(assertItem1.id)
|
||||||
|
assert.ok(assertItem2.id)
|
||||||
|
assert.notStrictEqual(assertItem1.id, assertItem2.id)
|
||||||
|
|
||||||
|
assert.strictEqual(db.get(db.data.myarr, assertItem1.id), assertItem1)
|
||||||
|
assert.strictEqual(db.get(db.data.myarr, assertItem2.id), assertItem2)
|
||||||
|
assert.strictEqual(db.get(db.data.myarr, assertItem2.id + 1), null)
|
||||||
|
|
||||||
|
await db.write()
|
||||||
|
|
||||||
|
let dbSec = await lowdb(util, logger, 'db_test.json')
|
||||||
|
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 2)
|
||||||
|
assert.notStrictEqual(dbSec.get(dbSec.data.myarr, assertItem1.id), assertItem1)
|
||||||
|
assert.notStrictEqual(dbSec.get(dbSec.data.myarr, assertItem2.id), assertItem2)
|
||||||
|
assert.deepEqual(dbSec.get(dbSec.data.myarr, assertItem1.id), assertItem1)
|
||||||
|
assert.deepEqual(dbSec.get(dbSec.data.myarr, assertItem2.id), assertItem2)
|
||||||
|
|
||||||
|
dbSec.upsert(dbSec.data.myarr, assertItem3)
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 3)
|
||||||
|
assert.ok(assertItem3.id)
|
||||||
|
assert.strictEqual(dbSec.get(dbSec.data.myarr, assertItem3.id), assertItem3)
|
||||||
|
assert.strictEqual(assertItem2.id + 1, assertItem3.id)
|
||||||
|
|
||||||
|
const assertItem4 = { a: 4, id: assertItem2.id }
|
||||||
|
dbSec.upsert(dbSec.data.myarr, assertItem4)
|
||||||
|
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 3)
|
||||||
|
assert.notDeepEqual(dbSec.get(dbSec.data.myarr, assertItem2.id), assertItem2)
|
||||||
|
assert.deepEqual(dbSec.get(dbSec.data.myarr, assertItem2.id), assertItem4)
|
||||||
|
|
||||||
|
const assertItem5 = { a: 5, id: assertItem1.id }
|
||||||
|
dbSec.upsert(dbSec.data.myarr, assertItem5)
|
||||||
|
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 3)
|
||||||
|
assert.notDeepEqual(dbSec.get(dbSec.data.myarr, assertItem1.id), assertItem1)
|
||||||
|
assert.deepEqual(dbSec.get(dbSec.data.myarr, assertItem1.id), assertItem5)
|
||||||
|
|
||||||
|
dbSec.remove(dbSec.data.myarr, assertItem2.id)
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 2)
|
||||||
|
assert.strictEqual(dbSec.get(dbSec.data.myarr, assertItem2.id), null)
|
||||||
|
|
||||||
|
dbSec.remove(dbSec.data.myarr, assertItem1.id)
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 1)
|
||||||
|
assert.strictEqual(dbSec.get(dbSec.data.myarr, assertItem1.id), null)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('should have basic database-like functions with string-like name of collection', async function() {
|
||||||
|
const assertItem1 = { a: 1 }
|
||||||
|
const assertItem2 = { a: 2 }
|
||||||
|
const assertItem3 = { a: 3 }
|
||||||
|
let db = await lowdb(util, logger, 'db_test.json')
|
||||||
|
assert.strictEqual(db.id, 'id')
|
||||||
|
|
||||||
|
db.data.myarr = []
|
||||||
|
db.upsert('myarr', assertItem1)
|
||||||
|
db.upsert('myarr', assertItem2)
|
||||||
|
|
||||||
|
assert.strictEqual(db.data.myarr.length, 2)
|
||||||
|
assert.ok(assertItem1.id)
|
||||||
|
assert.ok(assertItem2.id)
|
||||||
|
assert.notStrictEqual(assertItem1.id, assertItem2.id)
|
||||||
|
|
||||||
|
assert.strictEqual(db.get('myarr', assertItem1.id), assertItem1)
|
||||||
|
assert.strictEqual(db.get('myarr', assertItem2.id), assertItem2)
|
||||||
|
assert.strictEqual(db.get('myarr', assertItem2.id + 1), null)
|
||||||
|
|
||||||
|
await db.write()
|
||||||
|
|
||||||
|
let dbSec = await lowdb(util, logger, 'db_test.json')
|
||||||
|
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 2)
|
||||||
|
assert.notStrictEqual(dbSec.get('myarr', assertItem1.id), assertItem1)
|
||||||
|
assert.notStrictEqual(dbSec.get('myarr', assertItem2.id), assertItem2)
|
||||||
|
assert.deepEqual(dbSec.get('myarr', assertItem1.id), assertItem1)
|
||||||
|
assert.deepEqual(dbSec.get('myarr', assertItem2.id), assertItem2)
|
||||||
|
|
||||||
|
dbSec.upsert('myarr', assertItem3)
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 3)
|
||||||
|
assert.ok(assertItem3.id)
|
||||||
|
assert.strictEqual(dbSec.get('myarr', assertItem3.id), assertItem3)
|
||||||
|
assert.strictEqual(assertItem2.id + 1, assertItem3.id)
|
||||||
|
|
||||||
|
const assertItem4 = { a: 4, id: assertItem2.id }
|
||||||
|
dbSec.upsert('myarr', assertItem4)
|
||||||
|
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 3)
|
||||||
|
assert.notDeepEqual(dbSec.get('myarr', assertItem2.id), assertItem2)
|
||||||
|
assert.deepEqual(dbSec.get('myarr', assertItem2.id), assertItem4)
|
||||||
|
|
||||||
|
const assertItem5 = { a: 5, id: assertItem1.id }
|
||||||
|
dbSec.upsert('myarr', assertItem5)
|
||||||
|
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 3)
|
||||||
|
assert.notDeepEqual(dbSec.get('myarr', assertItem1.id), assertItem1)
|
||||||
|
assert.deepEqual(dbSec.get('myarr', assertItem1.id), assertItem5)
|
||||||
|
|
||||||
|
dbSec.remove('myarr', assertItem2.id)
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 2)
|
||||||
|
assert.strictEqual(dbSec.get('myarr', assertItem2.id), null)
|
||||||
|
|
||||||
|
dbSec.remove('myarr', assertItem1.id)
|
||||||
|
assert.strictEqual(dbSec.data.myarr.length, 1)
|
||||||
|
assert.strictEqual(dbSec.get('myarr', assertItem1.id), null)
|
||||||
|
})
|
||||||
|
|
133
test/http.test.mjs
Normal file
133
test/http.test.mjs
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
import { Eltro as t, assert, stub } from 'eltro'
|
||||||
|
import http from 'http'
|
||||||
|
import https from 'https'
|
||||||
|
import { request } from '../core/client.mjs'
|
||||||
|
import HttpServer from '../core/http.mjs'
|
||||||
|
|
||||||
|
const port = 61413
|
||||||
|
let prefix = `http://localhost:${port}/`
|
||||||
|
|
||||||
|
t.describe('config', function() {
|
||||||
|
t.test('should use https if https is true', function() {
|
||||||
|
let server = new HttpServer()
|
||||||
|
assert.strictEqual(server.creator, http)
|
||||||
|
assert.strictEqual(server.ishttps, false)
|
||||||
|
server = new HttpServer({ https: true })
|
||||||
|
assert.strictEqual(server.creator, https)
|
||||||
|
assert.strictEqual(server.ishttps, true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.describe('Sockets', function() {
|
||||||
|
let http = new HttpServer()
|
||||||
|
|
||||||
|
t.after(function() {
|
||||||
|
http.closeServer().then(function() { }, function(err) {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('should keep track of sockets through its lifetime', function(cb) {
|
||||||
|
let actives = []
|
||||||
|
|
||||||
|
let server = http.createServer(function(req, res) {
|
||||||
|
req.on('error', function(err) { cb(err) })
|
||||||
|
res.on('error', function(err) { cb(err) })
|
||||||
|
res.on('finish', function() { })
|
||||||
|
|
||||||
|
actives.push(res)
|
||||||
|
})
|
||||||
|
|
||||||
|
Promise.resolve()
|
||||||
|
.then(async function() {
|
||||||
|
await new Promise(function(res, rej) {
|
||||||
|
server.listen(port, function(err) { if (err) rej(err); res()})
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.strictEqual(actives.length, 0)
|
||||||
|
assert.strictEqual(http.sockets.size, 0)
|
||||||
|
|
||||||
|
request({}, prefix).then(function() {}, cb)
|
||||||
|
request({}, prefix).then(async function() {
|
||||||
|
while (http.sockets.size > 0) {
|
||||||
|
await new Promise(function(res) { setTimeout(res, 10) })
|
||||||
|
}
|
||||||
|
assert.strictEqual(http.sockets.size, 0)
|
||||||
|
cb()
|
||||||
|
}, cb)
|
||||||
|
|
||||||
|
while (actives.length < 2) {
|
||||||
|
await new Promise(function(res) { setTimeout(res, 10) })
|
||||||
|
}
|
||||||
|
assert.strictEqual(http.sockets.size, 2)
|
||||||
|
actives[0].statusCode = 200
|
||||||
|
actives[0].end('{}')
|
||||||
|
actives[1].statusCode = 200
|
||||||
|
actives[1].end('{}')
|
||||||
|
}).catch(cb)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.describe('Close', function() {
|
||||||
|
let http = new HttpServer()
|
||||||
|
|
||||||
|
t.after(function() {
|
||||||
|
http.closeServer().then(function() { }, function(err) {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('should support forcefully closing them on server close', function(cb) {
|
||||||
|
let requestErrors = []
|
||||||
|
let serverErrors = []
|
||||||
|
|
||||||
|
let server = http.createServer(function(req, res) {
|
||||||
|
req.on('error', function(err) { serverErrors.push(err) })
|
||||||
|
res.on('error', function(err) { serverErrors.push(err) })
|
||||||
|
res.on('finish', function() { })
|
||||||
|
})
|
||||||
|
|
||||||
|
Promise.resolve()
|
||||||
|
.then(async function() {
|
||||||
|
await new Promise(function(res, rej) {
|
||||||
|
server.listen(port, function(err) { if (err) rej(err); res()})
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.strictEqual(http.sockets.size, 0)
|
||||||
|
|
||||||
|
request({}, prefix).then(
|
||||||
|
function() { cb(new Error('first succeeded')) },
|
||||||
|
function(err) { requestErrors.push(err) }
|
||||||
|
)
|
||||||
|
request({}, prefix).then(
|
||||||
|
function() { cb(new Error('first succeeded')) },
|
||||||
|
function(err) { requestErrors.push(err) }
|
||||||
|
)
|
||||||
|
|
||||||
|
while (http.sockets.size < 2) {
|
||||||
|
await new Promise(function(res) { setTimeout(res, 10) })
|
||||||
|
}
|
||||||
|
|
||||||
|
http.closeServer().then(function() { }, cb)
|
||||||
|
|
||||||
|
while (requestErrors.length < 2) {
|
||||||
|
await new Promise(function(res) { setTimeout(res, 10) })
|
||||||
|
}
|
||||||
|
assert.strictEqual(http.sockets.size, 0)
|
||||||
|
assert.strictEqual(requestErrors.length, 2)
|
||||||
|
assert.strictEqual(serverErrors.length, 2)
|
||||||
|
assert.strictEqual(serverErrors[0].code, 'ECONNRESET')
|
||||||
|
assert.strictEqual(serverErrors[1].code, 'ECONNRESET')
|
||||||
|
assert.strictEqual(requestErrors[0].code, 'ECONNRESET')
|
||||||
|
assert.strictEqual(requestErrors[1].code, 'ECONNRESET')
|
||||||
|
|
||||||
|
while (requestErrors.length < 2) {
|
||||||
|
await new Promise(function(res) { setTimeout(res, 10) })
|
||||||
|
}
|
||||||
|
while (http.active) {
|
||||||
|
await new Promise(function(res) { setTimeout(res, 10) })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function() { cb()}, cb)
|
||||||
|
})
|
||||||
|
})
|
|
@ -29,10 +29,6 @@ t.describe('#getPathFromRoot()', function() {
|
||||||
t.describe('#getUrlFromRoot()', function() {
|
t.describe('#getUrlFromRoot()', function() {
|
||||||
t.test('should return an import compatible path', async function() {
|
t.test('should return an import compatible path', async function() {
|
||||||
var util = new Util(import.meta.url)
|
var util = new Util(import.meta.url)
|
||||||
let err = await assert.isRejected(import(util.getPathFromRoot('template.mjs')))
|
|
||||||
assert.match(err.message, /ESM/i)
|
|
||||||
assert.match(err.message, /file/i)
|
|
||||||
assert.match(err.message, /data/i)
|
|
||||||
|
|
||||||
let data = await import(util.getUrlFromRoot('template.mjs'))
|
let data = await import(util.getUrlFromRoot('template.mjs'))
|
||||||
assert.deepEqual(data.default, { a: 1 })
|
assert.deepEqual(data.default, { a: 1 })
|
||||||
|
|
Loading…
Reference in a new issue