Light-client: Implement a first basic scenario with Cypress for the dApp

Created on 28 May 2020  路  25Comments  路  Source: raiden-network/light-client

Description

This issue is a followup to #1404.
In #1580 the basics are done and Cypress works with the integration image.
The next step for us is to cover the basic dApp functionality with tests.

Acceptance criteria

  • Have tests for basic actions in the dApp
  • Runs in the CI
  • open channels
  • deposit to UDC
  • make a direct transfer
  • request a route
  • make a mediated transfer

Tasks

  • [x] Write down the scenario @christianbrb
  • [x] Cypress implementation @taleldayekh
  • [ ] Cleaning up the cypress code @taleldayekh
  • [x] Integrating in the CI @weilbith

Additional information

8 dApp 馃摫 test infrastructure 馃毀

Most helpful comment

In the case of the light client, it is harder to have pure UI tests since you would have to mock the SDK. If the integration image is used as a base I don't think that it would be a problem having e2e tests in Cypress, since everything happens in a controlled environment.

All 25 comments

Start with the basic main scenarios

I guess we need to discuss what the basic scenarios are and how to organise the tests.

@taleldayekh you assigned me as well. What tasks do you expect I should start to work on?

@weilbith I assigned you because I guess we will be having some discussions on how to best implement this stuff. :) But if you want you could resarch the CI integration.

Sounds good. Ping me when you have something ready I could try to make work with CI.

I was thinking about implementing the following scenario, but we would need to discuss how and if we break it down.

