Skip to content

Commit defe7e4

Browse files
authored
Merge pull request #1767 from Sifchain/piotr/coinbase-plugin-tests
test: Integration Tests Enhancement and Coinbase Commerce Integration
2 parents 9ecb44b + 566212c commit defe7e4

File tree

4 files changed

+197
-30
lines changed

4 files changed

+197
-30
lines changed

.github/workflows/integrationTests.yaml

+6-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ on:
33
push:
44
branches:
55
- "*"
6-
pull_request_target:
6+
pull_request:
77
branches:
88
- "*"
99

@@ -33,12 +33,9 @@ jobs:
3333
- name: Build packages
3434
run: pnpm build
3535

36-
- name: Check for API key
37-
run: |
38-
if [ -z "$OPENAI_API_KEY" ]; then
39-
echo "Error: OPENAI_API_KEY is not set."
40-
exit 1
41-
fi
42-
4336
- name: Run integration tests
44-
run: pnpm run integrationTests
37+
env:
38+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
39+
COINBASE_COMMERCE_KEY: ${{ secrets.COINBASE_COMMERCE_KEY }}
40+
run: |
41+
pnpm run integrationTests

packages/plugin-coinbase/src/plugins/commerce.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export async function getAllCharges(apiKey: string) {
8282
// Function to fetch details of a specific charge
8383
export async function getChargeDetails(apiKey: string, chargeId: string) {
8484
elizaLogger.debug("Starting getChargeDetails function");
85-
const getUrl = `${url}${chargeId}`;
85+
const getUrl = `${url}/${chargeId}`;
8686

8787
try {
8888
const response = await fetch(getUrl, {
@@ -204,8 +204,8 @@ export const createCoinbaseChargeAction: Action = {
204204
text: `Charge created successfully: ${chargeResponse.hosted_url}`,
205205
attachments: [
206206
{
207-
id: crypto.randomUUID(),
208-
url: chargeResponse.id,
207+
id: chargeResponse.id,
208+
url: chargeResponse.hosted_url,
209209
title: "Coinbase Commerce Charge",
210210
description: `Charge ID: ${chargeResponse.id}`,
211211
text: `Pay here: ${chargeResponse.hosted_url}`,
@@ -351,6 +351,7 @@ export const getAllChargesAction: Action = {
351351
callback(
352352
{
353353
text: `Successfully fetched all charges. Total charges: ${charges.length}`,
354+
attachments: charges,
354355
},
355356
[]
356357
);
@@ -439,17 +440,20 @@ export const getChargeDetailsAction: Action = {
439440

440441
elizaLogger.info("Fetched charge details:", chargeDetails);
441442

443+
const chargeData = chargeDetails.data;
444+
442445
callback(
443446
{
444447
text: `Successfully fetched charge details for ID: ${charge.id}`,
445448
attachments: [
446449
{
447-
id: crypto.randomUUID(),
448-
url: chargeDetails.hosted_url,
450+
id: chargeData.id,
451+
url: chargeData.hosted_url,
449452
title: `Charge Details for ${charge.id}`,
450-
description: `Details: ${JSON.stringify(chargeDetails, null, 2)}`,
451453
source: "coinbase",
452-
text: "",
454+
description: JSON.stringify(chargeDetails, null, 2),
455+
text: `Pay here: ${chargeData.hosted_url}`,
456+
contentType: "application/json",
453457
},
454458
],
455459
},

tests/test1.mjs

+145-4
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,155 @@ import { send, log, logError, runIntegrationTest } from "./testLibrary.mjs";
33

44
async function helloTrump() {
55
const reply = await send("Hi");
6-
assert(reply.length > 10);
6+
assert(reply.length > 0, "Response should not be empty");
7+
const response = reply[0];
8+
assert(response.text, "Response should have text property");
9+
assert(
10+
response.text.length > 10,
11+
`Response should be longer than 10 characters, is ${reply.length}`
12+
);
713
}
14+
helloTrump.description = "Hello Trump";
15+
helloTrump.skipIf = !process.env.OPENAI_API_KEY;
816

9-
async function coinbaseTest() {
10-
// TODO
17+
async function coinbaseCommerceChargeTest() {
18+
const chargeDescription = "Exclusive digital artwork collection";
19+
const chargeRequest = `Create a charge for $100 USD for Digital Art NFT with description '${chargeDescription}'`;
20+
const response = await send(chargeRequest);
21+
22+
// Verify response structure
23+
assert(Array.isArray(response), "Response should be an array");
24+
assert(response.length === 2, "Response should contain two messages");
25+
26+
// Verify initial response
27+
const initialResponse = response[0];
28+
assert.strictEqual(initialResponse.action, "CREATE_CHARGE");
29+
30+
// Verify charge creation response
31+
const chargeResponse = response[1];
32+
assert(
33+
chargeResponse.text.startsWith("Charge created successfully:"),
34+
"Should indicate successful charge creation"
35+
);
36+
assert(
37+
chargeResponse.text.includes("https://commerce.coinbase.com/pay/"),
38+
"Should contain valid Coinbase Commerce URL"
39+
);
40+
41+
// Verify attachment structure
42+
assert(
43+
Array.isArray(chargeResponse.attachments),
44+
"Should have attachments array"
45+
);
46+
assert(
47+
chargeResponse.attachments.length === 1,
48+
"Should have one attachment"
49+
);
50+
51+
const attachment = chargeResponse.attachments[0];
52+
assert.strictEqual(attachment.source, "coinbase");
53+
assert.strictEqual(attachment.title, "Coinbase Commerce Charge");
54+
assert(attachment.id, "Should have an ID");
55+
assert(attachment.url, "Should have a charge ID URL");
56+
assert(
57+
attachment.description.startsWith("Charge ID:"),
58+
"Should have charge ID description"
59+
);
60+
assert(attachment.text.startsWith("Pay here:"), "Should have payment URL");
61+
assert(
62+
attachment.text.includes("https://commerce.coinbase.com/pay/"),
63+
"Should have valid Coinbase Commerce URL"
64+
);
65+
66+
// Store the created charge ID for later comparison
67+
const createdChargeId = attachment.id;
68+
const createdChargeUrl = attachment.url;
69+
70+
// Fetch and verify all charges
71+
const chargesResponse = await send("Fetch all charges");
72+
73+
// Verify response structure
74+
assert(
75+
Array.isArray(chargesResponse),
76+
"Charges response should be an array"
77+
);
78+
assert(
79+
chargesResponse.length === 2,
80+
"Should have two messages (prompt and response)"
81+
);
82+
83+
// Verify charges data
84+
const charges = chargesResponse[1].attachments;
85+
assert(Array.isArray(charges), "Charges should be an array");
86+
assert(charges.length > 0, "Should have at least one charge");
87+
88+
// Verify each charge has required properties
89+
charges.forEach((charge) => {
90+
assert(charge.id, "Each charge should have an id");
91+
assert(charge.hosted_url, "Each charge should have a hosted_url");
92+
assert(
93+
charge.hosted_url.includes("commerce.coinbase.com/pay/"),
94+
"hosted_url should be a valid Coinbase URL"
95+
);
96+
assert(charge.web3_data, "Each charge should have web3_data object");
97+
});
98+
99+
// Verify the previously created charge exists in the list
100+
const foundCharge = charges.find((charge) => charge.id === createdChargeId);
101+
assert(foundCharge, "Previously created charge should exist in the list");
102+
assert.strictEqual(
103+
foundCharge.hosted_url,
104+
createdChargeUrl,
105+
"Hosted URL should match"
106+
);
107+
assert.strictEqual(
108+
foundCharge.description,
109+
chargeDescription,
110+
"Description should match"
111+
);
112+
113+
// Test GetChargeDetails action
114+
const getDetailsResponse = await send(
115+
`Get details for charge ID: ${createdChargeId}`
116+
);
117+
118+
// Verify response structure for charge details
119+
assert(
120+
Array.isArray(getDetailsResponse),
121+
"GetChargeDetails response should be an array"
122+
);
123+
assert(
124+
getDetailsResponse.length === 2,
125+
"Should have two messages (prompt and response)"
126+
);
127+
128+
// Verify charge details response
129+
const detailsResponse = getDetailsResponse[1];
130+
assert(
131+
Array.isArray(detailsResponse.attachments),
132+
"Should have attachments array"
133+
);
134+
135+
const detailsAttachment = detailsResponse.attachments[0];
136+
137+
const chargeData = JSON.parse(detailsAttachment.description);
138+
139+
assert.equal(
140+
chargeData.data.hosted_url,
141+
createdChargeUrl,
142+
"Hosted URLs should match"
143+
);
144+
assert.equal(
145+
chargeData.data.description,
146+
chargeDescription,
147+
"Charge description should match"
148+
);
11149
}
150+
coinbaseCommerceChargeTest.description = "Coinbase Commerce Charge";
151+
coinbaseCommerceChargeTest.skipIf =
152+
!process.env.OPENAI_API_KEY || !process.env.COINBASE_COMMERCE_KEY;
12153

13-
const testSuite = [helloTrump]; // Add tests here
154+
const testSuite = [helloTrump, coinbaseCommerceChargeTest];
14155
try {
15156
for (const test of testSuite) await runIntegrationTest(test);
16157
} catch (error) {

tests/testLibrary.mjs

+35-10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const DEFAULT_AGENT_ID = stringToUuid(DEFAULT_CHARACTER ?? uuidv4());
77

88
function projectRoot() {
99
return path.join(import.meta.dirname, "..");
10+
// return "/Users/piotr/Documents/GitHub/Sifchain/eliza"
1011
}
1112

1213
function log(message) {
@@ -109,7 +110,7 @@ async function sendPostRequest(url, method, payload) {
109110
if (!response.ok)
110111
throw new Error(`HTTP error! status: ${response.status}`);
111112
const data = await response.json();
112-
return data[0].text;
113+
return data;
113114
} catch (error) {
114115
throw new Error(`Failed to send message: ${error.message}`);
115116
}
@@ -125,15 +126,38 @@ async function send(message) {
125126
}
126127

127128
async function runIntegrationTest(fn) {
128-
const proc = await startAgent();
129-
try {
130-
await fn();
131-
log("✓ Test passed");
132-
} catch (error) {
133-
log("✗ Test failed");
134-
logError(error);
135-
} finally {
136-
await stopAgent(proc);
129+
log(fn);
130+
const skip = fn.hasOwnProperty("skipIf") ? fn.skipIf : false;
131+
if (skip) {
132+
log(
133+
fn.description
134+
? `Skipping test ${fn.description}...`
135+
: "Skipping test..."
136+
);
137+
} else {
138+
log(
139+
fn.description
140+
? `Running test ${fn.description}...`
141+
: "Running test..."
142+
);
143+
const proc = await startAgent();
144+
try {
145+
await fn();
146+
log(
147+
fn.description
148+
? `✓ Test ${fn.description} passed`
149+
: "✓ Test passed"
150+
);
151+
} catch (error) {
152+
log(
153+
fn.description
154+
? `✗ Test ${fn.description} failed`
155+
: "✗ Test failed"
156+
);
157+
logError(error);
158+
} finally {
159+
await stopAgent(proc);
160+
}
137161
}
138162
}
139163

@@ -149,4 +173,5 @@ export {
149173
runIntegrationTest,
150174
log,
151175
logError,
176+
sleep,
152177
};

0 commit comments

Comments
 (0)