Skip to content

Commit

Permalink
feat(NOTIFY-1245): add account syncing E2E helpers & basic tests (#28005
Browse files Browse the repository at this point in the history
)

## **Description**

This PR add a helper (`UserStorageMockttpController`) that helps mocking
how user storage behaves in the context of E2E tests.
This PR also adds two Account Syncing E2E tests to serve as a base to
expand upon.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/28005?quickstart=1)

## **Related issues**

https://consensyssoftware.atlassian.net/browse/NOTIFY-1245

## **Manual testing steps**

1. Run E2E tests
2. Verify that both new Account syncing E2E tests passes
3. Run unit tests
4. Verify that `UserStorageMockttpController` tests passes

## **Screenshots/Recordings**

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
mathieuartu authored Oct 23, 2024
1 parent 5fcb31b commit 4d26e24
Show file tree
Hide file tree
Showing 13 changed files with 725 additions and 25 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module.exports = {
'<rootDir>/development/**/*.test.(js|ts|tsx)',
'<rootDir>/test/unit-global/**/*.test.(js|ts|tsx)',
'<rootDir>/test/e2e/helpers.test.js',
'<rootDir>/test/e2e/helpers/**/*.test.(js|ts|tsx)',
],
testPathIgnorePatterns: ['<rootDir>/development/webpack/'],
testTimeout: 5500,
Expand Down
2 changes: 2 additions & 0 deletions test/e2e/fixture-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ function onboardingFixture() {
}),
providerConfig: { id: 'networkConfigurationId' },
},
NotificationServicesController: {},
PreferencesController: {
advancedGasFee: {},
currentLocale: 'en',
Expand Down Expand Up @@ -138,6 +139,7 @@ function onboardingFixture() {
},
},
},
UserStorageController: {},
TokensController: {
allDetectedTokens: {},
allIgnoredTokens: {},
Expand Down
304 changes: 304 additions & 0 deletions test/e2e/helpers/user-storage/userStorageMockttpController.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
import * as mockttp from 'mockttp';
import { UserStorageMockttpController } from './userStorageMockttpController';

describe('UserStorageMockttpController', () => {
let mockServer: mockttp.Mockttp;

const baseUrl = 'https://user-storage.api.cx.metamask.io/api/v1/userstorage';

describe('mimics user storage behaviour', () => {
mockServer = mockttp.getLocal({ cors: true });

it('handles GET requests that have empty response', async () => {
const controller = new UserStorageMockttpController();

controller.setupPath('accounts', mockServer);

const request = await controller.onGet('accounts', {
path: `${baseUrl}/accounts`,
});

expect(request.json).toEqual(null);
});

it('handles GET requests that have a pre-defined response', async () => {
const controller = new UserStorageMockttpController();
const mockedData = [
{
HashedKey:
'7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b',
Data: 'data1',
},
{
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data2',
},
];

controller.setupPath('accounts', mockServer, {
getResponse: mockedData,
});

const request = await controller.onGet('accounts', {
path: `${baseUrl}/accounts`,
});

expect(request.json).toEqual(mockedData);
});

it('handles batch GET requests', async () => {
const controller = new UserStorageMockttpController();
const mockedData = [
{
HashedKey:
'7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b',
Data: 'data1',
},
{
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data2',
},
];

controller.setupPath('accounts', mockServer, {
getResponse: mockedData,
});

const request = await controller.onGet('accounts', {
path: `${baseUrl}/accounts`,
});

expect(request.json).toEqual(mockedData);
});

it('handles GET requests for feature entries', async () => {
const controller = new UserStorageMockttpController();
const mockedData = [
{
HashedKey:
'7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b',
Data: 'data1',
},
{
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data2',
},
];

controller.setupPath('accounts', mockServer, {
getResponse: mockedData,
});

const request = await controller.onGet('accounts', {
path: `${baseUrl}/accounts/7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b`,
});

expect(request.json).toEqual(mockedData[0]);
});

it('handles PUT requests to create new entries', async () => {
const controller = new UserStorageMockttpController();
const mockedData = [
{
HashedKey:
'7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b',
Data: 'data1',
},
{
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data2',
},
];
const mockedAddedData = {
HashedKey:
'6afbe024087495b4e0d56c4bdfc981c84eba44a7c284d4f455b5db4fcabc2173',
Data: 'data3',
};

controller.setupPath('accounts', mockServer, {
getResponse: mockedData,
});

const putRequest = await controller.onPut('accounts', {
path: `${baseUrl}/accounts/6afbe024087495b4e0d56c4bdfc981c84eba44a7c284d4f455b5db4fcabc2173`,
body: {
getJson: async () => ({
data: mockedAddedData.Data,
}),
} as unknown as mockttp.CompletedBody,
});

expect(putRequest.statusCode).toEqual(204);

const getRequest = await controller.onGet('accounts', {
path: `${baseUrl}/accounts`,
});

expect(getRequest.json).toEqual([...mockedData, mockedAddedData]);
});

it('handles PUT requests to update existing entries', async () => {
const controller = new UserStorageMockttpController();
const mockedData = [
{
HashedKey:
'7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b',
Data: 'data1',
},
{
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data2',
},
];
const mockedUpdatedData = {
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data3',
};

controller.setupPath('accounts', mockServer, {
getResponse: mockedData,
});

const putRequest = await controller.onPut('accounts', {
path: `${baseUrl}/accounts/c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468`,
body: {
getJson: async () => ({
data: mockedUpdatedData.Data,
}),
} as unknown as mockttp.CompletedBody,
});

expect(putRequest.statusCode).toEqual(204);

const getRequest = await controller.onGet('accounts', {
path: `${baseUrl}/accounts`,
});

expect(getRequest.json).toEqual([mockedData[0], mockedUpdatedData]);
});

it('handles batch PUT requests', async () => {
const controller = new UserStorageMockttpController();
const mockedData = [
{
HashedKey:
'7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b',
Data: 'data1',
},
{
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data2',
},
];
const mockedUpdatedData = [
{
HashedKey:
'7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b',
Data: 'data3',
},
{
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data4',
},
];

controller.setupPath('accounts', mockServer, {
getResponse: mockedData,
});

const putData = {} as { [key: string]: string };
mockedUpdatedData.forEach((entry) => {
putData[entry.HashedKey] = entry.Data;
});

const putRequest = await controller.onPut('accounts', {
path: `${baseUrl}/accounts`,
body: {
getJson: async () => ({
data: putData,
}),
} as unknown as mockttp.CompletedBody,
});

expect(putRequest.statusCode).toEqual(204);

const getRequest = await controller.onGet('accounts', {
path: `${baseUrl}/accounts`,
});

expect(getRequest.json).toEqual(mockedUpdatedData);
});

it('handles DELETE requests', async () => {
const controller = new UserStorageMockttpController();
const mockedData = [
{
HashedKey:
'7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b',
Data: 'data1',
},
{
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data2',
},
];

controller.setupPath('accounts', mockServer, {
getResponse: mockedData,
});

const deleteRequest = await controller.onDelete('accounts', {
path: `${baseUrl}/accounts/c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468`,
});

expect(deleteRequest.statusCode).toEqual(204);

const getRequest = await controller.onGet('accounts', {
path: `${baseUrl}/accounts`,
});

expect(getRequest.json).toEqual([mockedData[0]]);
});

it('handles batch DELETE requests', async () => {
const controller = new UserStorageMockttpController();
const mockedData = [
{
HashedKey:
'7f8a7963423985c50f75f6ad42a6cf4e7eac43a6c55e3c6fcd49d73f01c1471b',
Data: 'data1',
},
{
HashedKey:
'c236b92ea7d513b2beda062cb546986961dfa7ca4334a2913f7837e43d050468',
Data: 'data2',
},
];

controller.setupPath('accounts', mockServer, {
getResponse: mockedData,
});

const deleteRequest = await controller.onDelete('accounts', {
path: `${baseUrl}/accounts`,
});

expect(deleteRequest.statusCode).toEqual(204);

const getRequest = await controller.onGet('accounts', {
path: `${baseUrl}/accounts`,
});

expect(getRequest.json).toEqual(null);
});
});
});
Loading

0 comments on commit 4d26e24

Please sign in to comment.