1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00
metamask-extension/test/e2e/fixture-server.js
Peter 0fca0e3542
Use deployed contracts in fixtures (#18107)
* substitute smart contact address in fixtures

* add smart contract fixtures

* rename fixture

* leverage fixture to import erc1155

* leverage fixture to import erc721

* fix flaky test
2023-03-13 14:31:14 +00:00

117 lines
3.3 KiB
JavaScript

const Koa = require('koa');
const { isObject, mapValues } = require('lodash');
const CURRENT_STATE_KEY = '__CURRENT__';
const DEFAULT_STATE_KEY = '__DEFAULT__';
const FIXTURE_SERVER_HOST = 'localhost';
const FIXTURE_SERVER_PORT = 12345;
const fixtureSubstitutionPrefix = '__FIXTURE_SUBSTITUTION__';
const CONTRACT_KEY = 'CONTRACT';
const fixtureSubstitutionCommands = {
currentDateInMilliseconds: 'currentDateInMilliseconds',
};
/**
* Perform substitutions on a single piece of state.
*
* @param {unknown} partialState - The piece of state to perform substitutions on.
* @param {object} contractRegistry - The smart contract registry.
* @returns {unknown} The partial state with substititions performed.
*/
function performSubstitution(partialState, contractRegistry) {
if (Array.isArray(partialState)) {
return partialState.map((item) =>
performSubstitution(item, contractRegistry),
);
} else if (isObject(partialState)) {
return mapValues(partialState, (item) =>
performSubstitution(item, contractRegistry),
);
} else if (
typeof partialState === 'string' &&
partialState.startsWith(fixtureSubstitutionPrefix)
) {
const substitutionCommand = partialState.substring(
fixtureSubstitutionPrefix.length,
);
if (
substitutionCommand ===
fixtureSubstitutionCommands.currentDateInMilliseconds
) {
return new Date().getTime();
} else if (partialState.includes(CONTRACT_KEY)) {
const contract = partialState.split(CONTRACT_KEY).pop();
return contractRegistry.getContractAddress(contract);
}
throw new Error(`Unknown substitution command: ${substitutionCommand}`);
}
return partialState;
}
/**
* Substitute values in the state fixture.
*
* @param {object} rawState - The state fixture.
* @param {object} contractRegistry - The smart contract registry.
* @returns {object} The state fixture with substitutions performed.
*/
function performStateSubstitutions(rawState, contractRegistry) {
return mapValues(rawState, (item) => {
return performSubstitution(item, contractRegistry);
});
}
class FixtureServer {
constructor() {
this._app = new Koa();
this._stateMap = new Map([[DEFAULT_STATE_KEY, Object.create(null)]]);
this._app.use(async (ctx) => {
// Firefox is _super_ strict about needing CORS headers
ctx.set('Access-Control-Allow-Origin', '*');
if (this._isStateRequest(ctx)) {
ctx.body = this._stateMap.get(CURRENT_STATE_KEY);
}
});
}
async start() {
const options = {
host: FIXTURE_SERVER_HOST,
port: FIXTURE_SERVER_PORT,
exclusive: true,
};
return new Promise((resolve, reject) => {
this._server = this._app.listen(options);
this._server.once('error', reject);
this._server.once('listening', resolve);
});
}
async stop() {
if (!this._server) {
return;
}
await new Promise((resolve, reject) => {
this._server.close();
this._server.once('error', reject);
this._server.once('close', resolve);
});
}
loadJsonState(rawState, contractRegistry) {
const state = performStateSubstitutions(rawState, contractRegistry);
this._stateMap.set(CURRENT_STATE_KEY, state);
}
_isStateRequest(ctx) {
return ctx.method === 'GET' && ctx.path === '/state.json';
}
}
module.exports = FixtureServer;