Resolve Module has not been loaded yet error Babel async-await - javascript

I am using babeljs to transform my javascript code. I am using async-await to handle asynchronous ajax calls in jquery. I haven't been able to figure out from the Babeljs Documentation exactly what configurations I need in order to get this to work. Using the below configurations I am gettin the error
Module name "babel-polyfill" has not been loaded yet for context: _. Use require([])
What configuration changes (or code changes) do I need to make in order to correctly configure Babel? Any additional explanation of working with Babel/es2015+ would be appreciated.
.babelrc
{
"plugins": [ "transform-async-to-generator" ],
"presets": ["env"]
}
package.json
{
"dependencies": {
"#types/jquery": "^2.0.46",
"#types/papaparse": "^4.1.28",
"#types/xrm": "^8.2.5",
"babel-polyfill": "^6.23.0",
"bootstrap": "^3.3.7",
"papaparse": "^4.3.3",
"requirejs": "^2.3.3",
"vue": "^2.3.3"
},
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"babel-preset-env": "^1.5.2"
},
"name": "mypackage",
"private": true,
"scripts": {
"build": "babel WebResources -d build/CCSEQ"
},
"version": "1.0.0"
}
main.js (pre-babel)
/// <reference path="../node_modules/#types/jquery/index.d.ts" />
"use strict";
require("babel-polyfill");
requirejs.config({
paths: {
PapaParse: "/papaparse.min",
Constants: "/build/CCSEQ/Constants",
Model: "/build/CCSEQ/Model",
WebAPI: "/build/CCSEQ/WebAPI",
Xrm: "/build/CCSEQ/Xrm",
Vue: "/node_modules/vue/dist/vue"
}
})
require(["PapaParse", "Constants", "Model", "WebAPI", "Xrm", "Vue"], function (Papa, Constants, Model, WebAPI, Xrm, Vue) {
function ImportExpenseTransaction(data) {
let newExpenseTransactions = new Array();
let entityID = Xrm.Page.getCurrentEntityID();
data.forEach(async (expense) => {
if (expense[0] !== "PR EMP ID") {
let newExpenseTransaction = new Model.Entity();
newExpenseTransaction.Type = Constants.EntityType.ExpenseTransaction;
newExpenseTransaction.Attributes.push(new Model.EntityField("ccseq_employeeid",
await WebAPI.Get(new Model.QueryDetails(Constants.EntityType.SystemUser, expense[0], ["systemuserid"], [new Model.Condition("ccseq_chnnavid", expense[0], Constants.Condition.EQUALS)])),
Constants.EntityType.SystemUser));
newExpenseTransactions.push(newExpenseTransaction);
}
});
});
main.js (post-babel)
/// <reference path="../node_modules/#types/jquery/index.d.ts" />
"use strict";
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
require("babel-polyfill");
requirejs.config({
paths: {
PapaParse: "/node_modules/papaparse/papaparse.min",
Constants: "/build/CCSEQ/Constants",
Model: "/build/CCSEQ/Model",
WebAPI: "/build/CCSEQ/WebAPI",
Xrm: "/build/CCSEQ/Xrm",
Vue: "/node_modules/vue/dist/vue"
}
});
require(["PapaParse", "Constants", "Model", "WebAPI", "Xrm", "Vue"], function (Papa, Constants, Model, WebAPI, Xrm, Vue) {
function ImportExpenseTransaction(data) {
var _this = this;
var newExpenseTransactions = new Array();
var entityID = Xrm.Page.getCurrentEntityID();
data.forEach(function () {
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(expense) {
var newExpenseTransaction;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!(expense[0] !== "PR EMP ID")) {
_context.next = 32;
break;
}
newExpenseTransaction = new Model.Entity();
newExpenseTransaction.Type = Constants.EntityType.ExpenseTransaction;
_context.t0 = newExpenseTransaction.Attributes;
_context.t1 = Model.EntityField;
_context.next = 7;
return WebAPI.Get(new Model.QueryDetails(Constants.EntityType.SystemUser, expense[0], ["systemuserid"], [new Model.Condition("ccseq_chnnavid", expense[0], Constants.Condition.EQUALS)]));
case 7:
_context.t2 = _context.sent;
_context.t3 = Constants.EntityType.SystemUser;
_context.t4 = new _context.t1("ccseq_employeeid", _context.t2, _context.t3);
_context.t0.push.call(_context.t0, _context.t4);
newExpenseTransactions.push(newExpenseTransaction);
case 32:
case "end":
return _context.stop();
}
}
}, _callee, _this);
}));
return function (_x) {
return _ref.apply(this, arguments);
};
}());
});