The scenario has been build under the assumption, that those are high level integration tests and not pure UI tests.

  • [x] 1. Open the dApp with the address, token and token amount as a paramter: https://lightclient.raiden.network/#/connect/0xE2b702eD684bEb02850ac604278f078A4ce8b6E6/0x1F916ab5cf1B30B22f24Ebf435f53Ee665344Acf?deposit=0.01
  • [x] 2. Accept the disclaimer
  • [x] 3. Connect
  • [x] 4. Open Channel
  • [x] 5. Navigate to the notification panel
  • [x] 6. Delete the notification
  • [x] 7. Make a direct transfer using the route with parameters (eg. https://lightclient.raiden.network/#/transfer/0x59105441977ecD9d805A4f5b060E34676F50F806/0x1F916ab5cf1B30B22f24Ebf435f53Ee665344Acf?amount=0.001)
  • [x] 8. Go to the account menu
  • [x] 9. Download the state
  • [x] 10. Disconnect (happens by default after state has been dowloaded)
    11. Delete the browser store
    12. Upload the state
  • [x] 13. Connect
  • [ ] 14. Make a mediated transfer (including depositing tokens to the UDC)
  • [x] 15. Open the token selection menu
  • [x] 16. Click on "Connect new token"
  • [x] 17. Select a token
  • [x] 18. Navigate back to the transfer screen
  • [x] 19. Deposit tokens
  • [x] 20. Go to the channel list
  • [x] 21. Withdraw tokens
  • [x] 22. Close the channel
  • [x] 23. Settle the channel (currently happens automatically directly after a channel is closed)
  • [x] 24. Navigate to the account screen
  • [x] 25. Transfer ETH to the Raiden Account
  • [x] 26. Withdraw tokens from the Raiden Account
  • [x] 27. Withdraw UDC tokens
  • [x] 29. Download the logs

The big question: Should we run this end to end or split the tests?

I am not quite sure. Reading the cypress best practice docs:

It is common for tests in Cypress to issue 30+ commands. Because nearly every command has a default assertion (and can therefore fail), even by limiting your assertions you鈥檙e not saving yourself anything because any single command could implicitly fail.

Watching the video:

grafik

They also do not recommend to do E2E tests with Cypress, but they also say:
grafik

Some further reading: https://github.com/NoriSte/ui-testing-best-practices

@christianbrb Nice, thanks for the good job and effort in thinking that through.

In the case of the light client, it is harder to have pure UI tests since you would have to mock the SDK. If the integration image is used as a base I don't think that it would be a problem having e2e tests in Cypress, since everything happens in a controlled environment.

The Dockerfile for the e2e tests is huge. Therefore I'm asking you @kelsos in the meantime. I don't understand how the following is possible: I start a new container based on this image. I test the light client and do some transactions etc. I stop and remove the container again. I restart that procedure. Now I can observe that the old blockchain data is still there. I take the oncounting block number as proof that the data is still there. How is that possible, if there is no volume attached and I take the same base image? Is there something stored else on my host system? I'm very confused...

By old blockchain data do you mean that the block number is not zero and there are some data there?. If that is the case then that is how things are supposed to be. The block number should not be zero. When the image is built, the Raiden contracts are deployed and a channel is opened between two Python Raiden nodes. Geth's state is then stored in the new image.

Each new container when started should have the contracts deployed and two python Raiden nodes with an open fully funded channel between them. This happens during the image creation and it is part of the image. The reason behind this is that we wanted to have a faster execution time when running the tests. Deploying the contracts and opening the channels takes time and it is not what we want to tests. That is one of the reasons the image is more complicated and takes time to build, however, it is way faster on runtime.

Does this help?

Does this help?

No, unfortunately not. That is what we know.
Let's say that after the image is built, the Geth node is at block number 200. Then we start a container based on this image. We connect the light-client to it and use it a bit. Now we are at block 230. There are open channels written to the state of the contract etc. Now stop and remove the container. Start a new one based on the same image as before.
What I would expect: I'm again at block 200, no contract state (except of the deployment).
Actually: Geth is now at block 230 and continues. The contracts state is still there.

I must admit that I technically don't understand this issue. There must be something persistent. But I don't know how this is possible due to the cgroup fo the container.

Do you properly delete the previous container? I remember always stopping, then deleting the container and then creating a new one.

I am probably asking stupid things, let me check the previous code and changes a bit maybe I can get an idea

@kelsos Don't waste your time. I can do this in the time I'm getting payed for. I just thought asking would be helpful.

@weilbith ok no worries. By checking I can see that you use the --rm flag now with docker so the image is supposed to be deleted when the execution terminates. Any change that the image is not getting deleted for some reason? maybe it doesn't stop properly so rm fails?

I'm 100% sure container is removed.
I do now a actual analysis of this. I try to reproduce what Talel saw in the light client with pure RPC requests and manual docker control.

I'm 100% sure container is removed.
I do now a actual analysis of this. I try to reproduce what Talel saw in the light client with pure RPC requests and manual docker control.

Ok, but in general giving a quick look at the changes, there is no reason why the state would persist when the image is removed. It didn't before and I didn't see any change in the Dockerfile that would change that.

ist when the image is removed

Wait what? Why should I remove the image? Only the container based on the image should get removed. Then a new container gets started based on this image.


Anyways. I could not reproduce the issue with the following test:

  • start container manually
  • query block number via direct RPC requests (ongoing number from ~230)
  • stop and remove the container manually
  • start the container manually again
  • query block number via direct RPC requests

-> They start again from the block after the image build was done and all contracts deployed.

This result is reproducable. The image is fine (happily, else I would have been super confused). So the issue must occur somewhere later in the setup. The debugging in the Cypress electron app was kinda clunky. So I don't trust these results anymore. Eventually it is just that Cypress cleans localstorage, but not the indexdb and then it looks like that.
So I continue to test it step by step.

Sorry I meant container

Thanks for your help. Was a nice feeling to have you on board for some minutes. :hugs:

Just for the protocol: what affected my confused mind was that Talel stated that if he rebuilt the image from scratch (apparently some layer caching is not working) this was working fine again. So I first thought the issue can't by at Cypress then...

But eventually the re-build just causes the new persistent layer of the dApp to create a new DB. Talel his electron app was pretty cluttered already.

Since also the script works fine (replaced the run of Cypress with two times quering the block number via RPC), it must be something with Cypress and how the dApp parses the old state in contrast to what the Eth node says.

Quick update: Talel told me that actually applying the manual delete of the database in the support index script is doing the job. Here is the issue of Cypress discussing the problem and providing the suggestion.

Good luck with that, I've been fighting it all day )

The Cypress tests have been implemented and @taleldayekh has shown the progress on his local machine.

Closing this issue to get better organized to talk about it in more detail within the planning.

Was this page helpful?
0 / 5 - 0 ratings