mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 18:18:53 +08:00
Compare commits
4 Commits
9cf7d0e5dc
...
0.27.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b59c21c14e | ||
|
|
4ed4b54a28 | ||
|
|
2c2bb7d6d3 | ||
|
|
efbd985b36 |
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "sqliteviz",
|
"name": "sqliteviz",
|
||||||
"version": "0.26.0",
|
"version": "0.27.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sqliteviz",
|
"name": "sqliteviz",
|
||||||
"version": "0.26.0",
|
"version": "0.27.1",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sqliteviz",
|
"name": "sqliteviz",
|
||||||
"version": "0.27.0",
|
"version": "0.27.1",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
:clickToClose="false"
|
:clickToClose="false"
|
||||||
:contentTransition="{ name: 'loading-dialog' }"
|
:contentTransition="{ name: 'loading-dialog' }"
|
||||||
:overlayTransition="{ name: 'loading-dialog' }"
|
:overlayTransition="{ name: 'loading-dialog' }"
|
||||||
@update:modelValue="$emit('update:modelValue', $event)"
|
@update:model-value="$emit('update:modelValue', $event)"
|
||||||
>
|
>
|
||||||
<div class="dialog-header">
|
<div class="dialog-header">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
@@ -60,12 +60,12 @@ export default {
|
|||||||
title: String,
|
title: String,
|
||||||
loading: Boolean
|
loading: Boolean
|
||||||
},
|
},
|
||||||
|
emits: ['cancel', 'action', 'update:modelValue'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: this.modelValue
|
show: this.modelValue
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['cancel', 'action', 'update:modelValue'],
|
|
||||||
watch: {
|
watch: {
|
||||||
modelValue() {
|
modelValue() {
|
||||||
this.show = this.modelValue
|
this.show = this.modelValue
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import LoadView from '@/views/LoadView'
|
|||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import database from '@/lib/database'
|
import database from '@/lib/database'
|
||||||
|
|
||||||
const routes = [
|
export const routes = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'Welcome',
|
name: 'Welcome',
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ export default {
|
|||||||
this.openSaveModal()
|
this.openSaveModal()
|
||||||
},
|
},
|
||||||
openSaveModal() {
|
openSaveModal() {
|
||||||
|
this.$modal.hide('inquiry-conflict')
|
||||||
this.errorMsg = null
|
this.errorMsg = null
|
||||||
this.name = ''
|
this.name = ''
|
||||||
this.$modal.show('save')
|
this.$modal.show('save')
|
||||||
@@ -190,8 +191,6 @@ export default {
|
|||||||
this.saveInquiry()
|
this.saveInquiry()
|
||||||
},
|
},
|
||||||
async saveInquiry() {
|
async saveInquiry() {
|
||||||
const dataSet = this.currentInquiryTab.result
|
|
||||||
const tabView = this.currentInquiryTab.view
|
|
||||||
const eventName =
|
const eventName =
|
||||||
this.currentInquiryTab.name && this.name
|
this.currentInquiryTab.name && this.name
|
||||||
? 'inquiry.saveAs'
|
? 'inquiry.saveAs'
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import sinon from 'sinon'
|
import sinon from 'sinon'
|
||||||
import { shallowMount } from '@vue/test-utils'
|
import { shallowMount, mount } from '@vue/test-utils'
|
||||||
import { createStore } from 'vuex'
|
import { createStore } from 'vuex'
|
||||||
import App from '@/App.vue'
|
import App from '@/App.vue'
|
||||||
import storedInquiries from '@/lib/storedInquiries'
|
import storedInquiries from '@/lib/storedInquiries'
|
||||||
|
import actions from '@/store/actions'
|
||||||
import mutations from '@/store/mutations'
|
import mutations from '@/store/mutations'
|
||||||
import { nextTick } from 'vue'
|
import { nextTick } from 'vue'
|
||||||
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
import { routes } from '@/router'
|
||||||
|
|
||||||
describe('App.vue', () => {
|
describe('App.vue', () => {
|
||||||
|
let clock
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
clock = sinon.useFakeTimers()
|
||||||
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
sinon.restore()
|
sinon.restore()
|
||||||
})
|
})
|
||||||
@@ -92,4 +101,134 @@ describe('App.vue', () => {
|
|||||||
{ id: 3, name: 'bar' }
|
{ id: 3, name: 'bar' }
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Closes with saving and does not change the next tab', async () => {
|
||||||
|
const inquiries = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'foo',
|
||||||
|
query: 'SELECT * FROM foo',
|
||||||
|
viewType: 'chart',
|
||||||
|
viewOptions: {},
|
||||||
|
createdAt: '2020-11-07T20:57:04.492Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'bar',
|
||||||
|
query: 'SELECT * FROM bar',
|
||||||
|
viewType: 'chart',
|
||||||
|
viewOptions: {},
|
||||||
|
createdAt: '2020-11-07T20:57:04.492Z'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
sinon.stub(storedInquiries, 'getStoredInquiries').returns(inquiries)
|
||||||
|
const tab1 = {
|
||||||
|
id: 1,
|
||||||
|
name: 'foo',
|
||||||
|
query: 'select * from foo',
|
||||||
|
viewType: 'chart',
|
||||||
|
viewOptions: {},
|
||||||
|
layout: {
|
||||||
|
sqlEditor: 'above',
|
||||||
|
table: 'bottom',
|
||||||
|
dataView: 'hidden'
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
columns: ['name', 'points'],
|
||||||
|
values: {
|
||||||
|
name: ['Gryffindor', 'Hufflepuff', 'Ravenclaw', 'Slytherin'],
|
||||||
|
points: [100, 90, 95, 80]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isSaved: false
|
||||||
|
}
|
||||||
|
const tab2 = {
|
||||||
|
id: 2,
|
||||||
|
name: 'bar',
|
||||||
|
query: 'SELECT * FROM bar',
|
||||||
|
viewType: 'chart',
|
||||||
|
viewOptions: {},
|
||||||
|
layout: {
|
||||||
|
sqlEditor: 'above',
|
||||||
|
table: 'hidden',
|
||||||
|
dataView: 'bottom'
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
columns: ['id'],
|
||||||
|
values: {
|
||||||
|
id: [1, 2, 3]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isSaved: true
|
||||||
|
}
|
||||||
|
// mock store state
|
||||||
|
const state = {
|
||||||
|
tabs: [tab1, tab2],
|
||||||
|
currentTabId: 1,
|
||||||
|
currentTab: tab1,
|
||||||
|
db: {},
|
||||||
|
inquiries
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = createStore({ state, mutations, actions })
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory(),
|
||||||
|
routes: routes
|
||||||
|
})
|
||||||
|
router.push('/workspace')
|
||||||
|
|
||||||
|
// After this line, router is ready
|
||||||
|
await router.isReady()
|
||||||
|
|
||||||
|
const wrapper = mount(App, {
|
||||||
|
attachTo: document.body,
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
'router-link': true,
|
||||||
|
teleport: true,
|
||||||
|
transition: false,
|
||||||
|
schema: true,
|
||||||
|
AppDiagnosticInfo: true,
|
||||||
|
DataView: {
|
||||||
|
template: '<div></div>',
|
||||||
|
methods: { getOptionsForSave: sinon.stub() }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: [store, router]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// click on the close icon of the first tab
|
||||||
|
const firstTabCloseIcon = wrapper.findAll('.tab')[0].find('.close-icon')
|
||||||
|
await firstTabCloseIcon.trigger('click')
|
||||||
|
|
||||||
|
// find 'Save and close' in the dialog
|
||||||
|
const closeBtn = wrapper
|
||||||
|
.findAll('.dialog-buttons-container button')
|
||||||
|
.find(button => button.text() === 'Save and close')
|
||||||
|
|
||||||
|
// click 'Save and close' in the dialog
|
||||||
|
await closeBtn.trigger('click')
|
||||||
|
|
||||||
|
await nextTick()
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
|
// check that tab is closed
|
||||||
|
expect(wrapper.findAllComponents({ name: 'Tab' })).to.have.lengthOf(1)
|
||||||
|
// check that the open tab didn't change
|
||||||
|
const firstTab = wrapper.findComponent({ name: 'Tab' })
|
||||||
|
expect(firstTab.props('tab').name).to.equal('bar')
|
||||||
|
expect(firstTab.props('tab').result).to.eql({
|
||||||
|
columns: ['id'],
|
||||||
|
values: {
|
||||||
|
id: [1, 2, 3]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect(firstTab.props('tab')).to.eql(tab2)
|
||||||
|
|
||||||
|
// check that the dialog is closed
|
||||||
|
await clock.tick(100)
|
||||||
|
await nextTick()
|
||||||
|
expect(wrapper.find('.dialog.vfm .vfm__content').exists()).to.equal(false)
|
||||||
|
wrapper.unmount()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -608,8 +608,6 @@ describe('MainMenu.vue', () => {
|
|||||||
.find(button => button.text() === 'Overwrite')
|
.find(button => button.text() === 'Overwrite')
|
||||||
.trigger('click')
|
.trigger('click')
|
||||||
|
|
||||||
await nextTick()
|
|
||||||
|
|
||||||
// check that the dialog is closed
|
// check that the dialog is closed
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
||||||
@@ -694,8 +692,6 @@ describe('MainMenu.vue', () => {
|
|||||||
.find(button => button.text() === 'Save')
|
.find(button => button.text() === 'Save')
|
||||||
.trigger('click')
|
.trigger('click')
|
||||||
|
|
||||||
await nextTick()
|
|
||||||
|
|
||||||
// check that the dialog is closed
|
// check that the dialog is closed
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
||||||
@@ -725,8 +721,6 @@ describe('MainMenu.vue', () => {
|
|||||||
.find(button => button.text() === 'Overwrite')
|
.find(button => button.text() === 'Overwrite')
|
||||||
.trigger('click')
|
.trigger('click')
|
||||||
|
|
||||||
await nextTick()
|
|
||||||
|
|
||||||
// check that the dialog is closed
|
// check that the dialog is closed
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
||||||
@@ -759,8 +753,7 @@ describe('MainMenu.vue', () => {
|
|||||||
createdAt: '2025-05-14T15:30:00Z'
|
createdAt: '2025-05-14T15:30:00Z'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
tabs: [tab],
|
tabs: [tab]
|
||||||
db: {}
|
|
||||||
}
|
}
|
||||||
const mutations = {
|
const mutations = {
|
||||||
updateTab: sinon.stub()
|
updateTab: sinon.stub()
|
||||||
@@ -795,22 +788,29 @@ describe('MainMenu.vue', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
await wrapper.find('#save-btn').trigger('click')
|
await wrapper.find('#save-btn').trigger('click')
|
||||||
|
|
||||||
// check that the conflict dialog is open
|
// check that the conflict dialog is open
|
||||||
expect(wrapper.find('.dialog.vfm').exists()).to.equal(true)
|
expect(wrapper.find('.dialog.vfm').exists()).to.equal(true)
|
||||||
expect(wrapper.find('.dialog.vfm .dialog-header').text()).to.contain(
|
expect(wrapper.find('.dialog.vfm .dialog-header').text()).to.contain(
|
||||||
'Inquiry saving conflict'
|
'Inquiry saving conflict'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await clock.tick(100)
|
||||||
|
|
||||||
// find "Save as new" in the dialog and click
|
// find "Save as new" in the dialog and click
|
||||||
|
|
||||||
await wrapper
|
await wrapper
|
||||||
.findAll('.dialog-buttons-container button')
|
.findAll('.dialog-buttons-container button')
|
||||||
.find(button => button.text() === 'Save as new')
|
.find(button => button.text() === 'Save as new')
|
||||||
.trigger('click')
|
.trigger('click')
|
||||||
|
|
||||||
await nextTick()
|
// Hiding any dialog is done with tiny animation. Give time to finish it:
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
|
// Note: don't call nextTick before clock.tick. That leads to extra trap in
|
||||||
|
// trapStack and the test fails with focus-trap error in afterEach hook
|
||||||
|
// when unmount the component
|
||||||
|
|
||||||
|
// check that only one dialog open
|
||||||
|
expect(wrapper.findAll('.dialog.vfm').length).to.equal(1)
|
||||||
// enter the new name
|
// enter the new name
|
||||||
await wrapper.find('.dialog-body input').setValue('foo_new')
|
await wrapper.find('.dialog-body input').setValue('foo_new')
|
||||||
|
|
||||||
@@ -820,8 +820,6 @@ describe('MainMenu.vue', () => {
|
|||||||
.find(button => button.text() === 'Save')
|
.find(button => button.text() === 'Save')
|
||||||
.trigger('click')
|
.trigger('click')
|
||||||
|
|
||||||
await nextTick()
|
|
||||||
|
|
||||||
// check that the dialog is closed
|
// check that the dialog is closed
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
||||||
@@ -1062,8 +1060,6 @@ describe('MainMenu.vue', () => {
|
|||||||
.find(button => button.text() === 'Save')
|
.find(button => button.text() === 'Save')
|
||||||
.trigger('click')
|
.trigger('click')
|
||||||
|
|
||||||
await nextTick()
|
|
||||||
|
|
||||||
// check that the dialog is closed
|
// check that the dialog is closed
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
||||||
@@ -1172,8 +1168,6 @@ describe('MainMenu.vue', () => {
|
|||||||
.find(button => button.text() === 'Save')
|
.find(button => button.text() === 'Save')
|
||||||
.trigger('click')
|
.trigger('click')
|
||||||
|
|
||||||
await nextTick()
|
|
||||||
|
|
||||||
// check that the dialog is closed
|
// check that the dialog is closed
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
||||||
@@ -1351,8 +1345,6 @@ describe('MainMenu.vue', () => {
|
|||||||
.find(button => button.text() === 'Save')
|
.find(button => button.text() === 'Save')
|
||||||
.trigger('click')
|
.trigger('click')
|
||||||
|
|
||||||
await nextTick()
|
|
||||||
|
|
||||||
// check that the dialog is closed
|
// check that the dialog is closed
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
expect(wrapper.find('.dialog.vfm').exists()).to.equal(false)
|
||||||
|
|||||||
@@ -228,7 +228,6 @@ describe('DataView.vue', () => {
|
|||||||
// Wait untill prepareCopy is finished
|
// Wait untill prepareCopy is finished
|
||||||
await wrapper.vm.$refs.viewComponent.prepareCopy.returnValues[0]
|
await wrapper.vm.$refs.viewComponent.prepareCopy.returnValues[0]
|
||||||
|
|
||||||
await nextTick()
|
|
||||||
// The dialog is not shown...
|
// The dialog is not shown...
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
expect(wrapper.find('.dialog.vfm .vfm__content').exists()).to.equal(false)
|
expect(wrapper.find('.dialog.vfm .vfm__content').exists()).to.equal(false)
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ describe('RunResult.vue', () => {
|
|||||||
|
|
||||||
// Switch to microtasks (let serialize run)
|
// Switch to microtasks (let serialize run)
|
||||||
await clock.tick(0)
|
await clock.tick(0)
|
||||||
await nextTick()
|
|
||||||
|
|
||||||
// The dialog is not shown...
|
// The dialog is not shown...
|
||||||
await clock.tick(100)
|
await clock.tick(100)
|
||||||
|
|||||||
Reference in New Issue
Block a user