Skip to content

Commit

Permalink
refactor tests to use snapshots (#1824)
Browse files Browse the repository at this point in the history
  • Loading branch information
YaroShkvorets authored Dec 11, 2024
1 parent f3c94f1 commit ae26254
Show file tree
Hide file tree
Showing 8 changed files with 1,562 additions and 697 deletions.

Large diffs are not rendered by default.

155 changes: 5 additions & 150 deletions packages/cli/src/protocols/ethereum/codegen/abi.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import path from 'node:path';
import fs from 'fs-extra';
import immutable from 'immutable';
import { afterAll, beforeAll, describe, expect, test } from 'vitest';
import * as ts from '../../../codegen/typescript.js';
import ABI from '../abi.js';
import AbiCodeGenerator from './abi.js';

let tempdir: string;
let abi: ABI;
let generatedTypes: any[];
let generatedTypes: any[] = [];

describe.concurrent('ABI code generation', () => {
beforeAll(async () => {
Expand Down Expand Up @@ -179,153 +177,10 @@ describe.concurrent('ABI code generation', () => {
});

describe('Generated types', () => {
test('All expected types are generated', () => {
expect(generatedTypes.map(type => type.name)).toEqual([
'Contract__getProposalResultValue0Struct',
'Contract__getProposalInputParam1Struct',
'Contract__getProposalInputParam1BarStruct',
'Contract__getProposalsResultValue1Struct',
'Contract__getProposalsResult',
'Contract',
]);
});
});

describe('Contract class', () => {
test('Exists', () => {
expect(generatedTypes.find(type => type.name === 'Contract')).toBeDefined();
});

test('Has methods', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
expect(contract.methods).toBeInstanceOf(Array);
});

test('Has `bind` method', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
expect(contract.methods.find((method: any) => method.name === 'bind')).toBeDefined();
});

test('Has methods for all callable functions', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
expect(contract.methods.map((method: any) => method.name)).toContain('getProposal');
});
});

describe('Methods for callable functions', () => {
test('Have correct parameters', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
expect(contract.methods.map((method: any) => [method.name, method.params])).toEqual([
['bind', immutable.List([ts.param('address', 'Address')])],
['read', immutable.List()],
['try_read', immutable.List()],
[
'getProposal',
immutable.List([
ts.param('proposalId', 'BigInt'),
ts.param('param1', 'Contract__getProposalInputParam1Struct'),
]),
],
[
'try_getProposal',
immutable.List([
ts.param('proposalId', 'BigInt'),
ts.param('param1', 'Contract__getProposalInputParam1Struct'),
]),
],
['getProposals', immutable.List()],
['try_getProposals', immutable.List()],
['overloaded', immutable.List([ts.param('param0', 'string')])],
['try_overloaded', immutable.List([ts.param('param0', 'string')])],
['overloaded1', immutable.List([ts.param('param0', 'BigInt')])],
['try_overloaded1', immutable.List([ts.param('param0', 'BigInt')])],
['overloaded2', immutable.List([ts.param('param0', 'Bytes')])],
['try_overloaded2', immutable.List([ts.param('param0', 'Bytes')])],
]);
});

test('Have correct return types', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
expect(contract.methods.map((method: any) => [method.name, method.returnType])).toEqual([
['bind', ts.namedType('Contract')],
['read', ts.namedType('Bytes')],
['try_read', 'ethereum.CallResult<Bytes>'],
['getProposal', ts.namedType('Contract__getProposalResultValue0Struct')],
['try_getProposal', 'ethereum.CallResult<Contract__getProposalResultValue0Struct>'],
['getProposals', ts.namedType('Contract__getProposalsResult')],
['try_getProposals', 'ethereum.CallResult<Contract__getProposalsResult>'],
['overloaded', ts.namedType('string')],
['try_overloaded', 'ethereum.CallResult<string>'],
['overloaded1', ts.namedType('string')],
['try_overloaded1', 'ethereum.CallResult<string>'],
['overloaded2', ts.namedType('string')],
['try_overloaded2', 'ethereum.CallResult<string>'],
]);
});
});

