Skip to content

Commit

Permalink
Merge pull request elizaOS#1767 from Sifchain/piotr/coinbase-plugin-t…
Browse files Browse the repository at this point in the history
…ests

test: Integration Tests Enhancement and Coinbase Commerce Integration
  • Loading branch information
monilpat authored Jan 10, 2025
2 parents 1f36712 + 2f52068 commit 57f4bc7
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 30 deletions.
15 changes: 6 additions & 9 deletions .github/workflows/integrationTests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ on:
push:
branches:
- "*"
pull_request_target:
pull_request:
branches:
- "*"

Expand Down Expand Up @@ -33,12 +33,9 @@ jobs:
- name: Build packages
run: pnpm build

- name: Check for API key
run: |
if [ -z "$OPENAI_API_KEY" ]; then
echo "Error: OPENAI_API_KEY is not set."
exit 1
fi
- name: Run integration tests
run: pnpm run integrationTests
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
COINBASE_COMMERCE_KEY: ${{ secrets.COINBASE_COMMERCE_KEY }}
run: |
pnpm run integrationTests
18 changes: 11 additions & 7 deletions packages/plugin-coinbase/src/plugins/commerce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export async function getAllCharges(apiKey: string) {
// Function to fetch details of a specific charge
export async function getChargeDetails(apiKey: string, chargeId: string) {
elizaLogger.debug("Starting getChargeDetails function");
const getUrl = `${url}${chargeId}`;
const getUrl = `${url}/${chargeId}`;

try {
const response = await fetch(getUrl, {
Expand Down Expand Up @@ -204,8 +204,8 @@ export const createCoinbaseChargeAction: Action = {
text: `Charge created successfully: ${chargeResponse.hosted_url}`,
attachments: [
{
id: crypto.randomUUID(),
url: chargeResponse.id,
id: chargeResponse.id,
url: chargeResponse.hosted_url,
title: "Coinbase Commerce Charge",
description: `Charge ID: ${chargeResponse.id}`,
text: `Pay here: ${chargeResponse.hosted_url}`,
Expand Down Expand Up @@ -351,6 +351,7 @@ export const getAllChargesAction: Action = {
callback(
{
text: `Successfully fetched all charges. Total charges: ${charges.length}`,
attachments: charges,
},
[]
);
Expand Down Expand Up @@ -439,17 +440,20 @@ export const getChargeDetailsAction: Action = {

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

const chargeData = chargeDetails.data;

callback(
{
text: `Successfully fetched charge details for ID: ${charge.id}`,
attachments: [
{
id: crypto.randomUUID(),
url: chargeDetails.hosted_url,
id: chargeData.id,
url: chargeData.hosted_url,
title: `Charge Details for ${charge.id}`,
description: `Details: ${JSON.stringify(chargeDetails, null, 2)}`,
source: "coinbase",
text: "",
description: JSON.stringify(chargeDetails, null, 2),
text: `Pay here: ${chargeData.hosted_url}`,
contentType: "application/json",
},
],
},
Expand Down
149 changes: 145 additions & 4 deletions tests/test1.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,155 @@ import { send, log, logError, runIntegrationTest } from "./testLibrary.mjs";

async function helloTrump() {
const reply = await send("Hi");
assert(reply.length > 10);
assert(reply.length > 0, "Response should not be empty");
const response = reply[0];
assert(response.text, "Response should have text property");
assert(
response.text.length > 10,
`Response should be longer than 10 characters, is ${reply.length}`
);
}
helloTrump.description = "Hello Trump";
helloTrump.skipIf = !process.env.OPENAI_API_KEY;

async function coinbaseTest() {
// TODO
async function coinbaseCommerceChargeTest() {
const chargeDescription = "Exclusive digital artwork collection";
const chargeRequest = `Create a charge for $100 USD for Digital Art NFT with description '${chargeDescription}'`;
const response = await send(chargeRequest);

// Verify response structure
assert(Array.isArray(response), "Response should be an array");
assert(response.length === 2, "Response should contain two messages");

// Verify initial response
const initialResponse = response[0];
assert.strictEqual(initialResponse.action, "CREATE_CHARGE");

// Verify charge creation response
const chargeResponse = response[1];
assert(
chargeResponse.text.startsWith("Charge created successfully:"),
"Should indicate successful charge creation"
);
assert(
chargeResponse.text.includes("https://commerce.coinbase.com/pay/"),
"Should contain valid Coinbase Commerce URL"
);

// Verify attachment structure
assert(
Array.isArray(chargeResponse.attachments),
"Should have attachments array"
);
assert(
chargeResponse.attachments.length === 1,
"Should have one attachment"
);

const attachment = chargeResponse.attachments[0];
assert.strictEqual(attachment.source, "coinbase");
assert.strictEqual(attachment.title, "Coinbase Commerce Charge");
assert(attachment.id, "Should have an ID");
assert(attachment.url, "Should have a charge ID URL");
assert(
attachment.description.startsWith("Charge ID:"),
"Should have charge ID description"
);
assert(attachment.text.startsWith("Pay here:"), "Should have payment URL");
assert(
attachment.text.includes("https://commerce.coinbase.com/pay/"),
"Should have valid Coinbase Commerce URL"
);

// Store the created charge ID for later comparison
const createdChargeId = attachment.id;
const createdChargeUrl = attachment.url;

// Fetch and verify all charges
const chargesResponse = await send("Fetch all charges");

// Verify response structure
assert(
Array.isArray(chargesResponse),
"Charges response should be an array"
);
assert(
chargesResponse.length === 2,
"Should have two messages (prompt and response)"
);

// Verify charges data
const charges = chargesResponse[1].attachments;
assert(Array.isArray(charges), "Charges should be an array");
assert(charges.length > 0, "Should have at least one charge");

// Verify each charge has required properties
charges.forEach((charge) => {
assert(charge.id, "Each charge should have an id");
assert(charge.hosted_url, "Each charge should have a hosted_url");
assert(
charge.hosted_url.includes("commerce.coinbase.com/pay/"),
"hosted_url should be a valid Coinbase URL"
);
assert(charge.web3_data, "Each charge should have web3_data object");
});

// Verify the previously created charge exists in the list
const foundCharge = charges.find((charge) => charge.id === createdChargeId);
assert(foundCharge, "Previously created charge should exist in the list");
assert.strictEqual(
foundCharge.hosted_url,
createdChargeUrl,
"Hosted URL should match"
);
assert.strictEqual(
foundCharge.description,
chargeDescription,
"Description should match"
);

// Test GetChargeDetails action
const getDetailsResponse = await send(
`Get details for charge ID: ${createdChargeId}`
);

// Verify response structure for charge details
assert(
Array.isArray(getDetailsResponse),
"GetChargeDetails response should be an array"
);
assert(
getDetailsResponse.length === 2,
"Should have two messages (prompt and response)"
);

// Verify charge details response
const detailsResponse = getDetailsResponse[1];
assert(
Array.isArray(detailsResponse.attachments),
"Should have attachments array"
);

const detailsAttachment = detailsResponse.attachments[0];

const chargeData = JSON.parse(detailsAttachment.description);

assert.equal(
chargeData.data.hosted_url,
createdChargeUrl,
"Hosted URLs should match"
);
assert.equal(
chargeData.data.description,
chargeDescription,
"Charge description should match"
);
}
coinbaseCommerceChargeTest.description = "Coinbase Commerce Charge";
coinbaseCommerceChargeTest.skipIf =
!process.env.OPENAI_API_KEY || !process.env.COINBASE_COMMERCE_KEY;

const testSuite = [helloTrump]; // Add tests here
const testSuite = [helloTrump, coinbaseCommerceChargeTest];
try {
for (const test of testSuite) await runIntegrationTest(test);
} catch (error) {
Expand Down
45 changes: 35 additions & 10 deletions tests/testLibrary.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const DEFAULT_AGENT_ID = stringToUuid(DEFAULT_CHARACTER ?? uuidv4());

function projectRoot() {
return path.join(import.meta.dirname, "..");
// return "/Users/piotr/Documents/GitHub/Sifchain/eliza"
}

function log(message) {
Expand Down Expand Up @@ -109,7 +110,7 @@ async function sendPostRequest(url, method, payload) {
if (!response.ok)
throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json();
return data[0].text;
return data;
} catch (error) {
throw new Error(`Failed to send message: ${error.message}`);
}
Expand All @@ -125,15 +126,38 @@ async function send(message) {
}

async function runIntegrationTest(fn) {
const proc = await startAgent();
try {
await fn();
log("✓ Test passed");
} catch (error) {
log("✗ Test failed");
logError(error);
} finally {
await stopAgent(proc);
log(fn);
const skip = fn.hasOwnProperty("skipIf") ? fn.skipIf : false;
if (skip) {
log(
fn.description
? `Skipping test ${fn.description}...`
: "Skipping test..."
);
} else {
log(
fn.description
? `Running test ${fn.description}...`
: "Running test..."
);
const proc = await startAgent();
try {
await fn();
log(
fn.description
? `✓ Test ${fn.description} passed`
: "✓ Test passed"
);
} catch (error) {
log(
fn.description
? `✗ Test ${fn.description} failed`
: "✗ Test failed"
);
logError(error);
} finally {
await stopAgent(proc);
}
}
}

Expand All @@ -149,4 +173,5 @@ export {
runIntegrationTest,
log,
logError,
sleep,
};

0 comments on commit 57f4bc7

Please sign in to comment.