how to setup visual studio code - npm

been working with visual studio code and I am trying to use the built debugger. I have found examples and have tried to set it up. I have successfully got the gulp serve task setup and it runs correctly with the command
⇧⌘B
not the actual play button in the debugger tab. The examples I have found for debugging with the chrome extension does not include grunt or gulp automated tasks. Is it possible to use the gulp tasks and the debugger?
launch.json
{
"version": "0.2.0",
"configurations": [
{
"request": "launch",
// Name of configuration; appears in the launch configuration drop down menu.
"name": "node gulp.js ..",
// Type of configuration. Possible values: "node", "mono".
"type": "node",
// Workspace relative or absolute path to the program.
"program": "${workspaceRoot}./node_modules/gulp/bin/gulp.js",
// Automatically stop program after launch.
"stopOnEntry": true,
// Command line arguments passed to the program.
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
],
// Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.
"cwd": "${workspaceRoot}.",
// Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH.
"runtimeExecutable": "${execPath}",
// Optional arguments passed to the runtime executable.
"runtimeArgs": [],
// Environment variables passed to the program.
"env": {},
// Use JavaScript source maps (if they exist).
"sourceMaps": false,
// If JavaScript source maps are enabled, the generated code is expected in this directory.
"outDir": "${workspaceRoot}out"
}
]
}
tasks.json
{
// See http://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "0.1.0",
"command": "gulp",
"isShellCommand": true,
"args": [
"--no-color"
],
"tasks": [
{
"taskName": "serve",
"args": [],
"isBuildCommand": true,
"isWatching": true,
"problemMatcher": [
"$lessCompile",
"$tsc",
"$jshint"
]
}
]
}
gulp.config.js
module.exports = function($, usehtml) {
// distribution folder
var dist = 'app/';
var source = 'src/'; // for abs path construction
var markupEngine = usehtml ? 'html' : 'jade';
var markupExt = '.' + markupEngine;
// main source folders
var srcLESS = source + 'less/';
var srcSCSS = source + 'scss/';
var srcHTML = source + markupEngine + '/';
var srcJS = source + 'js/';
// Shared config object
var config = {
// ---
// Paths
// ---
dist: dist,
distCSS: dist + 'css',
distJS: dist + 'js',
source: source,
srcLESS: srcLESS,
srcSCSS: srcSCSS,
srcHTML: srcHTML,
srcJS: srcJS,
html: {
index: [srcHTML + 'index' + markupExt],
views: [
srcHTML + '**/*' + markupExt,
'!'+srcHTML + 'index' + markupExt
],
templates: [
srcHTML + 'views/sidebar/*' + markupExt,
srcHTML + 'views/navbar/*' + markupExt,
srcHTML + 'views/layers/*' + markupExt,
srcHTML + 'views/filters/*' + markupExt,
srcHTML + 'views/modals/*' + markupExt
],
all: [srcHTML + '**/*' + markupExt]
},
less: {
styles: [srcLESS + 'styles.less'],
watch: [srcLESS + 'app/**/*.less'],
bootstrap: [srcLESS + 'bootstrap/bootstrap.less']
},
scss: {
styles: [srcSCSS + 'styles.scss'],
watch: [srcSCSS + 'app/**/*.scss'],
bootstrap: [srcSCSS + 'bootstrap.scss']
},
js: [srcJS + 'app.module.js', srcJS + 'modules/**/*.js', srcJS + 'custom/**/*.js'],
// ---
// Plugins
// ---
plato: {
js: srcJS + '**/*.js'
},
report: './report/',
tplcache: {
file: 'templates.js',
opts: {
standalone: false,
root: 'templates',
module: 'insight'
}
},
webserver: {
webroot: '.',
host: 'localhost',
port: '3000',
livereload: true,
directoryListing: false
},
prettify: {
indent_char: ' ',
indent_size: 3,
unformatted: ['a', 'sub', 'sup', 'b', 'i', 'u']
},
usemin: {
path: '.',
css: [$.minifyCss({ processImport: false }), 'concat', $.rev()],
// html: [$.minifyHtml({empty: true})],
vendor: [$.uglify( {preserveComments:'some'} ), $.rev()],
js: [$.ngAnnotate(), $.uglify( {preserveComments:'some'} ), $.rev()]
}
};
// scripts to check with jshint
config.lintJs = [].concat(config.js, config.distJS);
return config;
};
gulpfile.js
var argv = require('yargs').argv;
var usehtml = true;
var usertl = argv.usertl;
var usescss = argv.usescss;
var gulp = require('gulp'),
$ = require('gulp-load-plugins')(),
gutil = require('gulp-util'),
gulpsync = require('gulp-sync')(gulp),
path = require('path'),
glob = require('glob'),
del = require('del'),
runSequence = require('run-sequence'),
config = require('./gulp.config')($, usehtml);
// production mode
var isProduction = false;
//---------------
// TASKS
//---------------
// APP LESS
gulp.task('styles', function () {
log('Compiling styles to CSS..');
var stylesSrc = usescss ? config.scss.styles : config.less.styles;
return gulp.src(stylesSrc)
.pipe(isProduction ? gutil.noop() : $.sourcemaps.init())
.pipe(usescss ? $.sass() : $.less())
.on("error", handleError)
.pipe($.if(usertl, $.rtlcss()))
.pipe(isProduction ? $.minifyCss({processImport: false}) : gutil.noop())
.pipe(isProduction ? gutil.noop() : $.sourcemaps.write())
.pipe(gulp.dest(config.distCSS));
});
// BOOSTRAP
gulp.task('bootstrap', function () {
log('Compiling Bootstrap..');
var bsSrc = usescss ? config.scss.bootstrap : config.less.bootstrap;
return gulp.src(bsSrc)
.pipe(isProduction ? gutil.noop() : $.sourcemaps.init())
.pipe(usescss ? $.sass() : $.less())
.on("error", handleError)
.pipe($.if(usertl, $.rtlcss()))
.pipe(isProduction ? $.minifyCss({processImport: false}) : gutil.noop())
.pipe(isProduction ? gutil.noop() : $.sourcemaps.write())
.pipe(gulp.dest(config.distCSS));
});
// HTML
gulp.task('markup', ['index', 'views']);
gulp.task('views', buildMarkup(config.html.views, config.dist));
gulp.task('index', ['templatecache'], buildMarkup(config.html.index, '.', false, true));
gulp.task('templatecache', ['clean-scripts'], buildMarkup(config.html.templates, config.dist + 'js', true));
// SERVER
// -----------------------------------
gulp.task('webserver', function () {
log('Starting web server.. ');
return gulp.src(config.webserver.webroot)
.pipe($.webserver(config.webserver));
});
//---------------
// WATCH
//---------------
// Rerun the task when a file changes
gulp.task('watch', function () {
log('Starting watch with live reload ...');
$.livereload.listen();
if (usescss) gulp.watch([config.scss.watch, config.scss.styles], ['styles']);
else gulp.watch([config.less.watch, config.less.styles], ['styles']);
if (usescss) gulp.watch(config.scss.bootstrap, ['bootstrap']);
else gulp.watch(config.less.bootstrap, ['bootstrap']);
gulp.watch(config.html.all, ['markup']);
gulp.watch(config.html.templates, ['templatecache']);
gulp
.watch([].concat(config.less.watch, config.html.views, config.html.templates, config.js))
.on('change', function (event) {
setTimeout(function () {
$.livereload.changed(event.path);
}, 1400);
});
});
/**
* Clean
*/
gulp.task('clean', ['clean-scripts', 'clean-styles', 'clean-markup']);
gulp.task('clean-scripts', function (cb) {
var js = config.distJS + '/*{js,map}';
clean(js, cb);
});
gulp.task('clean-styles', function (cb) {
var css = config.distCSS + '/*{css,map}';
clean(css, cb);
});
gulp.task('clean-markup', function (cb) {
var html = ['index.html', config.dist + 'views/'];
clean(html, cb);
});
gulp.task('clean-build', function (cb) {
log('Removing development assets');
var delFiles = [
config.distJS + '/' + config.tplcache.file,
config.distCSS + '/bootstrap.css',
config.distCSS + '/styles.css'
];
clean(delFiles, cb);
});
/**
* vet the code and create coverage report
*/
gulp.task('lint', function () {
log('Analyzing source with JSHint');
return gulp
.src(config.lintJs)
.pipe($.jshint())
.pipe($.jshint.reporter('jshint-stylish', {verbose: true}))
.pipe($.jshint.reporter('fail'));
});
//---------------
// Visualizer report
//---------------
gulp.task('plato', function (done) {
log('Analyzing source with Plato');
log('Browse to /report/plato/index.html to see Plato results');
startPlatoVisualizer(done);
});
//---------------
// MAIN TASKS
//---------------
// build for production
gulp.task('build', [], function (cb) {
runSequence('clean', 'production', 'compile', 'clean-build', cb);
});
gulp.task('production', function () {
isProduction = true;
});
// default (no minify, sourcemaps and watch)
gulp.task('default', function (callback) {
runSequence('clean', 'compile', 'watch', 'done', callback);
}).task('done', done);
// serve development by default
gulp.task('serve', function (cb) {
runSequence('default', 'webserver', cb);
});
// optional serve production
gulp.task('serve-build', function (cb) {
runSequence('build', 'webserver', cb);
});
// run tasks without watch
gulp.task('compile', function (cb) {
runSequence(
'bootstrap',
'styles',
'templatecache',
'markup',
cb);
});
/////////////////
/**
* Error handler
*/
function handleError(err) {
console.log(err.toString());
this.emit('end');
}
/**
* Build html templates
* #param {string} src source files folder
* #param {string} dst target folder
* #param {boolean} useTplcache Should generate angular template cache
* #return {stream}
*/
function buildMarkup(src, dst, useTplcache, useMin) {
return function () {
log('Compiling HTML...');
if (useTplcache) log('Creating AngularJS templateCache..');
return gulp.src(src)
.pipe(isProduction ? gutil.noop() : $.changed(dst, {extension: '.html'}))
.pipe($.if(!usehtml, $.jade({
locals: {
scripts: glob.sync(config.source + 'js/**/*.js')
}
})
)
)
.on("error", handleError)
.pipe($.htmlPrettify(config.prettify))
// .pipe($.angularHtmlify())
.pipe(isProduction && useMin ?
$.usemin(config.usemin)
: gutil.noop()
)
.pipe(useTplcache ?
$.angularTemplatecache(config.tplcache.file, config.tplcache.opts)
: gutil.noop()
)
.pipe(gulp.dest(dst))
;
}
}
/**
* Delete all files in a given path
* #param {Array} path - array of paths to delete
* #param {Function} done - callback when complete
*/
function clean(path, done) {
log('Cleaning: ' + $.util.colors.blue(path));
del(path, done);
}
/**
* Start Plato inspector and visualizer
*/
function startPlatoVisualizer(done) {
log('Running Plato');
var files = glob.sync(config.plato.js);
var excludeFiles = /.*\.spec\.js/;
var plato = require('plato');
var options = {
title: 'Plato Inspections Report',
exclude: excludeFiles
};
var outputDir = config.report + 'plato/';
plato.inspect(files, outputDir, options, platoCompleted);
function platoCompleted(report) {
var overview = plato.getOverviewReport(report);
log(overview.summary);
if (done) {
done();
}
}
}
/**
* Just to be polite :)
*/
function done() {
setTimeout(function () { // it's more clear to show msg after all
log('Done.. Watching code and reloading on changes..');
}, 500);
};
/**
* Standard log
*/
function log(msg) {
var prefix = '*** ';
gutil.log(prefix + msg);
}

