Skip to content

Commit de706ac

Browse files
lutterclaude
andcommitted
gnd: Make codegen verification tests self-contained
Embed fixture data directly in the gnd crate instead of requiring graph-cli to be installed. This removes the GRAPH_CLI_PATH environment variable dependency and makes tests runnable without external setup. Added regenerate.sh script for updating fixtures when needed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 4efe2dc commit de706ac

File tree

69 files changed

+2006
-25
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2006
-25
lines changed

gnd/tests/codegen_verification.rs

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! Integration tests that verify `gnd codegen` produces compatible output
22
//! to `graph-cli codegen` using golden test fixtures.
33
//!
4-
//! Fixtures are sourced from graph-cli's validation test directory.
5-
//! Set `GRAPH_CLI_PATH` environment variable to specify the graph-cli repository path,
6-
//! or it defaults to `../graph-cli` relative to the graph-node repository.
4+
//! Fixtures are stored locally in `tests/fixtures/codegen_verification/`.
5+
//! To regenerate fixtures after graph-cli changes, run:
6+
//! ```sh
7+
//! ./tests/fixtures/regenerate.sh
8+
//! ```
79
//!
810
//! # Known Differences
911
//!
@@ -41,31 +43,12 @@ const FIXTURES: &[&str] = &[
4143
"topic0-is-valid",
4244
];
4345

44-
/// Get the path to the graph-cli repository
45-
fn graph_cli_path() -> PathBuf {
46-
if let Ok(path) = std::env::var("GRAPH_CLI_PATH") {
47-
PathBuf::from(path)
48-
} else {
49-
// Default: assume graph-cli is at ../graph-cli relative to graph-node repo
50-
let manifest_dir = env!("CARGO_MANIFEST_DIR");
51-
PathBuf::from(manifest_dir)
52-
.parent()
53-
.unwrap()
54-
.parent()
55-
.unwrap()
56-
.join("subgraphs")
57-
.join("graph-cli")
58-
}
59-
}
60-
6146
/// Get the path to the fixtures directory
6247
fn fixtures_path() -> PathBuf {
63-
graph_cli_path()
64-
.join("packages")
65-
.join("cli")
48+
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
6649
.join("tests")
67-
.join("cli")
68-
.join("validation")
50+
.join("fixtures")
51+
.join("codegen_verification")
6952
}
7053

