mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 18:18:53 +08:00
#115 tests
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
:disabled="value === 0"
|
:disabled="value === 0"
|
||||||
tooltip="First row"
|
tooltip="First row"
|
||||||
tooltip-position="top-left"
|
tooltip-position="top-left"
|
||||||
|
class="first"
|
||||||
@click="$emit('input', 0)"
|
@click="$emit('input', 0)"
|
||||||
>
|
>
|
||||||
<edge-arrow-icon :disabled="false" />
|
<edge-arrow-icon :disabled="false" />
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
:disabled="value === 0"
|
:disabled="value === 0"
|
||||||
tooltip="Previous row"
|
tooltip="Previous row"
|
||||||
tooltip-position="top-left"
|
tooltip-position="top-left"
|
||||||
|
class="prev"
|
||||||
@click="$emit('input', value - 1)"
|
@click="$emit('input', value - 1)"
|
||||||
>
|
>
|
||||||
<arrow-icon :disabled="false" />
|
<arrow-icon :disabled="false" />
|
||||||
@@ -20,7 +22,7 @@
|
|||||||
:disabled="value === total - 1"
|
:disabled="value === total - 1"
|
||||||
tooltip="Next row"
|
tooltip="Next row"
|
||||||
tooltip-position="top-left"
|
tooltip-position="top-left"
|
||||||
class="next-last"
|
class="next"
|
||||||
@click="$emit('input', value + 1)"
|
@click="$emit('input', value + 1)"
|
||||||
>
|
>
|
||||||
<arrow-icon :disabled="false" />
|
<arrow-icon :disabled="false" />
|
||||||
@@ -29,7 +31,7 @@
|
|||||||
:disabled="value === total - 1"
|
:disabled="value === total - 1"
|
||||||
tooltip="Last row"
|
tooltip="Last row"
|
||||||
tooltip-position="top-left"
|
tooltip-position="top-left"
|
||||||
class="next-last"
|
class="last"
|
||||||
@click="$emit('input', total - 1)"
|
@click="$emit('input', total - 1)"
|
||||||
>
|
>
|
||||||
<edge-arrow-icon :disabled="false" />
|
<edge-arrow-icon :disabled="false" />
|
||||||
@@ -60,7 +62,8 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.record-navigator .next-last {
|
.record-navigator .next,
|
||||||
|
.record-navigator .last {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
currentRowIndex () {
|
async currentRowIndex () {
|
||||||
|
await this.$nextTick()
|
||||||
if (this.selectedCellElement) {
|
if (this.selectedCellElement) {
|
||||||
const previouslySelected = this.selectedCellElement
|
const previouslySelected = this.selectedCellElement
|
||||||
this.selectCell(null)
|
this.selectCell(null)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
:key="format.value"
|
:key="format.value"
|
||||||
type="button"
|
type="button"
|
||||||
:aria-selected="currentFormat === format.value"
|
:aria-selected="currentFormat === format.value"
|
||||||
|
:class="format.value"
|
||||||
@click="currentFormat = format.value"
|
@click="currentFormat = format.value"
|
||||||
>
|
>
|
||||||
{{ format.text }}
|
{{ format.text }}
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
class="copy"
|
||||||
@click="copyToClipboard"
|
@click="copyToClipboard"
|
||||||
>
|
>
|
||||||
Copy
|
Copy
|
||||||
|
|||||||
@@ -1,159 +0,0 @@
|
|||||||
import { expect } from 'chai'
|
|
||||||
import { mount, createWrapper } from '@vue/test-utils'
|
|
||||||
import RunResult from '@/views/Main/Workspace/Tabs/Tab/RunResult'
|
|
||||||
import csv from '@/lib/csv'
|
|
||||||
import sinon from 'sinon'
|
|
||||||
|
|
||||||
describe('RunResult.vue', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
sinon.restore()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('shows alert when ClipboardItem is not supported', async () => {
|
|
||||||
const ClipboardItem = window.ClipboardItem
|
|
||||||
delete window.ClipboardItem
|
|
||||||
sinon.spy(window, 'alert')
|
|
||||||
const wrapper = mount(RunResult, {
|
|
||||||
propsData: {
|
|
||||||
tab: { id: 1 },
|
|
||||||
result: {
|
|
||||||
columns: ['id', 'name'],
|
|
||||||
values: {
|
|
||||||
id: [1],
|
|
||||||
name: ['foo']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const copyBtn = createWrapper(wrapper.findComponent({ name: 'clipboardIcon' }).vm.$parent)
|
|
||||||
await copyBtn.trigger('click')
|
|
||||||
|
|
||||||
expect(
|
|
||||||
window.alert.calledOnceWith(
|
|
||||||
"Your browser doesn't support copying into the clipboard. " +
|
|
||||||
'If you use Firefox you can enable it ' +
|
|
||||||
'by setting dom.events.asyncClipboard.clipboardItem to true.'
|
|
||||||
)
|
|
||||||
).to.equal(true)
|
|
||||||
|
|
||||||
window.ClipboardItem = ClipboardItem
|
|
||||||
})
|
|
||||||
|
|
||||||
it('copy to clipboard more than 1 sec', async () => {
|
|
||||||
sinon.stub(window.navigator.clipboard, 'writeText').resolves()
|
|
||||||
const clock = sinon.useFakeTimers()
|
|
||||||
const wrapper = mount(RunResult, {
|
|
||||||
propsData: {
|
|
||||||
tab: { id: 1 },
|
|
||||||
result: {
|
|
||||||
columns: ['id', 'name'],
|
|
||||||
values: {
|
|
||||||
id: [1],
|
|
||||||
name: ['foo']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
sinon.stub(csv, 'serialize').callsFake(() => {
|
|
||||||
clock.tick(5000)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Click copy to clipboard
|
|
||||||
const copyBtn = createWrapper(wrapper.findComponent({ name: 'clipboardIcon' }).vm.$parent)
|
|
||||||
await copyBtn.trigger('click')
|
|
||||||
|
|
||||||
// The dialog is shown...
|
|
||||||
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(true)
|
|
||||||
|
|
||||||
// ... with Building message...
|
|
||||||
expect(wrapper.find('.dialog-body').text()).to.equal('Building CSV...')
|
|
||||||
|
|
||||||
// Switch to microtasks (let serialize run)
|
|
||||||
clock.tick(0)
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
|
|
||||||
// The dialog is shown...
|
|
||||||
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(true)
|
|
||||||
|
|
||||||
// ... with Ready message...
|
|
||||||
expect(wrapper.find('.dialog-body').text()).to.equal('CSV is ready')
|
|
||||||
|
|
||||||
// Click copy
|
|
||||||
await wrapper.find('.dialog-buttons-container button.primary').trigger('click')
|
|
||||||
|
|
||||||
// The dialog is not shown...
|
|
||||||
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('copy to clipboard less than 1 sec', async () => {
|
|
||||||
sinon.stub(window.navigator.clipboard, 'writeText').resolves()
|
|
||||||
const clock = sinon.useFakeTimers()
|
|
||||||
const wrapper = mount(RunResult, {
|
|
||||||
propsData: {
|
|
||||||
tab: { id: 1 },
|
|
||||||
result: {
|
|
||||||
columns: ['id', 'name'],
|
|
||||||
values: {
|
|
||||||
id: [1],
|
|
||||||
name: ['foo']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
sinon.spy(wrapper.vm, 'copyToClipboard')
|
|
||||||
sinon.stub(csv, 'serialize').callsFake(() => {
|
|
||||||
clock.tick(500)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Click copy to clipboard
|
|
||||||
const copyBtn = createWrapper(wrapper.findComponent({ name: 'clipboardIcon' }).vm.$parent)
|
|
||||||
await copyBtn.trigger('click')
|
|
||||||
|
|
||||||
// Switch to microtasks (let serialize run)
|
|
||||||
clock.tick(0)
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
|
|
||||||
// The dialog is not shown...
|
|
||||||
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(false)
|
|
||||||
// copyToClipboard is called
|
|
||||||
expect(wrapper.vm.copyToClipboard.calledOnce).to.equal(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('cancel long copy', async () => {
|
|
||||||
sinon.stub(window.navigator.clipboard, 'writeText').resolves()
|
|
||||||
const clock = sinon.useFakeTimers()
|
|
||||||
const wrapper = mount(RunResult, {
|
|
||||||
propsData: {
|
|
||||||
tab: { id: 1 },
|
|
||||||
result: {
|
|
||||||
columns: ['id', 'name'],
|
|
||||||
values: {
|
|
||||||
id: [1],
|
|
||||||
name: ['foo']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
sinon.spy(wrapper.vm, 'copyToClipboard')
|
|
||||||
sinon.stub(csv, 'serialize').callsFake(() => {
|
|
||||||
clock.tick(5000)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Click copy to clipboard
|
|
||||||
const copyBtn = createWrapper(wrapper.findComponent({ name: 'clipboardIcon' }).vm.$parent)
|
|
||||||
await copyBtn.trigger('click')
|
|
||||||
|
|
||||||
// Switch to microtasks (let serialize run)
|
|
||||||
clock.tick(0)
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
|
|
||||||
// Click cancel
|
|
||||||
await wrapper.find('.dialog-buttons-container button.secondary').trigger('click')
|
|
||||||
|
|
||||||
// The dialog is not shown...
|
|
||||||
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(false)
|
|
||||||
// copyToClipboard is not called
|
|
||||||
expect(wrapper.vm.copyToClipboard.calledOnce).to.equal(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
116
tests/views/Main/Workspace/Tabs/Tab/RunResult/Record.spec.js
Normal file
116
tests/views/Main/Workspace/Tabs/Tab/RunResult/Record.spec.js
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import { expect } from 'chai'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import Record from '@/views/Main/Workspace/Tabs/Tab/RunResult/Record'
|
||||||
|
|
||||||
|
describe('Record.vue', () => {
|
||||||
|
it('shows record with selected cell', async () => {
|
||||||
|
const wrapper = mount(Record, {
|
||||||
|
propsData: {
|
||||||
|
dataSet: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [1, 2],
|
||||||
|
name: ['foo', 'bar']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowIndex: 1,
|
||||||
|
selectedColumnIndex: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const rows = wrapper.findAll('tbody tr')
|
||||||
|
expect(rows).to.have.lengthOf(2)
|
||||||
|
expect(rows.at(0).findAll('th').at(0).text()).to.equals('id')
|
||||||
|
expect(rows.at(0).findAll('td').at(0).text()).to.equals('2')
|
||||||
|
expect(rows.at(1).findAll('th').at(0).text()).to.equals('name')
|
||||||
|
expect(rows.at(1).findAll('td').at(0).text()).to.equals('bar')
|
||||||
|
|
||||||
|
const selectedCell = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
expect(selectedCell.text()).to.equals('bar')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('switches to the next or previous row', async () => {
|
||||||
|
const wrapper = mount(Record, {
|
||||||
|
propsData: {
|
||||||
|
dataSet: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [1, 2, 3],
|
||||||
|
name: ['foo', 'bar', 'baz']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowIndex: 0,
|
||||||
|
selectedColumnIndex: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let rows = wrapper.findAll('tbody tr')
|
||||||
|
expect(rows).to.have.lengthOf(2)
|
||||||
|
expect(rows.at(0).findAll('td').at(0).text()).to.equals('1')
|
||||||
|
expect(rows.at(1).findAll('td').at(0).text()).to.equals('foo')
|
||||||
|
let selectedCell = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
expect(selectedCell.text()).to.equals('1')
|
||||||
|
|
||||||
|
await wrapper.find('.next').trigger('click')
|
||||||
|
|
||||||
|
rows = wrapper.findAll('tbody tr')
|
||||||
|
expect(rows.at(0).findAll('td').at(0).text()).to.equals('2')
|
||||||
|
expect(rows.at(1).findAll('td').at(0).text()).to.equals('bar')
|
||||||
|
selectedCell = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
expect(selectedCell.text()).to.equals('2')
|
||||||
|
|
||||||
|
await wrapper.find('.prev').trigger('click')
|
||||||
|
|
||||||
|
rows = wrapper.findAll('tbody tr')
|
||||||
|
expect(rows.at(0).findAll('td').at(0).text()).to.equals('1')
|
||||||
|
expect(rows.at(1).findAll('td').at(0).text()).to.equals('foo')
|
||||||
|
selectedCell = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
expect(selectedCell.text()).to.equals('1')
|
||||||
|
|
||||||
|
await wrapper.find('.last').trigger('click')
|
||||||
|
|
||||||
|
rows = wrapper.findAll('tbody tr')
|
||||||
|
expect(rows.at(0).findAll('td').at(0).text()).to.equals('3')
|
||||||
|
expect(rows.at(1).findAll('td').at(0).text()).to.equals('baz')
|
||||||
|
selectedCell = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
expect(selectedCell.text()).to.equals('3')
|
||||||
|
|
||||||
|
await wrapper.find('.first').trigger('click')
|
||||||
|
|
||||||
|
rows = wrapper.findAll('tbody tr')
|
||||||
|
expect(rows.at(0).findAll('td').at(0).text()).to.equals('1')
|
||||||
|
expect(rows.at(1).findAll('td').at(0).text()).to.equals('foo')
|
||||||
|
selectedCell = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
expect(selectedCell.text()).to.equals('1')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('removes selection when click on selected cell', async () => {
|
||||||
|
const wrapper = mount(Record, {
|
||||||
|
propsData: {
|
||||||
|
dataSet: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [1, 2],
|
||||||
|
name: ['foo', 'bar']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowIndex: 1,
|
||||||
|
selectedColumnIndex: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedCell = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
await selectedCell.trigger('click')
|
||||||
|
|
||||||
|
const selectedCellAfterClick = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
expect(selectedCellAfterClick.exists()).to.equals(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
348
tests/views/Main/Workspace/Tabs/Tab/RunResult/RunResult.spec.js
Normal file
348
tests/views/Main/Workspace/Tabs/Tab/RunResult/RunResult.spec.js
Normal file
@@ -0,0 +1,348 @@
|
|||||||
|
import { expect } from 'chai'
|
||||||
|
import { mount, createWrapper } from '@vue/test-utils'
|
||||||
|
import RunResult from '@/views/Main/Workspace/Tabs/Tab/RunResult'
|
||||||
|
import csv from '@/lib/csv'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
describe('RunResult.vue', () => {
|
||||||
|
afterEach(() => {
|
||||||
|
sinon.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows alert when ClipboardItem is not supported', async () => {
|
||||||
|
const ClipboardItem = window.ClipboardItem
|
||||||
|
delete window.ClipboardItem
|
||||||
|
sinon.spy(window, 'alert')
|
||||||
|
const wrapper = mount(RunResult, {
|
||||||
|
propsData: {
|
||||||
|
tab: { id: 1 },
|
||||||
|
result: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [1],
|
||||||
|
name: ['foo']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const copyBtn = createWrapper(wrapper.findComponent({ name: 'clipboardIcon' }).vm.$parent)
|
||||||
|
await copyBtn.trigger('click')
|
||||||
|
|
||||||
|
expect(
|
||||||
|
window.alert.calledOnceWith(
|
||||||
|
"Your browser doesn't support copying into the clipboard. " +
|
||||||
|
'If you use Firefox you can enable it ' +
|
||||||
|
'by setting dom.events.asyncClipboard.clipboardItem to true.'
|
||||||
|
)
|
||||||
|
).to.equal(true)
|
||||||
|
|
||||||
|
window.ClipboardItem = ClipboardItem
|
||||||
|
})
|
||||||
|
|
||||||
|
it('copy to clipboard more than 1 sec', async () => {
|
||||||
|
sinon.stub(window.navigator.clipboard, 'writeText').resolves()
|
||||||
|
const clock = sinon.useFakeTimers()
|
||||||
|
const wrapper = mount(RunResult, {
|
||||||
|
propsData: {
|
||||||
|
tab: { id: 1 },
|
||||||
|
result: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [1],
|
||||||
|
name: ['foo']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
sinon.stub(csv, 'serialize').callsFake(() => {
|
||||||
|
clock.tick(5000)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Click copy to clipboard
|
||||||
|
const copyBtn = createWrapper(wrapper.findComponent({ name: 'clipboardIcon' }).vm.$parent)
|
||||||
|
await copyBtn.trigger('click')
|
||||||
|
|
||||||
|
// The dialog is shown...
|
||||||
|
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(true)
|
||||||
|
|
||||||
|
// ... with Building message...
|
||||||
|
expect(wrapper.find('.dialog-body').text()).to.equal('Building CSV...')
|
||||||
|
|
||||||
|
// Switch to microtasks (let serialize run)
|
||||||
|
clock.tick(0)
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
// The dialog is shown...
|
||||||
|
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(true)
|
||||||
|
|
||||||
|
// ... with Ready message...
|
||||||
|
expect(wrapper.find('.dialog-body').text()).to.equal('CSV is ready')
|
||||||
|
|
||||||
|
// Click copy
|
||||||
|
await wrapper.find('.dialog-buttons-container button.primary').trigger('click')
|
||||||
|
|
||||||
|
// The dialog is not shown...
|
||||||
|
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('copy to clipboard less than 1 sec', async () => {
|
||||||
|
sinon.stub(window.navigator.clipboard, 'writeText').resolves()
|
||||||
|
const clock = sinon.useFakeTimers()
|
||||||
|
const wrapper = mount(RunResult, {
|
||||||
|
propsData: {
|
||||||
|
tab: { id: 1 },
|
||||||
|
result: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [1],
|
||||||
|
name: ['foo']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
sinon.spy(wrapper.vm, 'copyToClipboard')
|
||||||
|
sinon.stub(csv, 'serialize').callsFake(() => {
|
||||||
|
clock.tick(500)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Click copy to clipboard
|
||||||
|
const copyBtn = createWrapper(wrapper.findComponent({ name: 'clipboardIcon' }).vm.$parent)
|
||||||
|
await copyBtn.trigger('click')
|
||||||
|
|
||||||
|
// Switch to microtasks (let serialize run)
|
||||||
|
clock.tick(0)
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
// The dialog is not shown...
|
||||||
|
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(false)
|
||||||
|
// copyToClipboard is called
|
||||||
|
expect(wrapper.vm.copyToClipboard.calledOnce).to.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('cancel long copy', async () => {
|
||||||
|
sinon.stub(window.navigator.clipboard, 'writeText').resolves()
|
||||||
|
const clock = sinon.useFakeTimers()
|
||||||
|
const wrapper = mount(RunResult, {
|
||||||
|
propsData: {
|
||||||
|
tab: { id: 1 },
|
||||||
|
result: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [1],
|
||||||
|
name: ['foo']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
sinon.spy(wrapper.vm, 'copyToClipboard')
|
||||||
|
sinon.stub(csv, 'serialize').callsFake(() => {
|
||||||
|
clock.tick(5000)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Click copy to clipboard
|
||||||
|
const copyBtn = createWrapper(wrapper.findComponent({ name: 'clipboardIcon' }).vm.$parent)
|
||||||
|
await copyBtn.trigger('click')
|
||||||
|
|
||||||
|
// Switch to microtasks (let serialize run)
|
||||||
|
clock.tick(0)
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
// Click cancel
|
||||||
|
await wrapper.find('.dialog-buttons-container button.secondary').trigger('click')
|
||||||
|
|
||||||
|
// The dialog is not shown...
|
||||||
|
expect(wrapper.find('[data-modal="prepareCSVCopy"]').exists()).to.equal(false)
|
||||||
|
// copyToClipboard is not called
|
||||||
|
expect(wrapper.vm.copyToClipboard.calledOnce).to.equal(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows value of selected cell - result set', async () => {
|
||||||
|
const wrapper = mount(RunResult, {
|
||||||
|
propsData: {
|
||||||
|
tab: { id: 1 },
|
||||||
|
result: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [1, 2],
|
||||||
|
name: ['foo', 'bar']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Open cell value panel
|
||||||
|
const viewValueBtn = createWrapper(
|
||||||
|
wrapper.findComponent({ name: 'viewCellValueIcon' }).vm.$parent
|
||||||
|
)
|
||||||
|
await viewValueBtn.trigger('click')
|
||||||
|
|
||||||
|
/*
|
||||||
|
Result set:
|
||||||
|
|1 | foo
|
||||||
|
+--+-----
|
||||||
|
|2 | bar
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Click on '1' cell
|
||||||
|
const rows = wrapper.findAll('table tbody tr')
|
||||||
|
await rows.at(0).findAll('td').at(0).trigger('click')
|
||||||
|
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('1')
|
||||||
|
|
||||||
|
// Go to 'foo' with right arrow key
|
||||||
|
await wrapper.find('table').trigger('keydown.right')
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('foo')
|
||||||
|
|
||||||
|
// Go to 'bar' with down arrow key
|
||||||
|
await wrapper.find('table').trigger('keydown.down')
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('bar')
|
||||||
|
|
||||||
|
// Go to '2' with left arrow key
|
||||||
|
await wrapper.find('table').trigger('keydown.left')
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('2')
|
||||||
|
|
||||||
|
// Go to '1' with up arrow key
|
||||||
|
await wrapper.find('table').trigger('keydown.up')
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('1')
|
||||||
|
|
||||||
|
// Click on 'bar' cell
|
||||||
|
await rows.at(1).findAll('td').at(1).trigger('click')
|
||||||
|
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('bar')
|
||||||
|
|
||||||
|
// Click on 'bar' cell again
|
||||||
|
await rows.at(1).findAll('td').at(1).trigger('click')
|
||||||
|
|
||||||
|
expect(wrapper.find('.value-viewer-container .table-preview').text())
|
||||||
|
.to.equals('No cell selected to view')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows value of selected cell - record view', async () => {
|
||||||
|
const wrapper = mount(RunResult, {
|
||||||
|
propsData: {
|
||||||
|
tab: { id: 1 },
|
||||||
|
result: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [1, 2],
|
||||||
|
name: ['foo', 'bar']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Open cell value panel
|
||||||
|
const viewValueBtn = createWrapper(
|
||||||
|
wrapper.findComponent({ name: 'viewCellValueIcon' }).vm.$parent
|
||||||
|
)
|
||||||
|
await viewValueBtn.trigger('click')
|
||||||
|
|
||||||
|
// Go to record view
|
||||||
|
const vierRecordBtn = createWrapper(
|
||||||
|
wrapper.findComponent({ name: 'rowIcon' }).vm.$parent
|
||||||
|
)
|
||||||
|
await vierRecordBtn.trigger('click')
|
||||||
|
|
||||||
|
/*
|
||||||
|
Record 1:
|
||||||
|
|id | 1
|
||||||
|
+-----+-----
|
||||||
|
|name | foo
|
||||||
|
|
||||||
|
Record 2:
|
||||||
|
|id | 2
|
||||||
|
+-----+-----
|
||||||
|
|name | bar
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Click '1' is selected by default
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('1')
|
||||||
|
|
||||||
|
// Go to 'foo' with down arrow key
|
||||||
|
await wrapper.find('table').trigger('keydown.down')
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('foo')
|
||||||
|
|
||||||
|
// Go to next record
|
||||||
|
await wrapper.find('.icon-btn.next').trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('bar')
|
||||||
|
|
||||||
|
// Go to '2' with up arrow key
|
||||||
|
await wrapper.find('table').trigger('keydown.up')
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('2')
|
||||||
|
|
||||||
|
// Go to prev record
|
||||||
|
await wrapper.find('.icon-btn.prev').trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('1')
|
||||||
|
|
||||||
|
// Click on 'foo' cell
|
||||||
|
const rows = wrapper.findAll('table tbody tr')
|
||||||
|
await rows.at(1).find('td').trigger('click')
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('foo')
|
||||||
|
|
||||||
|
// Click on 'foo' cell again
|
||||||
|
await rows.at(1).find('td').trigger('click')
|
||||||
|
expect(wrapper.find('.value-viewer-container .table-preview').text())
|
||||||
|
.to.equals('No cell selected to view')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('keeps selected cell when switch between record and regular view', async () => {
|
||||||
|
const wrapper = mount(RunResult, {
|
||||||
|
propsData: {
|
||||||
|
tab: { id: 1 },
|
||||||
|
result: {
|
||||||
|
columns: ['id', 'name'],
|
||||||
|
values: {
|
||||||
|
id: [...Array(30)].map((x, i) => i),
|
||||||
|
name: [...Array(30)].map((x, i) => `name-${i}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Open cell value panel
|
||||||
|
const viewValueBtn = createWrapper(
|
||||||
|
wrapper.findComponent({ name: 'viewCellValueIcon' }).vm.$parent
|
||||||
|
)
|
||||||
|
await viewValueBtn.trigger('click')
|
||||||
|
|
||||||
|
// Click on 'name-1' cell
|
||||||
|
const rows = wrapper.findAll('table tbody tr')
|
||||||
|
await rows.at(1).findAll('td').at(1).trigger('click')
|
||||||
|
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('name-1')
|
||||||
|
|
||||||
|
// Go to record view
|
||||||
|
const vierRecordBtn = createWrapper(
|
||||||
|
wrapper.findComponent({ name: 'rowIcon' }).vm.$parent
|
||||||
|
)
|
||||||
|
await vierRecordBtn.trigger('click')
|
||||||
|
|
||||||
|
// 'name-1' is selected
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('name-1')
|
||||||
|
let selectedCell = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
expect(selectedCell.text()).to.equals('name-1')
|
||||||
|
|
||||||
|
// Go to last record
|
||||||
|
await wrapper.find('.icon-btn.last').trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('name-29')
|
||||||
|
|
||||||
|
// Go to '29' with up arrow key
|
||||||
|
await wrapper.find('table').trigger('keydown.up')
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('29')
|
||||||
|
|
||||||
|
// Go to regular view
|
||||||
|
await vierRecordBtn.trigger('click')
|
||||||
|
|
||||||
|
// '29' is selected
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('29')
|
||||||
|
selectedCell = wrapper
|
||||||
|
.find('.sqliteviz-table tbody td[aria-selected="true"]')
|
||||||
|
expect(selectedCell.text()).to.equals('29')
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { expect } from 'chai'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import ValueViewer from '@/views/Main/Workspace/Tabs/Tab/RunResult/ValueViewer'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
describe('ValueViewer.vue', () => {
|
||||||
|
afterEach(() => {
|
||||||
|
sinon.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows value in text mode', async () => {
|
||||||
|
const wrapper = mount(ValueViewer, {
|
||||||
|
propsData: {
|
||||||
|
cellValue: 'foo'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('foo')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows error in json mode if the value is not json', async () => {
|
||||||
|
const wrapper = mount(ValueViewer, {
|
||||||
|
propsData: {
|
||||||
|
cellValue: 'foo'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
await wrapper.find('button.json').trigger('click')
|
||||||
|
expect(wrapper.find('.value-body').text()).to.equals('Can\'t parse JSON.')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('copy to clipboard', async () => {
|
||||||
|
sinon.stub(window.navigator.clipboard, 'writeText').resolves()
|
||||||
|
const wrapper = mount(ValueViewer, {
|
||||||
|
propsData: {
|
||||||
|
cellValue: 'foo'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.find('button.copy').trigger('click')
|
||||||
|
|
||||||
|
expect(window.navigator.clipboard.writeText.calledOnceWith('foo'))
|
||||||
|
.to.equal(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user