It seems there are multiple errors in your launch config.
Some of the paths in your config are wrong. for example:
"${workspaceRoot}./node_modules/gulp/bin/gulp.js"
should be
"${workspaceRoot}/node_modules/gulp/bin/gulp.js"
${workspaceRoot} is a placeholder for the absolute path to your workspace. You cannot use relative path syntax like ./[relativepath] in launch.json. just replace . with ${workspaceRoot}.
If you are using "type": "node" in your launch config "program": "${workspaceRoot}/node_modules/gulp/bin/gulp.js" should point to the index file of your node application and not to the gulp executable.
In your gulp file it looks like you are trying to debug a website. In this case you should use Debugger for Chrome or Debugger for Edge vscode extension

Related

How can I eject quasar cli and use Vue + Quasar UMD?

I'm using Quasar for SPA only. But I don't need all the things that come with Quasar CLI.
Is there a way to eject Quasar CLI and start using Vue + Quasar UMD?
Basically, stop using quasar dev and start using vue serve?
Yes, you can. The following changes should be made:
// vue.config.js
const QuasarLoader = require('./quasar-loader/index');
module.exports =
{
css:
{
loaderOptions:
{
scss:
{
prependData: `#import "~quasar/src/css/variables.sass";`
}
}
},
transpileDependencies: ['quasar'],
configureWebpack: (config) =>
{
if (!config.plugins) config.plugins = [];
config.plugins.push(new QuasarLoader());
},
}
// quasar-loader/auto-import.js
/**
* Quasar runtime for auto-importing
* components or directives.
*
* Warning! This file does NOT get transpiled by Babel
* but is included into the UI code.
*
* #param component {Vue} Component object
* #param type {String} One of 'components' or 'directives'
* #param items {Object} Object containing components or directives
*/
module.exports = function quasarLoader(component, type, items)
{
/* we use a workaround in functional templates
<template>
<component :is="$options.components.QBtn" ... />
</template>
*/
var target, i;
var opt = component.options;
if (!opt[type])
{
opt[type] = items
}
else
{
target = opt[type];
for (i in items)
{
if (!target[i])
{
target[i] = items[i]
}
}
}
};
// quasar-loader/index.js
const RuleSet = require('webpack/lib/RuleSet');
let vueLoaderPath;
try
{
vueLoaderPath = require.resolve('vue-loader');
}
catch (err)
{}
function isVueLoader(use)
{
return use.ident === 'vue-loader-options' ||
use.loader === 'vue-loader' ||
(vueLoaderPath && use.loader === vueLoaderPath)
}
class QuasarLoaderPlugin
{
constructor(options)
{
this.options = options || {}
}
apply(compiler)
{
// use webpack's RuleSet utility to normalize user rules
const rawRules = compiler.options.module.rules;
const { rules } = new RuleSet(rawRules);
// find the rule that applies to vue files
const vueRuleIndex = rules.findIndex(rule => rule.use && rule.use.find(isVueLoader));
const vueRule = rules[vueRuleIndex];
if (!vueRule)
{
throw new Error(
`[QuasarLoaderPlugin Error] No matching rule for vue-loader found.\n` +
`Make sure there is at least one root-level rule that uses vue-loader.`
)
}
vueRule.use.unshift({
loader: require.resolve('./loader'),
options: this.options || { nameCase: 'kebab' }
});
compiler.options.module.rules = rules;
}
}
module.exports = QuasarLoaderPlugin;
// quasar-loader/loader.js
const path = require('path');
const compiler = require('vue-template-compiler');
// const loaderOptions = require('loader-utils/lib/getOptions');
const stringifyRequest = require('loader-utils/lib/stringifyRequest');
const importData = require('quasar/dist/babel-transforms/auto-import.json');
const importTransform = require('quasar/dist/babel-transforms/imports.js');
const runtimePath = require.resolve('./auto-import.js');
// regex to match functional components
const funcCompRegex = new RegExp(
'var\\s+component\\s*=\\s*normalizer\\((?:[^,]+,){3}\\s*true,'
);
function transform(itemArray)
{
return itemArray
.map(name => `import ${name} from '${importTransform(name)}'`)
.join(`\n`)
}
module.exports = async function (content, sourceMap)
{
this.async();
this.cacheable();
if (!this.resourceQuery)
{
const readFile = path => new Promise((resolve, reject) =>
{
this.fs.readFile(path, function (err, data)
{
if (err) reject(err);
else resolve(data)
})
});
this.addDependency(this.resourcePath);
const tags = new Set();
const directives = new Set();
const file = (await readFile(this.resourcePath)).toString('utf8');
const component = compiler.parseComponent(file);
if (component.template)
{
if (component.template.src)
{
const externalFile = (await new Promise((resolve, reject) =>
this.resolve(path.dirname(this.resourcePath), component.template.src, (err, result) =>
{
if (err) reject(err);
else resolve(result)
})
));
component.template.content = (await readFile(externalFile)).toString('utf8'); // external content
}
const compRegexKebab = new RegExp('^' + importData.regex.kebabComponents + '$');
const compRegexPascal = new RegExp('^' + importData.regex.pascalComponents + '$');
const dirRegex = new RegExp('^' + importData.regex.directives + '$');
compiler.compile(component.template.content, {
modules: [{
postTransformNode: node =>
{
if ("directives" in node)
{
node.directives.forEach(({ name }) =>
{
if (dirRegex.test('v-' + name))
{
directives.add(importData.importName['v-' + name]);
}
});
}
if (compRegexKebab.test(node.tag))
{
tags.add(importData.importName[node.tag]);
}
else if (compRegexPascal.test(node.tag))
{
tags.add(node.tag);
}
}
}]
});
const arrTags = [...tags];
const arrDirs = [...directives];
if (arrTags.length > 0 || arrDirs.length > 0)
{
const functional = funcCompRegex.test(content);
let newContent = '/* quasar-loader */\n';
newContent += `import qInstall from ${stringifyRequest(this, runtimePath)}\n`;
if (arrTags.length > 0)
{
if (functional) console.error('Using workaround for local Vue components (' + arrTags.join(',') + ') in a functional template.');
newContent += transform(arrTags) + '\n';
newContent += `qInstall(component, "components", {${arrTags.join(",")}})\n`;
}
if (arrDirs.length > 0)
{
if (functional) console.error('Using local Vue directive (' + arrDirs.join(',') + ') in a functional component is not supported.');
newContent += transform(arrDirs) + '\n';
newContent += `qInstall(component, "directives", {${arrDirs.join(",")}})\n`;
}
// Insert our modification before the HMR code
const hotReload = content.indexOf('/* hot reload */');
if (hotReload > -1)
{
content = content.slice(0, hotReload) + newContent + '\n\n' + content.slice(hotReload)
}
else
{
content += '\n\n' + newContent
}
}
}
}
this.callback(null, content, sourceMap);
};
// src/main.js
import QuasarInstall from 'quasar/src/vue-plugin'
import iconSet from 'quasar/icon-set/svg-mdi-v5'
// import QuasarDialog from 'quasar/src/plugins/Dialog'
import '#/assets/scss/quasar.scss'
QuasarInstall.install(Vue, {
iconSet,
plugins:
{
// Dialog: QuasarDialog,
},
});
// src/assets/scss/quasar.scss
$primary : #409EFF;
$secondary : #26A69A;
$accent : #9C27B0;
$dark : #1D1D1D;
$positive : #20A835;
$negative : #F04025;
$info : #1975D0;
$warning : #F2C037;
#import '~quasar/src/css/index.sass';
If you want to use Quasar and Vue without CLI at all, you can check this starter project.
It's just Quasar UMD (ver.2) and vanilla Vue (ver.3).
Github: https://github.com/SaleCar/Quasar-UMD-Template
Demo: http://quasar.rf.gd/

