Stripe Checkout does not redirect to checkout page Express - express

I am trying to use the Stripe prebuilt Checkout page to capture the payment details of an user following this documentation.
I think I wrote the code right, but somehow my app does not redirect the user to the Stripe checkout page. My code is as follows:
In my Express backend:
router.get("/create-check-out", async (req, res, next) => {
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
mode: 'setup',
customer: req.body.id,
success_url: 'http://localhost:5000/ll_profile?session_id={CHECKOUT_SESSION_ID}',
cancel_url: 'http://localhost:5000/ll_profile',
});
res.send (session.id);
});
On my JavaScript client-side:
$.get("/create-check-out", { id: stripe_customer_id}, async (sessionId) => {
console.log(sessionId)
stripe.redirectToCheckout({
sessionId: sessionId,
name: "Yugue"
}).then(function(result) {
console.log(result)
});
The console log does not show sessionId nor result.
The problem is after the get request is sent, the web URL becomes: http://localhost:5000/ll_profile?name= from http://localhost:5000/ll_profile (the URL under which all the codes above live), and the app is stuck at the same page without any redirecting action. I thought that it is supposed to redirect to the Stripe built-in checkout page like this:
What did I do wrong?

Most likely you've got the button inside a <form> element and there is competition between the Checkout redirect and the form submit action. You should either not use a form, or otherwise ensure the click handler related to Checkout is using preventDefault().
If that's not the case, please share more context of your DOM structure and the click handler.

Related

Cypress auto submit on login page from beforeEach in second test

I'm working on a Cypress test for the Polish Wikipedia plugin, and I have this code in my cypress test:
Cypress.Commands.overwrite('visit', (orig, path, options) => {
return orig(`https://pl.wikipedia.org/${path}`);
});
Cypress.Commands.add('login', (pass) => {
cy.visit('/w/index.php?title=Specjalna:Zaloguj');
cy.get('#wpName1').type('<username>');
cy.get('#wpPassword1').type(pass);
cy.get('#userloginForm form').submit();
});
Cypress.Commands.add('dark_vector_wait', (pass) => {
cy.get('.vector-menu-content-list > li:nth-child(7)', { timeout: 10000 }).should('be.visible');
});
And in my spec:
describe('dark vector test', () => {
beforeEach('login', () => {
cy.login(Cypress.env('WIKI_PASSWORD'));
});
it('test discussion', () => {
cy.visit('/wiki/Dyskusja_wikipedysty:<username>');
cy.dark_vector_wait();
cy.matchImageSnapshot('discussion');
});
it('testing-page page', () => {
cy.visit('/wiki/Wikipedysta:<username>/testing-page');
cy.dark_vector_wait();
cy.matchImageSnapshot('testing-page');
});
});
And the second test is failing because as soon as Cypress type the password it automatically submits a form so cy.get('#userloginForm form').submit(); is executing after Cypress visits the home page (default redirect) and fail to find a form.
What's wrong? Why does Cypress auto-submit a form after a second time? This is not what Wikipedia is doing since the login form doesn't have any JavaScript code and you need to click login to be able to login to Wikipedia.
EDIT:
I've tried to
Use BaseURL and remove overwrite of visit.
Add type('{enter}'), but this only shows an error: cy.type() failed because this element is detached from the DOM.
EDIT 2
This is the screenshot of the action taken by cypress, second test has a page load without {enter} action and without form submit.
The problem is in Cypress.Commands.overwrite('visit').
You pass the parameter with a leading slash '/wiki/Dyskusja_wikipedysty:<username>' but concatinate to base which also has a trailing slash https://pl.wikipedia.org/${path}, so now the full path is
https://pl.wikipedia.org//wiki/Dyskusja_wikipedysty:<username>
If you set baseUrl in configuration, Cypress sorts it out for you
cypress.config.js
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
baseUrl: 'https://pl.wikipedia.org'
}
})
Then remove the Cypress.Commands.overwrite('visit').
With these changes, I was able to pass both tests.
Using cy.session()
The problem might be one specific to locality, I do not have any steps missing in the Cypress log.
You can try adding a session cache so that the first login is re-used.
Cypress.Commands.add('login', (pass) => {
cy.session('login', () => { // login occurs only once
// credentials are cached
cy.visit('/w/index.php?title=Specjalna:Zaloguj');
cy.get('#wpName1').type('Jack Bosko');
cy.get('#wpPassword1').type(pass);
cy.get('#userloginForm form').submit();
// for good measure, confirm login was successful
// by checking for your name on the page
cy.contains('span', 'Jack Bosko')
})
})
So the problem was the weird IME keyboard that is part of MediaWiki. I somehow got it enabled on my system even when I was not logged in. Maybe added globally with cookies or something.
I noticed that keyboard when I was asking questions on the MediaWiki support page.
This is not related to Cypress. I'm investigating why the keyboard is there, and why clean environment it.

Testcafe - How do you wait for the `before` hook to complete before loading the page