7154
/// Get the path to the gnd binary
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"type": "event",
4+
"name": "ExampleEvent",
5+
"inputs": [{ "type": "string" }]
6+
}
7+
]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
3+
import {
4+
ethereum,
5+
JSONValue,
6+
TypedMap,
7+
Entity,
8+
Bytes,
9+
Address,
10+
BigInt
11+
} from "@graphprotocol/graph-ts";
12+
13+
export class ExampleEvent extends ethereum.Event {
14+
get params(): ExampleEvent__Params {
15+
return new ExampleEvent__Params(this);
16+
}
17+
}
18+
19+
export class ExampleEvent__Params {
20+
_event: ExampleEvent;
21+
22+
constructor(event: ExampleEvent) {
23+
this._event = event;
24+
}
25+
26+
get param0(): string {
27+
return this._event.parameters[0].value.toString();
28+
}
29+
}
30+
31+
export class ExampleContract extends ethereum.SmartContract {
32+
static bind(address: Address): ExampleContract {
33+
return new ExampleContract("ExampleContract", address);
34+
}
35+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
3+
import {
4+
TypedMap,
5+
Entity,
6+
Value,
7+
ValueKind,
8+
store,
9+
Bytes,
10+
BigInt,
11+
BigDecimal
12+
} from "@graphprotocol/graph-ts";
13+
14+
export class MyEntity extends Entity {
15+
constructor(id: string) {
16+
super();
17+
this.set("id", Value.fromString(id));
18+
}
19+
20+
save(): void {
21+
let id = this.get("id");
22+
assert(id != null, "Cannot save MyEntity entity without an ID");
23+
if (id) {
24+
assert(
25+
id.kind == ValueKind.STRING,
26+
`Entities of type MyEntity must have an ID of type String but the id '${id.displayData()}' is of type ${id.displayKind()}`
27+
);
28+
store.set("MyEntity", id.toString(), this);
29+
}
30+
}
31+
32+
static loadInBlock(id: string): MyEntity | null {
33+
return changetype<MyEntity | null>(store.get_in_block("MyEntity", id));
34+
}
35+
36+
static load(id: string): MyEntity | null {
37+
return changetype<MyEntity | null>(store.get("MyEntity", id));
38+
}
39+
40+
get id(): string {
41+
let value = this.get("id");
42+
if (!value || value.kind == ValueKind.NULL) {
43+
throw new Error("Cannot return null for a required field.");
44+
} else {
45+
return value.toString();
46+
}
47+
}
48+
49+
set id(value: string) {
50+
this.set("id", Value.fromString(value));
51+
}
52+
53+
get childTokenURIs(): Array<Array<string>> {
54+
let value = this.get("childTokenURIs");
55+
if (!value || value.kind == ValueKind.NULL) {
56+
throw new Error("Cannot return null for a required field.");
57+
} else {
58+
return value.toStringArray();
59+
}
60+
}
61+
62+
set childTokenURIs(value: Array<Array<string>>) {
63+
this.set("childTokenURIs", Value.fromStringMatrix(value));
64+
}
65+
}

gnd/tests/fixtures/codegen_verification/2d-array-is-valid/mapping.ts

Whitespace-only changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
type MyEntity @entity(immutable: true) {
2+
id: ID!
3+
childTokenURIs: [[String!]!]! # string[][]
4+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
specVersion: 0.0.1
2+
repository: https://github.com/graphprotocol/test-subgraph
3+
description: Test subgraph
4+
schema:
5+
file: ./schema.graphql
6+
dataSources:
7+
- kind: ethereum/contract
8+
name: ExampleSubgraph
9+
source:
10+
abi: ExampleContract
11+
mapping:
12+
kind: ethereum/events
13+
apiVersion: 0.0.5
14+
language: wasm/assemblyscript
15+
file: ./mapping.ts
16+
entities:
17+
- ExampleEntity
18+
abis:
19+
- name: ExampleContract
20+
file: ./Abi.json
21+
eventHandlers:
22+
- event: ExampleEvent(string)
23+
handler: handleExampleEvent
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"type": "event",
4+
"name": "ExampleEvent",
5+
"inputs": [{ "type": "string" }]
6+
}
7+
]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
3+
import {
4+
ethereum,
5+
JSONValue,
6+
TypedMap,
7+
Entity,
8+
Bytes,
9+
Address,
10+
BigInt
11+
} from "@graphprotocol/graph-ts";
12+
13+
export class ExampleEvent extends ethereum.Event {
14+
get params(): ExampleEvent__Params {
15+
return new ExampleEvent__Params(this);
16+
}
17+
}
18+
19+
export class ExampleEvent__Params {
20+
_event: ExampleEvent;
21+
22+
constructor(event: ExampleEvent) {
23+
this._event = event;
24+
}
25+
26+
get param0(): string {
27+
return this._event.parameters[0].value.toString();
28+
}
29+
}
30+
31+
export class ExampleContract extends ethereum.SmartContract {
32+
static bind(address: Address): ExampleContract {
33+
return new ExampleContract("ExampleContract", address);
34+
}
35+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
3+
import {
4+
TypedMap,
5+
Entity,
6+
Value,
7+
ValueKind,
8+
store,
9+
Bytes,
10+
BigInt,
11+
BigDecimal
12+
} from "@graphprotocol/graph-ts";
13+
14+
export class MyEntity extends Entity {
15+
constructor(id: string) {
16+
super();
17+
this.set("id", Value.fromString(id));
18+
}
19+
20+
save(): void {
21+
let id = this.get("id");
22+
assert(id != null, "Cannot save MyEntity entity without an ID");
23+
if (id) {
24+
assert(
25+
id.kind == ValueKind.STRING,
26+
`Entities of type MyEntity must have an ID of type String but the id '${id.displayData()}' is of type ${id.displayKind()}`
27+
);
28+
store.set("MyEntity", id.toString(), this);
29+
}
30+
}
31+
32+
static loadInBlock(id: string): MyEntity | null {
33+
return changetype<MyEntity | null>(store.get_in_block("MyEntity", id));
34+
}
35+
36+
static load(id: string): MyEntity | null {
37+
return changetype<MyEntity | null>(store.get("MyEntity", id));
38+
}
39+
40+
get id(): string {
41+
let value = this.get("id");
42+
if (!value || value.kind == ValueKind.NULL) {
43+
throw new Error("Cannot return null for a required field.");
44+
} else {
45+
return value.toString();
46+
}
47+
}
48+
49+
set id(value: string) {
50+
this.set("id", Value.fromString(value));
51+
}
52+
53+
get childTokenURIs(): Array<Array<Array<string>>> {
54+
let value = this.get("childTokenURIs");
55+
if (!value || value.kind == ValueKind.NULL) {
56+
throw new Error("Cannot return null for a required field.");
57+
} else {
58+
return value.toStringArray();
59+
}
60+
}
61+
62+
set childTokenURIs(value: Array<Array<Array<string>>>) {
63+
this.set("childTokenURIs", Value.fromStringMatrix(value));
64+
}
65+
}

0 commit comments

Comments
 (0)