npm build error for Keen Bootstrap premium template

I just purchased the Keen theme from Bootstrap and whilst following the instructions to the letter I ran into an error executing 'npm run build' (see below). I've looked at the web pack.config.js file (see below), but as it's something I've not looked at in depth I can't figure out where the problem is. Any help will be greatly appreciated, thanks!
Error output:
0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'run', 'build' ]
2 info using npm#6.13.6
3 info using node#v13.8.0
4 verbose run-script [ 'prebuild', 'build', 'postbuild' ]
5 info lifecycle keen#1.4.2~prebuild: keen#1.4.2
6 info lifecycle keen#1.4.2~build: keen#1.4.2
7 verbose lifecycle keen#1.4.2~build: unsafe-perm in lifecycle true
8 verbose lifecycle keen#1.4.2~build: PATH: /usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/Users/julian/Downloads/compile/node_modules/.bin:/Users/julian/.rvm/gems/ruby-2.6.5/bin:/Users/julian/.rvm/gems/ruby-2.6.5#global/bin:/Users/julian/.rvm/rubies/ruby-2.6.5/bin:/Users/julian/.cargo/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public/:/Users/julian/.rvm/bin
9 verbose lifecycle keen#1.4.2~build: CWD: /Users/julian/Downloads/compile
10 silly lifecycle keen#1.4.2~build: Args: [ '-c', 'webpack' ]
11 silly lifecycle keen#1.4.2~build: Returned: code: 1 signal: null
12 info lifecycle keen#1.4.2~build: Failed to exec build script
13 verbose stack Error: keen#1.4.2 build: `webpack`
13 verbose stack Exit status 1
13 verbose stack at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:332:16)
13 verbose stack at EventEmitter.emit (events.js:321:20)
13 verbose stack at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack at ChildProcess.emit (events.js:321:20)
13 verbose stack at maybeClose (internal/child_process.js:1026:16)
13 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:286:5)
14 verbose pkgid keen#1.4.2
15 verbose cwd /Users/julian/Downloads/compile
16 verbose Darwin 19.3.0
17 verbose argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "build"
18 verbose node v13.8.0
19 verbose npm v6.13.6
20 error code ELIFECYCLE
21 error errno 1
22 error keen#1.4.2 build: `webpack`
22 error Exit status 1
23 error Failed at the keen#1.4.2 build script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]
webpack.config.js:
/**
* Main file of webpack config.
* Please do not modified unless you know what to do
*/
const path = require("path");
const glob = require("glob");
const webpack = require("webpack");
const fs = require("fs");
const parser = require("comment-parser");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const WebpackRTLPlugin = require("webpack-rtl-plugin");
const TerserJSPlugin = require("terser-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const WebpackMessages = require("webpack-messages");
const ExcludeAssetsPlugin = require("webpack-exclude-assets-plugin");
const atob = require("atob");
const slash = require("slash");
const del = require("del");
// optional
const ReplaceInFileWebpackPlugin = require("replace-in-file-webpack-plugin");
/**
* Known issues:
* 1) Remove webpack bootstrap for single-module apps
* https://github.com/webpack/webpack/issues/2638
*/
// arguments/params from the line command
const args = {};
// remove first 2 unused elements from array
const argv = JSON.parse(process.env.npm_config_argv).cooked.slice(2);
argv.forEach((arg, i) => {
if (arg.match(/^--/)) {
const next = argv[i + 1];
args[arg] = true;
if (next && !next.match(/^--/)) {
args[arg] = argv[i + 1];
}
}
});
// read parameters from the command executed by user
const rtl = args["--rtl"] || false;
const prod = args["--prod"] || false;
const css = args["--css"] || true;
const js = args["--js"] || true;
// theme name
const themeName = "keen";
// global variables
const release = true;
const apiUrl = false; // boolean
const rootPath = path.resolve(__dirname, "..");
const frameworkPath = path.resolve(__dirname, "..");
const distPath = rootPath + "/dist";
const configPath = rootPath + "/tools";
const assetDistPath = distPath + "/assets";
const srcPath = rootPath + "/src/assets";
// page scripts and styles
const pageScripts = glob.sync(srcPath + "/js/pages/**/!(_*).js");
const pagesScss = glob.sync(srcPath + "/sass/pages/**/!(_*).scss");
const extraPlugins = [];
const filesConfig = [];
const imageReference = {};
const exclude = [];
const nodeMedia = [];
// remove older folders and files
// (async () => {
// await del.sync(assetDistPath, {force: true});
// })();
// get all assets config
let files = glob.sync(configPath + "/webpack/**/*.js");
// parse comments to get the output location
files.forEach((filename) => {
// get file content
const text = fs.readFileSync(filename).toString();
// use parser plugin to parse the comment.
const parsed = parser(text);
if (parsed.length > 0 && parsed[0].tags.length > 0) {
// push to list
filesConfig.push({
filename: filename,
params: parsed[0].tags,
});
}
});
const entries = {};
filesConfig.forEach((file) => {
let output = "";
file.params.forEach((param) => {
// get output path
if (param.tag === "output") {
output = param.name;
}
});
entries[output] = file.filename;
});
// process skin scss
const skinScss = glob.sync(srcPath + "/sass/**/skins/**/!(_*|style*).scss");
skinScss.forEach((file) => {
const matched = file.match(/sass\/global\/layout\/(.*?)\.scss$/);
if (matched) {
entries["css/skins/" + matched[1].replace(/\/skins\//, "/")] = file;
}
});
// process pages scss
pagesScss.forEach((file) => {
const matched = file.match(/\/(pages\/.*?)\.scss$/);
if (matched) {
// keep image reference for output path rewrite
const imgMatched = fs.readFileSync(file).toString().match(/['|"](.*?\.(gif|png|jpe?g))['|"]/g);
if (imgMatched) {
imgMatched.forEach((img) => {
img = img.replace(/^['|"](.+(?=['|"]$))['|"]$/, '$1');
imageReference[path.basename(img)] = "css/" + matched[1] + ".css";
});
}
entries['css/' + matched[1]] = file;
}
});
// auto get page scripts from source
pageScripts.forEach(function (jsPath) {
const matched = jsPath.match(/js\/(pages\/.*?)\.js$/);
entries["js/" + matched[1]] = jsPath;
});
if (release) {
// copy html by demo
extraPlugins.push(new CopyWebpackPlugin([{
from: rootPath + "/src",
to: distPath,
}]));
}
if ((/true/i).test(rtl)) {
// enable rtl for css
extraPlugins.push(new WebpackRTLPlugin({
filename: "[name].rtl.css",
}));
}
if (!(/true/i).test(js)) {
// exclude js files
exclude.push('\.js$');
}
if (!(/true/i).test(css)) {
// exclude css files
exclude.push('\.s?css$');
}
if (exclude.length) {
// add plugin for exclude assets (js/css)
extraPlugins.push(new ExcludeAssetsPlugin({
path: exclude
}));
}
if (apiUrl) {
// replace api url to point to server
extraPlugins.push(new ReplaceInFileWebpackPlugin([{
dir: assetDistPath + "/js",
test: /\.js$/,
rules: [{
search: /inc\/api\//i,
replace: 'https://keenthemes.com/' + themeName + '/tools/preview/'
}]
}]));
}
const mainConfig = function () {
return {
// enabled/disable optimizations
mode: (/true/i).test(prod) ? "production" : "development",
// console logs output, https://webpack.js.org/configuration/stats/
stats: "errors-warnings",
performance: {
// disable warnings hint
hints: false
},
optimization: {
// js and css minimizer
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
},
entry: entries,
output: {
// main output path in assets folder
path: assetDistPath,
// output path based on the entries' filename
filename: "[name].js"
},
resolve: {
alias: {
"morris.js": "morris.js/morris.js",
"jquery-ui": "jquery-ui",
}
},
plugins: [
// webpack log message
new WebpackMessages({
name: themeName,
logger: str => console.log(`>> ${str}`)
}),
// create css file
new MiniCssExtractPlugin({
filename: "[name].css",
}),
// copy media
new CopyWebpackPlugin([{
from: srcPath + "/media",
to: assetDistPath + "/media",
}]),
{
apply: (compiler) => {
// hook name
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
filesConfig.forEach((file) => {
let output = "";
file.params.forEach((param) => {
// get output path
if (param.tag === "output") {
output = param.name;
}
if (param.tag === "images") {
param.name.split(",").forEach((file) => {
if (file) {
const outputPath = assetDistPath + "/" + pathWithoutFile(output) + "/images/";
// create dir
fs.mkdirSync(outputPath, {recursive: true});
// copy image
fs.copyFileSync(fs.realpathSync(srcPath + "/" + file), outputPath + path.basename(file));
}
});
}
});
});
});
}
},
].concat(extraPlugins),
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "sass-loader",
options: {
sourceMap: true,
// // use for separate css pages (custom pages, eg. wizard, invoices, etc.)
// includePaths: demos.map((demo) => {
// return slash(srcPath) + "/sass/theme/demos/" + demo;
// })
}
},
]
},
{
test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
include: [
path.resolve(__dirname, "node_modules"),
rootPath,
frameworkPath,
],
use: [
{
loader: "file-loader",
options: {
// prevent name become hash
name: "[name].[ext]",
// move files
outputPath: "plugins/global/fonts",
// rewrite path in css
publicPath: "fonts",
}
}
]
},
{
test: /\.(gif|png|jpe?g)$/,
include: [
path.resolve(__dirname, "node_modules"),
rootPath,
],
use: [{
loader: "file-loader",
options: {
// prevent name become hash
name: "[name].[ext]",
// move files
outputPath: (url, resourcePath) => {
// look for node_modules plugin
const matched = slash(resourcePath).match(/node_modules\/(.*?)\//);
if (matched) {
for (let i = 0; i < filesConfig.length; i++) {
if (filesConfig[i].filename.match(new RegExp(matched[1]))) {
let output = "";
filesConfig[i].params.forEach((param) => {
// get output path without filename
if (param.tag === "output") {
output = pathWithoutFile(param.name);
}
});
nodeMedia[url] = output + "/images/" + url;
return output + "/images/" + url;
}
}
}
// the rest of images put in media/misc/
return "media/misc/" + url;
},
// rewrite path in css
publicPath: (url, resourcePath) => {
if (imageReference[url]) {
// fix image rewrite path
const filePath = pathWithoutFile(imageReference[url]);
return slash(path.relative(assetDistPath + "/" + filePath, assetDistPath + "/media") + "/" + url);
}
if (nodeMedia[url]) {
return "images/" + url;
}
return "../../media/misc/" + url;
},
}
}]
},
]
},
// webpack dev server config
devServer: {
contentBase: distPath,
compress: true,
port: 3000
}
}
};
module.exports = function () {
return [mainConfig()];
};
function pathWithoutFile(filname) {
return filname.substring(0, filname.lastIndexOf("/"));
}
I just realized I forgot to include the src directory in the same parent directory as the included tools directory (:face_palm!)