One thing I can see is that you're not actually doing anything with
require("babel-polyfill")
as in require is returning the module's export for you to use. Simply having line 4 in main.js isn't enough.
That said I'm not sure exactly what you're supposed to do with that module in this context.
I ran into a polyfill issue with our test suite (we use karma) and had to work around it like this (from karma.conf.js)
module.exports = function (config) {
config.set({
// to run in additional browsers:
// 1. install corresponding karma launcher
// http://karma-runner.github.io/0.13/config/browsers.html
// 2. add it to the `browsers` array below.
browsers: ['PhantomJS'],
frameworks: ['mocha', 'sinon-chai'],
reporters: ['spec', 'coverage'],
files: [
'../../node_modules/babel-polyfill/dist/polyfill.js',
'./index.js'
],
preprocessors: {
'./index.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
},
coverageReporter: {
dir: './coverage',
reporters: [
{ type: 'lcov', subdir: '.' },
{ type: 'text-summary' }
]
}
})
}
I had to add the relative path to polyfill.js (that lives in the babel-polyfill module under /dist) into the files property. Maybe you need to do something similar?
But you'll probably want to store the return value of require into something like
var polyfill = require("babel-polyfill")
and then reference that somewhere.
Hope this helps.
¯\_(ツ)_/¯
maybe even in paths add something like:
Polyfill: "/node_modules/babel-polyfill/dist/polyfill.js"

Related

Vue JS 3 Application to run in older Firefox/Chrome

