Einkaufslisten anzeigen, Datenbankeinbindung

This commit is contained in:
Lukas Nowy
2018-10-27 01:10:46 +02:00
parent 5e3c83707f
commit 8e7d96310f
425 changed files with 77158 additions and 3 deletions

View File

@ -0,0 +1,36 @@
'use strict'
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const BluebirdPromise = require('bluebird')
const Pool = require('../')
const checkType = promise => {
expect(promise).to.be.a(BluebirdPromise)
return promise.catch(e => undefined)
}
describe('Bring your own promise', function () {
it('uses supplied promise for operations', co.wrap(function * () {
const pool = new Pool({ Promise: BluebirdPromise })
const client1 = yield checkType(pool.connect())
client1.release()
yield checkType(pool.query('SELECT NOW()'))
const client2 = yield checkType(pool.connect())
// TODO - make sure pg supports BYOP as well
client2.release()
yield checkType(pool.end())
}))
it('uses promises in errors', co.wrap(function * () {
const pool = new Pool({ Promise: BluebirdPromise, port: 48484 })
yield checkType(pool.connect())
yield checkType(pool.end())
yield checkType(pool.connect())
yield checkType(pool.query())
yield checkType(pool.end())
}))
})

View File

@ -0,0 +1,30 @@
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('Connection strings', function () {
it('pool delegates connectionString property to client', function (done) {
const connectionString = 'postgres://foo:bar@baz:1234/xur'
const pool = new Pool({
// use a fake client so we can check we're passed the connectionString
Client: function (args) {
expect(args.connectionString).to.equal(connectionString)
return {
connect: function (cb) {
cb(new Error('testing'))
},
on: function () { }
}
},
connectionString: connectionString
})
pool.connect(function (err, client) {
expect(err).to.not.be(undefined)
done()
})
})
})

View File

@ -0,0 +1,107 @@
'use strict'
const net = require('net')
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const before = require('mocha').before
const after = require('mocha').after
const Pool = require('../')
describe('connection timeout', () => {
before((done) => {
this.server = net.createServer((socket) => {
})
this.server.listen(() => {
this.port = this.server.address().port
done()
})
})
after((done) => {
this.server.close(done)
})
it('should callback with an error if timeout is passed', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port })
pool.connect((err, client, release) => {
expect(err).to.be.an(Error)
expect(err.message).to.contain('timeout')
expect(client).to.equal(undefined)
expect(pool.idleCount).to.equal(0)
done()
})
})
it('should reject promise with an error if timeout is passed', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port })
pool.connect().catch(err => {
expect(err).to.be.an(Error)
expect(err.message).to.contain('timeout')
expect(pool.idleCount).to.equal(0)
done()
})
})
it('should handle multiple timeouts', co.wrap(function * () {
const errors = []
const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port })
for (var i = 0; i < 15; i++) {
try {
yield pool.connect()
} catch (e) {
errors.push(e)
}
}
expect(errors).to.have.length(15)
}.bind(this)))
it('should timeout on checkout of used connection', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 })
pool.connect((err, client, release) => {
expect(err).to.be(undefined)
expect(client).to.not.be(undefined)
pool.connect((err, client) => {
expect(err).to.be.an(Error)
expect(client).to.be(undefined)
release()
pool.end(done)
})
})
})
it('should timeout on query if all clients are busy', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 })
pool.connect((err, client, release) => {
expect(err).to.be(undefined)
expect(client).to.not.be(undefined)
pool.query('select now()', (err, result) => {
expect(err).to.be.an(Error)
expect(result).to.be(undefined)
release()
pool.end(done)
})
})
})
it('should recover from timeout errors', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 })
pool.connect((err, client, release) => {
expect(err).to.be(undefined)
expect(client).to.not.be(undefined)
pool.query('select now()', (err, result) => {
expect(err).to.be.an(Error)
expect(result).to.be(undefined)
release()
pool.query('select $1::text as name', ['brianc'], (err, res) => {
expect(err).to.be(undefined)
expect(res.rows).to.have.length(1)
pool.end(done)
})
})
})
})
})

34
express-server/node_modules/pg-pool/test/ending.js generated vendored Normal file
View File

