Skip to content
This repository has been archived by the owner on Mar 6, 2024. It is now read-only.

Add E2E tests for PSP #55

Merged
merged 26 commits into from Apr 14, 2022
Merged

Add E2E tests for PSP #55

merged 26 commits into from Apr 14, 2022

Conversation

vponline
Copy link
Contributor

@vponline vponline commented Apr 6, 2022

This adds E2E tests for PSP beacon updates.

@vponline vponline self-assigned this Apr 6, 2022
package.json Outdated Show resolved Hide resolved
src/test/e2e/psp.feature.ts Outdated Show resolved Hide resolved
src/test/e2e/psp.feature.ts Outdated Show resolved Hide resolved
@vponline
Copy link
Contributor Author

vponline commented Apr 6, 2022

Do we need tests for multiple subscriptions? I might need help with setting those up.

Copy link
Contributor

@amarthadan amarthadan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I quite like this 👍

Could we maybe add some test(s) for unsuccessful updates? What are the cases when the update can fail?

Also, since we have that retry mechanism for API calls, can we test that too?

package.json Outdated Show resolved Hide resolved
src/test/e2e/psp.feature.ts Outdated Show resolved Hide resolved
@amarthadan
Copy link
Contributor

Do we need tests for multiple subscriptions? I might need help with setting those up.

I guess that would be nice. What's the problem with that?

@amarthadan amarthadan requested a review from Siegrift April 7, 2022 10:16
@amarthadan
Copy link
Contributor

@acenolaza @Siegrift Can you take a look at this as well?

@amarthadan
Copy link
Contributor

Oh, one thing I forgot, can you update README with instructions on how to run the e2e tests?

Copy link
Contributor

@acenolaza acenolaza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying my best to avoid having to add hardhat as a dep but I don't see any other way around when it comes to e2e. Unless we create a different repo that deploys an Airkeeper using the docker image etc. but that might be too much work at the moment.

The good thing is that now we could reference the contracts from lets say operations repo and build them locally to get the ABI instead of having them hardcoded in different files.

Comment on lines 136 to 139
expect(res).toEqual({
statusCode: 200,
body: JSON.stringify({ ok: true, data: { message: 'PSP beacon update execution has finished' } }),
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that this is enough to determine if the beacon was successfully updated. I think we should be spying on the DapiServer functions in order to check that the expected ones where actually called with the expected args. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we instead of spying just read the value and see if it's updated? (just asking, not sure if it would work)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes agreed, great suggestion, I'll add 👍

src/test/mock-utils.ts Outdated Show resolved Hide resolved
Comment on lines 48 to 50
//Reset the local hardhat network state for each test to keep the deployed Airnode and DapiServer contract addresses
//the same as the config files
await hre.network.provider.send('hardhat_reset');
Copy link
Contributor Author

@vponline vponline Apr 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This took me way too long to figure this out, but there were a couple issues with the original setup:

  1. The (dapiServer, airnodeProtocol) contracts were re-deployed for each test and since the hardhat network was running, those had different addresses for each test. Then the DapiServer and AirnodeRrp addressed in the config files didn't match and the values were not updated (even though the handler finishes correctly).

I had to make a few modifications to get this hardhat_reset to work (namely copy the hardhat.config.ts to the root after install), otherwise I got an error that he project 'was not a hardhat project'.

  1. mockReadFileSync does not seem to be working for this (even when I change it to mockImplementation), but it errors out saying that the airnode config cannot be found. So I changed the loadConfig functions to be mocked instead.

  2. I tried to derive the beaconid with the airnodeProtocol address and the templateId, but it ends up giving me a different id than getting it from the dapiServer contract with subscriptionIdToBeaconId(). I'm not sure why that is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about the 3), that seems like a thing which might bite us in production. Can you maybe check why is that? (not necessarily in this PR)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can you add spaces to comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vponline were you able to figure 3 out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Siegrift @acenolaza This was my bad, I was trying to derive it with the airnode protocol address instead of the airnode address from the config... 🤦 I updated beaconId to be derived now.

package.json Outdated
@@ -14,11 +14,18 @@
"*.js"
],
"scripts": {
"postinstall": "git clone https://github.com/api3dao/airnode.git airnode; cd airnode && git checkout 994d895f37ca871f57224ac1603ea58e79ef071e && yarn run bootstrap && yarn build && cd ..; cp -a airnode/node_modules/@api3/airnode-node/. node_modules/@api3/airnode-node; rm -rf airnode",
"postinstall": "git clone https://github.com/api3dao/airnode.git airnode; cd airnode && git checkout 994d895f37ca871f57224ac1603ea58e79ef071e && yarn run bootstrap && yarn build && cd ..; cp -a airnode/node_modules/@api3/airnode-node/. node_modules/@api3/airnode-node; cp -a src/test/hardhat.config.ts ./; rm -rf airnode",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need the hardhat file in the root folder so I'm copying there after installing, this can be also removed once we don't need the postinstall script.

@vponline
Copy link
Contributor Author

I've added tests for retries, invalid subscriptions, a second valid subscription, updated the README, checking updated values, and fixed a problem with hardhat. I think all PR improvements are now covered so please feel free to review again 😄

Copy link
Contributor

@amarthadan amarthadan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the last comments but otherwise LGTM 👍

ecosystem.config.js Outdated Show resolved Hide resolved
threshold: 10,
});