I'm developing an app in VueJS 3 and it seems that's working on my local computer.
But I have to make it runs also on older browsers like Firefox 38 Chrome 49.
My app uses some "fetch" functions to load content from api, to authenticate, to send commands, etc. After reading the following 2 links I believe I have some issues with it (despite it should works on CH 42). https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API and Babel not Polyfilling Fetch when using babel-preset-env
. What it is your opinion?
I have babel and in package.json the following settings:
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"Chrome > 48",
]
But the errors received in Firefox and Chrome are very cryptic and I don't know what how should I transpile that function. I would focus on Chrome 49 and I'll add some context
Indeed the async function is available after Chrome 55. But I don't know how to convert it
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
For example in Chrome 49 I have the following console error on the following page: webpack:///./node_modules/#vue/devtools-api/esm/proxy.js
Uncaught SyntaxError: Unexpected identifier proxy.js:94
The content of that file is:
import { HOOK_PLUGIN_SETTINGS_SET } from './const';
export class ApiProxy {
constructor(plugin, hook) {
this.target = null;
this.targetQueue = [];
this.onQueue = [];
this.plugin = plugin;
this.hook = hook;
const defaultSettings = {};
if (plugin.settings) {
for (const id in plugin.settings) {
const item = plugin.settings[id];
defaultSettings[id] = item.defaultValue;
}
}
const localSettingsSaveId = `__vue-devtools-plugin-settings__${plugin.id}`;
let currentSettings = Object.assign({}, defaultSettings);
try {
const raw = localStorage.getItem(localSettingsSaveId);
const data = JSON.parse(raw);
Object.assign(currentSettings, data);
}
catch (e) {
// noop
}
this.fallbacks = {
getSettings() {
return currentSettings;
},
setSettings(value) {
try {
localStorage.setItem(localSettingsSaveId, JSON.stringify(value));
}
catch (e) {
// noop
}
currentSettings = value;
},
};
if (hook) {
hook.on(HOOK_PLUGIN_SETTINGS_SET, (pluginId, value) => {
if (pluginId === this.plugin.id) {
this.fallbacks.setSettings(value);
}
});
}
this.proxiedOn = new Proxy({}, {
get: (_target, prop) => {
if (this.target) {
return this.target.on[prop];
}
else {
return (...args) => {
this.onQueue.push({
method: prop,
args,
});
};
}
},
});
this.proxiedTarget = new Proxy({}, {
get: (_target, prop) => {
if (this.target) {
return this.target[prop];
}
else if (prop === 'on') {
return this.proxiedOn;
}
else if (Object.keys(this.fallbacks).includes(prop)) {
return (...args) => {
this.targetQueue.push({
method: prop,
args,
resolve: () => { },
});
return this.fallbacks[prop](...args);
};
}
else {
return (...args) => {
return new Promise(resolve => {
this.targetQueue.push({
method: prop,
args,
resolve,
});
});
};
}
},
});
}
async setRealTarget(target) {
this.target = target;
for (const item of this.onQueue) {
this.target.on[item.method](...item.args);
}
for (const item of this.targetQueue) {
item.resolve(await this.target[item.method](...item.args));
}
}
}
I tried to change anything I found:
vue.config.js
transpileDependencies: [
"config",
"vue",
"vue-router",
"vuex",
"xml2js"
],
package.json
"dependencies": {
"#babel/polyfill": "^7.12.1",
"babel-polyfill": "^6.26.0",
"config": "^3.3.7",
"core-js": "^3.6.5",
"regenerator-runtime": "^0.13.9",
"vue": "^3.2.26",
"vue-router": "^4.0.12",
"vuex": "^4.0.2",
"xml2js": "^0.4.23"
},
"devDependencies": {
"#babel/cli": "^7.16.8",
"#babel/core": "^7.16.12",
"#babel/preset-env": "^7.16.11",
"#vue/babel-preset-app": "^4.5.15",
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-plugin-router": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.8.0",
"eslint-plugin-vue": "^7.0.0"
},
"browserslist": [
"defaults",
"> 1%",
"last 2 versions",
"not dead",
"Chrome > 48"
]
babel.config.js
module.exports = {
presets: [
[
'#vue/cli-plugin-babel/preset',
{
useBuiltIns: "usage",
forceAllTransforms: true,
targets: {
"chrome": "49"
},
}
]
]
};
main.js
import "#babel/polyfill";
import 'core-js/stable';
import 'regenerator-runtime/runtime';
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './_store'
createApp(App).use(router).use(store).mount('#app');
i setup a new vue 3 project and added async/await and fetch and did a build and it workes in chrome 48
I modified hello world component to
<script>
export default {
name: 'HelloWorld',
data() {
return {msg : ""}
},
mounted() {
async function fetchMoviesJSON() {
const response = await fetch('https://reqbin.com/echo/get/json');
const movies = await response.json();
return movies;
}
fetchMoviesJSON().then(data => {
this.msg = data; // fetched movies
});
}
}
</script>
added "Chrome > 47" to browserslist
also i installed browserslist
can you run after installing browserslist npx browserslist and check if you see chrome 47 there?
I saw in your error dev-tools i think it might be just the Vue dev tools
Update:
added vue router and installed the vue dev tools and when i run with serve i can see that the proxy file was compiled there and no errors.
are you building it in dev mode?
I would recommend you to clean up your babel plugins and try with the simple way.
also please let know the node/nom version. i read it might be the problem, and you should try to update node see here

Promise returns with 'undefined' or babel compiled code doesn't wait for return (async/await)

