So i am using cypress to log into google and create a google form. I have gotten through the login, but now that I want to select create new form, I am seeing cross origin errors which seem to be blocking such actions. Can anyone help me out here? Heres my code. Its the click on #1f that is not working
'''
describe('Test', function () {
it('logs into google', function () {
Cypress.on('uncaught:exception', (err, runnable) => {
return false
})
cy.visit('http://docs.google.com/forms/u/0')
cy.xpath("//input[#type='email']").type("userAlktest#gmail.com");
cy.xpath("//span[contains(text(),'Siguiente')]").click();
cy.wait(5000);
cy.xpath("//input[#type='password']").type("1Testagain");
cy.xpath("//span[contains(text(),'Siguiente')]").click();
cy.wait(5000);
///cy.xpath("//span[contains(text(),'Probar otra manera')]").click();
/// cy.wait(5000)
/// cy.xpath("//span[contains(text(),'Confirmar')]").click();
/// cy.wait(5000)
//cy.xpath("//span[contains(text(),'Untitled form')]").click();
//cy.wait(5000)
cy.get('#:1f').click();
cy.wait(5000);
'''
This is a cypress tradeoff and you can read about it from the cypress docs. In a nutshell, if you want to access two different URLs in one test you cannot. For this scenario, you have to write two tests where each URL is accessed. For e.g.
NOT OK ❌
it('navigates', () => {
cy.visit('https://apple.com')
cy.visit('https://google.com') // this will error
})
OK ✅
it('navigates', () => {
cy.visit('https://apple.com')
})
// split visiting different origin in another test
it('navigates to new origin', () => {
cy.visit('https://google.com') // yup all good
})
Maybe it would help it would help more if more clarity was provided on what the reason for creating a Google form.
Back to the question, the original domain your test is bounded is https://google.com. I imagine removing the describe() block and having two it() with no describe() could help you out.
Related
I can't count the number of DOM elements on a site written in React.
/// <reference types="cypress" />
context('Checking all components', () => {
beforeEach(() => {
cy.visit('https://news-israel.com');
});
it('Checking posts', () => {
cy.get('.posts-wrapper').find('a').should('exist');
cy.get('.posts-wrapper').find('a').its('length').should('be.gte', 100);
});
});
In this case, it doesn't find the "a" tags because React rendering them asynchronously and dynamically.
The "post-wrapper" class finds, followed by an exception:
The following error originated from your application code, not from Cypress.
Cannot read property 'substr' of undefined
When Cypress detects uncaught errors originating from your application it will automatically fail the current test.
How to correctly count the number of elements in this case, so that you can "wait for the elements"?
The site I'm testing is in production - https://news-israel.com
The error is coming from the app itself, and ultimately should be fixed in the app source.
But see this note in the log
This behavior is configurable, and you can choose to turn this off by listening to the uncaught:exception event.
This links to an event handler you can use to debug. Add this to the top of the test to suppress the test failing when the error occurs.
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false
})
Now the test works, provide you use the correct class posts-wrapper not post-wrapper.
If you are able to fix the source, the error comes from the react-typed library, which is used in BreakingNews.js at line 75
<Typed
strings={posts}
typeSpeed={15}
backSpeed={10}
backDelay={5000}
loop
/>
the posts variable is initially undefined, so you need a fallback value, e.g strings={posts || []}
To globally Handle Uncaught exceptions, Go to cypress/support/index.js and write:
Cypress.on('uncaught:exception', (err, runnable) => {
return false
})
Now to count the number of elements you do it via each() or by using Cypress.$
Using each():
cy.get('div.post-title').each((ele, list) => {}).then((list) => {
cy.log(list.length)
})
Using Cypress.$
cy.get('div').find('.post-title').then(ele => {
cy.log(Cypress.$(ele).length)
})
OR, As suggested by #Hiram
cy.get('div.post-title').then(ele => {
cy.log(Cypress.$(ele).length)
})
As the test suite grows I need to be able to run something in BeforeSuite() which will connect to external suite and skip the suite if an external resource is unavailable.
Feature('External Server');
BeforeSuite((I) => {
// Check if server is available and skip all scenarios if it is not
});
Scenario('Login to the server', (I) => {
// Do not run this if the server is not available
})
I understand I could probably set a variable, but I think it would be nice if there was a way to tell the runner that a suite has been skipped.
The goal is to have a suite marked as skipped in the output eg:
Registration --
✓ Registration - pre-checks in 4479ms
✓ Registration - email validation in 15070ms
✓ Registration - password validation in 8194ms
External Server -- [SKIPPED]
- Login to the server [SKIPPED]
maybe prepend x before every scenario in your feature? example xScenario. I don't think codecept supports something similar to only for features. it currently works with scenarios only as far as I know.
you can use
Scenario.skip
in your step definition to skip a scenario.
Note: if any steps have been executed before skipping then it will still show it in the report
https://codecept.io/basics/#todo-test
My answer is compiled from a number of comments on the CodeceptJS github and stackoverflow. However, I can't recall the exact links or comments which helped me derive this solution, it's been at least a year, maybe two, since I started and have slowly modified this.
Edit: Found the github thread - https://github.com/codeceptjs/CodeceptJS/issues/661
Edit2: I wrote a post about "selective execution" (which avoids tagging unwanted tests with skip status) https://github.com/codeceptjs/CodeceptJS/issues/3544
I'll add a snippet at the bottom.
I'm on CodeceptJS 3.3.6
Define a hook file (eg: skip.js) and link it to your codeceptjs.conf.js file.
exports.config = {
...
plugins: {
skipHook: {
require: "../path/to/skip.js",
enabled: true,
}
}
...
}
The basic code in skip.js is
module.exports = function () {
event.dispatcher.on(event.test.before, function (test) {
const skipThisTest = decideSkip(test.tags);
if (skipThisTest) {
test.run = function skip() {
this.skip();
};
return;
}
});
};
I've defined a decision function decideSkip like so:
function decideSkip(testTags) {
if (!Array.isArray(testTags)) {
output.log(`Tags not an array, don't skip.`);
return false;
}
if (testTags.includes("#skip")) {
output.log(`Tags contain [#skip], should skip.`);
return true;
}
if (
process.env.APP_ENVIRONMENT !== "development" &&
testTags.includes("#stageSkip")
) {
output.log(`Tags contain [#stageSkip], should skip on staging.`);
return true;
}
}
(Mine is a bit more complicated, including evaluating whether a series of test case ids are in a provided list but this shows the essence. Obviously feel free to tweak as desired, the point is a boolean value returned to the defined event listener for event.test.before.)
Then, using BDD:
#skip #otherTags
Scenario: Some scenario
Given I do something first
When I do another thing
Then I see a result
Or standard test code:
const { I } = inject();
Feature("Some Feature");
Scenario("A scenario description #tag1 #skip #tag2", async () => {
console.log("Execute some code here");
});
I don't know if that will necessarily give you the exact terminal output you want External Server -- [SKIPPED]; however, it does notate the test as skipped in the terminal and report it accordingly in allure or xunit results; at least insofar as CodeceptJS skip() reports it.
For "selective execution" (which is related but not the same as "skip"), I've implemented a custom mocha.grep() utilization in my bootstrap. A key snippet is as follows. To be added either to a bootstrap anonymous function on codecept.conf.js or some similar related location.
const selective = ["tag1", "tag2"];
const re = selective.join("|");
const regex = new RegExp(re);
mocha.grep(regex);
I am moving into functional reactive code starting with rxjs and have some questions about how to best import it as I am getting mixed results.
Currently, I have a simple implementation where I check a web service for if a username already exists.
Here is the code that works perfectly:
$(window).load(function() {
// setup an observable
submission = Rx.Observable.fromEvent($("#submitbutton"), "click").map(
event => {
return "justsomeusername";
}
);
submission
.concatMap(username => {
return Rx.Observable.fromPromise(
$.get(
"{{ site.serveraddress }}/checkuser?&username=" + username
)
).catch(() => Rx.Observable.empty());
})
.subscribe(rval => {
console.log(rval);
});
});
This all works great BUT when I try to add a debounce like submission.debounce(500).concatMap((username) =>
Rx.js:8512 Uncaught TypeError: this.durationSelector.call is not a function
at DebounceSubscriber._next (Rx.js:8512)
at DebounceSubscriber.Subscriber.next (Rx.js:424)
at MapSubscriber._next (Rx.js:5715)
at MapSubscriber.Subscriber.next (Rx.js:424)
at HTMLButtonElement.handler (Rx.js:3913)
at HTMLButtonElement.dispatch (jquery.min.js:3)
at HTMLButtonElement.r.handle (jquery.min.js:3)
That is what appears in the console.
I think that the way I am importing or referencing the library is the cause, this is where there is some confusion.
I am importing like this at the top of an HTML page:
<script src="https://unpkg.com/#reactivex/rxjs#5.5.6/dist/global/Rx.js"></script>
If I try to import any other reference the Rx object seems not to exist? Does this have to do with the filename maybe becoming the object namespace?
For example, I downloaded all the latest rxjs release and in the dist see rx.all.js but if I import locally one of the latest dists like:
<script src="/myapp/javascript/rx.all.js"></script>
I get Rx undefined. What is the nuance occurring between these two different ways of reference.
What is the surefire way to import rxjs for client-side use? Is this the likely cause of the debounce not working (not having the full lib)?
Thanks!
You should use debounceTime for this, not debounce. debounce takes a function parameter which must determine dynamically the debounce time, whereas debounceTime can be used exactly as you state:
$(window).load(function() {
// setup an observable
submission = Rx.Observable.fromEvent($("#submitbutton"), "click").map(
event => {
return "justsomeusername";
}
);
submission
.debounceTime(500)
.concatMap(username => {
return Rx.Observable.fromPromise(
$.get(
"{{ site.serveraddress }}/checkuser?&username=" + username
)
).catch(() => Rx.Observable.empty());
})
.subscribe(rval => {
console.log(rval);
});
});
If you wanted to use debounce, you'd do something like this:
submission
.debounce((val) => {
// Add whatever logic for determining the right
// debounce time for the value entered by the
// user, in this case, simply returning a hard
// coded 500 which will do exactly the same as
// debounceTime(500)
return 500;
})
.concatMap(username => {
// ... snip ...
});
});
It doesn't look like there is any problem with how you are importing RxJS - although I would advise if you're just starting with RxJS to go to v6 as it changes how a lot of things are done with operators like debounce and concatMap - it's a pain to change it all later so better to make the change when you're just starting!
I have node.js installed and protractor installed. I have experience with selenium-webdriver but Protractor is driving me nuts!!! I am also not that familiar with javascript.
This is what my code looks like:
describe('My app', function() {
var result = element(by.id('result-name'));
var enterBtn = element(by.id('enter'));
var clearFieldBtn = element(by.id('clear-field');
it('should bring up components on load', function() {
browser.get(`http://localhost:${process.env.PORT}`);
browser.wait(until.titleContains('Sample App'), 500);
browser.wait(until.presenceOf(browser.element(by.id('my-test-app'))), 500);
expect(enterBtn).isPresent;
});
it('result should equal username', function () {
browser.get(`http://localhost:${process.env.PORT}`);
expect(clearFieldBtn).isPresent;
expect(result.getText()).toEqual('John Smith'); //both tests pass without this line of code
});
});
The last line "expect(result.getText()).toEqual('John Smith');" throws me an error. I get:
expect(...).toEqual is not a function
Any help would be much appreciated. I have spent a couple of hours trying to find a solution and trying different things.
I also wanted to implement the isPresent function how it's done in the api docs which is like this: expect($('.item').isPresent()).toBeTruthy();
I tried to do:
expect(clearFieldBtn).isPresent().toBeTruthy();
But I get that isPresent is not a function...
The expect above that line seems poor. It should read
expect(clearFieldBtn.isPresent()).toBeTruthy();
not sure if that is causing the weird error on the line below...just thought I would throw it out there. All your protractor APIs need be be called within the expect because isPresent is not a attribute of expect
Have you tried these lines:
clearFieldBtn.isPresent().then(function(bln) {
expect(bln).toBe(true);
});
result.getText().then(function(tmpText) {
expect(tmpText).toBe('John Smith');
});
If you still get an error on result.getText(), please check the presence of the result object.
So I've been trying to figure out how front end testing works (unit testing) but I am getting stuck on some point.
So I have my jasmine test set up as follows:
describe('Blabla', function () {
it('returns true', function () {
var people = require(["people"], function(ppl) {
return ppl;
});
expect(people.getTitle()).toBe('People piolmjage');
});
});
But running this gets me:
TypeError: undefined is not a funtion
So obviously, people is undefined. So perhaps my callback comes in too late. But if I remove the callback I get following error:
it('returns true', function () {
var people = require("people");
expect(people.getTitle()).toBe('People piolmjage');
});
Error: Module name "people" has not been loaded yet for context: _. Use require([])
I figure there is something wrong in my setup...Anyone have any idea how to get this FE testing to work?
I did manage to get it to work from console and using define combined with phantomjs and the durandal test files but I need this to work outside of the console and hereby I cannot use this define because the test runner won't find my tests.
That's why I need to use the CommonJS was of getting the required viewmodels.
people model
define([],
function () {
var getTitle = function() {
return "hello";
}
var peopleViewModel = {
title: 'People page',
getTitle: getTitle
};
return peopleViewModel;
});
UPDATE
I got the code working but not with resharper. Following this page from the durandal webpage.
But this gets me console output which is way to unstructured to actually read through.
I can however use the define keyword and then it works fine. So I assume it is the require keyword where I mess up something?
UPDATE 2
So I used fiddler to check what is going on. I also finally got it working (kinda...).
My testfile looks like this now:
///<reference path="../../Scripts/require.js"/>
///<reference path="../../test/lib/jasmine-2.1.3/jasmine.js"/>
///<reference path="../../App/viewmodels/people.js"/>
describe('Blabla', function () {
it('require test', function (done) {
require(['people'], function (people) {
expect(people.title).toBe('People page');
done();
});
});
});
And then I changed my people file:
define("people", ["bla"], function (bla) {
return {
title: 'People page',
bla: bla
};
});
As you can see here, I name my viewmodel to be people.
This works for the testrunner but he doesn't actually get any files through requireJS but only the reference paths. Also this does not fit my needs because the durandal models are unnamed.
Fiddler screenshot:
So basically he does not use requireJS to get the viewmodels and therefor I cannot just use the require.config initializer to get to my viewmodels folder and download every viewmodel using requireJS. Any thoughts?
I finally got it working, took me like a day and a half.
Anyway I don't use resharper anymore, or it's test runner to be more precise.
Chutzpah is the one I turned to in the end. This too took me some research but I got it to the point where it includes everything as I want it to.
Check this post for sure
Here is what I did:
My people.js looks like this:
define(['viewmodels/bla'], function (bla) {
return {
title: 'People page',
bla: bla //testing dependencies on other viewmodels
};
});
Then I also made a bla.js
define(function() {
return {
bla: "bla"
};
});
And now for the tests:
describe('Blabla', function () {
it('require test', function (done) {
require(['viewmodels/people'], function (people) {
expect(people.title).toBe('People page');
done();
});
});
it('dependency on require test', function (done) {
require(['viewmodels/people'], function (people) {
console.log(people.bla);
expect(people.bla.bla).toBe('bla');
done();
});
});
});
And then eventually, reading the answers on the link provided on top I had to create a Chutzpah config file to create a test harnass:
{
"Framework": "jasmine",
"TestHarnessReferenceMode": "AMD",
"TestHarnessLocationMode": "SettingsFileAdjacent",
"References" : [
{"Path" : "../Scripts/require.js" },
{"Path" : "requireConfig.js" }
],
"Tests" : [
{"Path": "specs"}
]
}
Now, running the tests with Visual studio test runner actually gets me everything I need and as you can see, I can now access all my viewmodels through require like so: require(['viewmodels/whateverviewmodel'], function(whateverviewmodel){....})
I hope this answer can get people on their way to testing your (Durandal)SPA using Jasmine and RequireJS.
I know my viewmodels in this answer, nor in the question itself, say much but this should get you an idea of how to go about all of this.
Small Edit
You can now also skip the callback mess with require([]... inside of the tests and build your tests like you do your viewmodels with define
define(['viewmodels/people'], function (people) {
describe('Blabla', function () {
it('require test', function () {
expect(people.title).toBe('People page');
});
it('dependency on require test', function () {
console.log(people.bla);
expect(people.bla.bla).toBe('bla');
});
});
});
This gets you less indents and is more readable in itself.
The require call provided by RequireJS is inherently asynchronous so you need to do something like this:
it('returns true', function (done) {
require(["people"], function(people) {
expect(people.getTitle()).toBe('People piolmjage');
done(); // Signal that the test is done.
});
});
The first attempt you show in your question cannot work. That's the classical "trying to return values synchronously form asynchronous code" mistake. The second attempt with require("people") does not work either because this require call is pseudo-synchronous and will work only if the module requested is already loaded. See this answer for an explanation of how this pseudo-synchronous require works.