1
0
mirror of https://github.com/lana-k/sqliteviz.git synced 2025-12-06 18:18:53 +08:00

#116 JSON file import

This commit is contained in:
lana-k
2024-09-05 22:15:12 +02:00
parent a2464d839f
commit 1b6b7c71e9
13 changed files with 346 additions and 213 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "sqliteviz", "name": "sqliteviz",
"version": "0.24.1", "version": "0.25.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"private": true, "private": true,
"scripts": { "scripts": {

View File

@@ -8,8 +8,8 @@
:clickToClose="false" :clickToClose="false"
> >
<div class="dialog-header"> <div class="dialog-header">
CSV import {{ typeName }} import
<close-icon @click="cancelCsvImport" :disabled="disableDialog"/> <close-icon @click="cancelImport" :disabled="disableDialog"/>
</div> </div>
<div class="dialog-body"> <div class="dialog-body">
<text-field <text-field
@@ -18,15 +18,15 @@
width="484px" width="484px"
:disabled="disableDialog" :disabled="disableDialog"
:error-msg="tableNameError" :error-msg="tableNameError"
id="csv-table-name" id="csv-json-table-name"
/> />
<div class="chars"> <div v-if="!isJson && !isNdJson" class="chars">
<delimiter-selector <delimiter-selector
v-model="delimiter" v-model="delimiter"
width="210px" width="210px"
class="char-input" class="char-input"
@input="previewCsv"
:disabled="disableDialog" :disabled="disableDialog"
@input="preview"
/> />
<text-field <text-field
label="Quote char" label="Quote char"
@@ -36,6 +36,7 @@
:disabled="disableDialog" :disabled="disableDialog"
class="char-input" class="char-input"
id="quote-char" id="quote-char"
@input="preview"
/> />
<text-field <text-field
label="Escape char" label="Escape char"
@@ -49,52 +50,52 @@
:disabled="disableDialog" :disabled="disableDialog"
class="char-input" class="char-input"
id="escape-char" id="escape-char"
@input="preview"
/> />
</div> </div>
<check-box <check-box
@click="header = $event" v-if="!isJson && !isNdJson"
:init="true" :init="header"
label="Use first row as column headers" label="Use first row as column headers"
:disabled="disableDialog" :disabled="disableDialog"
@click="changeHeaderDisplaying"
/> />
<sql-table <sql-table
v-if="previewData v-if="previewData && previewData.rowCount > 0"
&& (previewData.rowCount > 0 || Object.keys(previewData).length > 0)
"
:data-set="previewData" :data-set="previewData"
class="preview-table"
:preview="true" :preview="true"
class="preview-table"
/> />
<div v-else class="no-data">No data</div> <div v-else class="no-data">No data</div>
<logs <logs
class="import-csv-errors" class="import-errors"
:messages="importCsvMessages" :messages="importMessages"
/> />
</div> </div>
<div class="dialog-buttons-container"> <div class="dialog-buttons-container">
<button <button
class="secondary" class="secondary"
:disabled="disableDialog" :disabled="disableDialog"
@click="cancelCsvImport" @click="cancelImport"
id="csv-cancel" id="import-cancel"
> >
Cancel Cancel
</button> </button>
<button <button
v-show="!importCsvCompleted" v-show="!importCompleted"
class="primary" class="primary"
:disabled="disableDialog" :disabled="disableDialog || disableImport"
@click="loadFromCsv(file)" @click="loadToDb(file)"
id="csv-import" id="import-start"
> >
Import Import
</button> </button>
<button <button
v-show="importCsvCompleted" v-show="importCompleted"
class="primary" class="primary"
:disabled="disableDialog" :disabled="disableDialog"
@click="finish" @click="finish"
id="csv-finish" id="import-finish"
> >
Finish Finish
</button> </button>
@@ -115,7 +116,7 @@ import fIo from '@/lib/utils/fileIo'
import events from '@/lib/utils/events' import events from '@/lib/utils/events'
export default { export default {
name: 'CsvImport', name: 'CsvJsonImport',
components: { components: {
CloseIcon, CloseIcon,
TextField, TextField,
@@ -124,33 +125,50 @@ export default {
SqlTable, SqlTable,
Logs Logs
}, },
props: ['file', 'db', 'dialogName'], props: {
file: File,
db: Object,
dialogName: String
},
data () { data () {
return { return {
disableDialog: false, disableDialog: false,
disableImport: false,
tableName: '', tableName: '',
delimiter: '', delimiter: '',
quoteChar: '"', quoteChar: '"',
escapeChar: '"', escapeChar: '"',
header: true, header: true,
importCsvCompleted: false, importCompleted: false,
importCsvMessages: [], importMessages: [],
previewData: null, previewData: null,
addedTable: null, addedTable: null,
tableNameError: '' tableNameError: ''
} }
}, },
computed: {
isJson () {
return fIo.isJSON(this.file)
},
isNdJson () {
return fIo.isNDJSON(this.file)
},
typeName () {
return this.isJson || this.isNdJson ? 'JSON' : 'CSV'
}
},
watch: { watch: {
quoteChar () { isJson () {
this.previewCsv() if (this.isJson) {
this.delimiter = '\u001E'
this.header = false
}
}, },
isNdJson () {
escapeChar () { if (this.isNdJson) {
this.previewCsv() this.delimiter = '\u001E'
}, this.header = false
}
header () {
this.previewCsv()
}, },
tableName: time.debounce(function () { tableName: time.debounce(function () {
this.tableNameError = '' this.tableNameError = ''
@@ -164,7 +182,11 @@ export default {
}, 400) }, 400)
}, },
methods: { methods: {
cancelCsvImport () { changeHeaderDisplaying (e) {
this.header = e
this.preview()
},
cancelImport () {
if (!this.disableDialog) { if (!this.disableDialog) {
if (this.addedTable) { if (this.addedTable) {
this.db.execute(`DROP TABLE "${this.addedTable}"`) this.db.execute(`DROP TABLE "${this.addedTable}"`)
@@ -175,14 +197,15 @@ export default {
} }
}, },
reset () { reset () {
this.header = true this.header = !this.isJson && !this.isNdJson
this.quoteChar = '"' this.quoteChar = '"'
this.escapeChar = '"' this.escapeChar = '"'
this.delimiter = '' this.delimiter = !this.isJson && !this.isNdJson ? '' : '\u001E'
this.tableName = '' this.tableName = ''
this.disableDialog = false this.disableDialog = false
this.importCsvCompleted = false this.disableImport = false
this.importCsvMessages = [] this.importCompleted = false
this.importMessages = []
this.previewData = null this.previewData = null
this.addedTable = null this.addedTable = null
this.tableNameError = '' this.tableNameError = ''
@@ -191,39 +214,69 @@ export default {
this.tableName = this.db.sanitizeTableName(fIo.getFileName(this.file)) this.tableName = this.db.sanitizeTableName(fIo.getFileName(this.file))
this.$modal.show(this.dialogName) this.$modal.show(this.dialogName)
}, },
async previewCsv () { async preview () {
this.importCsvCompleted = false this.disableImport = false
if (!this.file) {
return
}
this.importCompleted = false
const config = { const config = {
preview: 3, preview: 3,
quoteChar: this.quoteChar || '"', quoteChar: this.quoteChar || '"',
escapeChar: this.escapeChar, escapeChar: this.escapeChar,
header: this.header, header: this.header,
delimiter: this.delimiter delimiter: this.delimiter,
columns: !this.isJson && !this.isNdJson ? null : ['doc']
} }
try { try {
const start = new Date() const start = new Date()
const parseResult = await csv.parse(this.file, config) const parseResult = this.isJson
? await this.getJsonParseResult(this.file)
: await csv.parse(this.file, config)
const end = new Date() const end = new Date()
this.previewData = parseResult.data this.previewData = parseResult.data
this.previewData.rowCount = parseResult.rowCount
this.delimiter = parseResult.delimiter this.delimiter = parseResult.delimiter
// In parseResult.messages we can get parse errors // In parseResult.messages we can get parse errors
this.importCsvMessages = parseResult.messages || [] this.importMessages = parseResult.messages || []
if (this.previewData.rowCount === 0) {
this.disableImport = true
this.importMessages.push({
type: 'info',
message: 'No rows to import.'
})
}
if (!parseResult.hasErrors) { if (!parseResult.hasErrors) {
this.importCsvMessages.push({ this.importMessages.push({
message: `Preview parsing is completed in ${time.getPeriod(start, end)}.`, message: `Preview parsing is completed in ${time.getPeriod(start, end)}.`,
type: 'success' type: 'success'
}) })
} }
} catch (err) { } catch (err) {
this.importCsvMessages = [{ console.error(err)
this.importMessages = [{
message: err, message: err,
type: 'error' type: 'error'
}] }]
} }
}, },
async loadFromCsv (file) { async getJsonParseResult (file) {
const jsonContent = await fIo.getFileContent(file)
const isEmpty = !jsonContent.trim()
return {
data: {
columns: ['doc'],
values: { doc: !isEmpty ? [jsonContent] : [] }
},
hasErrors: false,
messages: [],
rowCount: +(!isEmpty)
}
},
async loadToDb (file) {
if (!this.tableName) { if (!this.tableName) {
this.tableNameError = "Table name can't be empty" this.tableNameError = "Table name can't be empty"
return return
@@ -234,17 +287,18 @@ export default {
quoteChar: this.quoteChar || '"', quoteChar: this.quoteChar || '"',
escapeChar: this.escapeChar, escapeChar: this.escapeChar,
header: this.header, header: this.header,
delimiter: this.delimiter delimiter: this.delimiter,
columns: !this.isJson && !this.isNdJson ? null : ['doc']
} }
const parseCsvMsg = { const parsingMsg = {
message: 'Parsing CSV...', message: `Parsing ${this.typeName}...`,
type: 'info' type: 'info'
} }
this.importCsvMessages.push(parseCsvMsg) this.importMessages.push(parsingMsg)
const parseCsvLoadingIndicator = setTimeout(() => { parseCsvMsg.type = 'loading' }, 1000) const parsingLoadingIndicator = setTimeout(() => { parsingMsg.type = 'loading' }, 1000)
const importMsg = { const importMsg = {
message: 'Importing CSV into a SQLite database...', message: `Importing ${this.typeName} into a SQLite database...`,
type: 'info' type: 'info'
} }
let importLoadingIndicator = null let importLoadingIndicator = null
@@ -256,27 +310,30 @@ export default {
try { try {
let start = new Date() let start = new Date()
const parseResult = await csv.parse(this.file, config) const parseResult = this.isJson
? await this.getJsonParseResult(file)
: await csv.parse(this.file, config)
let end = new Date() let end = new Date()
if (!parseResult.hasErrors) { if (!parseResult.hasErrors) {
const rowCount = parseResult.rowCount const rowCount = parseResult.rowCount
let period = time.getPeriod(start, end) let period = time.getPeriod(start, end)
parseCsvMsg.type = 'success' parsingMsg.type = 'success'
if (parseResult.messages.length > 0) { if (parseResult.messages.length > 0) {
this.importCsvMessages = this.importCsvMessages.concat(parseResult.messages) this.importMessages = this.importMessages.concat(parseResult.messages)
parseCsvMsg.message = `${rowCount} rows are parsed in ${period}.` parsingMsg.message = `${rowCount} rows are parsed in ${period}.`
} else { } else {
// Inform about csv parsing success // Inform about parsing success
parseCsvMsg.message = `${rowCount} rows are parsed successfully in ${period}.` parsingMsg.message = `${rowCount} rows are parsed successfully in ${period}.`
} }
// Loading indicator for csv parsing is not needed anymore // Loading indicator for parsing is not needed anymore
clearTimeout(parseCsvLoadingIndicator) clearTimeout(parsingLoadingIndicator)
// Add info about import start // Add info about import start
this.importCsvMessages.push(importMsg) this.importMessages.push(importMsg)
// Show import progress after 1 second // Show import progress after 1 second
importLoadingIndicator = setTimeout(() => { importLoadingIndicator = setTimeout(() => {
@@ -291,52 +348,105 @@ export default {
this.addedTable = this.tableName this.addedTable = this.tableName
// Inform about import success // Inform about import success
period = time.getPeriod(start, end) period = time.getPeriod(start, end)
importMsg.message = `Importing CSV into a SQLite database is completed in ${period}.` importMsg.message = `Importing ${this.typeName} into a SQLite database is completed in ${period}.`
importMsg.type = 'success' importMsg.type = 'success'
// Loading indicator for import is not needed anymore // Loading indicator for import is not needed anymore
clearTimeout(importLoadingIndicator) clearTimeout(importLoadingIndicator)
this.importCsvCompleted = true this.importCompleted = true
} else { } else {
parseCsvMsg.message = 'Parsing ended with errors.' parsingMsg.message = 'Parsing ended with errors.'
parseCsvMsg.type = 'info' parsingMsg.type = 'info'
this.importCsvMessages = this.importCsvMessages.concat(parseResult.messages) this.importMessages = this.importMessages.concat(parseResult.messages)
} }
} catch (err) { } catch (err) {
if (parseCsvMsg.type === 'loading') { console.error(err)
parseCsvMsg.type = 'info' if (parsingMsg.type === 'loading') {
parsingMsg.type = 'info'
} }
if (importMsg.type === 'loading') { if (importMsg.type === 'loading') {
importMsg.type = 'info' importMsg.type = 'info'
} }
this.importCsvMessages.push({ this.importMessages.push({
message: err, message: err,
type: 'error' type: 'error'
}) })
} }
clearTimeout(parseCsvLoadingIndicator) clearTimeout(parsingLoadingIndicator)
clearTimeout(importLoadingIndicator) clearTimeout(importLoadingIndicator)
this.db.deleteProgressCounter(progressCounterId) this.db.deleteProgressCounter(progressCounterId)
this.disableDialog = false this.disableDialog = false
}, },
async finish () { async finish () {
this.$modal.hide(this.dialogName) this.$modal.hide(this.dialogName)
const stmt = [ const stmt = this.getQueryExample()
'/*', const tabId = await this.$store.dispatch('addTab', { query: stmt })
this.$store.commit('setCurrentTabId', tabId)
this.importCompleted = false
this.$emit('finish')
events.send('inquiry.create', null, { auto: true })
},
getQueryExample () {
return this.isNdJson ? this.getNdJsonQueryExample()
: this.isJson ? this.getJsonQueryExample()
: [
'/*',
` * Your CSV file has been imported into ${this.addedTable} table.`, ` * Your CSV file has been imported into ${this.addedTable} table.`,
' * You can run this SQL query to make all CSV records available for charting.', ' * You can run this SQL query to make all CSV records available for charting.',
' */', ' */',
`SELECT * FROM "${this.addedTable}"` `SELECT * FROM "${this.addedTable}"`
].join('\n') ].join('\n')
const tabId = await this.$store.dispatch('addTab', { query: stmt }) },
this.$store.commit('setCurrentTabId', tabId) getNdJsonQueryExample () {
this.importCsvCompleted = false try {
this.$emit('finish') const firstRowJson = JSON.parse(this.previewData.values.doc[0])
events.send('inquiry.create', null, { auto: true }) const firstKey = Object.keys(firstRowJson)[0]
return [
'/*',
` * Your NDJSON file has been imported into ${this.addedTable} table.`,
` * Run this SQL query to get values of property ${firstKey} and make them available for charting.`,
' */',
`SELECT doc->>'${firstKey}'`,
`FROM "${this.addedTable}"`
].join('\n')
} catch (err) {
console.error(err)
return [
'/*',
` * Your NDJSON file has been imported into ${this.addedTable} table.`,
' */',
'SELECT *',
`FROM "${this.addedTable}"`
].join('\n')
}
},
getJsonQueryExample () {
try {
const firstRowJson = JSON.parse(this.previewData.values.doc[0])
const firstKey = Object.keys(firstRowJson)[0]
return [
'/*',
` * Your JSON file has been imported into ${this.addedTable} table.`,
` * Run this SQL query to get values of property ${firstKey} and make them available for charting.`,
' */',
'SELECT *',
`FROM "${this.addedTable}"`,
`JOIN json_each(doc, '$.${firstKey}')`
].join('\n')
} catch (err) {
console.error(err)
return [
'/*',
` * Your NDJSON file has been imported into ${this.addedTable} table.`,
' */',
'SELECT *',
`FROM "${this.addedTable}"`
].join('\n')
}
} }
} }
} }
@@ -347,10 +457,14 @@ export default {
padding-bottom: 0; padding-bottom: 0;
} }
#csv-json-table-name {
margin-bottom: 24px;
}
.chars { .chars {
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
margin: 24px 0 20px; margin: 0 0 20px;
} }
.char-input { .char-input {
margin-right: 44px; margin-right: 44px;
@@ -359,7 +473,7 @@ export default {
margin-top: 18px; margin-top: 18px;
} }
.import-csv-errors { .import-errors {
height: 136px; height: 136px;
margin-top: 8px; margin-top: 8px;
} }

View File

@@ -41,13 +41,13 @@
</div> </div>
<div id="error" class="error"></div> <div id="error" class="error"></div>
<!--Parse csv dialog --> <!--Parse csv or json dialog -->
<csv-import <csv-json-import
ref="addCsv" ref="addCsvJson"
:file="file" :file="file"
:db="newDb" :db="newDb"
dialog-name="importFromCsv" dialog-name="importFromCsvJson"
@cancel="cancelCsvImport" @cancel="cancelImport"
@finish="finish" @finish="finish"
/> />
</div> </div>
@@ -57,7 +57,7 @@
import fIo from '@/lib/utils/fileIo' import fIo from '@/lib/utils/fileIo'
import ChangeDbIcon from '@/components/svg/changeDb' import ChangeDbIcon from '@/components/svg/changeDb'
import database from '@/lib/database' import database from '@/lib/database'
import CsvImport from '@/components/CsvImport' import CsvJsonImport from '@/components/CsvJsonImport'
import events from '@/lib/utils/events' import events from '@/lib/utils/events'
export default { export default {
@@ -79,7 +79,7 @@ export default {
}, },
components: { components: {
ChangeDbIcon, ChangeDbIcon,
CsvImport CsvJsonImport
}, },
data () { data () {
return { return {
@@ -102,7 +102,7 @@ export default {
} }
}, },
methods: { methods: {
cancelCsvImport () { cancelImport () {
if (this.newDb) { if (this.newDb) {
this.newDb.shutDown() this.newDb.shutDown()
this.newDb = null this.newDb = null
@@ -128,21 +128,22 @@ export default {
if (fIo.isDatabase(file)) { if (fIo.isDatabase(file)) {
this.loadDb(file) this.loadDb(file)
} else { } else {
const isJson = fIo.isJSON(file) || fIo.isNDJSON(file)
events.send('database.import', file.size, { events.send('database.import', file.size, {
from: 'csv', from: isJson ? 'json' : 'csv',
new_db: true new_db: true
}) })
this.file = file this.file = file
await this.$nextTick() await this.$nextTick()
const csvImport = this.$refs.addCsv const csvJsonImportModal = this.$refs.addCsvJson
csvImport.reset() csvJsonImportModal.reset()
return Promise.all([csvImport.previewCsv(), this.animationPromise]) return Promise.all([csvJsonImportModal.preview(), this.animationPromise])
.then(csvImport.open) .then(csvJsonImportModal.open)
} }
}, },
browse () { browse () {
fIo.getFileFromUser('.db,.sqlite,.sqlite3,.csv') fIo.getFileFromUser('.db,.sqlite,.sqlite3,.csv,.json,.ndjson')
.then(this.checkFile) .then(this.checkFile)
}, },

View File

@@ -7,9 +7,9 @@ const hintsByCode = {
} }
export default { export default {
getResult (source) { getResult (source, columns) {
const result = { const result = {
columns: [] columns: columns || []
} }
const values = {} const values = {}
if (source.meta.fields) { if (source.meta.fields) {
@@ -24,8 +24,18 @@ export default {
return value return value
}) })
}) })
} else if (columns) {
columns.forEach((col, i) => {
values[col] = source.data.map(row => {
let value = row[i]
if (value instanceof Date) {
value = value.toISOString()
}
return value
})
})
} else { } else {
for (let i = 0; i <= source.data[0].length - 1; i++) { for (let i = 0; source.data[0] && i <= source.data[0].length - 1; i++) {
const colName = `col${i + 1}` const colName = `col${i + 1}`
result.columns.push(colName) result.columns.push(colName)
values[colName] = source.data.map(row => { values[colName] = source.data.map(row => {
@@ -76,7 +86,7 @@ export default {
let res let res
try { try {
res = { res = {
data: this.getResult(results), data: this.getResult(results, config.columns),
delimiter: results.meta.delimiter, delimiter: results.meta.delimiter,
hasErrors: false, hasErrors: false,
rowCount: results.data.length rowCount: results.data.length

View File

@@ -1,4 +1,10 @@
export default { export default {
isJSON (file) {
return file && file.type === 'application/json'
},
isNDJSON (file) {
return file && file.name.endsWith('.ndjson')
},
isDatabase (file) { isDatabase (file) {
const dbTypes = ['application/vnd.sqlite3', 'application/x-sqlite3'] const dbTypes = ['application/vnd.sqlite3', 'application/x-sqlite3']
return file.type return file.type
@@ -51,19 +57,20 @@ export default {
}, },
importFile () { importFile () {
const reader = new FileReader()
return this.getFileFromUser('.json') return this.getFileFromUser('.json')
.then(file => { .then(file => {
return new Promise((resolve, reject) => { return this.getFileContent(file)
reader.onload = e => {
resolve(e.target.result)
}
reader.readAsText(file)
})
}) })
}, },
getFileContent (file) {
const reader = new FileReader()
return new Promise(resolve => {
reader.onload = e => resolve(e.target.result)
reader.readAsText(file)
})
},
readFile (path) { readFile (path) {
return fetch(path) return fetch(path)
}, },

View File

@@ -10,7 +10,7 @@
</div> </div>
<db-uploader id="db-edit" type="small" /> <db-uploader id="db-edit" type="small" />
<export-icon tooltip="Export database" @click="exportToFile"/> <export-icon tooltip="Export database" @click="exportToFile"/>
<add-table-icon @click="addCsv"/> <add-table-icon @click="addCsvJson"/>
</div> </div>
<div v-show="schemaVisible" class="schema"> <div v-show="schemaVisible" class="schema">
<table-description <table-description
@@ -21,12 +21,12 @@
/> />
</div> </div>
<!--Parse csv dialog --> <!--Parse csv or json dialog -->
<csv-import <csv-json-import
ref="addCsv" ref="addCsvJson"
:file="file" :file="file"
:db="$store.state.db" :db="$store.state.db"
dialog-name="addCsv" dialog-name="addCsvJson"
/> />
</div> </div>
</template> </template>
@@ -40,7 +40,7 @@ import TreeChevron from '@/components/svg/treeChevron'
import DbUploader from '@/components/DbUploader' import DbUploader from '@/components/DbUploader'
import ExportIcon from '@/components/svg/export' import ExportIcon from '@/components/svg/export'
import AddTableIcon from '@/components/svg/addTable' import AddTableIcon from '@/components/svg/addTable'
import CsvImport from '@/components/CsvImport' import CsvJsonImport from '@/components/CsvJsonImport'
export default { export default {
name: 'Schema', name: 'Schema',
@@ -51,7 +51,7 @@ export default {
DbUploader, DbUploader,
ExportIcon, ExportIcon,
AddTableIcon, AddTableIcon,
CsvImport CsvJsonImport
}, },
data () { data () {
return { return {
@@ -80,16 +80,17 @@ export default {
exportToFile () { exportToFile () {
this.$store.state.db.export(`${this.dbName}.sqlite`) this.$store.state.db.export(`${this.dbName}.sqlite`)
}, },
async addCsv () { async addCsvJson () {
this.file = await fIo.getFileFromUser('.csv') this.file = await fIo.getFileFromUser('.csv,.json,.ndjson')
await this.$nextTick() await this.$nextTick()
const csvImport = this.$refs.addCsv const csvJsonImportModal = this.$refs.addCsvJson
csvImport.reset() csvJsonImportModal.reset()
await csvImport.previewCsv() await csvJsonImportModal.preview()
csvImport.open() csvJsonImportModal.open()
const isJson = fIo.isJSON(this.file) || fIo.isNDJSON(this.file)
events.send('database.import', this.file.size, { events.send('database.import', this.file.size, {
from: 'csv', from: isJson ? 'json' : 'csv',
new_db: false new_db: false
}) })
} }

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<main-menu /> <main-menu />
<keep-alive include="Workspace"> <keep-alive include="Workspace,Inquiries">
<router-view id="main-view" /> <router-view id="main-view" />
</keep-alive> </keep-alive>
</div> </div>

View File

@@ -2,10 +2,10 @@ import { expect } from 'chai'
import sinon from 'sinon' import sinon from 'sinon'
import Vuex from 'vuex' import Vuex from 'vuex'
import { mount } from '@vue/test-utils' import { mount } from '@vue/test-utils'
import CsvImport from '@/components/CsvImport' import CsvJsonImport from '@/components/CsvJsonImport'
import csv from '@/lib/csv' import csv from '@/lib/csv'
describe('CsvImport.vue', () => { describe('CsvJsonImport.vue', () => {
let state = {} let state = {}
let actions = {} let actions = {}
let mutations = {} let mutations = {}
@@ -40,11 +40,11 @@ describe('CsvImport.vue', () => {
} }
// mount the component // mount the component
wrapper = mount(CsvImport, { wrapper = mount(CsvJsonImport, {
store, store,
propsData: { propsData: {
file, file,
dialogName: 'addCsv', dialogName: 'addCsvJson',
db db
} }
}) })
@@ -74,11 +74,11 @@ describe('CsvImport.vue', () => {
}] }]
}) })
wrapper.vm.previewCsv() wrapper.vm.preview()
await wrapper.vm.open() await wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
expect(wrapper.find('[data-modal="addCsv"]').exists()).to.equal(true) expect(wrapper.find('[data-modal="addCsvJson"]').exists()).to.equal(true)
expect(wrapper.find('#csv-table-name input').element.value).to.equal('my_data') expect(wrapper.find('#csv-json-table-name input').element.value).to.equal('my_data')
expect(wrapper.findComponent({ name: 'delimiter-selector' }).vm.value).to.equal('|') expect(wrapper.findComponent({ name: 'delimiter-selector' }).vm.value).to.equal('|')
expect(wrapper.find('#quote-char input').element.value).to.equal('"') expect(wrapper.find('#quote-char input').element.value).to.equal('"')
expect(wrapper.find('#escape-char input').element.value).to.equal('"') expect(wrapper.find('#escape-char input').element.value).to.equal('"')
@@ -93,8 +93,8 @@ describe('CsvImport.vue', () => {
.to.include('Information about row 0. Comma was used as a standart delimiter.') .to.include('Information about row 0. Comma was used as a standart delimiter.')
expect(wrapper.findComponent({ name: 'logs' }).text()) expect(wrapper.findComponent({ name: 'logs' }).text())
.to.include('Preview parsing is completed in') .to.include('Preview parsing is completed in')
expect(wrapper.find('#csv-finish').isVisible()).to.equal(false) expect(wrapper.find('#import-finish').isVisible()).to.equal(false)
expect(wrapper.find('#csv-import').isVisible()).to.equal(true) expect(wrapper.find('#import-start').isVisible()).to.equal(true)
}) })
it('reparses when parameters changes', async () => { it('reparses when parameters changes', async () => {
@@ -111,7 +111,7 @@ describe('CsvImport.vue', () => {
rowCount: 1 rowCount: 1
}) })
wrapper.vm.previewCsv() wrapper.vm.preview()
wrapper.vm.open() wrapper.vm.open()
await csv.parse.returnValues[0] await csv.parse.returnValues[0]
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
@@ -234,7 +234,7 @@ describe('CsvImport.vue', () => {
rowCount: 1 rowCount: 1
}) })
wrapper.vm.previewCsv() wrapper.vm.preview()
wrapper.vm.open() wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
@@ -243,8 +243,8 @@ describe('CsvImport.vue', () => {
resolveParsing = resolve resolveParsing = resolve
})) }))
await wrapper.find('#csv-table-name input').setValue('foo') await wrapper.find('#csv-json-table-name input').setValue('foo')
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
// "Parsing CSV..." in the logs // "Parsing CSV..." in the logs
@@ -262,11 +262,11 @@ describe('CsvImport.vue', () => {
expect(wrapper.find('#quote-char input').element.disabled).to.equal(true) expect(wrapper.find('#quote-char input').element.disabled).to.equal(true)
expect(wrapper.find('#escape-char input').element.disabled).to.equal(true) expect(wrapper.find('#escape-char input').element.disabled).to.equal(true)
expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(true) expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(true)
expect(wrapper.find('#csv-cancel').element.disabled).to.equal(true) expect(wrapper.find('#import-cancel').element.disabled).to.equal(true)
expect(wrapper.find('#csv-finish').element.disabled).to.equal(true) expect(wrapper.find('#import-finish').element.disabled).to.equal(true)
expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(true) expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(true)
expect(wrapper.find('#csv-finish').isVisible()).to.equal(false) expect(wrapper.find('#import-finish').isVisible()).to.equal(false)
expect(wrapper.find('#csv-import').isVisible()).to.equal(true) expect(wrapper.find('#import-start').isVisible()).to.equal(true)
await resolveParsing() await resolveParsing()
await parse.returnValues[1] await parse.returnValues[1]
@@ -306,7 +306,7 @@ describe('CsvImport.vue', () => {
messages: [] messages: []
}) })
wrapper.vm.previewCsv() wrapper.vm.preview()
wrapper.vm.open() wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
@@ -315,8 +315,8 @@ describe('CsvImport.vue', () => {
resolveImport = resolve resolveImport = resolve
})) }))
await wrapper.find('#csv-table-name input').setValue('foo') await wrapper.find('#csv-json-table-name input').setValue('foo')
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await csv.parse.returnValues[1] await csv.parse.returnValues[1]
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
@@ -329,11 +329,11 @@ describe('CsvImport.vue', () => {
expect(wrapper.find('#quote-char input').element.disabled).to.equal(true) expect(wrapper.find('#quote-char input').element.disabled).to.equal(true)
expect(wrapper.find('#escape-char input').element.disabled).to.equal(true) expect(wrapper.find('#escape-char input').element.disabled).to.equal(true)
expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(true) expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(true)
expect(wrapper.find('#csv-cancel').element.disabled).to.equal(true) expect(wrapper.find('#import-cancel').element.disabled).to.equal(true)
expect(wrapper.find('#csv-finish').element.disabled).to.equal(true) expect(wrapper.find('#import-finish').element.disabled).to.equal(true)
expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(true) expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(true)
expect(wrapper.find('#csv-finish').isVisible()).to.equal(false) expect(wrapper.find('#import-finish').isVisible()).to.equal(false)
expect(wrapper.find('#csv-import').isVisible()).to.equal(true) expect(wrapper.find('#import-start').isVisible()).to.equal(true)
await resolveImport() await resolveImport()
}) })
@@ -377,12 +377,12 @@ describe('CsvImport.vue', () => {
resolveImport = resolve resolveImport = resolve
})) }))
wrapper.vm.previewCsv() wrapper.vm.preview()
wrapper.vm.open() wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-table-name input').setValue('foo') await wrapper.find('#csv-json-table-name input').setValue('foo')
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await csv.parse.returnValues[1] await csv.parse.returnValues[1]
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
@@ -397,11 +397,11 @@ describe('CsvImport.vue', () => {
expect(wrapper.find('#quote-char input').element.disabled).to.equal(true) expect(wrapper.find('#quote-char input').element.disabled).to.equal(true)
expect(wrapper.find('#escape-char input').element.disabled).to.equal(true) expect(wrapper.find('#escape-char input').element.disabled).to.equal(true)
expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(true) expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(true)
expect(wrapper.find('#csv-cancel').element.disabled).to.equal(true) expect(wrapper.find('#import-cancel').element.disabled).to.equal(true)
expect(wrapper.find('#csv-finish').element.disabled).to.equal(true) expect(wrapper.find('#import-finish').element.disabled).to.equal(true)
expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(true) expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(true)
expect(wrapper.find('#csv-finish').isVisible()).to.equal(false) expect(wrapper.find('#import-finish').isVisible()).to.equal(false)
expect(wrapper.find('#csv-import').isVisible()).to.equal(true) expect(wrapper.find('#import-start').isVisible()).to.equal(true)
await resolveImport() await resolveImport()
}) })
@@ -440,12 +440,12 @@ describe('CsvImport.vue', () => {
}] }]
}) })
wrapper.vm.previewCsv() wrapper.vm.preview()
wrapper.vm.open() wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-table-name input').setValue('foo') await wrapper.find('#csv-json-table-name input').setValue('foo')
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await csv.parse.returnValues[1] await csv.parse.returnValues[1]
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
@@ -460,11 +460,11 @@ describe('CsvImport.vue', () => {
expect(wrapper.find('#quote-char input').element.disabled).to.equal(false) expect(wrapper.find('#quote-char input').element.disabled).to.equal(false)
expect(wrapper.find('#escape-char input').element.disabled).to.equal(false) expect(wrapper.find('#escape-char input').element.disabled).to.equal(false)
expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(false) expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(false)
expect(wrapper.find('#csv-cancel').element.disabled).to.equal(false) expect(wrapper.find('#import-cancel').element.disabled).to.equal(false)
expect(wrapper.find('#csv-finish').element.disabled).to.equal(false) expect(wrapper.find('#import-finish').element.disabled).to.equal(false)
expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(false) expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(false)
expect(wrapper.find('#csv-finish').isVisible()).to.equal(false) expect(wrapper.find('#import-finish').isVisible()).to.equal(false)
expect(wrapper.find('#csv-import').isVisible()).to.equal(true) expect(wrapper.find('#import-start').isVisible()).to.equal(true)
}) })
it('has proper state before import is completed', async () => { it('has proper state before import is completed', async () => {
@@ -501,12 +501,12 @@ describe('CsvImport.vue', () => {
wrapper.vm.db.addTableFromCsv = sinon.stub() wrapper.vm.db.addTableFromCsv = sinon.stub()
.resolves(new Promise(resolve => { resolveImport = resolve })) .resolves(new Promise(resolve => { resolveImport = resolve }))
wrapper.vm.previewCsv() wrapper.vm.preview()
wrapper.vm.open() wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-table-name input').setValue('foo') await wrapper.find('#csv-json-table-name input').setValue('foo')
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await csv.parse.returnValues[1] await csv.parse.returnValues[1]
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
@@ -525,11 +525,11 @@ describe('CsvImport.vue', () => {
expect(wrapper.find('#quote-char input').element.disabled).to.equal(true) expect(wrapper.find('#quote-char input').element.disabled).to.equal(true)
expect(wrapper.find('#escape-char input').element.disabled).to.equal(true) expect(wrapper.find('#escape-char input').element.disabled).to.equal(true)
expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(true) expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(true)
expect(wrapper.find('#csv-cancel').element.disabled).to.equal(true) expect(wrapper.find('#import-cancel').element.disabled).to.equal(true)
expect(wrapper.find('#csv-finish').element.disabled).to.equal(true) expect(wrapper.find('#import-finish').element.disabled).to.equal(true)
expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(true) expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(true)
expect(wrapper.find('#csv-finish').isVisible()).to.equal(false) expect(wrapper.find('#import-finish').isVisible()).to.equal(false)
expect(wrapper.find('#csv-import').isVisible()).to.equal(true) expect(wrapper.find('#import-start').isVisible()).to.equal(true)
expect(wrapper.vm.db.addTableFromCsv.getCall(0).args[0]).to.equal('foo') // table name expect(wrapper.vm.db.addTableFromCsv.getCall(0).args[0]).to.equal('foo') // table name
// After resolving - loading indicator is not shown // After resolving - loading indicator is not shown
@@ -570,12 +570,12 @@ describe('CsvImport.vue', () => {
messages: [] messages: []
}) })
wrapper.vm.previewCsv() wrapper.vm.preview()
wrapper.vm.open() wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-table-name input').setValue('foo') await wrapper.find('#csv-json-table-name input').setValue('foo')
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await csv.parse.returnValues[1] await csv.parse.returnValues[1]
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
@@ -589,10 +589,10 @@ describe('CsvImport.vue', () => {
expect(wrapper.find('#quote-char input').element.disabled).to.equal(false) expect(wrapper.find('#quote-char input').element.disabled).to.equal(false)
expect(wrapper.find('#escape-char input').element.disabled).to.equal(false) expect(wrapper.find('#escape-char input').element.disabled).to.equal(false)
expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(false) expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(false)
expect(wrapper.find('#csv-cancel').element.disabled).to.equal(false) expect(wrapper.find('#import-cancel').element.disabled).to.equal(false)
expect(wrapper.find('#csv-finish').element.disabled).to.equal(false) expect(wrapper.find('#import-finish').element.disabled).to.equal(false)
expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(false) expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(false)
expect(wrapper.find('#csv-finish').isVisible()).to.equal(true) expect(wrapper.find('#import-finish').isVisible()).to.equal(true)
}) })
it('import fails', async () => { it('import fails', async () => {
@@ -627,12 +627,12 @@ describe('CsvImport.vue', () => {
wrapper.vm.db.addTableFromCsv = sinon.stub().rejects(new Error('fail')) wrapper.vm.db.addTableFromCsv = sinon.stub().rejects(new Error('fail'))
wrapper.vm.previewCsv() wrapper.vm.preview()
wrapper.vm.open() wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-table-name input').setValue('foo') await wrapper.find('#csv-json-table-name input').setValue('foo')
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await csv.parse.returnValues[1] await csv.parse.returnValues[1]
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
@@ -647,10 +647,10 @@ describe('CsvImport.vue', () => {
expect(wrapper.find('#quote-char input').element.disabled).to.equal(false) expect(wrapper.find('#quote-char input').element.disabled).to.equal(false)
expect(wrapper.find('#escape-char input').element.disabled).to.equal(false) expect(wrapper.find('#escape-char input').element.disabled).to.equal(false)
expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(false) expect(wrapper.findComponent({ name: 'check-box' }).vm.disabled).to.equal(false)
expect(wrapper.find('#csv-cancel').element.disabled).to.equal(false) expect(wrapper.find('#import-cancel').element.disabled).to.equal(false)
expect(wrapper.find('#csv-finish').element.disabled).to.equal(false) expect(wrapper.find('#import-finish').element.disabled).to.equal(false)
expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(false) expect(wrapper.findComponent({ name: 'close-icon' }).vm.disabled).to.equal(false)
expect(wrapper.find('#csv-finish').isVisible()).to.equal(false) expect(wrapper.find('#import-finish').isVisible()).to.equal(false)
}) })
it('import finish', async () => { it('import finish', async () => {
@@ -668,19 +668,19 @@ describe('CsvImport.vue', () => {
messages: [] messages: []
}) })
wrapper.vm.previewCsv() wrapper.vm.preview()
wrapper.vm.open() wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-finish').trigger('click') await wrapper.find('#import-finish').trigger('click')
expect(actions.addTab.calledOnce).to.equal(true) expect(actions.addTab.calledOnce).to.equal(true)
await actions.addTab.returnValues[0] await actions.addTab.returnValues[0]
expect(mutations.setCurrentTabId.calledOnceWith(state, newTabId)).to.equal(true) expect(mutations.setCurrentTabId.calledOnceWith(state, newTabId)).to.equal(true)
expect(wrapper.find('[data-modal="addCsv"]').exists()).to.equal(false) expect(wrapper.find('[data-modal="addCsvJson"]').exists()).to.equal(false)
expect(wrapper.emitted('finish')).to.have.lengthOf(1) expect(wrapper.emitted('finish')).to.have.lengthOf(1)
}) })
@@ -699,16 +699,16 @@ describe('CsvImport.vue', () => {
messages: [] messages: []
}) })
await wrapper.vm.previewCsv() await wrapper.vm.preview()
await wrapper.vm.open() await wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-cancel').trigger('click') await wrapper.find('#import-cancel').trigger('click')
expect(wrapper.find('[data-modal="addCsv"]').exists()).to.equal(false) expect(wrapper.find('[data-modal="addCsvJson"]').exists()).to.equal(false)
expect(wrapper.vm.db.execute.calledOnceWith('DROP TABLE "my_data"')).to.equal(true) expect(wrapper.vm.db.execute.calledOnceWith('DROP TABLE "my_data"')).to.equal(true)
expect(wrapper.vm.db.refreshSchema.calledOnce).to.equal(true) expect(wrapper.vm.db.refreshSchema.calledOnce).to.equal(true)
expect(wrapper.emitted('cancel')).to.have.lengthOf(1) expect(wrapper.emitted('cancel')).to.have.lengthOf(1)
@@ -716,29 +716,29 @@ describe('CsvImport.vue', () => {
it('checks table name', async () => { it('checks table name', async () => {
sinon.stub(csv, 'parse').resolves() sinon.stub(csv, 'parse').resolves()
await wrapper.vm.previewCsv() await wrapper.vm.preview()
await wrapper.vm.open() await wrapper.vm.open()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.find('#csv-table-name input').setValue('foo') await wrapper.find('#csv-json-table-name input').setValue('foo')
await clock.tick(400) await clock.tick(400)
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
expect(wrapper.find('#csv-table-name .text-field-error').text()).to.equal('') expect(wrapper.find('#csv-json-table-name .text-field-error').text()).to.equal('')
wrapper.vm.db.validateTableName = sinon.stub().rejects(new Error('this is a bad table name')) wrapper.vm.db.validateTableName = sinon.stub().rejects(new Error('this is a bad table name'))
await wrapper.find('#csv-table-name input').setValue('bar') await wrapper.find('#csv-json-table-name input').setValue('bar')
await clock.tick(400) await clock.tick(400)
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
expect(wrapper.find('#csv-table-name .text-field-error').text()) expect(wrapper.find('#csv-json-table-name .text-field-error').text())
.to.equal('this is a bad table name. Try another table name.') .to.equal('this is a bad table name. Try another table name.')
await wrapper.find('#csv-table-name input').setValue('') await wrapper.find('#csv-json-table-name input').setValue('')
await clock.tick(400) await clock.tick(400)
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
expect(wrapper.find('#csv-table-name .text-field-error').text()).to.equal('') expect(wrapper.find('#csv-json-table-name .text-field-error').text()).to.equal('')
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
expect(wrapper.find('#csv-table-name .text-field-error').text()) expect(wrapper.find('#csv-json-table-name .text-field-error').text())
.to.equal("Table name can't be empty") .to.equal("Table name can't be empty")
expect(wrapper.vm.db.addTableFromCsv.called).to.equal(false) expect(wrapper.vm.db.addTableFromCsv.called).to.equal(false)
}) })

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai' import { expect } from 'chai'
import { mount, shallowMount } from '@vue/test-utils' import { mount, shallowMount } from '@vue/test-utils'
import DelimiterSelector from '@/components/CsvImport/DelimiterSelector' import DelimiterSelector from '@/components/CsvJsonImport/DelimiterSelector'
describe('DelimiterSelector', async () => { describe('DelimiterSelector', async () => {
it('shows the name of value', async () => { it('shows the name of value', async () => {

View File

@@ -153,16 +153,16 @@ describe('DbUploader.vue', () => {
} }
}) })
const CsvImport = wrapper.vm.$refs.addCsv const CsvImport = wrapper.vm.$refs.addCsvJson
sinon.stub(CsvImport, 'reset') sinon.stub(CsvImport, 'reset')
sinon.stub(CsvImport, 'previewCsv').resolves() sinon.stub(CsvImport, 'preview').resolves()
sinon.stub(CsvImport, 'open') sinon.stub(CsvImport, 'open')
await wrapper.find('.drop-area').trigger('click') await wrapper.find('.drop-area').trigger('click')
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
expect(CsvImport.reset.calledOnce).to.equal(true) expect(CsvImport.reset.calledOnce).to.equal(true)
await wrapper.vm.animationPromise await wrapper.vm.animationPromise
expect(CsvImport.previewCsv.calledOnce).to.equal(true) expect(CsvImport.preview.calledOnce).to.equal(true)
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
expect(CsvImport.open.calledOnce).to.equal(true) expect(CsvImport.open.calledOnce).to.equal(true)
wrapper.destroy() wrapper.destroy()
@@ -186,9 +186,9 @@ describe('DbUploader.vue', () => {
} }
}) })
const CsvImport = wrapper.vm.$refs.addCsv const CsvImport = wrapper.vm.$refs.addCsvJson
sinon.stub(CsvImport, 'reset') sinon.stub(CsvImport, 'reset')
sinon.stub(CsvImport, 'previewCsv').resolves() sinon.stub(CsvImport, 'preview').resolves()
sinon.stub(CsvImport, 'open') sinon.stub(CsvImport, 'open')
await wrapper.find('.drop-area').trigger('click') await wrapper.find('.drop-area').trigger('click')

View File

@@ -152,20 +152,20 @@ describe('Schema.vue', () => {
const store = new Vuex.Store({ state, actions, mutations }) const store = new Vuex.Store({ state, actions, mutations })
const wrapper = mount(Schema, { store, localVue }) const wrapper = mount(Schema, { store, localVue })
sinon.spy(wrapper.vm.$refs.addCsv, 'previewCsv') sinon.spy(wrapper.vm.$refs.addCsvJson, 'preview')
sinon.spy(wrapper.vm, 'addCsv') sinon.spy(wrapper.vm, 'addCsvJson')
sinon.spy(wrapper.vm.$refs.addCsv, 'loadFromCsv') sinon.spy(wrapper.vm.$refs.addCsvJson, 'loadToDb')
await wrapper.findComponent({ name: 'add-table-icon' }).find('svg').trigger('click') await wrapper.findComponent({ name: 'add-table-icon' }).find('svg').trigger('click')
await wrapper.vm.$refs.addCsv.previewCsv.returnValues[0] await wrapper.vm.$refs.addCsvJson.preview.returnValues[0]
await wrapper.vm.addCsv.returnValues[0] await wrapper.vm.addCsvJson.returnValues[0]
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
expect(wrapper.find('[data-modal="addCsv"]').exists()).to.equal(true) expect(wrapper.find('[data-modal="addCsvJson"]').exists()).to.equal(true)
await wrapper.find('#csv-import').trigger('click') await wrapper.find('#import-start').trigger('click')
await wrapper.vm.$refs.addCsv.loadFromCsv.returnValues[0] await wrapper.vm.$refs.addCsvJson.loadToDb.returnValues[0]
await wrapper.find('#csv-finish').trigger('click') await wrapper.find('#import-finish').trigger('click')
expect(wrapper.find('[data-modal="addCsv"]').exists()).to.equal(false) expect(wrapper.find('[data-modal="addCsvJson"]').exists()).to.equal(false)
await state.db.refreshSchema.returnValues[0] await state.db.refreshSchema.returnValues[0]
expect(wrapper.vm.$store.state.db.schema).to.eql([ expect(wrapper.vm.$store.state.db.schema).to.eql([