export const buildLocalConfig2 = () => ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only difference is the ETH -> BTC right? Wouldn't it be better to just override that one parameter in the test instead of the whole new quite big object?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought (while reading the test code) I'm ok with it. Maybe just add a comment saying that one is an ETH and one is a BTC subscription.

Copy link
Contributor Author

@vponline vponline Apr 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I thought all the subscriptionIds, templateIds, encoded parameters etc. were required to be valid? Please correct me if this is not the case for the future

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They do afaik. Why do you ask? I just don't understand what it has to do with what I wrote.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, you're talking about buildLocalConfig2, for some reason I was thinking about how that would work with the airkeeper config 🤦

I'll add the comments

});
});

it('updates the beacon successfully with one invalid subscription present', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, you're adding a new invalid subscription. It took me a while. I thought that you were failing one of those two already there. Wouldn't that be better? That way we can check that the value was actually not updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great idea, ill update

Copy link
Contributor

@Siegrift Siegrift left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 LGTM

**/.serverless/**
**/coverage/**

**/config/*.json
**/node_modules/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also want to add airnode here temprarily.


### Unit Tests

Unit tests can then be run with:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙏 Thanks

Comment on lines 48 to 50
//Reset the local hardhat network state for each test to keep the deployed Airnode and DapiServer contract addresses
//the same as the config files
await hre.network.provider.send('hardhat_reset');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about the 3), that seems like a thing which might bite us in production. Can you maybe check why is that? (not necessarily in this PR)

value: hre.ethers.utils.parseEther('1'),
});

// Setup ETH Subscription
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mhh, does this comment refer to something?

Copy link
Contributor Author

@vponline vponline Apr 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes so I added this for it to be clear that the following lines are for setting up the ETH subscription (i.e. from buildLocalConfig)

Maybe these should be renamed to buildLocalConfigETH and buildLocalConfigBTC to be clear

it('updates the beacon successfully with one invalid provider present', async () => {
jest
.spyOn(config, 'loadAirnodeConfig')
.mockImplementation(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mhh, does this work in combination with mockImplementationOnce below? (are they different actually?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To answer your question, it does work, so mockImplementation is setting the default value to be returned after any mockImplementationOnce cases are handled

But in this case it's not needed since we want the airnode config to always include the invalid provider, I'll change this to just have mockImplementation 👍

Comment on lines 48 to 50
//Reset the local hardhat network state for each test to keep the deployed Airnode and DapiServer contract addresses
//the same as the config files
await hre.network.provider.send('hardhat_reset');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can you add spaces to comment?

src/test/e2e/psp.feature.ts Outdated Show resolved Hide resolved
src/test/e2e/psp.feature.ts Outdated Show resolved Hide resolved
src/test/e2e/psp.feature.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@Siegrift Siegrift left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing, why is the test folder inside the src? It should be alongside src.

@amarthadan
Copy link
Contributor

Is this still waiting for something?

@vponline
Copy link
Contributor Author

Is this still waiting for something?

Only @acenolaza's final approval 😄

Copy link
Contributor

@acenolaza acenolaza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies @vponline. It's now approved 👍🏻

@vponline vponline merged commit 9ff35e4 into main Apr 14, 2022
@vponline vponline deleted the psp-e2e-test branch April 14, 2022 13:55
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants