access browserify -r params in karma - karma-runner

I call browserify with npm from the package.json scripts block. Here's an abbreviated version of the script.
"build:js": "browserify -r ./config.js:config -e -d src/index.js > build/index.js"
Everything works great. Inside index.js, I just refer to this parameter using: require('config') and browserify does the rest.
Now I'm trying to set up karma with browserify for testing, and karma-browserify can't find that variable. I've looked around and haven't found much, but tried to add require: ['./src/app/config/config-dev.js'] to my karma.conf.js inside the browserify object, like so:
browserify: {
debug: true,
require: ['./src/app/config/config-dev.js']
}
But karma doesn't make the connection between the require statement in the index to the parameter file, if nothing else, then because it isn't named. What I need to know is the syntax for karma when I use browserify CLI to add a param.
Any pointers to documentation explaining this or ideas about what I could try here would be super helpful. Thanks!

Try adding your require resolution to your package.json under the "browser" field.
E.g.:
"browser": {
"config": "./config"
}

If you’re trying to have a different config based on your environment then you could do:
./config.js:
if (process.env.NODE_ENV === 'production') {
module.exports = { /* production config */ };
} else if (process.env.NODE_ENV === 'development') {
module.exports = { /* development config */ };
} else if (process.env.NODE_ENV === 'test') {
module.exports = { /* test config */ };
}
then in your package.json you would have something like:
"scripts": {
"build:js": "NODE_ENV=production browserify -d -e src/index.js",
"test": "NODE_ENV=test karma"
},
"browserify": {
"transform": [
"envify"
]
}
envify being a crucial part which allows you to replace environment variables with their string directly in the code. e.g.: process.env.NODE_ENV === 'development' might become simply 'development' === 'development'. Such things can then be removed with a minification tool like uglifyjs.

Related

Trying to write a vuepress plugin

