Version info
Angular CLI: 6.0.8
Node: 8.11.2
OS: win32 x64
Angular: 6.0.3
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router
Package Version
-----------------------------------------------------------
#angular-devkit/architect 0.6.3
#angular-devkit/build-angular 0.6.3
#angular-devkit/build-optimizer 0.6.3
#angular-devkit/core 0.6.3
#angular-devkit/schematics 0.6.8
#angular/cdk 6.1.0
#angular/cli 6.0.8
#angular/flex-layout 6.0.0-beta.17
#angular/material 6.1.0
#ngtools/webpack 6.0.3
#schematics/angular 0.6.8
#schematics/update 0.6.8
rxjs 6.2.0
typescript 2.7.2
webpack 4.8.3
Protractor: 5.4.0
jasmine-core: 2.6.2
jasmine-spec-reporter: 4.1.0
Problem
I wanted to make a simple e2e test to check the inner text of an element after the browser has redirected to a page. However, when checking inside of the element, the browser simply sits on the page for 10 seconds and then gives the following error:
1) material App should re-route to login page
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
- ScriptTimeoutError: Timed out waiting for asynchronous Angular tasks to finish after 10 seconds. This may be because the current page is not an Angular application. Please see the FAQ for more details: htt
ps://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular
While waiting for element with locator - Locator: By(css selector, #globTitle)
Executed 1 of 1 spec (1 FAILED) in 14 secs.
[20:04:24] I/launcher - 0 instance(s) of WebDriver still running
[20:04:24] I/launcher - chrome #01 failed 1 test(s)
[20:04:24] I/launcher - overall: 1 failed spec(s)
[20:04:24] E/launcher - Process exited with error code 1
An unexpected error occured: undefined
Here is my code:
HTML:
<div class="main-container">
<mat-toolbar [ngStyle]="{'background-color': topBarColor, 'color': 'white'}" class="topbar telative" style = "z-index: 0 !important;">
<button mat-icon-button (click)="snav.toggle()" *ngIf = "showbtn" value="sidebarclosed">
<mat-icon>menu</mat-icon>
</button>
<span id = "globTitle">Programme Admin Dashboard</span>
<span style = "flex: 1 1 auto;"></span>
<button mat-raised-button colour = "warn" *ngIf = "showbtn" (click) = "signOut(); snav.close();" style = "margin-right: 20px;">Sign out</button>
<img src="assets/images/logo.png" alt="No logo available" style = "height: inherit; margin-bottom: 5px;">
</mat-toolbar>
<mat-sidenav-container class="example-sidenav-container" [style.marginTop.px]="mobileQuery.matches ? 0 : 0">
<mat-sidenav style = "text-align: center;" #snav id="snav" class="dark-sidebar pl-xs" [mode]="mobileQuery.matches ? 'side' : 'over'" fixedTopGap="0" [opened]= false [disableClose]="mobileQuery.matches" >
<app-sidebar (click) = "snav.close()"></app-sidebar>
</mat-sidenav>
<mat-sidenav-content class="page-wrapper">
<div class="page-content">
<router-outlet><app-spinner></app-spinner></router-outlet>
</div>
</mat-sidenav-content>
<ng-template #loadingSpinner>
<mat-spinner></mat-spinner>
<p>Fetching permissions...</p>
</ng-template>
</mat-sidenav-container>
</div>
app.po.ts:
import {browser, by, element, protractor} from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/');
}
getURIChange(url: string) {
const ec = protractor.ExpectedConditions;
browser.wait(ec.urlContains(url), 2000);
}
}
app.e2e-spec.ts:
(Note that when i remove the last line of code, the test manages to run. In fact, even up to element(by.css('#globTitle')) works fine.
But if i change it to element(by.css('#globTitle')).getText(), this is where the browser just waits and i get the error mentioned above.
import { AppPage } from './app.po';
import {browser, element, by} from 'protractor';
describe('material App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should re-route to login page', async () => {
console.log('Waiting for angular');
await browser.waitForAngularEnabled();
console.log('Angular initialized');
console.log('Waiting on navigation to page');
// page.navigateTo();
await browser.get('http://localhost:4201/');
console.log('Navigation completed, should be redirected to the login page');
page.getURIChange('/login');
expect(element(by.css('#globTitle')).getText()).toEqual('Programme Admin Dashboard');
});
});
Also, i'm not sure if this would help, but here are my protractor configuration and karma configurations just in case.
protractor.conf.js:
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 10000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 10000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
karma.conf.js:
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '#angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('#angular-devkit/build-angular/plugins/karma')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
customLaunchers: {
ChromeNoSandbox: {
base: 'Chrome',
flags: ['--no-sandbox']
}
},
singleRun: false,
});
};
Try this :
const el1 = await $('#globTitle').getText();
expect(el1).toEqual('Programme Admin Dashboard');
getText() waits for a promise to resolve and hence doesn't work the way it was before.
Hello you are not returning the callback in your step definitions.
So jasmine thinks you are doing or waiting for some actions to happen.But once timeout occured that is 10 seconds it throws an error
it('should re-route to login page', async (done) => {
console.log('Waiting for angular');
await browser.waitForAngularEnabled();
console.log('Angular initialized');
console.log('Waiting on navigation to page'); // page.navigateTo();
await browser.get('http://localhost:4201/');
console.log('Navigation completed, should be redirected to the login page');
page.getURIChange('/login');
Var a = element(by.css('#globTitle');
Var b = a.getText().then((value)=>{console.log('title is'+value);
return value;})
expect(b).toEqual('Programme Admin Dashboard'); done()
});
Related
I have the api build in laravel, so I enabled the maintenance mode : php artisan down;
Now on frontend, I use vuejs :
router.beforeEach(async (to, from, next) => {
const _next = next;
next = function newnext(loc) {
return _next(loc);
};
await initStore();
console.log('-----BEFORE------');
await getCSRFCookie();
console.log("-----IS MAINTENANCE ON ----- : " +
$store.getters['system/maintenanceIsOn']);
if ($store.getters['system/maintenanceIsOn']) {
if (to.fullPath !== '/maintenance') {
next({ name: 'maintenance' });
}
}
............
503 error is intercepted correctly by axios; Now the question is how I can redirect to my maintenance page ? I tried with router.push but a loop is started;
By maintenance route :
{
path: '/maintenance',
name: 'maintenance',
meta: {
title: 'Maintenance',
centered: true,
public: true,
maintenance: true,
},
component: () => import(/* webpackChunkName: "maintenance" */ '#/views/Maintenance.vue'),
},
Here is the browser console with all logs :
I tried like this but there is a loop and I'm not redirected to maintenance:
if ($store.getters['system/maintenanceIsOn']) {
console.log('-------REDIRECT------------');
return next({ name: 'maintenance' });
}
I am using Cypress version 10.9.0 for e2e testing. Of course, there are more step defs but it stops at the first then step as it can be seen from the SS image.
When('I enter an invalid username on the login page', () => {
cy.get('#username').type('portal').invoke('removeAttr', 'value').click({ force: true }, { timeout: 30000 })
cy.get('#password').type('SwY66bc3VZLUFR9')
cy.get('[type="submit"]').click()
})
Then('an error message is displayed with the text Invalid username/password', () => {
cy.get(".invalid.text-left").should('contain.text', 'Invalid username/password')
})
Cypress GUI error
DOM element
The error says cannot find #username but clearly it is present, so you may have a shadowroot in the DOM above the <input>.
If so, add a configuration to allow searching within, in cypress.config.js
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:1234'
},
includeShadowDom: true,
})
If you don't see shadowroot, look for an <iframe> element.
Handling an iframe is best done with Cypress iframe
I want to use socket.io in my Nuxtjs. Is it possible?
I tried this tutorial but I am getting the following error:
These dependencies were not found:
* fs in ./node_modules/socket.io/lib/index.js
* uws in ./node_modules/engine.io/lib/server.js
The better way to play with Nuxt.js + Socket.io is to follow this official example from core-team: https://github.com/nuxt/nuxt.js/tree/dev/examples/with-sockets
Updated answer with linked example on GitHub
I would suggest to use the nuxt-socket-io module. It is really easy to set up and has a nice documentation.
I built this litte demo example and I will list the steps that I took to build it (this is even a bit more thorough than the Setup section of the npm package):
Add nuxt-socket-io dependency to your project:
yarn add nuxt-socket-io # or npm install nuxt-socket-io
(If you already have a socket.io server you can skip this part)
Add following line to your nuxt.config.js file: serverMiddleware: [ "~/serverMiddleware/socket-io-server.js" ] (Please do not mix up serverMiddleware with middleware, this are two different things)
Then, create the file ./serverMiddleware/socket-io-server.js where you can implement your socket.io server.
// This file is executed once when the server is started
// Setup a socket.io server on port 3001 that has CORS disabled
// (do not set this to port 3000 as port 3000 is where
// the nuxt dev server serves your nuxt application)
const io = require("socket.io")(3001, {
cors: {
// No CORS at all
origin: '*',
}
});
var i = 0;
// Broadcast "tick" event every second
// Or do whatever you want with io ;)
setInterval(() => {
i++;
io.emit("tick", i);
}, 1000);
// Since we are a serverMiddleware, we have to return a handler,
// even if this it does nothing
export default function (req, res, next) {
next()
}
(If you already have Vuex set up, you can skip this)
Add following empty Vuex store, i.e., create the file ./store/index.js, since the module needs Vuex set up.
export const state = () => ({})
Add nuxt-socket-io to the modules section of nuxt.config.js, this will enable socket-io client:
{
modules: [
'nuxt-socket-io',
],
// socket.io configuration
io: {
// we could have multiple sockets that we identify with names
// one of these sockets may have set "default" to true
sockets: [{
default: true, // make this the default socket
name: 'main', // give it a name that we can later use to choose this socket in the .vue file
url: 'http://localhost:3001' // URL wherever your socket IO server runs
}]
},
}
Use it in your components:
{
data() {
return {
latestTickId: 0,
};
},
mounted() {
const vm = this;
// use "main" socket defined in nuxt.config.js
vm.socket = this.$nuxtSocket({
name: "main" // select "main" socket from nuxt.config.js - we could also skip this because "main" is the default socket
});
vm.socket.on("tick", (tickId) => {
vm.latestTickId = tickId;
});
},
}
Run it with npm run dev and enjoy your tick events :)
Nuxt + socket.io
For me worked:
Create project as nodejs app (not static page);
Install socket.io npm i socket.io;
Add serverMiddleware section to nuxt.config.js:
export default {
...,
serverMiddleware: [
{path: '/ws', handler: '~/api/srv.js'},
],
}
Create middleware /app/srv.js:
const app = require('express')()
const socket = require('socket.io')
let server = null
let io = null
app.all('/init', (req, res) => {
if (!server) {
server = res.connection.server
io = socket(server)
io.on('connection', function (socket) {
console.log('Made socket connection');
socket.on('msg', msg => {
console.log('Recived: ' + msg)
setTimeout(() => {
socket.emit('msg', `Response to: ${msg}`)
}, 1000)
})
socket.on('disconnect', () => console.log('disconnected'))
})
}
res.json({ msg: 'server is set' })
})
module.exports = app
Socket.io needs server which is not created in middleware, that's why is taken from firest request to app from res.connection.server.
Create page pages/index.vue:
<template>
<div class="container">
<input v-model="msg">
<button #click="socket.emit('msg', msg)">send</button>
<br/>
<textarea v-model="resps"></textarea>
</div>
</template>
<script>
export default {
head: {
script: [
{src: 'https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js'},
],
},
data () {
return {
socket: null,
msg: 'wwJd',
resps: '',
}
},
mounted () {
this.$axios.$get('/ws/init')
.then(resp => {
this.socket = io()
this.socket.on('msg', msg => this.resps += `${msg}\n`)
})
},
}
</script>
Run it npm run dev;
Modify and enjoy :-)
I am getting my head around protractor and phantomjs. The test looks like this, it works fine with
just chrome:
describe('angularjs homepage', function () {
beforeEach(function () {
browser.driver.manage().window().setSize(1124, 850);
});
it('should greet the named user', function () {
browser.driver.get('https://angularjs.org/');
element(by.model('yourName')).sendKeys('Julie');
var greeting = element(by.binding('yourName'));
expect(greeting.getText()).toEqual('Hello Julie!');
});
});
the protractor.config looks like this :
// An example configuration file.
exports.config = {
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'phantomjs',
'phantomjs.binary.path': 'C:/ptor_testing/node_modules/phantomjs/lib/phantom/phantomjs.exe'
},
// For speed, let's just use the Chrome browser.
//chromeOnly: true,
// Spec patterns are relative to the current working directly when
// protractor is called.
specs: ['example.spec.js'],
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
// onComplete will be called just before the driver quits.
onComplete: null,
// If true, display spec names.
isVerbose: true,
// If true, print colors to the terminal.
showColors: true,
// If true, include stack traces in failures.
includeStackTrace: true,
// Default time to wait in ms before a test fails.
defaultTimeoutInterval: 30000
},
seleniumAddress: 'http://localhost:4444/wd/hub'
};
When I run this i get:
Error: Error while waiting for Protractor to sync with the page: {"message":"Can't find variable: angular","name":"ReferenceError","line":4,"stack":"ReferenceError: Can't find variable: angular\n at :4\n at anonymous (:13)\n at Na (phantomjs://webpage.evaluate():14)\n at phantomjs://webpage.evaluate():15\n at phantomjs://webpage.evaluate():15\n at phantomjs://webpage.evaluate():16\n at phantomjs://webpage.evaluate():16\n at phantomjs://webpage.evaluate():16","stackArray":[{"sourceURL":"","line":4},{"sourceURL":"","line":13,"function":"anonymous"},{"sourceURL":"phantomjs://webpage.evaluate()","line":14,"function":"Na"},{"sourceURL":"phantomjs://webpage.evaluate()","line":15},{"sourceURL":"phantomjs://webpage.evaluate()","line":15},{"sourceURL":"phantomjs://webpage.evaluate()","line":16},{"sourceURL":"phantomjs://webpage.evaluate()","line":16},{"sourceURL":"phantomjs://webpage.evaluate()","line":16}],"sourceId":81819056}
How can I fix this?
I'm trying to run this on a Windows machine and keep getting a timeout. I have Selenium running but it seems like its not able to fulfill connecting to the URL.
var client = require('webdriverjs').remote({
desiredCapabilities: {
browserName: 'chrome'
},
logLevel: 'verbose'
});
var expect = require('chai').expect;
describe('Test example.com', function(){
before(function(done) {
client.init().url('http://example.com', done);
});
describe('Check homepage', function(){
it('should see the correct title', function(done) {
client.getTitle(function(err, title){
expect(title).to.have.string('Example Domain');
done();
});
});
});
after(function(done) {
client.end();
done();
});
});
This is the error I receive:
1) Test example.com "before all" hook:
Error: timeout of 10000ms exceeded
at null.<anonymous> (C:\Users\sandy_000\AppData\Roaming\npm\node_modules\m
ocha\lib\runnable.js:139:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
I found this website: http://aboutcode.net/2013/12/02/automating-chrome-on-windows-with-javascript-using-selenium-webdriverjs.html
I needed to download the associating executable driver and start selenium with it like so:
c:\myproject>java -jar selenium-server-standalone-2.35.0.jar -Dwebdriver.chrome.driver=chromedriver.exe