There is an async function (send) in which if the msg attribute is not defined, another function (getNextProcess) sets its value.
getNextProcess performs a database query within a Promise. The query callback the Promise resolve function.
Problem:
After translating the code with Babel, msg will always be 'undefined'.
Promise runs in the background independently and returns with the correct value (checked with console log).
/* ORIGINAL */
class MyClass(){
/*
construct & other codes here...
*/
getNextProcess(){
new Promise(res => {
logDb.get("SELECT * FROM process WHERE details NOT LIKE '%isComplete:true%' ORDER BY id LIMIT 1", (e, r) => {
let result = JSON.parse(r.details);
result.id = r.id;
res(result);
});
});
}
async send(msg = undefined){
if (!msg) msg = await this.getNextProcess();
webView.send('webview:receive', msg);
}
}
/* Transformed */
{
key: "send",
value: function () {
var _send = (0, _asyncToGenerator2["default"])(
/*#__PURE__*/
_regenerator["default"].mark(function _callee() {
var msg,
_args = arguments;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
msg = _args.length > 0 && _args[0] !== undefined ? _args[0] : undefined;
if (msg) {
_context.next = 5;
break;
}
_context.next = 4;
return this.getNextProcess();
case 4:
msg = _context.sent;
case 5:
this.webView.send('webview:receive', msg);
case 6:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function send() {
return _send.apply(this, arguments);
}
return send;
}()
}
/* package.json */
// ...
"scripts": {
"start": "npm run compile && electron main.js",
"compile": "browserify -t [ babelify --presets [ #babel/preset-env ] ] src/app.js -o js/app.js",
},
"devDependencies": {
"#babel/core": "^7.4.5",
"#babel/plugin-transform-async-to-generator": "^7.4.4",
"#babel/plugin-transform-regenerator": "^7.4.5",
"#babel/plugin-transform-runtime": "^7.4.4",
"#babel/preset-env": "^7.4.5",
"#babel/runtime": "^7.4.5",
"babel-core": "^7.0.0-bridge.0",
"babelify": "^10.0.0",
"browserify": "^13.0.1",
"electron": "^4.1.4",
"electron-rebuild": "^1.8.5"
},
// ...
/* .babelrc */
{
"presets": [
[
"#babel/preset-env",
{
"useBuiltIns": "entry"
}
]
],
"ignore": [
"../node_modules/jquery/dist/jquery.js"
],
"plugins": [
["#babel/plugin-transform-runtime", {
"helpers": true,
"regenerator": true
}],
"#babel/plugin-transform-async-to-generator",
"#babel/plugin-transform-regenerator",
]
}
It looks like you forgot to return the promise in getNextProcess.
await doesn't know what to wait for if you don't give it a promise.
getNextProcess(){
return new Promise(res => {
//...
});
}

ES6 + jQuery + Bootstrap - Uncaught ReferenceError: jQuery is not defined?

How can I import jQuery as the dependency for bootstrap in ES6?
I tried with:
import {$,jQuery} from 'jquery';
import bootstrap from 'bootstrap';
But I always get this error:
transition.js:59 Uncaught ReferenceError: jQuery is not defined
Which points to this file:
/* ========================================================================
* Bootstrap: transition.js v3.3.7
* http://getbootstrap.com/javascript/#transitions
* ========================================================================
* Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
WebkitTransition : 'webkitTransitionEnd',
MozTransition : 'transitionend',
OTransition : 'oTransitionEnd otransitionend',
transition : 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}
return false // explicit for ie8 ( ._.)
}
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false
var $el = this
$(this).one('bsTransitionEnd', function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}
$(function () {
$.support.transition = transitionEnd()
if (!$.support.transition) return
$.event.special.bsTransitionEnd = {
bindType: $.support.transition.end,
delegateType: $.support.transition.end,
handle: function (e) {
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
}
}
})
}(jQuery);
Any ideas?
EDIT:
my gulp file:
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var gutil = require('gulp-util');
gulp.task('es6', function() {
browserify({
entries: 'js/app.js',
debug: true
})
.transform(babelify, { presets: ['es2015'] })
.on('error',gutil.log)
.bundle()
.on('error',gutil.log)
.pipe(source('compile.js'))
.pipe(gulp.dest('js'));
});
gulp.task('default', ['es6']);
EDIT 2:
package.json:
{
"name": "es6",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-preset-es2015": "^6.16.0",
"babelify": "^7.3.0",
"browserify": "^13.1.0",
"gulp": "^3.9.1",
"gulp-uglify": "^2.0.0",
"gulp-util": "^3.0.7",
"pump": "^1.0.1",
"vinyl-source-stream": "^1.1.0"
},
"browser": {
"jquery": "./node_modules/jquery/dist/jquery.js",
},
"browserify-shim": {
"jquery": "$", // or change it to jQuery
},
"browserify": {
"transform": [
"browserify-shim"
]
}
}
error:
Starting 'build'... events.js:160
throw er; // Unhandled 'error' event
^
Error: SyntaxError: Unexpected token } in JSON at position 526 while
parsing json file
I've tried this answer and it worked.
// webpack.config.js
module.exports = {
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
};
In general the destructuring you are doing in the import is not right, as the $ or jQuery object is the main one:
import $ from 'jquery';
// or
import jQuery from 'jquery'
In your case you are dealing with a module (boostrap-transition) which does want jQuery in the global scope to be used.
I had a similar issue some time ago with the materialize module too on this thing.
If you are using webpack you can follow #galkowskit answer steps.
In case you are using browserify instead, what you need is a browserify transform as the follow:
"browser": {
"jquery": "./node_modules/jquery/dist/jquery.js",
},
"browserify-shim": {
"jquery": "$", // or change it to jQuery
},
"browserify": {
"transform": [
"browserify-shim"
]
}
You can put this inside your package.json file: when Gulp is going to call browserify it will read your package.json for configuration tips and execute this shim for jQuery.
In Webpack I usually use (webpack.config.js):
externals: {
jquery: "jQuery"
}
And then:
import jQuery from 'jQuery';
You could also try:
import * as jQuery from 'jQuery';
If you are using curley bracket in es6 you are saying you want only that segment from several segment this module returns.
Jquery expose only one thing so you could do:
import $ from 'jquery';
Or
import jQuery from 'jquery';
It will always expose to one default variable
import jQuery from 'jquery';
or
import $ from 'jquery';

Protractor + CucumberJS + Gulp-Protractor = When test fails browser does not get closed

Hi!
I'm dealing when trying to close the browser once the test had failed, currently, when it passes it does get closed.
I'm using
"cucumber": "^0.9.2",
"gulp": "~3.9.0",
"gulp-protractor": "^2.1.0",
"protractor": "3.0.0",
"protractor-cucumber-framework": "^0.3.2",
"selenium-standalone": "4.8.0",
$ node --version
v5.3.0
$ npm --version
3.5.2
My Gulp-protractor looks like:
/**
* run protractor
*/
var args = require('yargs').argv;
module.exports = function(gulp, plugins) {
return function (done) {
var protractorConfig = '',
testConfig = '',
environment = args.environment || 'devel',
tag = args.tag || '#Sanity',
baseUrl;
if (!args.baseUrl) {
baseUrl = 'http://test.me/frontend-build-tests/';
} else if (args.baseUrl.match(/^(?:https?\:)?\/\//)) {
baseUrl = args.baseUrl;
} else {
baseUrl = 'http://test.me/frontend-build-tests/' + args.baseUrl + '/';
}
switch(environment) {
case 'devel' :
protractorConfig = 'e2e/protractor.config.devel.js';
testConfig = '../config/devel';
break;
case 'live' :
protractorConfig = 'e2e/protractor.config.live.js';
testConfig = '../config/live';
break;
case 'remote' :
protractorConfig = 'e2e/protractor.config.remote.js';
testConfig = '../config/live';
break;
default:
case 'build' :
protractorConfig = 'e2e/protractor.config.build.js';
testConfig = '../config/build';
break;
}
gulp.src([
'e2e/features/*.feature'
])
.pipe(plugins.protractor.protractor({
configFile: protractorConfig,
args: [
'--verbose',
'--no-stackTrace',
'--params.test.config', testConfig,
'--baseUrl', baseUrl,
'--cucumberOpts.tags', tag
]
}))
//.on('end', function(){
// console.log('E2E Testing complete');
// process.exit();
// })
.on('error', function() {
done();
//protractor.driver.quit();
process.exit(1);
//var protractor = require("gulp-protractor").protractor;
//console.log("ON Error");
//protractor.browser.quit();
//throw e;
});
};
};
And my protractor.config has:
exports.config = {
//seleniumServerJar: './node_modules/protractor/selenium/selenium-server-standalone-2.47.1.jar',
seleniumAddress: 'http://localhost:4444/wd/hub',
//directConnect: true,//To run test directly against Chrome/FFs
specs: [
'e2e/features/*.feature'
],
multiCapabilities: [
{
'browserName': 'chrome',
'chromeOptions': {
'args': ['show-fps-counter=true','enable-logging','v=1','net-log-level=0']
}
},
// {
// 'browserName': 'firefox'
// },
// {
// 'browserName': 'safari'
// },
// {
// 'browserName': 'phantomjs',
// 'phantomjs.binary.path':'./node_modules/phantomjs/bin/phantomjs',
// 'phantomjs.cli.args':'--debug=true --loglevel=DEBUG --webdriver --webdriver-loglevel=DEBUG'
// }
],
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
cucumberOpts: {
require: 'features/step_definitions/**/*.js',
format: 'json'
//tags: "#Sanity"
},
resultJsonOutputFile: 'report.json',
//count: 2,
//shardTestFiles: true,
//maxInstances:2,
onPrepare: function () {
browser.getCapabilities().then(function (capabilities) {
browser.capabilities = capabilities;
});
browser.driver.manage().window().maximize();
browser.ignoreSynchronization = true; //This is set for non-Angular apps
browser.manage().timeouts().implicitlyWait(20000);
}
//,
//onCleanUp: function(exitCode) {
// if (exitCode ==1){
// console.log("Getting out");
// browser.quit();
// };
//},
};
The tests fails, and the browser remains open, this on the CI server causes memory leaks! what do I have to do to solve this?
Please help!!
EDIT
my failing step looks like:
this.Then(/^I see that the slider has moved/, function (done) {
browser.sleep(500);
sliderWidgetPage.getImageAndAttribute(0,'data-url').then(function (attrVal) {
expect(attrAtX1Time).to.eventually.not.be.equal(attrVal);
});
done();
});
Maybe you need to write it like...
.be.equal(attrVal).notify(done)
https://github.com/domenic/chai-as-promised/blob/master/README.md

How can I use Jasmine with CucumberJS?

How can I use jasmine with cucumberjs ?
I tried this solution from https://stackoverflow.com/a/30763260/5453732
But I have always this error : TypeError: this.expect(...).toBe is not a function at World. (/myApp/tests/e2e/steps/main.step.js:33:79)
Line 39 :
this.expect(element(by.css('[data-el="' + field + '"]')).isPresent()).toBe(true);
app/modules/user/tests/e2e/user.feature
#user.feature
Feature: Login feature
As a user
I want authenticate my account
Scenario: Authentication success
Given I am on "#/" page
Given I check if "navbar-menu-user-module" is visible
Given I wait "3" seconds
/tests/e2e/steps/main.step.js
module.exports = function () {
this.World = require("../support/world.js").World;
this.path = '#/';
this.Given(/^I am on "?([^"]*)"? page$/, function (arg1, callback) {
browser.get(arg1);
callback();
});
this.Given(/^I wait "?([^"]*)"? seconds$/, function (arg1, callback) {
browser.sleep(3000);
callback();
});
this.Given(/^I check if "?([^"]*)"? is visible$/, function (field, callback) {
this.expect(element(by.css('[data-el="' + field + '"]')).isPresent()).toBe(true);
callback();
});
};
/tests/e2e/support/world.js
var World, chai, chaiAsPromised;
chai = require('chai');
chaiAsPromised = require('chai-as-promised');
World = function World(callback) {
chai.use(chaiAsPromised);
this.expect = chai.expect;
callback();
}
module.exports.World = World;
protractor.conf.js
/* protractor.conf.js */
exports.config = {
directConnect: true,
seleniumServerJar: 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.48.2.jar',
specs: [
'app/modules/user/tests/e2e/*.feature'
],
getPageTimeout: 30000,
capabilities: {
'browserName': 'chrome',
version: '',
platform: 'ANY'
},
onPrepare: function() {
var width = 1024, height = 800;
browser.get('#/');
browser.driver.manage().window().setSize(width, height);
},
framework: 'cucumber',
cucumberOpts: {
require: [
'tests/e2e/steps/main.step.js'
],
format: 'pretty', // or summary
keepAlive: false
},
onCleanUp: function() {}
};
and my html :
<a data-el="navbar-menu-user-module" href="./#/user">User Module</a>
package.json
{
"name": "myApp",
"version": "1.0.0",
"description": "myApp",
"dependencies": {
},
"devDependencies": {
"chai": "^3.3.0",
"chai-as-promised": "^5.1.0",
"jasmine-core": "~2.3.4",
...
"protractor": "^2.5.1",
"selenium-server": "^2.48.2",
"selenium-standalone": "^4.7.0",
"selenium-webdriver": "^2.48.0",
}
}
The key thing to remember is that CucumberJS and Jasmine are mutually exclusive. You can only use Jasmine's expect's in conjunction with the Jasmine framework. toBe() is a function that is provided by Jasmine's expect, which doesn't exist in your framework. That is why you are receiving the error you described.
Since you are using CucumberJS to structure your test you need to use a separate assertion library, the most popular one being Chai. You'll need to use a function provided by Chai for your assertion. In your case you'll probably want to use the equal() function. Also remember that Protractor's isPresent() function returns a promise, so you'll want to use the eventually chain provided by chai-as-promised. All together, the following assertion:
this.expect(element(by.css('[data-el="' + field + '"]')).isPresent()).toBe(true);
should be changed to:
this.expect(element(by.css('[data-el="' + field + '"]')).isPresent()).to.eventually.equal(true);
You can use our jasmine-expect library. We took out the expectation library from Jasmine and released it as a separate module.
https://www.npmjs.com/package/xolvio-jasmine-expect

Categories