@ -0,0 +1,34 @@
'use strict'
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('pool ending', () => {
it('ends without being used', (done) => {
const pool = new Pool()
pool.end(done)
})
it('ends with a promise', () => {
return new Pool().end()
})
it('ends with clients', co.wrap(function * () {
const pool = new Pool()
const res = yield pool.query('SELECT $1::text as name', ['brianc'])
expect(res.rows[0].name).to.equal('brianc')
return pool.end()
}))
it('allows client to finish', co.wrap(function * () {
const pool = new Pool()
const query = pool.query('SELECT $1::text as name', ['brianc'])
yield pool.end()
const res = yield query
expect(res.rows[0].name).to.equal('brianc')
}))
})

View File

@ -0,0 +1,146 @@
'use strict'
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('pool error handling', function () {
it('Should complete these queries without dying', function (done) {
const pool = new Pool()
let errors = 0
let shouldGet = 0
function runErrorQuery () {
shouldGet++
return new Promise(function (resolve, reject) {
pool.query("SELECT 'asd'+1 ").then(function (res) {
reject(res) // this should always error
}).catch(function (err) {
errors++
resolve(err)
})
})
}
const ps = []
for (let i = 0; i < 5; i++) {
ps.push(runErrorQuery())
}
Promise.all(ps).then(function () {
expect(shouldGet).to.eql(errors)
pool.end(done)
})
})
describe('calling release more than once', () => {
it('should throw each time', co.wrap(function * () {
const pool = new Pool()
const client = yield pool.connect()
client.release()
expect(() => client.release()).to.throwError()
expect(() => client.release()).to.throwError()
return yield pool.end()
}))
})
describe('calling connect after end', () => {
it('should return an error', function * () {
const pool = new Pool()
const res = yield pool.query('SELECT $1::text as name', ['hi'])
expect(res.rows[0].name).to.equal('hi')
const wait = pool.end()
pool.query('select now()')
yield wait
expect(() => pool.query('select now()')).to.reject()
})
})
describe('using an ended pool', () => {
it('rejects all additional promises', (done) => {
const pool = new Pool()
const promises = []
pool.end()
.then(() => {
const squash = promise => promise.catch(e => 'okay!')
promises.push(squash(pool.connect()))
promises.push(squash(pool.query('SELECT NOW()')))
promises.push(squash(pool.end()))
Promise.all(promises).then(res => {
expect(res).to.eql(['okay!', 'okay!', 'okay!'])
done()
})
})
})
it('returns an error on all additional callbacks', (done) => {
const pool = new Pool()
pool.end(() => {
pool.query('SELECT *', (err) => {
expect(err).to.be.an(Error)
pool.connect((err) => {
expect(err).to.be.an(Error)
pool.end((err) => {
expect(err).to.be.an(Error)
done()
})
})
})
})
})
})
describe('error from idle client', () => {
it('removes client from pool', co.wrap(function * () {
const pool = new Pool()
const client = yield pool.connect()
expect(pool.totalCount).to.equal(1)
expect(pool.waitingCount).to.equal(0)
expect(pool.idleCount).to.equal(0)
client.release()
yield new Promise((resolve, reject) => {
process.nextTick(() => {
pool.once('error', (err) => {
expect(err.message).to.equal('expected')
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(0)
pool.end().then(resolve, reject)
})
client.emit('error', new Error('expected'))
})
})
}))
})
describe('passing a function to pool.query', () => {
it('calls back with error', (done) => {
const pool = new Pool()
console.log('passing fn to query')
pool.query((err) => {
expect(err).to.be.an(Error)
pool.end(done)
})
})
})
describe('pool with lots of errors', () => {
it('continues to work and provide new clients', co.wrap(function * () {
const pool = new Pool({ max: 1 })
const errors = []
for (var i = 0; i < 20; i++) {
try {
yield pool.query('invalid sql')
} catch (err) {
errors.push(err)
}
}
expect(errors).to.have.length(20)
expect(pool.idleCount).to.equal(0)
expect(pool.query).to.be.a(Function)
const res = yield pool.query('SELECT $1::text as name', ['brianc'])
expect(res.rows).to.have.length(1)
expect(res.rows[0].name).to.equal('brianc')
return pool.end()
}))
})
})

