From bcaebd4840a8406b60167a60a11ed4cc3ef7cbf2 Mon Sep 17 00:00:00 2001 From: lana-k Date: Wed, 5 May 2021 21:44:44 +0200 Subject: [PATCH] Create an empty database #44 --- src/components/DbUploader/index.vue | 21 +++- src/components/svg/changeDb.vue | 2 +- src/lib/database/index.js | 19 +-- src/views/Main/Editor/Schema/index.vue | 2 +- src/views/Main/Editor/index.vue | 70 ++++++------ src/views/Welcome.vue | 4 +- .../components/DbUploader/DbUploader.spec.js | 108 +++++++++++------- tests/lib/database/database.spec.js | 6 +- 8 files changed, 130 insertions(+), 102 deletions(-) diff --git a/src/components/DbUploader/index.vue b/src/components/DbUploader/index.vue index 4889ee7..7cc1c54 100644 --- a/src/components/DbUploader/index.vue +++ b/src/components/DbUploader/index.vue @@ -1,7 +1,7 @@ diff --git a/src/lib/database/index.js b/src/lib/database/index.js index fae3c1d..a42c085 100644 --- a/src/lib/database/index.js +++ b/src/lib/database/index.js @@ -50,7 +50,7 @@ class Database { delete this.importProgresses[id] } - async createDb (name, data, progressCounterId) { + async importDb (name, data, progressCounterId) { const result = await this.pw.postMessage({ action: 'import', columns: data.columns, @@ -66,14 +66,15 @@ class Database { } async loadDb (file) { - const fileContent = await fu.readAsArrayBuffer(file) + const fileContent = file ? await fu.readAsArrayBuffer(file) : null const res = await this.pw.postMessage({ action: 'open', buffer: fileContent }) if (res.error) { throw new Error(res.error) } - return this.getSchema(file.name.replace(/\.[^.]+$/, '')) + const dbName = file ? file.name.replace(/\.[^.]+$/, '') : 'database' + return this.getSchema(dbName) } async getSchema (name) { @@ -85,12 +86,14 @@ class Database { const result = await this.execute(getSchemaSql) // Parse DDL statements to get column names and types const parsedSchema = [] - result.values.forEach(item => { - parsedSchema.push({ - name: item[0], - columns: getColumns(item[1]) + if (result && result.values) { + result.values.forEach(item => { + parsedSchema.push({ + name: item[0], + columns: getColumns(item[1]) + }) }) - }) + } // Return db name and schema return { diff --git a/src/views/Main/Editor/Schema/index.vue b/src/views/Main/Editor/Schema/index.vue index 375b2c7..a741522 100644 --- a/src/views/Main/Editor/Schema/index.vue +++ b/src/views/Main/Editor/Schema/index.vue @@ -5,7 +5,7 @@
- + {{ dbName }}
diff --git a/src/views/Main/Editor/index.vue b/src/views/Main/Editor/index.vue index 9e64cbe..f24d661 100644 --- a/src/views/Main/Editor/index.vue +++ b/src/views/Main/Editor/index.vue @@ -6,13 +6,7 @@ :after="{ size: 80, max: 100 }" > diff --git a/tests/components/DbUploader/DbUploader.spec.js b/tests/components/DbUploader/DbUploader.spec.js index b26006e..d9460a5 100644 --- a/tests/components/DbUploader/DbUploader.spec.js +++ b/tests/components/DbUploader/DbUploader.spec.js @@ -11,6 +11,7 @@ describe('DbUploader.vue', () => { let state = {} let mutations = {} let store = {} + let place beforeEach(() => { // mock store state and mutations @@ -20,10 +21,14 @@ describe('DbUploader.vue', () => { setDb: sinon.stub() } store = new Vuex.Store({ state, mutations }) + + place = document.createElement('div') + document.body.appendChild(place) }) afterEach(() => { sinon.restore() + place.remove() }) it('loads db on click and redirects to /editor', async () => { @@ -44,15 +49,22 @@ describe('DbUploader.vue', () => { // mount the component const wrapper = shallowMount(DbUploader, { + attachTo: place, store, - mocks: { $router, $route } + mocks: { $router, $route }, + propsData: { + type: 'illustrated' + } }) await wrapper.find('.drop-area').trigger('click') expect(db.loadDb.calledOnceWith(file)).to.equal(true) await db.loadDb.returnValues[0] + await wrapper.vm.animationPromise + await wrapper.vm.$nextTick() expect(mutations.saveSchema.calledOnceWith(state, schema)).to.equal(true) expect($router.push.calledOnceWith('/editor')).to.equal(true) + wrapper.destroy() }) it('loads db on drop and redirects to /editor', async () => { @@ -69,8 +81,12 @@ describe('DbUploader.vue', () => { // mount the component const wrapper = shallowMount(DbUploader, { + attachTo: place, store, - mocks: { $router, $route } + mocks: { $router, $route }, + propsData: { + type: 'illustrated' + } }) // mock a file dropped by a user @@ -84,8 +100,11 @@ describe('DbUploader.vue', () => { await wrapper.find('.drop-area').trigger('drop', dropData) expect(db.loadDb.calledOnceWith(file)).to.equal(true) await db.loadDb.returnValues[0] + await wrapper.vm.animationPromise + await wrapper.vm.$nextTick() expect(mutations.saveSchema.calledOnceWith(state, schema)).to.equal(true) expect($router.push.calledOnceWith('/editor')).to.equal(true) + wrapper.destroy() }) it("doesn't redirect if already on /editor", async () => { @@ -106,13 +125,20 @@ describe('DbUploader.vue', () => { // mount the component const wrapper = shallowMount(DbUploader, { + attachTo: place, store, - mocks: { $router, $route } + mocks: { $router, $route }, + propsData: { + type: 'illustrated' + } }) await wrapper.find('.drop-area').trigger('click') await db.loadDb.returnValues[0] + await wrapper.vm.animationPromise + await wrapper.vm.$nextTick() expect($router.push.called).to.equal(false) + wrapper.destroy() }) }) @@ -122,6 +148,7 @@ describe('DbUploader.vue import CSV', () => { let actions = {} const newTabId = 1 let store = {} + let place // mock router const $router = { } @@ -150,15 +177,24 @@ describe('DbUploader.vue import CSV', () => { $router.push = sinon.stub() + place = document.createElement('div') + document.body.appendChild(place) + // mount the component wrapper = mount(DbUploader, { + attachTo: place, store, - mocks: { $router, $route } + mocks: { $router, $route }, + propsData: { + type: 'illustrated' + } }) }) afterEach(() => { sinon.restore() + wrapper.destroy() + place.remove() }) it('shows parse dialog if gets csv file', async () => { @@ -184,6 +220,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() expect(wrapper.find('[data-modal="parse"]').exists()).to.equal(true) expect(wrapper.findComponent({ name: 'delimiter-selector' }).vm.value).to.equal('|') expect(wrapper.find('#quote-char input').element.value).to.equal('"') @@ -219,6 +256,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() parse.onCall(1).resolves({ delimiter: ',', @@ -328,6 +366,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() let resolveParsing parse.onCall(1).returns(new Promise(resolve => { @@ -395,6 +434,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() await wrapper.find('#csv-import').trigger('click') await csv.parse.returnValues[1] @@ -452,6 +492,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() await wrapper.find('#csv-import').trigger('click') await csv.parse.returnValues[1] @@ -511,6 +552,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() await wrapper.find('#csv-import').trigger('click') await csv.parse.returnValues[1] @@ -563,7 +605,7 @@ describe('DbUploader.vue import CSV', () => { let resolveImport = sinon.stub() const newDb = { - createDb: sinon.stub().resolves(new Promise(resolve => { resolveImport = resolve })), + importDb: sinon.stub().resolves(new Promise(resolve => { resolveImport = resolve })), createProgressCounter: sinon.stub().returns(1), deleteProgressCounter: sinon.stub() } @@ -573,6 +615,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() await wrapper.find('#csv-import').trigger('click') await csv.parse.returnValues[1] @@ -598,11 +641,11 @@ describe('DbUploader.vue import CSV', () => { expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(true) expect(wrapper.find('#csv-finish').isVisible()).to.equal(false) expect(wrapper.find('#csv-import').isVisible()).to.equal(true) - expect(newDb.createDb.getCall(0).args[0]).to.equal('foo') // file name + expect(newDb.importDb.getCall(0).args[0]).to.equal('foo') // file name // After resolving - loading indicator is not shown await resolveImport() - await newDb.createDb.returnValues[0] + await newDb.importDb.returnValues[0] expect( wrapper.findComponent({ name: 'logs' }).findComponent({ name: 'LoadingIndicator' }).exists() ).to.equal(false) @@ -621,7 +664,7 @@ describe('DbUploader.vue import CSV', () => { hasErrors: false, messages: [] }) - + // we need to separate calles because messages will mutate parse.onCall(1).resolves({ delimiter: '|', data: { @@ -637,7 +680,7 @@ describe('DbUploader.vue import CSV', () => { const schema = {} const newDb = { - createDb: sinon.stub().resolves(schema), + importDb: sinon.stub().resolves(schema), createProgressCounter: sinon.stub().returns(1), deleteProgressCounter: sinon.stub() } @@ -647,6 +690,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() await wrapper.find('#csv-import').trigger('click') await csv.parse.returnValues[1] @@ -681,7 +725,7 @@ describe('DbUploader.vue import CSV', () => { hasErrors: false, messages: [] }) - + // we need to separate calles because messages will mutate parse.onCall(1).resolves({ delimiter: '|', data: { @@ -696,7 +740,7 @@ describe('DbUploader.vue import CSV', () => { }) const newDb = { - createDb: sinon.stub().rejects(new Error('fail')), + importDb: sinon.stub().rejects(new Error('fail')), createProgressCounter: sinon.stub().returns(1), deleteProgressCounter: sinon.stub() } @@ -706,6 +750,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() await wrapper.find('#csv-import').trigger('click') await csv.parse.returnValues[1] @@ -729,8 +774,7 @@ describe('DbUploader.vue import CSV', () => { }) it('import final', async () => { - const parse = sinon.stub(csv, 'parse') - parse.onCall(0).resolves({ + sinon.stub(csv, 'parse').resolves({ delimiter: '|', data: { columns: ['col1', 'col2'], @@ -742,22 +786,9 @@ describe('DbUploader.vue import CSV', () => { messages: [] }) - parse.onCall(1).resolves({ - delimiter: '|', - data: { - columns: ['col1', 'col2'], - values: [ - [1, 'foo'], - [2, 'bar'] - ] - }, - hasErrors: false, - messages: [] - }) - const schema = {} const newDb = { - createDb: sinon.stub().resolves(schema), + importDb: sinon.stub().resolves(schema), createProgressCounter: sinon.stub().returns(1), deleteProgressCounter: sinon.stub() } @@ -767,6 +798,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() await wrapper.find('#csv-import').trigger('click') await csv.parse.returnValues[1] @@ -784,8 +816,7 @@ describe('DbUploader.vue import CSV', () => { }) it('import cancel', async () => { - const parse = sinon.stub(csv, 'parse') - parse.onCall(0).resolves({ + sinon.stub(csv, 'parse').resolves({ delimiter: '|', data: { columns: ['col1', 'col2'], @@ -797,22 +828,9 @@ describe('DbUploader.vue import CSV', () => { messages: [] }) - parse.onCall(1).resolves({ - delimiter: '|', - data: { - columns: ['col1', 'col2'], - values: [ - [1, 'foo'], - [2, 'bar'] - ] - }, - hasErrors: false, - messages: [] - }) - const schema = {} const newDb = { - createDb: sinon.stub().resolves(schema), + importDb: sinon.stub().resolves(schema), createProgressCounter: sinon.stub().returns(1), deleteProgressCounter: sinon.stub(), shutDown: sinon.stub() @@ -823,6 +841,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() await wrapper.find('#csv-import').trigger('click') await csv.parse.returnValues[1] @@ -856,7 +875,7 @@ describe('DbUploader.vue import CSV', () => { const schema = {} const newDb = { - createDb: sinon.stub().resolves(schema), + importDb: sinon.stub().resolves(schema), createProgressCounter: sinon.stub().returns(1), deleteProgressCounter: sinon.stub(), loadDb: sinon.stub().resolves() @@ -867,6 +886,7 @@ describe('DbUploader.vue import CSV', () => { await csv.parse.returnValues[0] await wrapper.vm.animationPromise await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() await wrapper.find('#csv-import').trigger('click') await csv.parse.returnValues[1] diff --git a/tests/lib/database/database.spec.js b/tests/lib/database/database.spec.js index 9a0f124..58fe7fd 100644 --- a/tests/lib/database/database.spec.js +++ b/tests/lib/database/database.spec.js @@ -146,7 +146,7 @@ describe('database.js', () => { } const progressHandler = sinon.spy() const progressCounterId = db.createProgressCounter(progressHandler) - const { dbName, schema } = await db.createDb('foo', data, progressCounterId) + const { dbName, schema } = await db.importDb('foo', data, progressCounterId) expect(dbName).to.equal('foo') expect(schema).to.have.lengthOf(1) expect(schema[0].name).to.equal('csv_import') @@ -164,7 +164,7 @@ describe('database.js', () => { expect(progressHandler.secondCall.calledWith(100)).to.equal(true) }) - it('createDb throws errors', async () => { + it('importDb throws errors', async () => { const data = { columns: ['id', 'name'], values: [ @@ -174,7 +174,7 @@ describe('database.js', () => { } const progressHandler = sinon.stub() const progressCounterId = db.createProgressCounter(progressHandler) - await expect(db.createDb('foo', data, progressCounterId)) + await expect(db.importDb('foo', data, progressCounterId)) .to.be.rejectedWith('column index out of range') })