describe('Tuples', () => {
test('Tuple types exist for function parameters', () => {
let tupleType = generatedTypes.find(
type => type.name === 'Contract__getProposalInputParam1Struct',
);

// Verify that the tuple type has methods
expect(tupleType.methods).toBeDefined();

// Verify that the tuple type has getters for all tuple fields with
// the right return types
expect(tupleType.methods.map((method: any) => [method.name, method.returnType])).toEqual([
['get foo', 'i32'],
['get bar', 'Contract__getProposalInputParam1BarStruct'],
]);

// Inner tuple:
tupleType = generatedTypes.find(
type => type.name === 'Contract__getProposalInputParam1BarStruct',
);

// Verify that the tuple type has methods
expect(tupleType.methods).toBeDefined();

// Verify that the tuple type has getters for all tuple fields with
// the right return types
expect(tupleType.methods.map((method: any) => [method.name, method.returnType])).toEqual([
['get baz', 'Address'],
]);
});

test('Tuple types exist for function return values', () => {
const tupleType = generatedTypes.find(
type => type.name === 'Contract__getProposalResultValue0Struct',
);

// Verify that the tuple type has methods
expect(tupleType.methods).toBeDefined();

// Verify that the tuple type has getters for all tuple fields with
// the right return types
expect(tupleType.methods.map((method: any) => [method.name, method.returnType])).toEqual([
['get result', 'i32'],
['get target', 'Address'],
['get data', 'Bytes'],
['get proposer', 'Address'],
['get feeRecipient', 'Address'],
['get fee', 'BigInt'],
['get startTime', 'BigInt'],
['get yesCount', 'BigInt'],
['get noCount', 'BigInt'],
]);
});

test('Function bodies are generated correctly for tuple arrays', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
const getter = contract.methods.find((method: any) => method.name === 'getProposals');

expect(getter.body).not.toContain('toTupleArray<undefined>');
expect(getter.body).toContain(
'result[1].toTupleArray<Contract__getProposalsResultValue1Struct>()',
);
test(`Type test`, () => {
for (const generatedType of generatedTypes) {
expect(generatedType).toMatchSnapshot();
}
});
});
});
69 changes: 69 additions & 0 deletions packages/cli/src/scaffold/__snapshots__/cosmos.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Cosmos subgraph scaffolding > Manifest 1`] = `
"specVersion: 1.0.0
indexerHints:
prune: auto
schema:
file: ./schema.graphql
dataSources:
- kind: cosmos
name: CosmosHub
network: cosmoshub-4
source:
startBlock: 0
mapping:
apiVersion: 0.0.5
language: wasm/assemblyscript
entities:
- ExampleEntity
blockHandlers:
- handler: handleBlock
file: ./src/contract.ts
"
`;

exports[`Cosmos subgraph scaffolding > Mapping (default) 1`] = `
"import { cosmos, BigInt } from "@graphprotocol/graph-ts"
import { ExampleEntity } from "../generated/schema"
export function handleBlock(block: cosmos.Block): void {
// Entities can be loaded from the store using a string ID; this ID
// needs to be unique across all entities of the same type
let entity = ExampleEntity.load(block.header.hash.toHex())
// Entities only exist after they have been saved to the store;
// \`null\` checks allow to create entities on demand
if (!entity) {
entity = new ExampleEntity(block.header.hash.toHex())
// Entity fields can be set using simple assignments
entity.count = BigInt.fromI32(0)
}
// BigInt and BigDecimal math are supported
entity.count = entity.count + BigInt.fromI32(1)
// Entity fields can be set based on receipt information
entity.height = block.header.height
// Entities can be written to the store with \`.save()\`
entity.save()
// Note: If a handler doesn't require existing field values, it is faster
// _not_ to load the entity from the store. Instead, create it fresh with
// \`new Entity(...)\`, set the fields that should be updated and save the
// entity back to the store. Fields that were not set or unset remain
// unchanged, allowing for partial updates to be applied.
}
"
`;

exports[`Cosmos subgraph scaffolding > Schema (default) 1`] = `
"type ExampleEntity @entity {
id: ID!
block: Bytes!
count: BigInt!
}
"
`;
Loading

0 comments on commit ae26254

Please sign in to comment.