87
express-server/node_modules/pg-pool/test/events.js generated vendored Normal file
View File

@ -0,0 +1,87 @@
'use strict'
const expect = require('expect.js')
const EventEmitter = require('events').EventEmitter
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('events', function () {
it('emits connect before callback', function (done) {
const pool = new Pool()
let emittedClient = false
pool.on('connect', function (client) {
emittedClient = client
})
pool.connect(function (err, client, release) {
if (err) return done(err)
release()
pool.end()
expect(client).to.be(emittedClient)
done()
})
})
it('emits "connect" only with a successful connection', function (done) {
const pool = new Pool({
// This client will always fail to connect
Client: mockClient({
connect: function (cb) {
process.nextTick(() => {
cb(new Error('bad news'))
setImmediate(done)
})
}
})
})
pool.on('connect', function () {
throw new Error('should never get here')
})
return pool.connect().catch(e => expect(e.message).to.equal('bad news'))
})
it('emits acquire every time a client is acquired', function (done) {
const pool = new Pool()
let acquireCount = 0
pool.on('acquire', function (client) {
expect(client).to.be.ok()
acquireCount++
})
for (let i = 0; i < 10; i++) {
pool.connect(function (err, client, release) {
if (err) return done(err)
release()
})
pool.query('SELECT now()')
}
setTimeout(function () {
expect(acquireCount).to.be(20)
pool.end(done)
}, 100)
})
it('emits error and client if an idle client in the pool hits an error', function (done) {
const pool = new Pool()
pool.connect(function (err, client) {
expect(err).to.equal(undefined)
client.release()
setImmediate(function () {
client.emit('error', new Error('problem'))
})
pool.once('error', function (err, errClient) {
expect(err.message).to.equal('problem')
expect(errClient).to.equal(client)
done()
})
})
})
})
function mockClient (methods) {
return function () {
const client = new EventEmitter()
Object.assign(client, methods)
return client
}
}

View File

@ -0,0 +1,79 @@
'use strict'
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
const wait = time => new Promise((resolve) => setTimeout(resolve, time))
describe('idle timeout', () => {
it('should timeout and remove the client', (done) => {
const pool = new Pool({ idleTimeoutMillis: 10 })
pool.query('SELECT NOW()')
pool.on('remove', () => {
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(0)
done()
})
})
it('times out and removes clients when others are also removed', co.wrap(function * () {
const pool = new Pool({ idleTimeoutMillis: 10 })
const clientA = yield pool.connect()
const clientB = yield pool.connect()
clientA.release()
clientB.release(new Error())
const removal = new Promise((resolve) => {
pool.on('remove', () => {
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(0)
resolve()
})
})
const timeout = wait(100).then(() =>
Promise.reject(new Error('Idle timeout failed to occur')))
try {
yield Promise.race([removal, timeout])
} finally {
pool.end()
}
}))
it('can remove idle clients and recreate them', co.wrap(function * () {
const pool = new Pool({ idleTimeoutMillis: 1 })
const results = []
for (var i = 0; i < 20; i++) {
let query = pool.query('SELECT NOW()')
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(1)
results.push(yield query)
yield wait(2)
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(0)
}
expect(results).to.have.length(20)
}))
it('does not time out clients which are used', co.wrap(function * () {
const pool = new Pool({ idleTimeoutMillis: 1 })
const results = []
for (var i = 0; i < 20; i++) {
let client = yield pool.connect()
expect(pool.totalCount).to.equal(1)
expect(pool.idleCount).to.equal(0)
yield wait(10)
results.push(yield client.query('SELECT NOW()'))
client.release()
expect(pool.idleCount).to.equal(1)
expect(pool.totalCount).to.equal(1)
}
expect(results).to.have.length(20)
return pool.end()
}))
})

229
express-server/node_modules/pg-pool/test/index.js generated vendored Normal file
View File

