mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-07 02:28:54 +08:00
add CSV support #27
This commit is contained in:
@@ -4,6 +4,7 @@ import Vuex from 'vuex'
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import DbUpload from '@/components/DbUpload.vue'
|
||||
import fu from '@/fileUtils'
|
||||
import database from '@/database.js'
|
||||
|
||||
describe('DbUploader.vue', () => {
|
||||
afterEach(() => {
|
||||
@@ -24,7 +25,10 @@ describe('DbUploader.vue', () => {
|
||||
|
||||
// mock db loading
|
||||
const schema = {}
|
||||
const $db = { loadDb: sinon.stub().resolves(schema) }
|
||||
const db = {
|
||||
loadDb: sinon.stub().resolves(schema)
|
||||
}
|
||||
database.getNewDatabase = sinon.stub().returns(db)
|
||||
|
||||
// mock router
|
||||
const $router = { push: sinon.stub() }
|
||||
@@ -33,12 +37,12 @@ describe('DbUploader.vue', () => {
|
||||
// mount the component
|
||||
const wrapper = shallowMount(DbUpload, {
|
||||
store,
|
||||
mocks: { $db, $router, $route }
|
||||
mocks: { $router, $route }
|
||||
})
|
||||
|
||||
await wrapper.find('.drop-area').trigger('click')
|
||||
expect($db.loadDb.calledOnceWith(file)).to.equal(true)
|
||||
await $db.loadDb.returnValues[0]
|
||||
expect(db.loadDb.calledOnceWith(file)).to.equal(true)
|
||||
await db.loadDb.returnValues[0]
|
||||
expect(mutations.saveSchema.calledOnceWith(state, schema)).to.equal(true)
|
||||
expect($router.push.calledOnceWith('/editor')).to.equal(true)
|
||||
})
|
||||
@@ -53,7 +57,10 @@ describe('DbUploader.vue', () => {
|
||||
|
||||
// mock db loading
|
||||
const schema = {}
|
||||
const $db = { loadDb: sinon.stub().resolves(schema) }
|
||||
const db = {
|
||||
loadDb: sinon.stub().resolves(schema)
|
||||
}
|
||||
database.getNewDatabase = sinon.stub().returns(db)
|
||||
|
||||
// mock router
|
||||
const $router = { push: sinon.stub() }
|
||||
@@ -62,7 +69,7 @@ describe('DbUploader.vue', () => {
|
||||
// mount the component
|
||||
const wrapper = shallowMount(DbUpload, {
|
||||
store,
|
||||
mocks: { $db, $router, $route }
|
||||
mocks: { $router, $route }
|
||||
})
|
||||
|
||||
// mock a file dropped by a user
|
||||
@@ -74,8 +81,8 @@ describe('DbUploader.vue', () => {
|
||||
})
|
||||
|
||||
await wrapper.find('.drop-area').trigger('drop', dropData)
|
||||
expect($db.loadDb.calledOnceWith(file)).to.equal(true)
|
||||
await $db.loadDb.returnValues[0]
|
||||
expect(db.loadDb.calledOnceWith(file)).to.equal(true)
|
||||
await db.loadDb.returnValues[0]
|
||||
expect(mutations.saveSchema.calledOnceWith(state, schema)).to.equal(true)
|
||||
expect($router.push.calledOnceWith('/editor')).to.equal(true)
|
||||
})
|
||||
@@ -94,7 +101,10 @@ describe('DbUploader.vue', () => {
|
||||
|
||||
// mock db loading
|
||||
const schema = {}
|
||||
const $db = { loadDb: sinon.stub().resolves(schema) }
|
||||
const db = {
|
||||
loadDb: sinon.stub().resolves(schema)
|
||||
}
|
||||
database.getNewDatabase = sinon.stub().returns(db)
|
||||
|
||||
// mock router
|
||||
const $router = { push: sinon.stub() }
|
||||
@@ -103,11 +113,11 @@ describe('DbUploader.vue', () => {
|
||||
// mount the component
|
||||
const wrapper = shallowMount(DbUpload, {
|
||||
store,
|
||||
mocks: { $db, $router, $route }
|
||||
mocks: { $router, $route }
|
||||
})
|
||||
|
||||
await wrapper.find('.drop-area').trigger('click')
|
||||
await $db.loadDb.returnValues[0]
|
||||
await db.loadDb.returnValues[0]
|
||||
expect($router.push.called).to.equal(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -184,7 +184,6 @@ describe('MainMenu.vue', () => {
|
||||
|
||||
it('Ctrl R calls currentTab.execute if running is enabled and route.path is "/editor"',
|
||||
async () => {
|
||||
console.log('ctrl r')
|
||||
const state = {
|
||||
currentTab: {
|
||||
query: 'SELECT * FROM foo',
|
||||
|
||||
@@ -4,7 +4,6 @@ import { mount, createLocalVue } from '@vue/test-utils'
|
||||
import Vuex from 'vuex'
|
||||
import Schema from '@/components/Schema.vue'
|
||||
import TableDescription from '@/components/TableDescription.vue'
|
||||
import fu from '@/fileUtils.js'
|
||||
|
||||
const localVue = createLocalVue()
|
||||
localVue.use(Vuex)
|
||||
@@ -99,75 +98,4 @@ describe('Schema.vue', () => {
|
||||
expect(tables.at(1).vm.name).to.equal('bar')
|
||||
expect(tables.at(2).vm.name).to.equal('foobar')
|
||||
})
|
||||
|
||||
it('Change DB', async () => {
|
||||
// mock store state and mutations
|
||||
const mutations = {
|
||||
saveSchema: sinon.stub()
|
||||
}
|
||||
|
||||
const state = {
|
||||
dbName: 'fooDB',
|
||||
schema: [
|
||||
{
|
||||
name: 'foo',
|
||||
columns: [
|
||||
{ name: 'foo_id', type: 'INTEGER' },
|
||||
{ name: 'foo_title', type: 'NVARCHAR(24)' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'foo_prices',
|
||||
columns: [
|
||||
{ name: 'foo_id', type: 'INTEGER' },
|
||||
{ name: 'foo_price', type: 'INTEGER' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const store = new Vuex.Store({ state, mutations })
|
||||
|
||||
// stub getFileFromUser
|
||||
const file = { file: 'hello' }
|
||||
sinon.stub(fu, 'getFileFromUser').resolves(file)
|
||||
|
||||
// mock $db.loadDb()
|
||||
const newSchema = {
|
||||
dbName: 'barDB',
|
||||
schema: [
|
||||
{
|
||||
name: 'bar',
|
||||
columns: [
|
||||
{ name: 'bar_id', type: 'INTEGER' },
|
||||
{ name: 'bar_title', type: 'NVARCHAR(24)' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'bar_prices',
|
||||
columns: [
|
||||
{ name: 'bar_id', type: 'INTEGER' },
|
||||
{ name: 'bar_price', type: 'INTEGER' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
const $db = {
|
||||
loadDb: sinon.stub().resolves(newSchema)
|
||||
}
|
||||
|
||||
// mount the component
|
||||
const wrapper = mount(Schema, { store, localVue, mocks: { $db } })
|
||||
|
||||
// trigger the event
|
||||
await wrapper.find('#db-edit').trigger('click')
|
||||
|
||||
expect(fu.getFileFromUser.calledOnceWith('.db,.sqlite,.sqlite3')).to.equal(true)
|
||||
|
||||
await fu.getFileFromUser.returnValues[0]
|
||||
expect($db.loadDb.calledOnceWith(file)).to.equal(true)
|
||||
|
||||
await $db.loadDb.returnValues[0]
|
||||
expect(mutations.saveSchema.calledOnceWith(state, newSchema)).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -145,18 +145,17 @@ describe('Tab.vue', () => {
|
||||
it('Shows .result-in-progress message when executing query', (done) => {
|
||||
// mock store state
|
||||
const state = {
|
||||
currentTabId: 1
|
||||
currentTabId: 1,
|
||||
db: {
|
||||
execute () { return new Promise(() => {}) }
|
||||
}
|
||||
}
|
||||
|
||||
const store = new Vuex.Store({ state, mutations })
|
||||
const $db = {
|
||||
execute () { return new Promise(() => {}) }
|
||||
}
|
||||
// mount the component
|
||||
const wrapper = mount(Tab, {
|
||||
store,
|
||||
stubs: ['chart'],
|
||||
mocks: { $db },
|
||||
propsData: {
|
||||
id: 1,
|
||||
initName: 'foo',
|
||||
@@ -178,18 +177,17 @@ describe('Tab.vue', () => {
|
||||
it('Shows error when executing query ends with error', async () => {
|
||||
// mock store state
|
||||
const state = {
|
||||
currentTabId: 1
|
||||
currentTabId: 1,
|
||||
db: {
|
||||
execute () { return Promise.reject(new Error('There is no table foo')) }
|
||||
}
|
||||
}
|
||||
|
||||
const store = new Vuex.Store({ state, mutations })
|
||||
const $db = {
|
||||
execute () { return Promise.reject(new Error('There is no table foo')) }
|
||||
}
|
||||
// mount the component
|
||||
const wrapper = mount(Tab, {
|
||||
store,
|
||||
stubs: ['chart'],
|
||||
mocks: { $db },
|
||||
propsData: {
|
||||
id: 1,
|
||||
initName: 'foo',
|
||||
@@ -210,7 +208,10 @@ describe('Tab.vue', () => {
|
||||
it('Passes result to sql-table component', async () => {
|
||||
// mock store state
|
||||
const state = {
|
||||
currentTabId: 1
|
||||
currentTabId: 1,
|
||||
db: {
|
||||
execute () { return Promise.resolve(result) }
|
||||
}
|
||||
}
|
||||
|
||||
const store = new Vuex.Store({ state, mutations })
|
||||
@@ -221,14 +222,11 @@ describe('Tab.vue', () => {
|
||||
[2, 'bar']
|
||||
]
|
||||
}
|
||||
const $db = {
|
||||
execute () { return Promise.resolve(result) }
|
||||
}
|
||||
|
||||
// mount the component
|
||||
const wrapper = mount(Tab, {
|
||||
store,
|
||||
stubs: ['chart'],
|
||||
mocks: { $db },
|
||||
propsData: {
|
||||
id: 1,
|
||||
initName: 'foo',
|
||||
|
||||
@@ -1,129 +1,113 @@
|
||||
import { expect } from 'chai'
|
||||
import chai from 'chai'
|
||||
import chaiAsPromised from 'chai-as-promised'
|
||||
import initSqlJs from 'sql.js'
|
||||
import db from '@/database.js'
|
||||
const config = {
|
||||
locateFile: filename => 'js/sql-wasm.wasm'
|
||||
}
|
||||
import database from '@/database.js'
|
||||
chai.use(chaiAsPromised)
|
||||
const expect = chai.expect
|
||||
chai.should()
|
||||
|
||||
const db = database.getNewDatabase()
|
||||
const getSQL = initSqlJs()
|
||||
|
||||
describe('database.js', () => {
|
||||
it('creates schema', () => {
|
||||
return initSqlJs(config)
|
||||
.then(SQL => {
|
||||
const database = new SQL.Database()
|
||||
database.run(`
|
||||
CREATE TABLE test (
|
||||
col1,
|
||||
col2 integer,
|
||||
col3 decimal(5,2),
|
||||
col4 varchar(30)
|
||||
)
|
||||
`)
|
||||
it('creates schema', async () => {
|
||||
const SQL = await getSQL
|
||||
const tempDb = new SQL.Database()
|
||||
tempDb.run(`CREATE TABLE test (
|
||||
col1,
|
||||
col2 integer,
|
||||
col3 decimal(5,2),
|
||||
col4 varchar(30)
|
||||
)`)
|
||||
|
||||
const data = database.export()
|
||||
const buffer = new Blob([data])
|
||||
return db.loadDb(buffer)
|
||||
})
|
||||
.then(({ dbName, schema }) => {
|
||||
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')
|
||||
expect(schema[0].columns[2].name).to.equal('col3')
|
||||
expect(schema[0].columns[2].type).to.equal('decimal(5, 2)')
|
||||
expect(schema[0].columns[3].name).to.equal('col4')
|
||||
expect(schema[0].columns[3].type).to.equal('varchar(30)')
|
||||
})
|
||||
const data = tempDb.export()
|
||||
const buffer = new Blob([data])
|
||||
|
||||
const { schema } = await db.loadDb(buffer)
|
||||
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')
|
||||
expect(schema[0].columns[2].name).to.equal('col3')
|
||||
expect(schema[0].columns[2].type).to.equal('decimal(5, 2)')
|
||||
expect(schema[0].columns[3].name).to.equal('col4')
|
||||
expect(schema[0].columns[3].type).to.equal('varchar(30)')
|
||||
})
|
||||
|
||||
it('creates schema with virtual table', () => {
|
||||
return initSqlJs(config)
|
||||
.then(SQL => {
|
||||
const database = new SQL.Database()
|
||||
database.run(`
|
||||
CREATE VIRTUAL TABLE test_virtual USING fts4(
|
||||
col1, col2,
|
||||
notindexed=col1, notindexed=col2,
|
||||
tokenize=unicode61 "tokenchars=.+#")
|
||||
`)
|
||||
it('creates schema with virtual table', async () => {
|
||||
const SQL = await getSQL
|
||||
const tempDb = new SQL.Database()
|
||||
tempDb.run(`
|
||||
CREATE VIRTUAL TABLE test_virtual USING fts4(
|
||||
col1, col2,
|
||||
notindexed=col1, notindexed=col2,
|
||||
tokenize=unicode61 "tokenchars=.+#")
|
||||
`)
|
||||
|
||||
const data = database.export()
|
||||
const buffer = new Blob([data])
|
||||
return db.loadDb(buffer)
|
||||
})
|
||||
.then(({ dbName, schema }) => {
|
||||
expect(schema[0].name).to.equal('test_virtual')
|
||||
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('N/A')
|
||||
})
|
||||
const data = tempDb.export()
|
||||
const buffer = new Blob([data])
|
||||
|
||||
const { schema } = await db.loadDb(buffer)
|
||||
expect(schema[0].name).to.equal('test_virtual')
|
||||
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('N/A')
|
||||
})
|
||||
|
||||
it('returns a query result', () => {
|
||||
return initSqlJs(config)
|
||||
.then(SQL => {
|
||||
const database = new SQL.Database()
|
||||
database.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');
|
||||
`)
|
||||
it('returns a 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 = database.export()
|
||||
const buffer = new Blob([data])
|
||||
return db.loadDb(buffer)
|
||||
})
|
||||
.then(({ dbName, schema }) => {
|
||||
return db.execute('SELECT * from test')
|
||||
})
|
||||
.then(result => {
|
||||
expect(result.columns).to.have.lengthOf(3)
|
||||
expect(result.columns[0]).to.equal('id')
|
||||
expect(result.columns[1]).to.equal('name')
|
||||
expect(result.columns[2]).to.equal('faculty')
|
||||
expect(result.values).to.have.lengthOf(2)
|
||||
expect(result.values[0][0]).to.equal(1)
|
||||
expect(result.values[0][1]).to.equal('Harry Potter')
|
||||
expect(result.values[0][2]).to.equal('Griffindor')
|
||||
expect(result.values[1][0]).to.equal(2)
|
||||
expect(result.values[1][1]).to.equal('Draco Malfoy')
|
||||
expect(result.values[1][2]).to.equal('Slytherin')
|
||||
})
|
||||
const data = tempDb.export()
|
||||
const buffer = new Blob([data])
|
||||
|
||||
await db.loadDb(buffer)
|
||||
const result = await db.execute('SELECT * from test')
|
||||
expect(result.columns).to.have.lengthOf(3)
|
||||
expect(result.columns[0]).to.equal('id')
|
||||
expect(result.columns[1]).to.equal('name')
|
||||
expect(result.columns[2]).to.equal('faculty')
|
||||
expect(result.values).to.have.lengthOf(2)
|
||||
expect(result.values[0][0]).to.equal(1)
|
||||
expect(result.values[0][1]).to.equal('Harry Potter')
|
||||
expect(result.values[0][2]).to.equal('Griffindor')
|
||||
expect(result.values[1][0]).to.equal(2)
|
||||
expect(result.values[1][1]).to.equal('Draco Malfoy')
|
||||
expect(result.values[1][2]).to.equal('Slytherin')
|
||||
})
|
||||
|
||||
it('returns an error', () => {
|
||||
return initSqlJs(config)
|
||||
.then(SQL => {
|
||||
const database = new SQL.Database()
|
||||
database.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');
|
||||
`)
|
||||
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 = database.export()
|
||||
const buffer = new Blob([data])
|
||||
return db.loadDb(buffer)
|
||||
})
|
||||
.then(() => {
|
||||
return db.execute('SELECT * from foo')
|
||||
})
|
||||
.catch(result => {
|
||||
expect(result).to.equal('no such table: foo')
|
||||
})
|
||||
const data = tempDb.export()
|
||||
const buffer = new Blob([data])
|
||||
await db.loadDb(buffer)
|
||||
await expect(db.execute('SELECT * from foo')).to.be.rejectedWith(/^no such table: foo$/)
|
||||
})
|
||||
})
|
||||
|
||||
17
tests/unit/dbUtils.spec.js
Normal file
17
tests/unit/dbUtils.spec.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { expect } from 'chai'
|
||||
import dbUtils from '@/dbUtils.js'
|
||||
|
||||
describe('dbUtils.js', () => {
|
||||
it('generator', () => {
|
||||
const arr = ['1', '2', '3', '4', '5']
|
||||
const size = 2
|
||||
const chunks = dbUtils.generateChunks(arr, size)
|
||||
const output = []
|
||||
for (const chunk of chunks) {
|
||||
output.push(chunk)
|
||||
}
|
||||
expect(output[0]).to.eql(['1', '2'])
|
||||
expect(output[1]).to.eql(['3', '4'])
|
||||
expect(output[2]).to.eql(['5'])
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user