Javascript task processing but not updating with new code

I am making edits to my JS files but my gulp task is not updating them live or writing new code. It did used to work but all of a sudden it has stopped.
I tried upgrading the gulp to version 4 but that just created more issues and didn't fix the fact the JS wasn't working.
Added jshint to see if that threw any errors but seems fine too.
'use strict';
const
// source and build folders
dir = {
src : './src/',
build : './'
},
// Gulp and plugins
gulp = require('gulp'),
gutil = require('gulp-util'),
newer = require('gulp-newer'),
imagemin = require('gulp-imagemin'),
sass = require('gulp-sass'),
postcss = require('gulp-postcss'),
deporder = require('gulp-deporder'),
concat = require('gulp-concat'),
stripdebug = require('gulp-strip-debug'),
uglify = require('gulp-uglify'),
ftp = require( 'vinyl-ftp' ),
jshint = require('gulp-jshint');
// configure the jshint task
gulp.task('jshint', function() {
return gulp.src(dir.src + '/assets/js/*.js')
.pipe(jshint())
.pipe(jshint.reporter('jshint-stylish'));
});
// Browser-sync
var browsersync = false;
//Dev FTP Connections
function getDevFtpConnection() {
return ftp.create({
host: '109.169.64.171',
// port: 20,
user: 'admin#powdersky.net',
password: '=Lx0$Zf=a}ZW',
parallel: 5,
log: gutil.log
});
}
//Deploy to dev
gulp.task('ftp-deploy-dev', function() {
var conn = getDevFtpConnection();
return gulp.src([dir.build + '/**/**/**/*',
"!./{src/,src/**/*}",
"!./{node_modules/,node_modules/**/**/**/*}",
"!./gulpfile.js",
"!./package-lock.json",
"!./package.json"], { base: '.', buffer: false })
.pipe( conn.newer( '/inthesnow.com/wp-content/themes/inthesnow/' ) ) // only upload newer files
.pipe( conn.dest( '/inthesnow.com/wp-content/themes/inthesnow/' ) )
;
});
// PHP settings
const php = {
src : dir.src + 'templates/**/*.php',
build : dir.build
};
// copy pugins files
gulp.task('php', () => {
return gulp.src([
dir.build + '/includes/**/**/**/*.php',
dir.build + '*.php'
])
.pipe(newer(dir.build))
.pipe(gulp.dest(dir.build))
.pipe(browsersync ? browsersync.reload({ stream: true }) : gutil.noop());
});
gulp.task('php-templates', () => {
return gulp.src([
dir.build + '*.php'
])
.pipe(newer(dir.build))
.pipe(gulp.dest(dir.build))
.pipe(browsersync ? browsersync.reload({ stream: true }) : gutil.noop());
});
// image settings
const images = {
src : dir.src + 'assets/images/**/*',
build : dir.build + 'assets/images/'
};
// image processing
gulp.task('images', () => {
return gulp.src(images.src)
.pipe(newer(images.build))
.pipe(imagemin())
.pipe(gulp.dest(images.build));
});
// CSS settings
var css = {
src : dir.src + 'assets/scss/style.scss',
watch : dir.src + 'assets/scss/**/**/*',
build : dir.build,
sassOpts: {
outputStyle : 'compressed',
imagePath : images.build,
precision : 3,
errLogToConsole : true
},
processors: [
require('postcss-assets')({
loadPaths: ['images/'],
basePath: dir.build,
baseUrl: '/wp-content/themes/inthesnow/'
}),
require('autoprefixer')({
browsers: ['last 2 versions', '> 2%']
}),
require('css-mqpacker'),
require('cssnano'),
]
};
// CSS processing
gulp.task('css', ['images'], () => {
return gulp.src([
css.src,
])
.pipe(sass(css.sassOpts))
.pipe(postcss(css.processors))
.pipe(concat('style.css'))
.pipe(gulp.dest(css.build))
.pipe(browsersync ? browsersync.reload({ stream: true }) : gutil.noop());
});
// Vendor JavaScript settings
const build_vendor_js = {
src : dir.src + 'assets/js/vendor/*',
build : dir.build + 'assets/js/',
filename : 'jquery.vendor.js'
};
// JavaScript processing
gulp.task('build_vendor_js', () => {
return gulp.src(build_vendor_js.src)
.pipe(deporder())
.pipe(concat(build_vendor_js.filename))
.pipe(stripdebug())
.pipe(uglify())
.pipe(gulp.dest(build_vendor_js.build))
.pipe(browsersync ? browsersync.reload({ stream: true }) : gutil.noop());
});
// General JavaScript processing
gulp.task('build_general_js', () => {
return gulp.src([
// dir.build + 'includes/plugins/**/assets/js/*.js',
dir.src + 'assets/js/*',
])
.pipe(deporder())
// .pipe(concat('jquery.functions.js'))
.pipe(stripdebug())
.pipe(uglify())
.pipe(gulp.dest(dir.build + 'assets/js/'))
.pipe(browsersync ? browsersync.reload({ stream: true }) : gutil.noop());
});
// run all tasks
gulp.task('build', ['css', 'build_vendor_js','build_general_js']);
// Browsersync options
const syncOpts = {
proxy : 'http://inthesnow',
reloadOnRestart: true,
ui: {
port: 8080
}
};
// browser-sync
gulp.task('browsersync', () => {
if (browsersync === false) {
browsersync = require('browser-sync').create();
browsersync.init(syncOpts);
}
});
// watch for file changes
gulp.task('watch', ['browsersync'], () => {
// page changes
// gulp.watch(php.src, ['php'], browsersync ? browsersync.reload : {});
// gulp.watch(php.src, ['php-templates'], browsersync ? browsersync.reload : {});
// image changes
gulp.watch(images.src, ['images']);
// CSS changes
gulp.watch(css.watch, ['css']);
// JavaScript main changes
gulp.watch([ dir.src + '/assets/js/*.js' ], ['jshint', 'build_general_js']);
//vendor
gulp.watch(build_vendor_js.src, ['build_vendor_js']);
});
gulp.task('default', ['build', 'watch']);
It seems to be correct to me but obviously not! I am assuming something may have updated that has triggered something but cant find which module it could be, the CSS task runs fine as well.
So this was me being silly, I didn't notice the stripdebug module which is was my alert/console.log wasn't working!
Rookie error

