o1js
Version:
TypeScript framework for zk-SNARKs and zkApps
354 lines (310 loc) • 9.88 kB
text/typescript
import { PrivateKey, TokenId } from 'o1js';
import {
createActionsList,
fetchAccount,
fetchActions,
fetchEvents,
setArchiveDefaultHeaders,
setArchiveGraphqlEndpoint,
setGraphqlEndpoint,
setMinaDefaultHeaders,
} from './fetch.js';
import { mockFetchActionsResponse as fetchResponseWithTxInfo } from './fixtures/fetch-actions-response-with-transaction-info.js';
import { mockFetchActionsResponse as fetchResponseNoTxInfo } from './fixtures/fetch-actions-response-without-transaction-info.js';
import { test, describe, beforeEach, afterEach } from 'node:test';
import { removeJsonQuotes } from './graphql.js';
import { expect } from 'expect';
console.log('testing regex helpers');
let input, actual, expected;
input = `{
"array": [
{"data": "string with \\"escaped quotes\\": 1"}, { "otherdata": "otherstrin\\"g"}]
}`;
expected = `{
array: [
{
data: "string with \\"escaped quotes\\": 1"
},
{
otherdata: "otherstrin\\"g"
}
]
}`;
actual = removeJsonQuotes(input);
expect(actual).toEqual(expected);
input = `{
"array": [
{
"data" : "x"
},
{
"data": 1},{
"data": {
"otherData": "x"
}
}
]
}`;
expected = `{
array: [
{
data: "x"
},
{
data: 1
},
{
data: {
otherData: "x"
}
}
]
}`;
actual = removeJsonQuotes(input);
expect(actual).toEqual(expected);
input = `{
"FirstName" :"abc",
"Email" : "a@a.com",
"Id" : "1",
"Phone" : "1234567890",
"Date" : "2 May 2016 23:59:59"
}`;
expected = `{
FirstName: "abc",
Email: "a@a.com",
Id: "1",
Phone: "1234567890",
Date: "2 May 2016 23:59:59"
}`;
actual = removeJsonQuotes(input);
expect(actual).toEqual(expected);
input = `{
"FirstName":"abc",
"Email" : "a@a.com",
"Id" : "1",
"Phone" :"1234567890",
"Date":
"2 May 2016 23:59:59"
}`;
expected = `{
FirstName: "abc",
Email: "a@a.com",
Id: "1",
Phone: "1234567890",
Date: "2 May 2016 23:59:59"
}`;
actual = removeJsonQuotes(input);
expect(actual).toEqual(expected);
input = `{
"First-Name":"abc",
"Email" : "a@a.com",
"Id" : "1",
"Phone" :"1234567890",
"Date":
"2 May 2016 23:59:59"
}`;
expected = `{
First-Name: "abc",
Email: "a@a.com",
Id: "1",
Phone: "1234567890",
Date: "2 May 2016 23:59:59"
}`;
actual = removeJsonQuotes(input);
expect(actual).toEqual(expected);
console.log('regex tests complete 🎉');
describe('Fetch', () => {
describe('#createActionsList with default params', () => {
const defaultPublicKey = PrivateKey.random().toPublicKey().toBase58();
const defaultActionStates = {
fromActionState: undefined,
endActionState: undefined,
};
const defaultAccountInfo = {
publicKey: defaultPublicKey,
actionStates: defaultActionStates,
tokenId: TokenId.default.toString(),
};
describe('with a payload that is missing transaction info', () => {
const actionsList = createActionsList(defaultAccountInfo, fetchResponseNoTxInfo.data.actions);
test('orders the actions correctly', () => {
const correctActionsHashes = [
'10619825168606131449407092474314250900469658818945385329390497057469974757422',
'25525130517416993227046681664758665799110129890808721833148757111140891481208',
'290963518424616502946790040851348455652296009700336010663574777600482385855',
'20673199655841577810393943638910551364027795297920791498278816237738641857371',
'5284016523143033193387918577616839424871122381326995145988133445906503263869',
'16944163018367910067334012882171366051616125936127175065464614786387687317044',
'23662159967366296714544063539035629952291787828104373633198732070740691309118',
'1589729766029695153975344283092689798747741638003354620355672853210932754595',
'10964420428484427410756859799314206378989718180435238943573393516522086219419',
];
expect(actionsList.map(({ hash }) => hash)).toEqual(correctActionsHashes);
});
});
describe('with a payload that includes transaction info', () => {
const actionsList = createActionsList(
defaultAccountInfo,
fetchResponseWithTxInfo.data.actions
);
test('orders the actions correctly', () => {
const correctActionsHashes = [
'23562173419146814432140831830018386191372262558717813981702672868292521523493',
'17091049856171838105194364005412166905307014398334933913160405653259432088216',
'17232885850087529233459756382038742870248640044940153006158312935267918515979',
'12636308717155378495657553296284990333618148856424346334743675423201692801125',
'17082487567758469425757467457967473265642001333824907522427890208991758759731',
'14226491442770650712364681911870921131508915865197379983185088742764625929348',
'13552033292375176242184292341671233419412691991179711376625259275814019808194',
];
expect(actionsList.map(({ hash }) => hash)).toEqual(correctActionsHashes);
});
});
});
const minaEndpoint = 'https://mina.dummy/graphql';
const archiveEndpoint = 'https://archive.dummy/graphql';
describe('Testing fetch headers', () => {
let originalFetch: typeof global.fetch;
let lastFetchOptions: any = null;
beforeEach(() => {
originalFetch = global.fetch;
lastFetchOptions = undefined;
global.fetch = ((input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
lastFetchOptions = init;
let url: string;
if (typeof input === 'string') {
url = input;
} else if (input instanceof URL) {
url = input.toString();
} else {
url = input.url;
}
if (url.includes('archive.dummy')) {
return Promise.resolve({
ok: true,
json: async () => ({
data: {
events: [],
},
}),
} as Response);
} else {
return Promise.resolve({
ok: true,
json: async () => ({
data: {},
}),
} as Response);
}
}) as typeof fetch;
setGraphqlEndpoint(minaEndpoint);
setArchiveGraphqlEndpoint(archiveEndpoint);
setMinaDefaultHeaders({ Authorization: 'Bearer mina-default-token' });
setArchiveDefaultHeaders({
Authorization: 'Bearer archive-default-token',
});
});
afterEach(() => {
global.fetch = originalFetch;
lastFetchOptions = null;
});
test('Mina default headers with per request headers', async () => {
const perRequestHeaders = { 'X-Custom': 'custom-value' };
await fetchAccount(
{ publicKey: PrivateKey.random().toPublicKey().toBase58() },
minaEndpoint,
{
headers: perRequestHeaders,
}
);
expect(lastFetchOptions.headers).toMatchObject({
'Content-Type': 'application/json',
Authorization: 'Bearer mina-default-token',
'X-Custom': 'custom-value',
});
});
test('Per request headers overrides default headers', async () => {
const perRequestHeaders = {
Authorization: 'Bearer override-token',
'X-Test': 'value',
};
await fetchAccount(
{ publicKey: PrivateKey.random().toPublicKey().toBase58() },
minaEndpoint,
{
headers: perRequestHeaders,
}
);
expect(lastFetchOptions.headers).toMatchObject({
'Content-Type': 'application/json',
Authorization: 'Bearer override-token',
'X-Test': 'value',
});
});
test('Archive default headers with per request headers', async () => {
const perRequestHeaders = { 'X-Another': 'another-value' };
await fetchEvents(
{
publicKey: PrivateKey.random().toPublicKey().toBase58(),
},
archiveEndpoint,
perRequestHeaders
);
expect(lastFetchOptions.headers).toMatchObject({
'Content-Type': 'application/json',
Authorization: 'Bearer archive-default-token',
'X-Another': 'another-value',
});
});
test('Only default and base headers are used', async () => {
setMinaDefaultHeaders({
'X-Default': 'default-header',
Authorization: 'Bearer mina-default-token',
});
await fetchAccount(
{ publicKey: PrivateKey.random().toPublicKey().toBase58() },
minaEndpoint,
{}
);
expect(lastFetchOptions.headers).toMatchObject({
'Content-Type': 'application/json',
'X-Default': 'default-header',
Authorization: 'Bearer mina-default-token',
});
});
test('Default and per request headers are used for fetchActions', async () => {
setMinaDefaultHeaders({
Authorization: 'Bearer archive-default-token',
});
const perRequestHeaders = {
'X-Default': 'default-header',
};
await fetchActions(
{
publicKey: PrivateKey.random().toPublicKey().toBase58(),
actionStates: {
fromActionState: '',
endActionState: '',
},
},
minaEndpoint,
perRequestHeaders
);
expect(lastFetchOptions.headers).toMatchObject({
'Content-Type': 'application/json',
Authorization: 'Bearer archive-default-token',
'X-Default': 'default-header',
});
});
test('Only base headers are used', async () => {
await fetchAccount(
{ publicKey: PrivateKey.random().toPublicKey().toBase58() },
minaEndpoint,
{}
);
expect(lastFetchOptions.headers).toMatchObject({
'Content-Type': 'application/json',
});
});
});
});