I am using the test.before hook. My understanding is that this would be completed before the test would load the page.
What I am required to do is a navigateTo as the first action in my test.
test.page("/home").before(async t => {
await setupMockApis()
})("The bank account is added", async t => {
// the mock APIs are not finished setting up
// so I am required to do a navigateTo first
t.navigateTo("/home");
});
Is this the expected behaviour? Is it possible to get the before to complete before the test loads the page?
The common scenario is to login in before hook and it is implied that the page is loaded. In your case, you can avoid unnecessary page load omitting the page function call and navigating to your page in the hook as follows:
test.before(async t => {
await setupMockApis();
await t.navigateTo("/home");
})("The bank account is added", async t => {
});

testcafe - CAS authentication

New to TestCafe. Got some simple example tests working easily. However, I wasn't able to find any examples of features that would seem to allow me to log in to my application via a CAS authentication page.
This code works to find the login button on the login page and click it.
fixture`VRT`
.page `http://myapp.com/login/`;
test('Find Login button', async t => {
const input = Selector('input.btn');
await t.click(input);
});
And this would work to type in the username and password on the login page:
test('Login using CAS', async t => {
await t
.expect("#username").exists
.typeText('#username', 'myuser')
.typeText('#password', '***')
.click('#submit');
});
But the problem is that there seems to be no way to continue from one test to another. So I can't go from the first test that opens the login page, to the next test that enters the credentials. It seems like, for TestCafe, every test has to specify its own page.
If I try to go to the CAS login page directly, by specifying it as the fixture "page", TestCafe fails to open the page, I think because the URL is extremely long.
Thanks for any suggestions.
Update:
So, using roles got me a bit further (thanks) but had to get through one more CAS page with an input button to click before getting to the page I wanted to test. Was able to add in another click to the role login:
import { Role } from 'testcafe';
import { Selector } from 'testcafe';
const finalLoginBtn = Selector('input.btn');
const myUserRole = Role('http://example.com/login', async t => {
await t
.click('input.btn')
.typeText('#username', 'my-username')
.typeText('#password', '*****')
.click('#submit')
.click(finalLoginBtn);
}, { preserveUrl: true });
fixture`VRT`
test("My User Page", async t => {
await t.navigateTo(`http://example.com`)
await t.useRole(myUserRole);
});
The TestCafe 'User Roles' functionality should suit your requirements. Please, refer to the following topic in the TestCafe documentation for details: https://devexpress.github.io/testcafe/documentation/test-api/authentication/user-roles.html

Using Cypress to Test an App That Relies on OAuth

I've inherited a Node.js web app that uses relies on OAuth. Whenever you visit a page the app ensures you've authenticated. Please note, there no Angular, React, Vue, etc here. Each page is straight up HTML.
I want to test this site using Cypress. My problem is, I'm stuck on the initial redirect from the auth provider. Cypress acknowledge OAuth is a challenge.
commands.js
Cypress.Commands.add('login', (credentials) => {
var settings = {
'clientId':'<id>',
'scope':'<scope-list>',
...
};
var body = `client_id=${settings.clientId}&scope=${settings.scope}...`;
var requestOptions = {
method: 'POST',
url: 'https://login.microsoftonline.com/...',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: body
}
cy.request(requestOptions);
});
Then, in my test, I have:
context('Home', () => {
it('Visits Successfully', () => {
cy.login();
cy.title().should('include', 'welcome');
});
});
In the test runner, I see the login POST request is occurring. I confirmed that an access token is being received using a console.log, however, my title is empty. It's like the redirect after OAuth isn't happening in Cypress. However, when I visit the site in the browser, the redirect is happening as expected.
What am I missing?
What you might be missing is confusing between the actual UI flow and the programmatic flow of doing OAuth with a 3rd party website.
What you would want to do is to complete the programmatic login and then send the required parameters to your OAuth callback URL for your app manually in the test code.
an example is given here (though it uses a different grant type it gives you an idea) https://auth0.com/blog/end-to-end-testing-with-cypress-and-auth0/#Writing-tests-using-Cypress-Login-Command
another issue on the cypress github that deals with a similar problem
https://github.com/cypress-io/cypress/issues/2085
this also might help:
https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/logging-in__single-sign-on/cypress/integration/logging-in-single-sign-on-spec.js

Podio POST request returns unauthorized

I'm working on a Podio integration as a Slack bot.
I'm starting to use it just for use for my company to test it, then I could share it with everybody.
I've used the podio-js platform with Node JS, and started locally with a "web app" by starting from this example: https://github.com/podio/podio-js/tree/master/examples/password_auth
I need to do a post request, so I maintained all the code of the example in order to log in with user and password. The original code worked, then I changed the code to make a post request, in particular I change the lines of index.js into this:
router.get('/user', function(req, res) {
podio.isAuthenticated().then(function () {
var requestData = { "title": "sample_value" };
return podio.request('POST', '/item/app/15490175', requestData);
})
.then(function(responseData) {
res.render('user', { data: responseData });
})
.catch(function () {
res.send(401);
});
});
But in the end is giving a "Unauthorized" response.
It seems like the password auth doesn't let to make POST request to add new items! Is that possible?
I've already read all the documentation but I'm not able to explain why and how I can solve this.
Regards