Running Protractor Tests Through Jenkins on Remote Selenium Server Getting No Specs Found

I am able to run tests locally on my remote selenium server and they run just fine.
When I go to run them on my Jenkins box on the same remote selenium server in Jenkins I am getting No Specs found, and in the output of my selenium server I am seeing the following:
21:33:41.256 INFO - Executing: [execute async script: try { return (function (attempts, ng12Hybrid, asyncCallback) {
var callback = function(args) {
setTimeout(function() {
asyncCallback(args);
}, 0);
};
var check = function(n) {
try {
if (!ng12Hybrid && window.getAllAngularTestabilities) {
callback({ver: 2});
} else if (window.angular && window.angular.resumeBootstrap) {
callback({ver: 1});
} else if (n < 1) {
if (window.angular) {
callback({message: 'angular never provided resumeBootstrap'});
} else {
callback({message: 'retries looking for angular exceeded'});
}
} else {
window.setTimeout(function() {check(n - 1);}, 1000);
}
} catch (e) {
callback({message: e});
}
};
check(attempts);
}).apply(this, arguments); }
catch(e) { throw (e instanceof Error) ? e : new Error(e); }, [10, false]])
21:33:41.273 INFO - Done: [execute async script: try { return (function (attempts, ng12Hybrid, asyncCallback) {
var callback = function(args) {
setTimeout(function() {
asyncCallback(args);
}, 0);
};
var check = function(n) {
try {
if (!ng12Hybrid && window.getAllAngularTestabilities) {
callback({ver: 2});
} else if (window.angular && window.angular.resumeBootstrap) {
callback({ver: 1});
} else if (n < 1) {
if (window.angular) {
callback({message: 'angular never provided resumeBootstrap'});
} else {
callback({message: 'retries looking for angular exceeded'});
}
} else {
window.setTimeout(function() {check(n - 1);}, 1000);
}
} catch (e) {
callback({message: e});
}
};
check(attempts);
}).apply(this, arguments); }
catch(e) { throw (e instanceof Error) ? e : new Error(e); }, [10, false]]
21:33:41.288 INFO - Executing: [execute script: return (function (trackOutstandingTimeouts) {
var ngMod = angular.module('protractorBaseModule_', []).config([
'$compileProvider',
function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(true);
}
}
]);
if (trackOutstandingTimeouts) {
ngMod.config([
'$provide',
function ($provide) {
$provide.decorator('$timeout', [
'$delegate',
function ($delegate) {
var $timeout = $delegate;
var taskId = 0;
if (!window['NG_PENDING_TIMEOUTS']) {
window['NG_PENDING_TIMEOUTS'] = {};
}
var extendedTimeout= function() {
var args = Array.prototype.slice.call(arguments);
if (typeof(args[0]) !== 'function') {
return $timeout.apply(null, args);
}
taskId++;
var fn = args[0];
window['NG_PENDING_TIMEOUTS'][taskId] =
fn.toString();
var wrappedFn = (function(taskId_) {
return function() {
delete window['NG_PENDING_TIMEOUTS'][taskId_];
return fn.apply(null, arguments);
};
})(taskId);
args[0] = wrappedFn;
var promise = $timeout.apply(null, args);
promise.ptorTaskId_ = taskId;
return promise;
};
extendedTimeout.cancel = function() {
var taskId_ = arguments[0] && arguments[0].ptorTaskId_;
if (taskId_) {
delete window['NG_PENDING_TIMEOUTS'][taskId_];
}
return $timeout.cancel.apply($timeout, arguments);
};
return extendedTimeout;
}
]);
}
]);
}
}).apply(null, arguments);, [true]])
21:33:41.312 INFO - Done: [execute script: return (function (trackOutstandingTimeouts) {
var ngMod = angular.module('protractorBaseModule_', []).config([
'$compileProvider',
function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(true);
}
}
]);
if (trackOutstandingTimeouts) {
ngMod.config([
'$provide',
function ($provide) {
$provide.decorator('$timeout', [
'$delegate',
function ($delegate) {
var $timeout = $delegate;
var taskId = 0;
if (!window['NG_PENDING_TIMEOUTS']) {
window['NG_PENDING_TIMEOUTS'] = {};
}
var extendedTimeout= function() {
var args = Array.prototype.slice.call(arguments);
if (typeof(args[0]) !== 'function') {
return $timeout.apply(null, args);
}
taskId++;
var fn = args[0];
window['NG_PENDING_TIMEOUTS'][taskId] =
fn.toString();
var wrappedFn = (function(taskId_) {
return function() {
delete window['NG_PENDING_TIMEOUTS'][taskId_];
return fn.apply(null, arguments);
};
})(taskId);
args[0] = wrappedFn;
var promise = $timeout.apply(null, args);
promise.ptorTaskId_ = taskId;
return promise;
};
extendedTimeout.cancel = function() {
var taskId_ = arguments[0] && arguments[0].ptorTaskId_;
if (taskId_) {
delete window['NG_PENDING_TIMEOUTS'][taskId_];
}
return $timeout.cancel.apply($timeout, arguments);
};
return extendedTimeout;
}
]);
}
]);
}
}).apply(null, arguments);, [true]]
Like I said, these run just fine locally, so I am not sure what is going on with my Jenkins machine.
Here is my protractor config file:
// Configuration constants
var downloadsFolder = 'test/downloads/',
today = ("0" + (new Date()).getDate()).slice(-2),
month = ("0" + ((new Date()).getMonth() + 1)).slice(-2),
baseUrl = 'BASE URL GOES HERE';
// Test report setup w/ screenshot
var HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter');
var reporter = new HtmlScreenshotReporter({
dest: 'test/report',
filename: 'e2e-report.html'
});
// Protractor config
exports.config = {
suites: {
explore: '.protractor/src/app/exploration/tests/exploration.scenario.js',
login: '.protractor/src/auth-app/login/tests/login.scenario.js',
stories: '.protractor/src/app/story/tests/story.scenario.js',
cohorts: '.protractor/src/app/cohort/tests/cohort.scenario.js',
visualize: '.protractor/src/app/visualize/tests/visualize.scenario.js'
},
baseUrl: 'BASE URL GOES HERE',
directConnect: false,
// Override default 11s timeout for long requests such as visualize's "Recommended Visualizations"
// See https://github.com/angular/protractor/blob/master/docs/timeouts.md
allScriptsTimeout: 25 * 1000,
jasmineNodeOpts: {
defaultTimeoutInterval: 90 * 1000
},
multiCapabilities: [
{
browserName: 'chrome',
seleniumAddress: "http://SELENIUM SERVER URL HERE:4444/wd/hub",
platform: 'ANY',
version: 'ANY',
chromeOptions: {
args: ['--no-sandbox', '--test-type=browser', '--lang=en', '--start-maximized'],
prefs: {
download: {
prompt_for_download: false,
directory_upgrade: true,
default_directory: 'test/downloads'
},
},
}
// shardTestFiles: true,
// maxInstances: 2
}
],
onPrepare: function() {
// Set browser window size
browser.driver.manage().window().maximize();
//Setup screenshots
jasmine.getEnv().addReporter(reporter);
browser.get('BASE URL GOES HERE');
},
// Setup the report before any tests start
beforeLaunch: function() {
return new Promise(function(resolve){
reporter.beforeLaunch(resolve);
});
},
// Close the report after all tests finish
afterLaunch: function(exitCode) {
return new Promise(function(resolve){
reporter.afterLaunch(resolve.bind(this, exitCode));
});
},
params: {
baseUrl: baseUrl,
downloadsFolder: 'test/downloads',
cohort: {
listView: baseUrl + 'cohorts',
newView: baseUrl + 'cohorts/new'
},
story: {
listView: baseUrl + 'stories',
newView: baseUrl + 'story/new',
displayView: baseUrl + 'story'
},
visualize: {
listView: baseUrl + 'visualize',
newView: baseUrl + 'visualize/new'
},
explore: {
listView: baseUrl + 'explorations',
newView: baseUrl + 'explorations/new',
excelFilename: downloadsFolder + `DataExport_2016-${month}-${today}.xlsx`,
csvFilename: downloadsFolder + `DataExport_2016-${month}-${today}.csv`,
maxDownloadTime: 10 * 1000
}
}
};
This boiled down to a permissions issue. Once I added my jenkins user to sudo I was able to do a make command on the project which built all of the necessary files and which also converted my typescript tests over to Javascript and allowed them to run.

