1
0
mirror of https://github.com/lana-k/sqliteviz.git synced 2025-12-06 10:08:52 +08:00
Files
sqliteviz/tests/lib/database/database.spec.js
twoxfh 53b2d8372f Updating how database object information is getting retrieved (#79)
* Updating how database object information is getting retrieved

I updated the SQLite query for gathering database objects to make use of the JSON1 extension so you can grab tables and views name, their associated columns with types and set it to the schema. This removes the need to work with DDL's. Hints for Tables and Views works since my approach is they are both database objects.
2021-08-18 20:22:30 +02:00

250 lines
7.2 KiB
JavaScript

import chai from 'chai'
import sinon from 'sinon'
import chaiAsPromised from 'chai-as-promised'
import initSqlJs from 'sql.js'
import database from '@/lib/database'
import fu from '@/lib/utils/fileIo'
chai.use(chaiAsPromised)
const expect = chai.expect
chai.should()
const getSQL = initSqlJs()
let db
describe('database.js', () => {
beforeEach(() => {
db = database.getNewDatabase()
})
afterEach(() => {
db.shutDown()
sinon.restore()
})
it('creates schema', async () => {
const SQL = await getSQL
const tempDb = new SQL.Database()
tempDb.run('CREATE TABLE test (col1, col2 integer)')
const data = tempDb.export()
const buffer = new Blob([data])
buffer.name = 'foo.sqlite'
sinon.spy(db, 'refreshSchema')
await db.loadDb(buffer)
await db.refreshSchema.returnValues[0]
const schema = db.schema
expect(db.dbName).to.equal('foo')
expect(schema).to.have.lengthOf(1)
expect(schema[0].name).to.equal('test')
expect(schema[0].columns[0].name).to.equal('col1')
expect(schema[0].columns[0].type).to.equal('N/A')
expect(schema[0].columns[1].name).to.equal('col2')
expect(schema[0].columns[1].type).to.equal('integer')
})
it('creates empty db with name database', async () => {
sinon.spy(db, 'refreshSchema')
await db.loadDb()
await db.refreshSchema.returnValues[0]
expect(db.dbName).to.equal('database')
})
it('loadDb throws errors', async () => {
const buffer = new Blob([])
buffer.name = 'foo.sqlite'
sinon.stub(db.pw, 'postMessage').resolves({ error: new Error('foo') })
await expect(db.loadDb(buffer)).to.be.rejectedWith('foo')
})
it('returns the last query result', async () => {
const SQL = await getSQL
const tempDb = new SQL.Database()
tempDb.run(`
CREATE TABLE test (
id integer,
name varchar(100),
faculty varchar(100)
);
INSERT INTO test (id, name, faculty)
VALUES
( 1, 'Harry Potter', 'Griffindor'),
( 2, 'Draco Malfoy', 'Slytherin');
`)
const data = tempDb.export()
const buffer = new Blob([data])
buffer.name = 'foo.sqlite'
await db.loadDb(buffer)
const result = await db.execute('SELECT * from test limit 1; SELECT * from test;')
expect(result.values).to.eql({
id: [1, 2],
name: ['Harry Potter', 'Draco Malfoy'],
faculty: ['Griffindor', 'Slytherin']
})
})
it('returns an error', async () => {
const SQL = await getSQL
const tempDb = new SQL.Database()
tempDb.run(`
CREATE TABLE test (
id integer,
name varchar(100),
faculty varchar(100)
);
INSERT INTO test (id, name, faculty)
VALUES
( 1, 'Harry Potter', 'Griffindor'),
( 2, 'Draco Malfoy', 'Slytherin');
`)
const data = tempDb.export()
const buffer = new Blob([data])
buffer.name = 'foo.sqlite'
await db.loadDb(buffer)
await expect(db.execute('SELECT * from foo')).to.be.rejectedWith(/^no such table: foo$/)
})
it('adds table from csv', async () => {
const data = {
columns: ['id', 'name', 'faculty'],
values: {
id: [1, 2],
name: ['Harry Potter', 'Draco Malfoy'],
faculty: ['Griffindor', 'Slytherin']
}
}
const progressHandler = sinon.spy()
const progressCounterId = db.createProgressCounter(progressHandler)
sinon.spy(db, 'refreshSchema')
await db.addTableFromCsv('foo', data, progressCounterId)
await db.refreshSchema.returnValues[0]
expect(db.dbName).to.equal('database')
expect(db.schema).to.have.lengthOf(1)
expect(db.schema[0].name).to.equal('foo')
expect(db.schema[0].columns).to.have.lengthOf(3)
expect(db.schema[0].columns[0]).to.eql({ name: 'id', type: 'REAL' })
expect(db.schema[0].columns[1]).to.eql({ name: 'name', type: 'TEXT' })
expect(db.schema[0].columns[2]).to.eql({ name: 'faculty', type: 'TEXT' })
const result = await db.execute('SELECT * from foo')
expect(result).to.eql(data)
expect(progressHandler.calledTwice).to.equal(true)
expect(progressHandler.firstCall.calledWith(0)).to.equal(true)
expect(progressHandler.secondCall.calledWith(100)).to.equal(true)
})
it('addTableFromCsv throws errors', async () => {
const data = {
columns: [],
values: {
id: [1, 2],
name: ['Harry Potter', 'Draco Malfoy'],
faculty: null
}
}
const progressHandler = sinon.stub()
const progressCounterId = db.createProgressCounter(progressHandler)
await expect(db.addTableFromCsv('foo', data, progressCounterId)).to.be.rejected
})
it('progressCounters', () => {
const firstHandler = sinon.stub()
const firstId = db.createProgressCounter(firstHandler)
db.worker.dispatchEvent(new MessageEvent('message', {
data: {
progress: 50,
id: firstId
}
}))
expect(firstHandler.calledOnceWith(50)).to.equal(true)
const secondHandler = sinon.stub()
const secondId = db.createProgressCounter(secondHandler)
db.worker.dispatchEvent(new MessageEvent('message', {
data: {
progress: 70,
id: secondId
}
}))
expect(firstId).to.not.equals(secondId)
expect(secondHandler.calledOnceWith(70)).to.equal(true)
db.worker.dispatchEvent(new MessageEvent('message', {
data: {
progress: 80,
id: firstId
}
}))
expect(firstHandler.calledTwice).to.equal(true)
expect(firstHandler.secondCall.calledWith(80)).to.equal(true)
db.deleteProgressCounter(firstId)
expect(db.importProgresses[firstId]).to.equal(undefined)
})
it('exports db', async () => {
sinon.stub(fu, 'exportToFile').resolves()
// create db with table foo
const stmt = `
CREATE TABLE foo(id, name);
INSERT INTO foo VALUES (1, 'Harry Potter')
`
let result = await db.execute(stmt)
// export db to a file
await db.export('fooDb.sqlite')
expect(fu.exportToFile.called).to.equal(true)
// get data from export
const data = fu.exportToFile.getCall(0).args[0]
const file = new Blob([data])
file.name = 'fooDb.sqlite'
// loadDb from exported data
const anotherDb = database.getNewDatabase()
await anotherDb.loadDb(file)
// check that new db works and has the same table and data
result = await anotherDb.execute('SELECT * from foo')
expect(result).to.eql({
columns: ['id', 'name'],
values: {
id: [1],
name: ['Harry Potter']
}
})
})
it('sanitizeTableName', () => {
let name = 'foo[]bar'
expect(db.sanitizeTableName(name)).to.equal('foo_bar')
name = '1 foo(01.05.2020)'
expect(db.sanitizeTableName(name)).to.equal('_1_foo_01_05_2020_')
})
it('validateTableName', async () => {
await db.execute('CREATE TABLE foo(id)')
await expect(db.validateTableName('foo')).to.be.rejectedWith('table "foo" already exists')
await expect(db.validateTableName('1foo'))
.to.be.rejectedWith("Table name can't start with a digit")
await expect(db.validateTableName('foo(05.08.2020)'))
.to.be.rejectedWith('Table name can contain only letters, digits and underscores')
await expect(db.validateTableName('sqlite_foo'))
.to.be.rejectedWith("Table name can't start with sqlite_")
})
})