AngularJS : Running e2e tests using Karma - testing

I want to run my Jasmine e2e tests using KarmaJS (0.9.2). I use Google Closure with AngularJS (1.0.7) on Windows 7. When I start karma using karma start config\karma-e2e.js everything works fine (browser navigates to correct page) but it doesn't execute my tests (stops on 'browser navigate to').
The config\karma-e2e.js file:
basePath = '../';
frameworks = ['ng-scenario'];
files = [
'tests/e2e/**/*.js'
];
autoWatch = true;
singleRun = false;
browsers = ['Chrome'];
urlRoot = '/__karma/';
proxies = {
'/': 'http://localhost:8080/'
}
plugins = [
'karma-ng-scenario'
'karma-chrome-launcher'
]
Test source (tests\e2e\scenarios.coffee) is:
describe 'Intro page view', ->
it 'has hello world message', ->
browser().navigateTo '/app/client/'
expect(element('#text').text()).toBe 'Hello World'
I'm using html5Mode routes, angular is bootstraped manualy using angular.bootstrap, all my coffee scripts are compiled by IDE and I see no errors in browser console or command line. So how should I do it? Am I doing something wrong?
Thanks!

I solved this problem. Seems angular scenario needs ng-app directive which is at least weird (or it's a bug). So I added ng-app attribute to body after calling App.bootstrap() on index page. Everything works fine now.
<script type="text/javascript">
App.bootstrap();
document.body.setAttribute('ng-app', 'App');
</script>

Related

Embed script only on production with Vue CLI 3

My main goal is to inject a tag into my index.html only in production (it's a New Relic monitoring code snippet).
My Vue.js is built and served as a static resource, so using {% %} tags to surround the script block with a condition doesn't seem to work in this use case.
So I tried to add the New Relic code snippet on my Vue.js app using html-webpack-plugin, since I found a simple Webpack plugin using on html-webpack-plugin. It's a pretty simple plugin, it just create the node and pushes it in the page body : https://github.com/robrap/html-webpack-new-relic-plugin/blob/master/src/index.js#L25
I register the plugin by setting my vue.config.js this way (I first tried to add the script no matter the environment) :
var HtmlWebpackPlugin = require('html-webpack-plugin');
var HtmlWebpackNewRelicPlugin = require('#yodatech/html-webpack-new-relic-plugin');
module.exports = {
configureWebpack: {
plugins: [
new HtmlWebpackPlugin(),
new HtmlWebpackNewRelicPlugin({the plugin options})
]
}
}
The plugin actually does its job well (the code snippet is injected), but its execution messes up with Vue CLI default configuration.
Some stylesheets and scripts aren't referenced anymore in the final index.html file, the <div id=app></div> is not there anymore, the app is broken.
I don't know if using HtmlWebpackPlugin is a dead end, but I currently don't know any other way to reach my goal.
Has anyone an idea on how I could make this work ?
Thanks a lot to anyone passing by.
EDIT : The plugin I was trying to use seemed to be flawed, I had to modify it to make it work with Vue CLI. My main problem has been solved by the selected answer.
vue.config.js option configureWebpack just merges the options you provide to a webpack config provided by Vue CLI. So by using your code, you are running 2 distinct HtmlWebpackPlugins (one from your config and one default from Vue CLI)
Try this instead:
var HtmlWebpackNewRelicPlugin = require('#yodatech/html-webpack-new-relic-plugin');
module.exports = {
configureWebpack: {
plugins: [
new HtmlWebpackNewRelicPlugin({the plugin options})
]
}
}

Cypress - run test in iframe

I'm trying to find elements in iframe but it doesn't work.
Is there anyone who have some system to run tests with Cypress in iframe? Some way to get in iframe and work in there.
It's a known issue mentioned here. You can create your own custom cypress command which mocks the iframe feature. Add following function to your cypress/support/commands.js
Cypress.Commands.add('iframe', { prevSubject: 'element' }, ($iframe, selector) => {
Cypress.log({
name: 'iframe',
consoleProps() {
return {
iframe: $iframe,
};
},
});
return new Cypress.Promise(resolve => {
resolve($iframe.contents().find(selector));
});
});
Then you can use it like this:
cy.get('#iframe-id')
.iframe('body #elementToFind')
.should('exist')
Also, because of CORS/same-origin policy reasons, you might have to set chromeWebSecurity to false in cypress.json (Setting chromeWebSecurity to false allows you to access cross-origin iframes that are embedded in your application and also navigate to any superdomain without cross-origin errors).
This is a workaround though, it worked for me locally but not during CI runs.
This works for me locally and via CI. Credit: Gleb Bahmutov iframes blog post
export const getIframeBody = (locator) => {
// get the iframe > document > body
// and retry until the body element is not empty
return cy
.get(locator)
.its('0.contentDocument.body').should('not.be.empty')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
// https://on.cypress.io/wrap
.then(cy.wrap)
}
spec file:
let iframeStripe = 'iframe[name="stripe_checkout_app"]'
getIframeBody(iframeStripe).find('button[type="submit"] .Button-content > span').should('have.text', `Buy me`)
that is correct. Cypress doesn't support Iframes. It is simple not possible at the moment. You can follow (and upvote) this ticket: https://github.com/cypress-io/cypress/issues/136

Vue CLI 3 Nightwatch page object configuration

I'm using Vue CLI 3 version 3.0.5.
In project configuration, I use Nightwatch as e2e test tool.
I try to use page objects, so I had nightwatch.config.js file in project root, and add page_objects_path inside like below:
{
page_objects_path : "/tests/e2e/page-objects"
}
Then I create page-objects folder as this path: /tests/e2e/page-objects.
Then I setup a page object Entry.js under that folder and try to use it in test:
/tests/e2e/page-objects/Entry.js
vmodule.exports = {
'Test Page Object': browser => {
browser
.url(process.env.VUE_DEV_SERVER_URL)
.waitForElementVisible('#app', 5000)
browser.page.Entry().sayHello()
browser.end()
}
}
And the error message shows:
Cannot read property 'Entry' of undefined .
It looks like my page object setup is not correct...
Could anyone help providing a correct implementation of NightWatch page object in Vue CLI v3.0.5 ? Thanks...
Ah, I know why it won't work.
Because nightwatch.config.js is a javascript file, I should export it first, then the plugin can read it.
module.export = {
page_objects_path : "/tests/e2e/page-objects"
}
Sorry for the dumb question.

requirejs loading file from different path

I've a webpage , where I've included the requirejs via script tag like -
<script data-main="/media/course-book-app/courses.require.main.js" src="/media/common/vendor/requirejs/require.js"></script>
On Safari browser, I'm getting error like -
What is causing this issue?
This issue is very frequent on Safari but on chrome it is less frequent.
Testing URL
From https://requirejs.org/docs/errors.html#scripterror (which is linked right there in the error). Follow the instructions and look at the script that caused the error
This occurs when the script.onerror function is triggered in a
browser. This usually means there is a JavaScript syntax error or
other execution problem running the script. To fix it, examine the
script that generated the error in a script debugger.
This error may not show up in IE, just other browsers, and instead, in
IE you may see the No define call for ... error when you see "Script
error". This is due to IE's quirks in detecting script errors.
Here is the way to use requirejs correctly. This ensures the configuration gets loaded before loading any module -
define('requireconfig', function(){
require.config({
paths: {
"jquery": "/common/vendor/jquery/jquery-1.9.1.min",
"backbone": "/common/vendor/backbone/backbone.min-1.1.2",
"underscore": mediaPath + "/common/vendor/underscore/underscore.min-1.7.0"
},
shim: {
backbone : {
deps: ["jquery","underscore"],
exports: "Backbone"
},
}
});
});
define('main', ['requireconfig'], function () {
'use strict';
});
// loading main module which loads the requirejs configuration
requirejs(['main'],()=>{
requirejs(['jquery'], ($)=>{//jquery loaded});
}, ()=>{//error loading module})

Sencha Touch [APPNAME].app is undefined only when testing with Jasmine

I'm trying to set up some test cases for a view using the Jasmine 2.3.4 assertion library for my Sencha Touch 2.4 app. Things seem great (I see the view rendered to a div) except the browser does not know what MyApp.app is. I have this line at my onContainerInitialize function from my view/container code:
var controller = MyApp.app.getController('loginController');
which gives this Jasmine error:
TypeError: Cannot read property 'getController' of undefined
At the time the Jasmine tests are called, from my console I do have a MyApp global object with the following structure (attached). If you expand app you will see the class name of the controller listed in an array under _controllers. The line that causes this error in my spec file is:
var myView = new MyApp.view.someViewName({ renderTo: 'test' });
I modeled my setup after a few tutorials, one of which is Sencha's https://docs.sencha.com/extjs/4.2.5/#!/guide/testing
(wish there was one for a recent version of Touch). I think my problem may be related to this note midway down that page:
Note: this Application definition is not a copy and paste of your
regular Application definition in your app.js. This version will only
include the controllers, stores, models, etc and when launch is called
it will invoke the Jasmine tests.
It may be related, but I also couldn't follow their:
ctrl = newMyApp.controller.MyController();
where I would get this error:
TypeError: app.getRouter is not a function at Ext.define.applyRoutes (http://localhost:8080/touch/sencha-t...ug.js:45800:26)
Instead, I had to add in this argument like this:
var ctrl = new Kaacoo.controller.loginController({ application : app });
Additionally, my launch file is set up like this:
Ext.require('Ext.app.Application');
Ext.Loader.setConfig({
enabled: true,
disableCaching: true
});
Ext.Loader.setPath('MyApp', '../../app');
// this file is a couple levels deep from the root of my project
Ext.application({
name : 'MyApp',
extend: 'MyApp.Application',
autoCreateViewport: true,
controllers: [
'loginController'
],
requires : [
],
launch: function() {
// Jasmine is bootstrapped with boot.js referenced in the html runner, so nothing here. My test specs are being called after this launch function is executed.
}
});
The order I have listed my resources in my html runner are: Jasmine Library with boot.js> Touch All Debug Library > Project Source Files > Spec Files > Launch file
Building and simulating the app is fine, so why can't I also have access to MyApp.app.getController('loginController') as well in my test environment?
Thanks!