Testing React withRouter

One area I’ve always found tricky when writing tests for React is where Higher Order Components are involved. I’ve found this complicates the test setup process. There are ways around this, which may or may not be possible depending on many factors. Sometimes you work on third party code that won’t accept ‘dramatic’ refactors just to scratch your own testing itches.

One example of where this problem might occur (particularly if you don’t read the docs!!) is with React Router, specifically when using withRouter.

In this example I have MyComponent which wants to history.push('/some/location') when the user completes some action.

I’d like to test that this process takes place as expected.

Here was my first attempt. This way works, but there are some drawbacks:

This works.

There are a couple of drawbacks to this:

  • It involves a couple of extra imports.
  • Behind the scenes, withRouter is still used (afaik) but by wrapping in another Router, we can override the history prop.

As this particular approach is so common, React Router gives us an alternative / preferable way to test this workflowWrappedComponent.

The necessary actions to ‘run’ this test are unchanged. However, there are fewer lines as we can make use of the existing constructs provided by React Router to aid our testing workflow.

This may have been extremely obvious to you.

I can’t remember if WrappedComponent has always been available and I have overlooked it, or it is something new since I last had to do testing with a project using React Router.

Either way, it’s time I refreshed my knowledge of the documentation. And hopefully this helps someone else when testing withRouter at some point in the future.

Why would I do function() and not function blah()?

Today I got asked the question:

In JavaScript (the best language) what is the difference between these two:

The first is an anonymous function.

The second is a named function.

Anonymous functions are one time deals.

Named functions can be used as many times as needed. Even zero times.

An example of an anonymous function:

The function (n) => n + 1 is anonymous. It has no name.

But you could define it as a named function:

And then you could repeat the map with the named function:

And likewise you could use the function again and again:

Even if your function is a one-and-done deal, naming functions can help you better explain your code to others (or yourself 5 minutes from now).

As soon as you name an anonymous function, it is no longer anonymous.

And that’s all I have to say about that.

How I Fixed: React Native – Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.

This one had me kicking myself.

What you see on your phone

I really like VSCode for JS projects, but man-oh-mally, on this occasion it bit me. I wonder if I need another plugin, or something?

Bit easier to see in Chrome developer tools debugging session

The error in full for Google searchers:

Solving this, for me, was actually really straightforward. The issue was a typo of fail proportions.

I’d been playing around with using functional components with React Native, instead of the more typical (from all the examples I’ve seen anyway) class component approach:

Pretty basic, right? I always feel somehow much worse about myself when my most basic creations fail unexpectedly.

The problem is (as best I can tell) a syntax error. But neither VSCode nor WebStorm flag this up.

Ok, so to put us all out of our misery:

But why doesn’t the IDE flag this?

I’m not sure how this initial fat arrow could ever be valid syntax? I’ve tried playing around in the console and I can’t seem to make it work.

Anyway, hopefully for you, it’s something similar if not identical. Fat fingers, fat arrows.

How I Fixed: Server channel error: 406, message: PRECONDITION_FAILED – inequivalent arg ‘type’ for exchange ‘my_exchange’ in vhost ‘/’: received ‘fanout’ but current is ‘direct’

Not a fun way to start a Saturday morning. With a bit of spare time this morning I wanted to continue some refactoring work on a tool I’ve been working on for checking broken links on any given website.

The project is quite cool (in my opinion), using a bunch of interesting software / tech such as RabbitMQ with Symfony’s Messenger component, STOMP for real time stuff, React with Hooks, Tailwinds for CSS… and a bunch more buzz-wordy, CV helping stuff that keeps me gainfully employed.

Anyway, the first thing I did was spin up the Symfony docker containers that run the various services to handle incoming broken link checking requests. And as ever, I ran a composer update to bring Symfony up to 4.3.x.

I’m not sure if bumping up to Symfony 4.3 was the cause of this problem. I suspect not. It’s been a while since I’ve worked on this part of the code, but it was all working the last time I brought the project up. And it’s working live and online, too, so something has gone awry.

Anyway, after the composer update completed successfully:

I tried to run my messenger consumer:

Knickers. It all blew up quite badly.

There’s a lot of info to process, and without some nice terminal colouring it’s all a bit of a blur.

The interesting line is:

What I think has gone wrong is that at some point in the past, I’ve switched over my RabbitMQ exchange to use direct, and by default, Symfony’s Messenger component will try to create an exchange with the type of fanout.

To clarify, my exchange and queue combo already exists at: amqp://{username}:{password}@rabbitmq:5672/%2f/fetch

It exists because I have previously configured my RabbitMQ instance to boot up with this exchange / queue combo ready and good to go.

Because Symfony’s Messenger component is not immediately aware that this queue will already exist, it tries to create it.

It cannot create it because the default type of exchange that Symfony’s Messenger component will try to use is fanout.

In order to make this work, I needed to manually specify the config that explicitly sets this exchange / queue combo to the desired setting of direct.

Finding this out via the documentation wasn’t super straightforward. Here’s a few of the steps I took:

bin/console config:dump-reference framework

This shows that for each framework.messenger.transports entry in your config/packages/messenger.yaml file, you can have a variety of additional settings.

As it was, my original config looked like this:

By providing just a DSN (by way of environment variables), all the default config would be used.

What I needed to do was swap over to this:

And after doing so, it all started working again:

In short, this isn’t directly a Symfony / Symfony Messenger problem. It’s a config problem. The messaging could be a little more clear, as could the documentation for what things are viable as options.

How to Change File Modified Date on All Files to Midnight

Bit of an obscure one, but I searched Google without finding a specific example.

After back up, I want to set all my files in a given directory to be modified at midnight of the current day. The real modified date is not very important to me, so this command suffices. I have a specific reason for this process, though it’s quite unusual.

Anyway, here goes:

As ever, use with caution / practice on a copy of your data first.