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

add tests in github actions

This commit is contained in:
lana-k
2021-01-13 21:51:04 +01:00
parent 3168c77c17
commit 6612f4444b
10 changed files with 191 additions and 154 deletions

30
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Run tests
on:
workflow_dispatch:
push:
branches:
- 'master'
jobs:
test:
name: Run karma tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: 10.x
- name: Install chromium
run:
sudo DEBIAN_FRONTEND=noninteractive apt-get update &&
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y chromium-browser
- name: Install the project
run: npm install
- name: Run lint
run: npm run lint
- name: Run tests
run: npm run test:unit

View File

@@ -1,31 +1,33 @@
// Karma configuration // Karma configuration
"use strict"; 'use strict'
const path = require("path"); const path = require('path')
const VueLoaderPlugin = require("vue-loader/lib/plugin"); const VueLoaderPlugin = require('vue-loader/lib/plugin')
function resolve(dir) { function resolve (dir) {
return path.join(__dirname, dir); return path.join(__dirname, dir)
} }
module.exports = function(config) { module.exports = function (config) {
config.set({ config.set({
// base path that will be used to resolve all patterns (eg. files, exclude) // base path that will be used to resolve all patterns (eg. files, exclude)
basePath: "", basePath: '',
// frameworks to use // frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ["mocha", "sinon-chai"], frameworks: ['mocha', 'sinon-chai'],
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files: [ files: [
"./karma.files.js", './karma.files.js',
{ pattern: 'node_modules/sql.js/dist/sql-wasm.wasm', {
pattern: 'node_modules/sql.js/dist/sql-wasm.wasm',
watched: false, watched: false,
included: false, included: false,
served: true, served: true,
nocache: false nocache: false
}, },
{ pattern: 'node_modules/sql.js/dist/worker.sql-wasm.js', {
pattern: 'node_modules/sql.js/dist/worker.sql-wasm.js',
watched: false, watched: false,
included: false, included: false,
served: true, served: true,
@@ -39,29 +41,29 @@ module.exports = function(config) {
// preprocess matching files before serving them to the browser // preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: { preprocessors: {
"./karma.files.js": ["webpack"] './karma.files.js': ['webpack']
}, },
// test results reporter to use // test results reporter to use
// possible values: 'dots', 'progress' // possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter // available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ["spec", "coverage"], reporters: ['spec', 'coverage'],
coverageReporter: { coverageReporter: {
dir: "coverage", dir: 'coverage',
reporters: [{ type: "lcov", subdir: "." }, { type: "text-summary" }] reporters: [{ type: 'lcov', subdir: '.' }, { type: 'text-summary' }]
}, },
// !!DONOT delete this reporter, or vue-cli-addon-ui-karma doesnot work // !!DONOT delete this reporter, or vue-cli-addon-ui-karma doesnot work
jsonResultReporter: { jsonResultReporter: {
outputFile: "report/karma-result.json", outputFile: 'report/karma-result.json',
isSynchronous: true isSynchronous: true
}, },
junitReporter: { junitReporter: {
outputDir: "report", // results will be saved as $outputDir/$browserName.xml outputDir: 'report', // results will be saved as $outputDir/$browserName.xml
outputFile: undefined, // if included, results will be saved as $outputDir/$browserName/$outputFile outputFile: undefined, // if included, results will be saved as $outputDir/$browserName/$outputFile
suite: "", // suite will become the package name attribute in xml testsuite element suite: '', // suite will become the package name attribute in xml testsuite element
useBrowserName: true, // add browser name to report and classes names useBrowserName: true, // add browser name to report and classes names
nameFormatter: undefined, // function (browser, result) to customize the name attribute in xml testcase element nameFormatter: undefined, // function (browser, result) to customize the name attribute in xml testcase element
classNameFormatter: undefined, // function (browser, result) to customize the classname attribute in xml testcase element classNameFormatter: undefined, // function (browser, result) to customize the classname attribute in xml testcase element
@@ -83,7 +85,7 @@ module.exports = function(config) {
// start these browsers // start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ["ChromiumHeadless"], browsers: ['ChromiumHeadless'],
// Continuous Integration mode // Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits // if true, Karma captures browsers, runs the tests and exits
@@ -98,16 +100,16 @@ module.exports = function(config) {
}, },
browserConsoleLogOptions: { browserConsoleLogOptions: {
terminal: true, terminal: true,
level: "" level: ''
}, },
webpack: { webpack: {
mode: "development", mode: 'development',
entry: "./src/main.js", entry: './src/main.js',
resolve: { resolve: {
extensions: [".js", ".vue", ".json"], extensions: ['.js', '.vue', '.json'],
alias: { alias: {
vue$: "vue/dist/vue.esm.js", vue$: 'vue/dist/vue.esm.js',
"@": resolve("src") '@': resolve('src')
} }
}, },
module: { module: {
@@ -117,7 +119,7 @@ module.exports = function(config) {
exclude: /(node_modules|bower_components)/, exclude: /(node_modules|bower_components)/,
use: [ use: [
{ {
loader: "babel-loader" loader: 'babel-loader'
} }
] ]
}, },
@@ -127,7 +129,7 @@ module.exports = function(config) {
exclude: /(node_modules|bower_components|\.spec\.js$|\/file)/, exclude: /(node_modules|bower_components|\.spec\.js$|\/file)/,
use: [ use: [
{ {
loader: "istanbul-instrumenter-loader", loader: 'istanbul-instrumenter-loader',
options: { options: {
esModules: true esModules: true
} }
@@ -136,34 +138,34 @@ module.exports = function(config) {
}, },
{ {
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: "url-loader" loader: 'url-loader'
}, },
{ {
test: /\.vue$/, test: /\.vue$/,
loader: "vue-loader", loader: 'vue-loader',
options: { options: {
loaders: { loaders: {
js: "babel-loader" js: 'babel-loader'
}, },
postLoaders: { postLoaders: {
js: "istanbul-instrumenter-loader?esModules=true" js: 'istanbul-instrumenter-loader?esModules=true'
} }
} }
}, },
{ {
test: /\.css$/, test: /\.css$/,
use: ["vue-style-loader", "css-loader"] use: ['vue-style-loader', 'css-loader']
}, },
{ {
test: /\.scss$/, test: /\.scss$/,
use: ["vue-style-loader", "css-loader", "sass-loader"] use: ['vue-style-loader', 'css-loader', 'sass-loader']
}, },
{ {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: "url-loader", loader: 'url-loader',
options: { options: {
limit: 10000, limit: 10000,
name: resolve("fonts/[name].[hash:7].[ext]") name: resolve('fonts/[name].[hash:7].[ext]')
} }
} }
] ]
@@ -174,7 +176,7 @@ module.exports = function(config) {
} }
}, },
proxies: { proxies: {
"/js/": "/base/node_modules/sql.js/dist/" '/js/': '/base/node_modules/sql.js/dist/'
} }
}); })
}; }

View File

@@ -1,16 +1,16 @@
import Vue from "vue"; import Vue from 'vue'
Vue.config.productionTip = false; Vue.config.productionTip = false
// require all test files (files that ends with .spec.js) // require all test files (files that ends with .spec.js)
const testsContext = require.context("./tests/unit", true, /\.spec.js$/); const testsContext = require.context('./tests/unit', true, /\.spec.js$/)
// Read more about why we need to call testContext: // Read more about why we need to call testContext:
// https://www.npmjs.com/package/require-context#context-api // https://www.npmjs.com/package/require-context#context-api
testsContext.keys().forEach(testsContext); testsContext.keys().forEach(testsContext)
// require all src files except main.js for coverage. // require all src files except main.js for coverage.
// you can also change this to match only the subset of files that // you can also change this to match only the subset of files that
// you want coverage for. // you want coverage for.
const srcContext = require.context("./src", true, /^\.\/(?!main(\.js)?$)/); const srcContext = require.context('./src', true, /^\.\/(?!main(\.js)?$)/)
srcContext.keys().forEach(srcContext); srcContext.keys().forEach(srcContext)

22
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "sqliteviz", "name": "sqliteviz",
"version": "0.6.0", "version": "1.0.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "sqliteviz", "name": "sqliteviz",
"version": "0.6.0", "version": "1.0.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"codemirror": "^5.57.0", "codemirror": "^5.57.0",
@@ -34,7 +34,7 @@
"@vue/cli-plugin-vuex": "^4.4.0", "@vue/cli-plugin-vuex": "^4.4.0",
"@vue/cli-service": "^4.4.0", "@vue/cli-service": "^4.4.0",
"@vue/eslint-config-standard": "^5.1.2", "@vue/eslint-config-standard": "^5.1.2",
"@vue/test-utils": "^1.0.3", "@vue/test-utils": "^1.1.2",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"chai": "^4.1.2", "chai": "^4.1.2",
"eslint": "^6.7.2", "eslint": "^6.7.2",
@@ -2166,14 +2166,18 @@
} }
}, },
"node_modules/@vue/test-utils": { "node_modules/@vue/test-utils": {
"version": "1.0.3", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.0.3.tgz", "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.1.2.tgz",
"integrity": "sha512-mmsKXZSGfvd0bH05l4SNuczZ2MqlJH2DWhiul5wJXFxbf/gRRd2UL4QZgozEMQ30mRi9i4/+p4JJat8S4Js64Q==", "integrity": "sha512-utbIL7zn9c+SjhybPwh48lpWCiluFCbP1yyRNAy1fQsw/6hiNFioaWy05FoVAFIZXC5WwBf+5r4ypfM1j/nI4A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"dom-event-types": "^1.0.0", "dom-event-types": "^1.0.0",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"pretty": "^2.0.0" "pretty": "^2.0.0"
},
"peerDependencies": {
"vue": "2.x",
"vue-template-compiler": "^2.x"
} }
}, },
"node_modules/@vue/web-component-wrapper": { "node_modules/@vue/web-component-wrapper": {
@@ -24288,9 +24292,9 @@
"dev": true "dev": true
}, },
"@vue/test-utils": { "@vue/test-utils": {
"version": "1.0.3", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.0.3.tgz", "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.1.2.tgz",
"integrity": "sha512-mmsKXZSGfvd0bH05l4SNuczZ2MqlJH2DWhiul5wJXFxbf/gRRd2UL4QZgozEMQ30mRi9i4/+p4JJat8S4Js64Q==", "integrity": "sha512-utbIL7zn9c+SjhybPwh48lpWCiluFCbP1yyRNAy1fQsw/6hiNFioaWy05FoVAFIZXC5WwBf+5r4ypfM1j/nI4A==",
"dev": true, "dev": true,
"requires": { "requires": {
"dom-event-types": "^1.0.0", "dom-event-types": "^1.0.0",

View File

@@ -6,7 +6,7 @@
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
"build": "NODE_OPTIONS=--max_old_space_size=4096 vue-cli-service build", "build": "NODE_OPTIONS=--max_old_space_size=4096 vue-cli-service build",
"test:unit": "vue-cli-service test:unit", "test:unit": "vue-cli-service karma",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
@@ -35,7 +35,7 @@
"@vue/cli-plugin-vuex": "^4.4.0", "@vue/cli-plugin-vuex": "^4.4.0",
"@vue/cli-service": "^4.4.0", "@vue/cli-service": "^4.4.0",
"@vue/eslint-config-standard": "^5.1.2", "@vue/eslint-config-standard": "^5.1.2",
"@vue/test-utils": "^1.0.3", "@vue/test-utils": "^1.1.2",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"chai": "^4.1.2", "chai": "^4.1.2",
"eslint": "^6.7.2", "eslint": "^6.7.2",

View File

@@ -2,15 +2,15 @@ import { expect } from 'chai'
import initSqlJs from 'sql.js' import initSqlJs from 'sql.js'
import db from '@/database.js' import db from '@/database.js'
const config = { const config = {
locateFile: filename => `js/sql-wasm.wasm` locateFile: filename => 'js/sql-wasm.wasm'
} }
describe('database.js', () => { describe('database.js', () => {
it('creates schema', () => { it('creates schema', () => {
return initSqlJs(config) return initSqlJs(config)
.then(SQL => { .then(SQL => {
const database = new SQL.Database() const database = new SQL.Database()
database.run(` database.run(`
CREATE TABLE test ( CREATE TABLE test (
col1, col1,
col2 integer, col2 integer,
@@ -19,53 +19,53 @@ describe('database.js', () => {
) )
`) `)
const data = database.export() const data = database.export()
const buffer = new Blob([data]) const buffer = new Blob([data])
return db.loadDb(buffer) return db.loadDb(buffer)
}) })
.then(({dbName, schema}) => { .then(({ dbName, schema }) => {
expect(schema).to.have.lengthOf(1) expect(schema).to.have.lengthOf(1)
expect(schema[0].name).to.equal('test') expect(schema[0].name).to.equal('test')
expect(schema[0].columns[0].name).to.equal('col1') expect(schema[0].columns[0].name).to.equal('col1')
expect(schema[0].columns[0].type).to.equal('N/A') expect(schema[0].columns[0].type).to.equal('N/A')
expect(schema[0].columns[1].name).to.equal('col2') expect(schema[0].columns[1].name).to.equal('col2')
expect(schema[0].columns[1].type).to.equal('integer') expect(schema[0].columns[1].type).to.equal('integer')
expect(schema[0].columns[2].name).to.equal('col3') expect(schema[0].columns[2].name).to.equal('col3')
expect(schema[0].columns[2].type).to.equal('decimal(5, 2)') expect(schema[0].columns[2].type).to.equal('decimal(5, 2)')
expect(schema[0].columns[3].name).to.equal('col4') expect(schema[0].columns[3].name).to.equal('col4')
expect(schema[0].columns[3].type).to.equal('varchar(30)') expect(schema[0].columns[3].type).to.equal('varchar(30)')
}) })
}) })
it('creates schema with virtual table', () => { it('creates schema with virtual table', () => {
return initSqlJs(config) return initSqlJs(config)
.then(SQL => { .then(SQL => {
const database = new SQL.Database() const database = new SQL.Database()
database.run(` database.run(`
CREATE VIRTUAL TABLE test_virtual USING fts4( CREATE VIRTUAL TABLE test_virtual USING fts4(
col1, col2, col1, col2,
notindexed=col1, notindexed=col2, notindexed=col1, notindexed=col2,
tokenize=unicode61 "tokenchars=.+#") tokenize=unicode61 "tokenchars=.+#")
`) `)
const data = database.export() const data = database.export()
const buffer = new Blob([data]) const buffer = new Blob([data])
return db.loadDb(buffer) return db.loadDb(buffer)
}) })
.then(({dbName, schema}) => { .then(({ dbName, schema }) => {
expect(schema[0].name).to.equal('test_virtual') expect(schema[0].name).to.equal('test_virtual')
expect(schema[0].columns[0].name).to.equal('col1') expect(schema[0].columns[0].name).to.equal('col1')
expect(schema[0].columns[0].type).to.equal('N/A') expect(schema[0].columns[0].type).to.equal('N/A')
expect(schema[0].columns[1].name).to.equal('col2') expect(schema[0].columns[1].name).to.equal('col2')
expect(schema[0].columns[1].type).to.equal('N/A') expect(schema[0].columns[1].type).to.equal('N/A')
}) })
}) })
it('returns a query result', () => { it('returns a query result', () => {
return initSqlJs(config) return initSqlJs(config)
.then(SQL => { .then(SQL => {
const database = new SQL.Database() const database = new SQL.Database()
database.run(` database.run(`
CREATE TABLE test ( CREATE TABLE test (
id integer, id integer,
name varchar(100), name varchar(100),
@@ -77,33 +77,33 @@ describe('database.js', () => {
( 2, 'Draco Malfoy', 'Slytherin'); ( 2, 'Draco Malfoy', 'Slytherin');
`) `)
const data = database.export() const data = database.export()
const buffer = new Blob([data]) const buffer = new Blob([data])
return db.loadDb(buffer) return db.loadDb(buffer)
}) })
.then(({dbName, schema}) => { .then(({ dbName, schema }) => {
return db.execute('SELECT * from test') return db.execute('SELECT * from test')
}) })
.then(result => { .then(result => {
expect(result.columns).to.have.lengthOf(3) expect(result.columns).to.have.lengthOf(3)
expect(result.columns[0]).to.equal('id') expect(result.columns[0]).to.equal('id')
expect(result.columns[1]).to.equal('name') expect(result.columns[1]).to.equal('name')
expect(result.columns[2]).to.equal('faculty') expect(result.columns[2]).to.equal('faculty')
expect(result.values).to.have.lengthOf(2) expect(result.values).to.have.lengthOf(2)
expect(result.values[0][0]).to.equal(1) expect(result.values[0][0]).to.equal(1)
expect(result.values[0][1]).to.equal('Harry Potter') expect(result.values[0][1]).to.equal('Harry Potter')
expect(result.values[0][2]).to.equal('Griffindor') expect(result.values[0][2]).to.equal('Griffindor')
expect(result.values[1][0]).to.equal(2) expect(result.values[1][0]).to.equal(2)
expect(result.values[1][1]).to.equal('Draco Malfoy') expect(result.values[1][1]).to.equal('Draco Malfoy')
expect(result.values[1][2]).to.equal('Slytherin') expect(result.values[1][2]).to.equal('Slytherin')
}) })
}) })
it('returns an error', () => { it('returns an error', () => {
return initSqlJs(config) return initSqlJs(config)
.then(SQL => { .then(SQL => {
const database = new SQL.Database() const database = new SQL.Database()
database.run(` database.run(`
CREATE TABLE test ( CREATE TABLE test (
id integer, id integer,
name varchar(100), name varchar(100),
@@ -115,16 +115,15 @@ describe('database.js', () => {
( 2, 'Draco Malfoy', 'Slytherin'); ( 2, 'Draco Malfoy', 'Slytherin');
`) `)
const data = database.export() const data = database.export()
const buffer = new Blob([data]) const buffer = new Blob([data])
return db.loadDb(buffer) return db.loadDb(buffer)
}) })
.then(() => { .then(() => {
return db.execute('SELECT * from foo') return db.execute('SELECT * from foo')
}) })
.catch(result => { .catch(result => {
console.log(result) expect(result).to.equal('no such table: foo')
expect(result).to.equal('no such table: foo') })
})
}) })
}) })

View File

@@ -17,9 +17,12 @@ describe('mutations', () => {
const state = {} const state = {}
const schema = [ const schema = [
{ name: 'table1', columns: [ {
{ name: 'id', type: 'INTEGER' } name: 'table1',
]} columns: [
{ name: 'id', type: 'INTEGER' }
]
}
] ]
saveSchema(state, { saveSchema(state, {
dbName: 'test', dbName: 'test',
@@ -323,7 +326,7 @@ describe('mutations', () => {
it('setCurrentTab', () => { it('setCurrentTab', () => {
// mock state // mock state
const state = { const state = {
currentTab: { id: 1} currentTab: { id: 1 }
} }
setCurrentTab(state, { id: 2 }) setCurrentTab(state, { id: 2 })
@@ -372,7 +375,6 @@ describe('mutations', () => {
}) })
}) })
describe('actions', () => { describe('actions', () => {
it('addTab (new)', async () => { it('addTab (new)', async () => {
// mock state // mock state
@@ -429,8 +431,8 @@ describe('actions', () => {
// mock state // mock state
const state = { const state = {
tabs: [ tab1, tab2 ], tabs: [tab1, tab2],
untitledLastIndex: 0, untitledLastIndex: 0
} }
await addTab({ state }, tab1) await addTab({ state }, tab1)

View File

@@ -2,7 +2,7 @@ import { expect } from 'chai'
import storedQueries from '@/storedQueries.js' import storedQueries from '@/storedQueries.js'
describe('storedQueries.js', () => { describe('storedQueries.js', () => {
beforeEach(()=> { beforeEach(() => {
localStorage.removeItem('myQueries') localStorage.removeItem('myQueries')
}) })
@@ -14,7 +14,7 @@ describe('storedQueries.js', () => {
it('getStoredQueries', () => { it('getStoredQueries', () => {
const data = [ const data = [
{ id: 1 }, { id: 1 },
{ id: 2 }, { id: 2 }
] ]
storedQueries.updateStorage(data) storedQueries.updateStorage(data)
const queries = storedQueries.getStoredQueries() const queries = storedQueries.getStoredQueries()
@@ -23,7 +23,7 @@ describe('storedQueries.js', () => {
it('duplicateQuery', () => { it('duplicateQuery', () => {
const now = new Date() const now = new Date()
const nowPlusMinute = new Date(now.getTime() + 60*1000) const nowPlusMinute = new Date(now.getTime() + 60 * 1000)
const base = { const base = {
id: 1, id: 1,
name: 'foo', name: 'foo',
@@ -43,14 +43,14 @@ describe('storedQueries.js', () => {
}) })
it('isTabNeedName returns false when the query has a name and is not predefined', () => { it('isTabNeedName returns false when the query has a name and is not predefined', () => {
let tab = { const tab = {
initName: 'foo' initName: 'foo'
} }
expect(storedQueries.isTabNeedName(tab)).to.be.false expect(storedQueries.isTabNeedName(tab)).to.be.false
}) })
it('isTabNeedName returns true when the query has no name and is not predefined', () => { it('isTabNeedName returns true when the query has no name and is not predefined', () => {
let tab = { const tab = {
initName: null, initName: null,
tempName: 'Untitled' tempName: 'Untitled'
} }
@@ -58,7 +58,7 @@ describe('storedQueries.js', () => {
}) })
it('isTabNeedName returns true when the qiery is predefined', () => { it('isTabNeedName returns true when the qiery is predefined', () => {
let tab = { const tab = {
initName: 'foo', initName: 'foo',
isPredefined: true isPredefined: true
} }

View File

@@ -18,9 +18,9 @@ module.exports = {
svgRule.uses.clear() svgRule.uses.clear()
svgRule svgRule
.use('url-loader') .use('url-loader')
.loader('url-loader') .loader('url-loader')
.options({ .options({
limit: 10000 limit: 10000
}) })
} }
} }