React + GraphQL: defining undefined data in Unit Tests

You are a frontend developer (or maybe a full-stack developer doing some frontend now), and you were tasked to build just another React component that makes use of the shiny new GraphQL call – say, present details of the last credit card transaction to the end user.

Sure thing, you say, why not? The pattern is well-known and there are plenty of examples in the codebase to copy-paste from. Apollo Client provides you with it’s useful useQuery() hook, GraphQL query is conveniently generated for you by some home-grown or third-party tool and is ready to use. So you quickly end up with something like this:

function LastTransaction() {
  const { loading, data, error } = useQuery(gql(getLastTransaction));
  return (
    <>
      { loading && <Loader /> }
      { error && <Error /> }
      { data && <span>Last charge: {data.getLastTransaction.amount}</span> }
    </>
  );
}

You embed your new component in the app and it shows the transaction amount. So far, so good. Time to move on to the unit tests. Again, the pattern is known and no surprises expected. You have MockedProvider from Apollo Client, and you are well-aware that even the mocked client will take you through the loading stage of the component lifecycle – just need to waait a bit for the data to be rendered. Here it goes:

it('should fetch and display the last transaction', async () => {
  const mocks = [{
    request: { query: gql(getLastTransaction) },
    result: {
      data: {
        getLastTransaction: { 
          amount: '$42'
        }
      }
    }
  }];
  const wrapper = mount(
    <MockedProvider mocks={mocks} addTypename={false}>
      <LastTransaction />
    </MockedProvider>
  );
  expect(wrapper.find('Loader').length).toBe(1);
  await wait(0);
  expect(wrapper.find('Loader').length).toBe(0);
  expect(wrapper.find('span').at(0).text()).toContain('$42');
});

Here it gets more bumpy. Suddenly your test fails, with no data shown on the page.

Maybe your request is wrong, and it isn’t matched? You convert result to a function and expect it to be called. It does, so the request is matched, and the Loader is gone too. Time to switch to real debugging mode – and discover that the data is undefined in the main component! How come? All other similar tests are passing, and quick googling reveals nothing interesting or relevant…

It appears that the caveat is in the generated GraphQL query statement, which “conveniently” contains all the fields available on the getLastTransaction query. This includes fields that your new component is not using – and thus you did not bother to define in your mock data. However, Apollo Client still does it’s job to make sure that the data you get back matches your request. Note that this including null values for the nullable fields – that’s what you had supposedly requested, so Apollo Client is obliged to provide them back.

In our case, getLastTransaction query included merchant field, and once you add it to the mock the test works like a charm:

    result: {
      data: {
        getLastTransaction: { 
          merchant: 'Amazon',
          amount: '$42'
        }
      }

Another potential caveat in the generated queries lays in the future schema changes. Some day more fields may be added to the schema of the query you are using – for example, your backend people will realize that it makes sense to add a timestamp of the last transaction. The generated queries will be updated, and your unit tests will start failing again – this time with no frontend changes at all.

How to fix WebSphere 7.0 on Windows 2003 that hangs on startup

WebSphere Today I spent several hours troubleshooting the fresh install of WebSphere 7.0 on Windows 2003. The server passed all post-installation steps successfully, but refused to start after the OS reboot. The last line in the server logs was “Server launched. Waiting for initialization status.”, and the actual server state was unclear – any attempt to start it anew claimed that the service was running, but the server console was not available.

It appears that the Windows service installation, which happens by default during setup time, was problematic. Once you remove the service and reboot the system, you can start WebSphere manually without any trouble.

Here is how to remove the Windows service:

  1. Go to the “bin” folder under WAS installation directory (usually “C:\Program Files\IBM\WebSphere\AppServer\bin”)
  2. Execute the following command: “WASService –remove <name-of-server-node>”

Typically, the name of server node is composed from the computer name with “Node01” suffix.
For example, the node name on “was70-win.mycompany.com” will probably be “was70-winNode01”.

Hat tip to this IBM DeveloperWorks community post for the hints!

Cisco ASA: “Not enough space on device” error fixed

Cisco Logo Several hours ago I took the ASA device in my lab to the routine software upgrade. I started with the fresh ASDM image upload, but it failed with the error message “Not enough space on device”. The reason sounds obvious, but it is not so trivial – how can you clean up some space on the physical appliance?

It appears that ASA does not clean up old software packages after their installation via ASDM. After several upgrades the flash memory of the device will be full of unused files, with no room to upload new ones. This is the time for manual cleanup. Continue reading “Cisco ASA: “Not enough space on device” error fixed”

How to upgrade Microsoft UAG 2010 SP1 to SP2

How do you upgrade from UAG 2010 SP1 to UAG 2010 SP2? Well, it appears that such upgrade is not as trivial as expected.

First, Microsoft UAG is based on another Microsoft product – Microsoft TMG, – which has to be upgraded separately. Besides that, there is no direct upgrade package for the UAG itself. Thus, the correct upgrade path would be as follows: UAG SP1 => UAG SP1 Update 1 => TMG SP2 => UAG SP2. Of course, the whole process is documented in TechNet – but you have to be aware about this upgrade path first…

There is another caveat in this upgrade. In case you have some UAG trunks configured (and I assume you have some, since what do you need UAG for otherwise?), you have to active UAG configuration after each step in the upgrade process, otherwise you’ll end up without configured trunks – they will disappear silently during the process. Thanks to TechNet forums for solving this one for me!

Deployment of New VM from Template Fails with VMDK Locked Error

Some time ago I managed to isolate an ugly vSphere 5 bug that caused me some unpleasant moments. Today I finally reproduced this behavior in a clean lab environment, so I feel confident enough to describe it in public. Don’t worry, the way to recover is described also!

Take a vSphere 5 environment with a template (say, “MyTemplate”) that you want to deploy a virtual machine from. Step through a regular deployment wizard and select “Edit Virtual Hardware” on the last page. In the VM properties, choose the hard disk and change its size. The new VM (say, “MyVM”) will be created successfully, but the next time you’ll go through the deployment process it will fail with a strange message: “Unable to access file ‘MyTemplate/MyTemplate.vmdk’ since it is locked”…

A quick search in VMware KB (or just in Google) will tell you that the vmdk (the virtual disk of the VM) is usually locked when some other VM uses the same disk. Hey, this is a template! No other VMs are supposed to use the template disk, right? Well, the truth is that this disk is now attached to MyVM – yes, that one with different disk size… But let the lock alone. Your lovely template is now gone, since the disk that belonged to the template is now owned by the running virtual machine – with new name, settings and maybe even software!

Well, how do you recover from this situation? The good news are that the original disk from MyTemplate is not gone. In fact, vSphere really cloned a new vmdk file for MyVM and placed it where it should usually reside – in ‘MyVM/MyVM.vmdk’ – but for some reason set the MyVM to use a template file instead. At this moment you can take a deep breath, shut down MyVM, point it to the right virtual disk and physically swap the files in the datastore… Continue reading “Deployment of New VM from Template Fails with VMDK Locked Error”