@ -0,0 +1,229 @@
'use strict'
const expect = require('expect.js')
const _ = require('lodash')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('pool', function () {
describe('with callbacks', function () {
it('works totally unconfigured', function (done) {
const pool = new Pool()
pool.connect(function (err, client, release) {
if (err) return done(err)
client.query('SELECT NOW()', function (err, res) {
release()
if (err) return done(err)
expect(res.rows).to.have.length(1)
pool.end(done)
})
})
})
it('passes props to clients', function (done) {
const pool = new Pool({ binary: true })
pool.connect(function (err, client, release) {
release()
if (err) return done(err)
expect(client.binary).to.eql(true)
pool.end(done)
})
})
it('can run a query with a callback without parameters', function (done) {
const pool = new Pool()
pool.query('SELECT 1 as num', function (err, res) {
expect(res.rows[0]).to.eql({ num: 1 })
pool.end(function () {
done(err)
})
})
})
it('can run a query with a callback', function (done) {
const pool = new Pool()
pool.query('SELECT $1::text as name', ['brianc'], function (err, res) {
expect(res.rows[0]).to.eql({ name: 'brianc' })
pool.end(function () {
done(err)
})
})
})
it('passes connection errors to callback', function (done) {
const pool = new Pool({ port: 53922 })
pool.query('SELECT $1::text as name', ['brianc'], function (err, res) {
expect(res).to.be(undefined)
expect(err).to.be.an(Error)
// a connection error should not polute the pool with a dead client
expect(pool.totalCount).to.equal(0)
pool.end(function (err) {
done(err)
})
})
})
it('does not pass client to error callback', function (done) {
const pool = new Pool({ port: 58242 })
pool.connect(function (err, client, release) {
expect(err).to.be.an(Error)
expect(client).to.be(undefined)
expect(release).to.be.a(Function)
pool.end(done)
})
})
it('removes client if it errors in background', function (done) {
const pool = new Pool()
pool.connect(function (err, client, release) {
release()
if (err) return done(err)
client.testString = 'foo'
setTimeout(function () {
client.emit('error', new Error('on purpose'))
}, 10)
})
pool.on('error', function (err) {
expect(err.message).to.be('on purpose')
expect(err.client).to.not.be(undefined)
expect(err.client.testString).to.be('foo')
err.client.connection.stream.on('end', function () {
pool.end(done)
})
})
})
it('should not change given options', function (done) {
const options = { max: 10 }
const pool = new Pool(options)
pool.connect(function (err, client, release) {
release()
if (err) return done(err)
expect(options).to.eql({ max: 10 })
pool.end(done)
})
})
it('does not create promises when connecting', function (done) {
const pool = new Pool()
const returnValue = pool.connect(function (err, client, release) {
release()
if (err) return done(err)
pool.end(done)
})
expect(returnValue).to.be(undefined)
})
it('does not create promises when querying', function (done) {
const pool = new Pool()
const returnValue = pool.query('SELECT 1 as num', function (err) {
pool.end(function () {
done(err)
})
})
expect(returnValue).to.be(undefined)
})
it('does not create promises when ending', function (done) {
const pool = new Pool()
const returnValue = pool.end(done)
expect(returnValue).to.be(undefined)
})
it('never calls callback syncronously', function (done) {
const pool = new Pool()
pool.connect((err, client) => {
if (err) throw err
client.release()
setImmediate(() => {
let called = false
pool.connect((err, client) => {
if (err) throw err
called = true
client.release()
setImmediate(() => {
pool.end(done)
})
})
expect(called).to.equal(false)
})
})
})
})
describe('with promises', function () {
it('connects, queries, and disconnects', function () {
const pool = new Pool()
return pool.connect().then(function (client) {
return client.query('select $1::text as name', ['hi']).then(function (res) {
expect(res.rows).to.eql([{ name: 'hi' }])
client.release()
return pool.end()
})
})
})
it('executes a query directly', () => {
const pool = new Pool()
return pool
.query('SELECT $1::text as name', ['hi'])
.then(res => {
expect(res.rows).to.have.length(1)
expect(res.rows[0].name).to.equal('hi')
return pool.end()
})
})
it('properly pools clients', function () {
const pool = new Pool({ poolSize: 9 })
const promises = _.times(30, function () {
return pool.connect().then(function (client) {
return client.query('select $1::text as name', ['hi']).then(function (res) {
client.release()
return res
})
})
})
return Promise.all(promises).then(function (res) {
expect(res).to.have.length(30)
expect(pool.totalCount).to.be(9)
return pool.end()
})
})
it('supports just running queries', function () {
const pool = new Pool({ poolSize: 9 })
const text = 'select $1::text as name'
const values = ['hi']
const query = { text: text, values: values }
const promises = _.times(30, () => pool.query(query))
return Promise.all(promises).then(function (queries) {
expect(queries).to.have.length(30)
return pool.end()
})
})
it('recovers from query errors', function () {
const pool = new Pool()
const errors = []
const promises = _.times(30, () => {
return pool.query('SELECT asldkfjasldkf')
.catch(function (e) {
errors.push(e)
})
})
return Promise.all(promises).then(() => {
expect(errors).to.have.length(30)
expect(pool.totalCount).to.equal(0)
expect(pool.idleCount).to.equal(0)
return pool.query('SELECT $1::text as name', ['hi']).then(function (res) {
expect(res.rows).to.eql([{ name: 'hi' }])
return pool.end()
})
})
})
})
})