(The doc on writing a plugin is pretty sparse...)
THE GOAL
Create a plugin to add headers to a page.
THE ATTEMPT
Created a plugin following guidelines and an example plugin (that presumably works...) to do something similar.
THE ISSUE
Plugin won't load.
config.js
plugins: [
[
'vuepress-plugin-headertags',
{ headerTags: ["<script src='https://cdn.jsdelivr.net/npm/netlify-identity-widget#1.5.2/build/netlify-identity-widget.min.js'></script>"]}
]
],
(the <script> tag is what I'm trying to insert, in this instance.
PLUGIN index.js
const { path } = require('path')
// was: const { path } = require('#vuepress/shared-utils')
// dunno. No documentation on this...
// got the current version from the 'default-theme' code
module.exports = (options) => ({
define () {
return {
headerTags: options.headerTags || []
}
},
enhanceAppFiles () {
return [path.resolve(__dirname, 'enhanceAppFile.js')]
},
globalUIComponents: ['HeaderTags']
})
PLUGIN INSTALLATION
I published it to npm as vuepress-plugin-headertags, and then installed it with:
yarn add -D vuepress-plugin-headertags
Here's the relevant package.json content:
{
"name": "vuepress-netlifycms",
"version": "0.0.0",
"scripts": {
"dev": "vuepress dev",
"build": "vuepress build",
"debug": "node --nolazy --inspect=9229 /home/rickb/.yarn/bin/vuepress build"
},
"devDependencies": {
"vuepress": "^0.14.8",
"vuepress-plugin-headertags": "^1.0.3"
},
"dependencies": {}
}
VUEPRESS INSTALLATION
I cloned the vuepress repo from git and did a yarn link, which makes it globally available. With that, I can trace it in the debugger via the 'debug' script.
TRACING
I've followed the VP source code in the debugger and get to resolvePathPackage() in moduleResolver.js. The incoming path is not correct:
/home/(...)/VuePress-NetlifyCMS/vuepress-plugin-headertags
It should be:
/home/(...)/VuePress-NetlifyCMS/node_modules/vuepress-plugin-headertags
At any rate, it doesn't resolve, even after the 'normalization' process.
MORE EYES
I need more eyes on this to help me figure it out. The project is already up on github as 'rickbsgu/VuePress-NetlifyCMS.git'. If you do an install, the plugin will be in the project directory under 'node_modules/vuepress-plugin-headertags'
Any thoughts appreciated
And it works, now. Two problems:
Version I was running/debugging was not the same as the version in package.json. There is the vuepress executable and the vuepress libraries the plugin requires. The library was always the older version at runtime.
I needed to change the path import in index.html from const { path } = require('path') to const { path } = require('#vuepress/shared-utils'). That's my doc issue - I don't see that documented anywhere.
Thanks #Sun Haoran for getting me to look in the right place.

Webpack with Babel lazy load module using ES6 recommended Import() approach not working

I'm trying to do code splitting and lazy loading with webpack using the import() method
import('./myLazyModule').then(function(module) {
// do something with module.myLazyModule
}
I'm getting
'import' and 'export' may only appear at the top level
Note top level imports are working fine, i'm just getting an issue when I try and using the dynamic variant of import()
var path = require('path');
module.exports = {
entry: {
main: "./src/app/app.module.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name]-application.js"
},
module: {
rules: [
{
test: /\.js$/,
use: [{
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}]
}
]
},
resolve : {
modules : [
'node_modules',
'bower_components'
]
},
devtool : "source-map"
}
EDIT:
If I change it so the syntax reads, it works.... but the chunk comments don't work to label the bundle. I'm confused because the documentation says the the following is depreciated.
The use of System.import in webpack did not fit the proposed spec, so
it was deprecated in webpack 2.1.0-beta.28 in favor of import().
System.import('./myLazyModule').then(function(module) {
// do something with module.myLazyModule
}
You need the plugin syntax-dynamic-import to be able to use the import() function with Babel.
Install it with:
npm install --save-dev #babel/plugin-syntax-dynamic-import
And add it to your plugins:
{
presets: ['es2015'],
plugins: ['#babel/plugin-syntax-dynamic-import']
}

Karma test won't run

Please help. I am new to testing with karma. When I run "karma start karma.local.conf.js" the Chrome browser window comes up but the test doesn't run. I think my app.js and my test.js are ok and I suspect that the issue is incorrect versions of the packages I'm loading in my package.json. I know I also need to include mocha and chai:
{
"devDependencies": {
"browserify": "10.2.3",
"gulp": "3.8.11",
"gulp-browserify": "0.5.1",
"karma": "0.12.16",
"karma-chai": "0.1.0",
"karma-chrome-launcher": "0.1.4",
"karma-mocha": "0.1.4",
"http-status": "0.1.8",
"underscore": "1.5.2"
}
}
Here is my karma.local.conf.js file:
module.exports = function(config) {
config.set({
files: [
'http://code.jquery.com/jquery-1.11.3.js',
'https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js',
// For ngMockE2E
'https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-mocks.js',
'./app.js',
'./test.js'
],
frameworks: ['mocha', 'chai'],
browsers: ['Chrome'],
proxies : {
'/': 'http://localhost:3000'
}
});
};
I can also post the app.js and the test.js if need be, but I think they are ok. I think the issue is in the package.json and getting the right versions of the npm packages I need.
Here is my app.js:
var app = angular.module('myApp', ['ng']);
app.directive('userMenu', function() {
return {
controller: 'MyHttpController',
template: '<div class="user" ng-show="user">' +
' Current User: {{user.profile.username}}' +
'</div>' +
'<div ng-show="!user">' +
' <a href="/auth/facebook">' +
' Log In' +
' </a>' +
'</div>'
}
});
app.controller('MyHttpController', function($scope, $http) {
$http.get('/api/v1/me').success(function(data) {
$scope.user = data.user;
});
});
Here is my test.js:
describe('Nav Bar', function() {
var injector;
var element;
var scope;
var compiler;
var httpBackend;
beforeEach(function() {
injector = angular.injector(['myApp', 'ngMockE2E']);
intercepts = {};
injector.invoke(function($rootScope, $compile, $httpBackend) {
scope = $rootScope.$new();
compiler = $compile;
httpBackend = $httpBackend;
});
});
it('shows logged in users name', function(done) {
httpBackend.expectGET('/api/v1/me').respond({
user: { profile: { username: 'John' } }
});
element = compiler('<user-menu></user-menu>')(scope);
scope.$apply();
httpBackend.flush();
assert.notEqual(element.find('.user').css('display'), 'none');
assert.equal(element.find('.user').text().trim(), 'Current User: John');
done();
});
});
Thanks in advance,
William
Here is what I did to get my tests to run:
1. Run "npm install <package name> without a version number for each package in my package.json file
2. Run "karma init" to create a new config file. By default this command creates karma.conf.js
3. Modify karma.conf.js with the information from karma.local.conf.js
4. Run "karma start". By default this command looks for a file named karma.conf.js (I had already run "npm install -g karma-cli" so I was able to run "karma start" without specifying a path
5. Next I will run "npm ls" to see what package versions were installed and create a new version of package.json for future projects.
Another solution might be to run "npm install" and then run "ncu -u" to update all the packages to the latest versions. That might work but I haven't tested it.

How do I parameterize the baseUrl property of the protractor config file

I need to run my protractor tests in different contexts with different baseUrls in the config files. I don't want to use separate config files for each situation since that is more difficult to maintain. Rather, I want to pass the base url in as a command line parameter. Here is what I have tried so far:
The protractor.conf.js:
exports.config = {
onPrepare : {
...
exports.config.baseUrl = browser.params.baseUrl;
...
}
}
And to invoke protractor:
protractor protractor.conf.js --params.baseUrl 'http://some.server.com'
This does not work since it seems like the browser instance is already configured before onPrepare is called.
Similarly, I have tried this:
exports.config = {
baseUrl : browser.params.baseUrl
}
But this doesn't work either since it seems like the browser instance is not available when the config is being generated.
It looks like I can use standard node process.argv to access all command line arguments, but that seems to be going against the spirit of protractor.
What is the best way for me to do what I need to do?
Seems like this is already possible, but the documentation is spotty in this area. Looking at the code, however, protractor does support a number of seemingly undocumented command line arguments.
So, running something like this will work:
protractor --baseUrl='http://some.server.com' my.conf.js
The other option is to use gruntfile.js and have it call the protractor config file.
//gruntfile.js
module.exports = function (grunt) {
grunt.registerTask("default", "", function () {
});
//Configure main project settings
grunt.initConfig({
//Basic settings and infor about our plugins
pkg: grunt.file.readJSON('package.json'),
//Name of plugin
cssmin: {
},
protractor: {
options: {
configFile: "conf.js", // Default config file
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false, // If true, protractor will not use colors in its output.
args: {
baseUrl: grunt.option('baseUrl') || 'http://localhost:6034/'
}
},
your_target: { // Grunt requires at least one target to run so you can simply put 'all: {}' here too.
options: {
configFile: "conf.js", // Target-specific config file
args: {
baseUrl: grunt.option('baseUrl') || 'http://localhost:63634/'
}
}
},
},
//uglify
uglify: {
}
});
//Load the plugin
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-protractor-runner');
//Do the Task
grunt.registerTask('default', ['cssmin']);
};
the Protractor config file: conf.js
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome',
'chromeOptions': {
args: ['--no-sandbox']
}
},
chromeOnly: true,
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: ['specs/*/*_spec.js'],
suites : {
abcIdentity : 'specs/abcIdentity/*_spec.js' //picks up all the _spec.js files
},
params: {
UserName: 'abc#test.com',
Password: '123'
},
// Options to be passed to Jasmine.
jasmineNodeOpts: {
defaultTimeoutInterval: 30000,
includeStackTrace: true
},
onPrepare: function () {
browser.driver.manage().window().maximize();
if (process.env.TEAMCITY_VERSION) {
var jasmineReporters = require('jasmine-reporters');
jasmine.getEnv().addReporter(new jasmineReporters.TeamCityReporter());
}
}
};
//To run with default url http://localhost:6034
grunt protractor
//To run with any other url
grunt protractor --baseUrl:"http://dev.abc.com/"
I know, old one. but if anyone is still looking for a way to define a url based on capability (I had to do this because Ionic 5 will run in browser on port 8100, but in the app - unchangable - without port declaration on port 80, I use Appium)
add a baseUrl parameter inside your capability declaration.
{
browserName: 'chrome',
baseUrl: 'http://localhost:8100' //not required but as example
}
{
...
app: 'path to app.apk',
baseUrl: 'http://localhost'
...
}
and then configure your onPrepare method as follows.
async onPrepare() {
const config = await browser.getProcessedConfig();
if(config.capabilities.hasOwnProperty('baseUrl')) {
browser.baseUrl = config.capabilities.baseUrl;
}
}
OnPrepare runs for each capability you define in your multiCapabilities array. the getProcessedConfig returns the config as you defined it, with the addition of the current capability. Since that method returns a promise, I use async/await for readability.
This way, you can have multiple capabilities running, with each different a different host.
Base url should be declared baseUrl: "", in config.ts
I am using cucumber hooks and the below code is added in hooks file to pass the required url based upon the environments
if(browser.params.baseUrl==="QA"){
console.log("Hello QA")
await browser.get("https://www.google.com");
} else {
console.log("Hi Dev")
await browser.get("https://www.gmail.com");
}
run the tests using protractor command
protractor --params.baseUrl 'QA' typeScript/config/config.js --cucumberOpts.tags="#CucumberScenario"

grunt.initConfig in a callback does not work

I want to use grunt for deployment and therefore want to read in configuration of remote hosts based on the already existing ~/.ssh/config file.
To load that configuration I'm using sshconf but need to include the grunt.initConfig() call in the callback to have the configuration when defining environments.
var sshconf = require('sshconf');
module.exports = function(grunt) {
// Read in ssh configuration
sshconf.read(function(err, sshHosts) {
if (err)
console.log(err);
// SSH config loaded, now init grunt
grunt.initConfig({
sshconfig: {
staging: {
privateKey: grunt.file.read(sshHosts['project_staging'].properties.IdentityFile),
host: sshHosts['project_staging'].properties.HostName,
username: sshHosts['project_staging'].properties.User,
port: sshHosts['project_staging'].properties.Port || 22,
path: "/var/www/project"
},
production: {
// ...
}
},
// Tasks to be executed on remote server
sshexec: {
example_task: {
command: 'uptime && hostname'
}
},
sftp: {
deploy: {
files: {
"./": ["*.json", "*.js", "config/**", "controllers/**", "lib/**", "models/**", "public/**", "views/**"]
},
options: {
//srcBasePath: "test/",
createDirectories: true
}
}
}
// More tasks
// ...
});
grunt.loadNpmTasks('grunt-ssh');
// More plugins ...
});
};
When I call grunt --help it states:
> grunt --help
Grunt: The JavaScript Task Runner (v0.4.1)
…
Available tasks
(no tasks found)
If I do not wrap the grunt initiation in that callback (sshconf.read(function(err, sshHosts) {})) everything is working fine (except for the ssh config not loaded or not yet ready to be used).
Is what I am trying even possible and if so, how? Am I missing something obvious?
Grunt init cannot be used in an async fashion like this. Either read the sshconf synchronously, or use a task, as described in this answer: How can I perform an asynchronous operation before grunt.initConfig()?