Testing CouchDB views, filters, lists, shows etc

What testing frameworks are available to test views and it's map and reduce functions, filters, lists, shows etc. of my CouchDB?
Ideally the framework allows to unit test each function, as well as provide support to test a given set of views, filters etc. against a dataset on a CouchDB instance.
I have found a blog post on writing a test suite for the CouchDB API but it's from 2010 and I was wondering what has happened since.
I would use the Expresso TDD framework for Node.js. The overhead of writing a Node.js application will not be a wasted effort.
Install Node.js from the download page: nodejs.org/download
Make sure you also get the npm (node.js package manager).
With the expresso framework you can easily test any of the RESTful functions in CouchDB.
Here is a sample node.js test that communicates with CouchDB:
var http = require('http');
var url = require('url');
var log_level = 5;
var base_url = 'http://localhost:5984/';
var delete_db_at_end = false;
/**
* This test fetches all the data from a database and verifies that the data is
* returned as it should.
*/
exports.testCouchDBCartoonsAllDocs = function(beforeExit, assert) {
curl('GET', base_url + 'cartoons/_all_docs', null, function(response) {
assert.equal(7, response.total_rows);
assert.equal('Donald Duck', response.rows[1].id);
});
}
/**
* This test creates a database for this test only and deletes it at the end if the
* global parameter delete_db_at_end is set to true, otherwise it is left as is for
* human inspection.
*
*/
exports.testCreateDatabaseTestAddAndDestroy = function(beforeExit, assert) {
var dbname = 'test_db_cartoon';
deleteExistingDatabase(dbname, assert, function(response) {
/* Create the database */
curl('PUT', base_url + dbname, null, function(response) {
assert.equal(true, response.ok);
curl('PUT', base_url + dbname + '/Donald+Duck', '{"publisher":"Walt Disney"}', function(response){
assert.equal(true, response.ok);
assert.equal('Donald Duck', response.id);
curl('GET', base_url + dbname + '/Donald+Duck', null, function(response) {
assert.equal('Donald Duck', response._id);
assert.equal('Walt Disney', response.publisher);
/* Finally we delete the database from CouchDB */
if (delete_db_at_end) {
deleteExistingDatabase(dbname, assert, function(response) {
assert.equal(true, response.ok);
});
}
});
});
});
});
}
/**
* This is a helper function that deletes the database if it exists so
* that the tests can run even if they where interrupted.
*/
function deleteExistingDatabase(dbname, assert, callback) {
curl('GET', base_url + dbname, null, function(response) {
if (response.db_name === dbname) {
log(1, 'About to delete the database ' + dbname);
curl('DELETE', base_url + '/' + dbname, null, function(response) {
callback(response);
});
} else {
callback(response);
}
});
}
/**
* This is a helper method to manage the RESTful sending to the database
*/
function curl(method, urlString, payload, callback) {
log(1, method + ' ' + urlString);
var auth = 'Basic ' + new Buffer('username:password').toString('base64');
log(7, auth);
var options = url.parse(urlString);
options.method = method;
options.headers = {
'Content-Encoding': 'UTF8',
'Content-Type': 'application/json',
'Authorization' : auth
};
log(7, options);
var req = http.request(options, function (res) {
var data = "";
res.setEncoding('UTF8');
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function (chunk) {
var response = JSON.parse(data);
log(5, response);
callback(response);
});
});
if (payload) {
req.write(payload);
}
req.end();
}
/**
* This simple logger logs message depending on the log_level set at
* the top of this file.
*/
function log(level, message) {
if (level<=log_level) {
console.log(message);
}
}
In the same folder as you have this file stored execute this command:
npm install expresso
Run the test by issuing this command:
node_modules/expresso/bin/expresso test.js
This is the console output from the command above:
GET http://localhost:5984/cartoons/_all_docs
GET http://localhost:5984/test_db_cartoon
{ error: 'not_found', reason: 'no_db_file' }
PUT http://localhost:5984/test_db_cartoon
{ total_rows: 7,
offset: 0,
rows:
[ { id: 'Batman', key: 'Batman', value: [Object] },
{ id: 'Donald Duck', key: 'Donald Duck', value: [Object] },
{ id: 'Iron Man', key: 'Iron Man', value: [Object] },
{ id: 'Mickey Mouse', key: 'Mickey Mouse', value: [Object] },
{ id: 'Spider-Man', key: 'Spider-Man', value: [Object] },
{ id: 'Superman', key: 'Superman', value: [Object] },
{ id: '_design/select', key: '_design/select', value: [Object] } ] }
{ ok: true }
PUT http://localhost:5984/test_db_cartoon/Donald+Duck
{ ok: true,
id: 'Donald Duck',
rev: '1-1c431dfb2c46991ec999743830a5363b' }
GET http://localhost:5984/test_db_cartoon/Donald+Duck
{ _id: 'Donald Duck',
_rev: '1-1c431dfb2c46991ec999743830a5363b',
publisher: 'Walt Disney' }
100% 2 tests
You can easily expand the test with additional
exports.testname = function(beforeExit, assert) {
}