I'm trying to do a pretty simple intercept in Cypress using a Vue's application. My component has a setup method using render function as such:
setup() {
useInfiniteLoading({ runner: ... })
}
Then on my tests I do the following:
describe("List todo resource", () => {
it("Checks it loads more todos when scrolling to the bottom", function () {
cy.intercept('/todo').as('getTodos');
cy.visit("/todos");
cy.wait("#getTodos").then(({response}) => {
console.log(response);
})
})
})
When running the test I see that the intercept is not stubbing the response.
As you can see from the image the request makes a request to my actual server running locally and the response is stubed. The weird part is that in a previous test I have:
it("Checks the todo list gets updated when clicking on to resolve it (from true to false)", function () {
cy.visit("/todos");
const resolved = false;
const shouldHaveClass = resolved
? "mdi-checkbox-marked-outline"
: "mdi-checkbox-blank-outline";
cy.intercept("GET", "todo", {
fixture: "resources/todo/list.todo.json",
}).as("getTodos");
cy.intercept("PUT", "todo", {
body: { data: { ...this.updateTodoFixture.data, resolved } },
}).as("updateTodo");
cy.get(".todo-list-item__resolve")
.first()
.each((btn) => {
btn.click();
});
cy.get(".todo-list-item__resolve")
.first()
.should("satisfy", ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes(shouldHaveClass);
});
});
And the response is stubbed using intercept as you can see from the previous screenshot. Is it possible that the previous test is affecting the next test? I have tried taking a look into "Intercept too soon" but no luck on trying to apply the fix described in the page.
Any idea on what could be causing the stub not to happen?
My code works fine when I write in browser localhost:4200/pay;id=1. This show Pay component with credit card fields generated by a external javascript (This javascript script is loaded from this component). But if i come from another component to this, Pay component doesn't show the credit card fields but load external script. How can I fix this?
My code
first.component.ts
let datos = {
id:'6'
}
this.router.navigate(['pay',datos]);
pay.component.ts
ngOnInit(): void {
this.loadScripts();
}
loadScripts() {
this.dynamicScriptLoader.load('2payjs').then(data => {
// Script Loaded Successfully
console.log('All elements loaded successfully')
this.loadElement();
}).catch(error => console.log(error));
}
loadElement(){
let that = this;
let id = this.router.snapshot.paramMap.get('id');
window.addEventListener('load', function() {
// Initialize the JS Payments SDK client.
let jsPaymentClient = new TwoPayClient('AVLRNG');
// Create the component that will hold the card fields.
let component = jsPaymentClient.components.create('card');
component.mount('#card-element');
// Handle form submission.
document.getElementById('payment-form').addEventListener('submit', (event) => {
event.preventDefault();
/// Extract the Name field value
const billingDetails = {
name: document.querySelector('#name').value
};
// Call the generate method using the component as the first parameter
// and the billing details as the second one
jsPaymentClient.tokens.generate(component, billingDetails).then((response) => {
//console.log(response.token);
let data = {
token:response.token
}
}).catch((error) => {
console.error(error);
});
});
});
}
const navigationExtras: NavigationExtras = {
queryParams: {
id: 1,
},
queryParamsHandling: 'merge'
};
this.router.navigate(['pay'], navigationExtras);
you need navigationExtras in order to create params in your router link and able to fetch by another component
Already solved. I just delete window load event listener.
I'm new to Cypress. My app as a "routing system" manually changes window.location.hash.
At some point, I click on a button that changes the hash and consequently should change the page during the test. I can see a "new url" entry appearing during the execution, but how can I make cypress visit that url?
In few words, what the problem is: you can see I type the password and then {enter}. Running the test I can see the hash change in the address bar, but the page doesn't change in accord to the hash change.
This is the testing code
context("Workflow", () => {
it("login", () => {
cy.visit("http://localhost:3000/src/#login")
cy.get("#username").type("demo").should("have.value", "demouser")
cy.get("#password").type("demo{enter}").should("have.value", "demo") // this should redirect to "/#home"
//cy.wait(10000)
cy.get(".subtitle").should("have.value", "Welcome") //this line fails as ".subtitle" is an element of "/#home"
})
})
EDIT: Following tons of failed attempts, I came up with a partially working, clunky and hacky solution. I think I shouldn't need to use reload() to solve that (there must be a better solution..), but to make it works I have to wait for all the remote requests to be done (otherwise reload() cancels them). I say partially working because you can see from the comments in the code if I try to visit #login first, then follow the redirect in #home and then change the page to #browser, the last one doesn't work (I can see the hash changing to #browser, but the page is still #home).
import 'cypress-wait-until';
let i = 0;
context("Workflow", () => {
it("login", () => {
cy.server( {
onRequest: () => {
i++;
},
onResponse: () => {
i--;
}
});
cy.visit("http://localhost:3000/src/#login")
cy.get("#username").type("demouser").should("have.value", "demouser")
cy.get("#password").type("demouser").should("have.value", "demouser")
cy.get("form#formLogin").submit()
cy.waitUntil(() => i > 0)
cy.waitUntil(() => i === 0)
cy.reload(); // it correctly change the hash AND the page to #home!
cy.url().should("include", "#home")
cy.get(".version").contains( "v2.0.0-beta") // it works!!
cy.get("a[data-id=browser]").click({force: true}) // it correctly changes the hash to #browser
cy.waitUntil(() => i > 0)
cy.waitUntil(() => i === 0)
cy.reload();
// the hash in the address bar is #browser, but the web page is #home
})
})
Cypress has an event called url:changed. See doc on Events here
Using this, something like this may work:
context("Workflow", () => {
it("login", () => {
cy.on('url:changed', url => {
cy.location('hash').then(hash => {
if (!url.endsWith(hash)) {
cy.visit(url);
}
});
});
cy.visit("http://localhost:3000/src/#login")
cy.get("#username").type("demo").should("have.value", "demouser")
cy.get("#password").type("demo{enter}").should("have.value", "demo") // this should redirect to "/#home"
cy.get(".subtitle").should("have.value", "Welcome") //this line fails as ".subtitle" is an element of "/#home"
})
})
Edit: just for troubleshooting purposes and to focus on your issue, can you try it like this without cy.location():
context("Workflow", () => {
it("login", () => {
cy.on('url:changed', url => {
cy.visit(url);
});
cy.visit("http://localhost:3000/src/#login")
cy.get("#username").type("demo").should("have.value", "demouser")
cy.get("#password").type("demo{enter}").should("have.value", "demo") // this should redirect to "/#home"
cy.get(".subtitle").should("have.value", "Welcome") //this line fails as ".subtitle" is an element of "/#home"
})
})
Edit: Have you tried cy.reload()
context("Workflow", () => {
it("login", () => {
cy.visit("http://localhost:3000/src/#login")
cy.get("#username").type("demo").should("have.value", "demouser")
cy.get("#password").type("demo{enter}").should("have.value", "demo") // this should redirect to "/#home"
cy.reload();
cy.get(".subtitle").should("have.value", "Welcome");
})
})
Thanks for all the attempts to solve, but they were all tricky workarounds to something as simple as "trigger the related listener when window.location.hash changes".
The root of the problem was a bug in Cypress. The bug on window.location.hash is present in 4.5.0, but it has been solved somewhere between 4.5.0 and 4.12.1.
In 4.12.1 the problem is solved.
There are some ways to do that. One of the basic approach is like this:
cy.visit(`your_login_page`)
cy.get('[data-testid="input-username"]').type(`demo`, { force: true })
cy.get('[data-testid="input-password"]')
.type(`demo`, {
force: true,
})
.wait(1000)
.then(() => {
cy.location().should((loc) => {
expect(loc.pathname).to.eq(your_new_url)
})
})
You should add data-testid or findByTestId to your elements with a unique id.
To visit the new URL, you can use cy.visit(loc.pathname)
I have a little bit of a problem with the angular navigator 2
I'm in my detail projects page and I have a component that is in my detail page that will show me the next project.
So in my component I recall the same page which is' /projects/id
when I click in the navigation bar it changes the id well but the content does not change and I do not understand why because I make a router. navigate of my page.
my init controller projectDetail
ngOnInit() {
this.nextProjectId = this.activedRoute.snapshot.queryParams.nextProject;
const id = this.activedRoute.snapshot.params.id
this.projectsService.projectsAll().then( (projects) => {
if (projects[this.nextProjectId]) {
this.nextProject = projects[this.nextProjectId];
} else {
this.nextProject = projects[0];
}
});
this.projectsService.projectFind(id).then( project => this.project = project);
}
my function navigate in component nextProject
nextProjectDetail(id, nextProject) {
const next = parseInt(nextProject, 0) + 1
this.router.navigate(['projects/', id], { queryParams: {nextProject: next }}).then(
function(){
console.log('navigate success');
},
function(){
console.log('navigate failure');
}
);
}
I even tried to use this function in the init of detail projects to see when the url changes but it doesn't work.
this.params.subscribe(params => {
console.log("dfsd");
});
there is another way to refresh the same page in a component on the same page?
thanks
I have this code:
Template.messageList.onCreated(function onCreated() {
this.state = new ReactiveDict();
this.state.setDefault({
limit: 5
});
this.autorun(() => {
this.subscribe('messages', {limit: this.state.get('limit')});
});
});
Template.messageList.helpers({
messages () {
const instance = Template.instance();
return Messages.find({}, MessagesFilter.common({limit: instance.state.get('limit')}));
}
});
Template.messageList.events({
'click .ui.button.more' (event, instance) {
const limit = instance.state.get('limit');
instance.state.set('limit', limit + 5);
}
});
It's intended to be a infinite scroll, but it presents weird events. Right now, the elements on page are reloaded when the limit changes.
Looks like meteor is re-subscribing (which is expected by the documentation) but this is reloading all the documents, it deletes the messages and then reload the with the new limit value.
How can I prevent it? I want a infinite scroll, but the way it behaves right now looks impossible.
Here's a video of what's happening.
http://recordit.co/mlsGThOdHp
Here's the repository:
https://github.com/Sornii/sayito/tree/infinite-scroll
I changed
this.autorun(() => {
this.subscribe('messages', {limit: this.state.get('limit')});
});
To
Tracker.autorun(() => {
this.subscribe('messages', {limit: this.state.get('limit')});
});
And now it works the way I want to.