20
express-server/node_modules/pg-pool/test/logging.js generated vendored Normal file
View File

@ -0,0 +1,20 @@
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('logging', function () {
it('logs to supplied log function if given', function () {
const messages = []
const log = function (msg) {
messages.push(msg)
}
const pool = new Pool({ log: log })
return pool.query('SELECT NOW()').then(function () {
expect(messages.length).to.be.greaterThan(0)
return pool.end()
})
})
})

4
express-server/node_modules/pg-pool/test/mocha.opts generated vendored Normal file
View File

@ -0,0 +1,4 @@
--require test/setup.js
--no-exit
--bail
--timeout 10000

10
express-server/node_modules/pg-pool/test/setup.js generated vendored Normal file
View File

@ -0,0 +1,10 @@
const crash = reason => {
process.on(reason, err => {
console.error(reason, err.stack)
process.exit(-1)
})
}
crash('unhandledRejection')
crash('uncaughtError')
crash('warning')

44
express-server/node_modules/pg-pool/test/sizing.js generated vendored Normal file
View File

@ -0,0 +1,44 @@
const expect = require('expect.js')
const co = require('co')
const _ = require('lodash')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('pool size of 1', () => {
it('can create a single client and use it once', co.wrap(function * () {
const pool = new Pool({ max: 1 })
expect(pool.waitingCount).to.equal(0)
const client = yield pool.connect()
const res = yield client.query('SELECT $1::text as name', ['hi'])
expect(res.rows[0].name).to.equal('hi')
client.release()
pool.end()
}))
it('can create a single client and use it multiple times', co.wrap(function * () {
const pool = new Pool({ max: 1 })
expect(pool.waitingCount).to.equal(0)
const client = yield pool.connect()
const wait = pool.connect()
expect(pool.waitingCount).to.equal(1)
client.release()
const client2 = yield wait
expect(client).to.equal(client2)
client2.release()
return yield pool.end()
}))
it('can only send 1 query at a time', co.wrap(function * () {
const pool = new Pool({ max: 1 })
const queries = _.times(20, (i) => {
return pool.query('SELECT COUNT(*) as counts FROM pg_stat_activity')
})
const results = yield Promise.all(queries)
const counts = results.map(res => parseInt(res.rows[0].counts), 10)
expect(counts).to.eql(_.times(20, i => 1))
return yield pool.end()
}))
})

View File

@ -0,0 +1,19 @@
'use strict'
const Cursor = require('pg-cursor')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('submittle', () => {
it('is returned from the query method', false, (done) => {
const pool = new Pool()
const cursor = pool.query(new Cursor('SELECT * from generate_series(0, 1000)'))
cursor.read((err, rows) => {
expect(err).to.be(undefined)
expect(!!rows).to.be.ok()
cursor.close(done)
})
})
})

0
express-server/node_modules/pg-pool/test/timeout.js generated vendored Normal file
View File

25
express-server/node_modules/pg-pool/test/verify.js generated vendored Normal file
View File

@ -0,0 +1,25 @@
'use strict'
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('verify', () => {
it('verifies a client with a callback', false, (done) => {
const pool = new Pool({
verify: (client, cb) => {
client.release()
cb(new Error('nope'))
}
})
pool.connect((err, client) => {
expect(err).to.be.an(Error)
expect(err.message).to.be('nope')
pool.end()
done()
})
})
})