How to test the onClick routing event using Jest/Enzyme? - reactjs

I have a button with Link tag and routes to a new url and content onClick, basically calls a function.
I wanted to know if I can test whether the url is changed/new content is displayed post click, but I am not able to do so with 'simulate'. Is it possible to check that using jest/enzyme?

I view you can test that using E2E testing.
I prefer https://www.cypress.io/, it is very easy for testing URL changing.
cy.getByTestId('your_button')
.click()
.url()
.should('include', 'expected_url')
FYI: https://docs.cypress.io/api/commands/url.html#No-Args

Related

How do I use custom Javascript in Next js

Coming from React, i am really confused. In pages/index.js, suppose I have a button with onClick listener, and clicking on that button will log "you clicked" in the console. How do i implement this? I want that page to be statically generated and also give that button some functionality.
The reason I am having a lot of trouble is because in React tutorials or even in my projects, if i needed some functionality i'd do this:
function handleClick() {
document.body.style.background = "black"
console.log("you clicked") //nothing is logged in console
}
export default function App() {
return(
<button onClick{() => handleClick}>Click Me</button>
)
}
I was gonna use this Next.js to see how state works. But I encountered a different problem. Unless I use inline function in onClick, it doesnt work. If I use a seperate handleClick function, the DOM doens't even show that I had an onclick event. I learned that's because Nextjs is rendered server side, so it doesnt have access to DOM and console etc. Then how do i do this?
I just transitioned from React, and in every tutorial, those guys would use handleClick func or whatever to handle events and stuff. But I couldnt find a solution to do this in Next, how does everyone handle this then? Because pages have interactive buttons right? Are those pages not statically generated then?
You forgot call function handleClick:
<button onClick{() => handleClick()}></button>
the same way you do it in react with your onClick function
Static generation pre-rendering does not change the interactivity of any page, check the following from Next.js documentation :
Each generated HTML is associated with minimal JavaScript code
necessary for that page. When a page is loaded by the browser, its
JavaScript code runs and makes the page fully interactive. (This
process is called hydration.)
https://nextjs.org/docs/basic-features/pages

How can i open a component in new Tab in react.js?

I have a dropdown which will a client list. Based on what i select in the dropdown i want to open a new tab for that particular client. Is there any way to do it?
I tried window.open(), while it works but it appends URl to http://localhost:3000/[object%20Object]. I dont what object to get appended in the URL. TIA
The window.open() method accepts a URL, so passing a component/javascript in the way that you require is not possible.
Consider setting up a route, say /popup-tableau that exclusively renders the <Tableau /> component, and then call:
window.open('/popup-tableau')
The idea here is that your application will open the new window, and a second instance of your application will be started (inside the new window), and directed to the route /popup-tableau which will display the <Tableau /> component in the way you require.

React Router Dom Prevent Prompt When Params Change

I am building a React Redux application and I am using <Prompt/> from react-router-dom to prevent a user from navigating away from a page when a specific icon is being rendered on the page.
It works fine except for when the params in the url change and then it fires the <Prompt/> when I don't want it to fire because I haven't actually tried to navigate anywhere. My url looks like:
http://localhost:8080/#/path/im/on?ids=1%2C24&from=1512518400000&searchRequest=e0007&to=1512604799000
When the ids in the url become successful, they are removed from the url but <Prompt/> is still fired.
Is there any way I can prevent <Prompt/> from firing when the url params change and the first part of the url stays the same? i.e. http://localhost:8080/#/path/im/on
Not sure if this is still relevant to you but you can do the following:
'message' prop in the Prompt component can either be a string or a function that returns a string or boolean.
<Prompt
message={(location) => {
return location.pathname.startsWith("your url")
? true
: `Are you sure you want to go to ${location.pathname}?`
}}
/>
if a function is passed to message prop then it will be called with the next location and action the user is attempting to navigate to. Return a string to show a prompt to the user or true to allow the transition.
here is the documentation link: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Prompt.md

React-Router v4 - Prevent Transition With Function

I was able to prevent navigation as per the v4 docs, but I'm trying to hook up a function so that I can use a modal instead of an alert.
Function:
abandonForm = (route) => {
this.props.showModal('confirm');
console.log('leaving..');
}
In my page:
<NavigationPrompt when={true} message={(location) => this.abandonForm('confirm')} />
this.props.showModal('confirm') activates the modal successfully, but behind the modal the page still transitions - how can I prevent transition until a button in the modal is clicked?
Browsers only allow navigation cancellation by means of the alert box that you've mentioned. This restriction is motivated by phishing/scamming sites that try to use javascript gimmicks to create user experiences that convincingly mimic something that a browser or the OS would do (whom the user trusts). Even the format of the text shown in the alert box is crafted so that it's obvious that it originates from the site.
Of course, as long as the current URL stays within your app, you have control over it using react-router's history. For example you can do the following on navigation:
allow the navigation without confirmation
immediately navigate back to the previous location, but now with a modal on top
navigate away for real this time when the user clicks on a button in the modal.
The disadvantage of this approach (leaving out the sheer complexity of it) is that the user will not get a confirmation dialog if they try to navigate to a different site entirely.
Use:
this.unBlock = this.props.history.block((location, navigateToSelectedRoute) => {
// save navigateToSelectedRoute eg this.navigateToSelectedRoute =
// navigateToSelectedRoute;
// use this.navigateToSelectedRoute() afterwards to navigate to link
// show custom modal using setState
});
and when unblocking is done then call this.unBlock() to remove the listener.
Documentation here for history api

Converting existing web app to use hashtag URIs using Backbone.js

I'm attempting to use Backbone and it's Router to turn an app into an ajax app, however it currently uses several different methods (helpers) of generating links. Unfortunately, this means manually changing each and every link to use a hashtag is out of the question.
What would be the best method of ensuring every link, form post, redirect, etc. gets parsed as a hashtag URL that can be caught by Backbone's Router? Or, even better, is it possible for the Router to accept "true URL's" from a request? Example: a request to /app/mail/inbox.php is caught by a rule in the Router, and is turned into #/mail/inbox after firing the appropriate method to handle the request.
What would be the best method of ensuring every link, form post, redirect, etc. gets parsed as a hashtag URL that can be caught by Backbone's Router?
I don't think that Backbone.Router is supposed to handle, say, form posts. It's supposed to give your application view state—bookmark-friendly and refreshable URLs [1].
If you want to ‘ajaxify’ forms, then you probably should add a handler for form's submit event and do something like $.ajax() there, preventing the default action.
Regarding plain old links, History.pushState() support has been added to Backbone recently. It means that you can define your routes as /app/*, and don't need to replace old href attributes. However, you'll still need to catch link click events to prevent default action.
For example:
var handle_link_click = function(e) {
path = $(e.target).attr('href');
app.main_router.navigate(path, true); // This.
e.preventDefault();
};
$('a:internal').click(handle_link_click);
Router's navigate() method will do history.pushState() if it's available, falling back to old hashchange. And true as a second argument means that it will fire corresponding handler action.
[1] See also this presentation about Backbone

Resources