feat: add JSON output files and improve test flow

- Add .generated directory for test artifacts
- Save key derivation data to key_derivation.json
- Save account initialization to account_init.json
- Save registration data to registration.json
- Save claim details to claim_details.json
- Save test environment to test-env.sh
- Save contacts data to contacts.json
- Add proper error handling for file operations
- Improve deeplink test flow with JSON-based data
- Add color output and better status messages
- Add ADB device detection and fallback to print mode

Technical Changes:
- Add file system operations with proper error handling
- Standardize JSON output format across Python/TypeScript
- Update test flow to use generated JSON files
- Add proper typing for registration response
- Improve error reporting and debug output

This improves the test workflow by saving all intermediate
data as JSON files that can be used by other test scripts.
The deeplink testing now uses this data instead of environment
variables for better reliability.
This commit is contained in:
Matthew Raymer
2025-03-08 13:01:15 +00:00
parent c57a7487e6
commit 9237f5a8d6
3 changed files with 401 additions and 177 deletions

View File

@@ -10,6 +10,8 @@ import { HDNode } from '@ethersproject/hdnode';
import { Wallet } from '@ethersproject/wallet';
import { createJWT, ES256KSigner, SimpleSigner } from 'did-jwt';
import axios from 'axios';
import { mkdir, writeFile } from 'fs/promises';
import { join } from 'path';
// Constants
const DEFAULT_ROOT_DERIVATION_PATH = "m/84737769'/0'/0'/0'";
@@ -32,6 +34,19 @@ interface IIdentifier {
services: any[];
}
// Create .generated directory if it doesn't exist
const GENERATED_DIR = '.generated';
// Initialize directory creation
async function initializeDirectories() {
try {
await mkdir(GENERATED_DIR, { recursive: true });
} catch (err) {
console.error('Error creating .generated directory:', err);
throw err;
}
}
/**
* Generate a new mnemonic seed phrase
*/
@@ -62,6 +77,24 @@ async function deriveAddress(
console.log(` Private Key: ${privateHex.substring(0,8)}...`);
console.log(` Public Key: ${publicHex.substring(0,8)}...`);
// Save derivation data
const derivationData = {
mnemonic,
derivationPath,
address,
privateKey: privateHex,
publicKey: publicHex
};
try {
await mkdir(GENERATED_DIR, { recursive: true });
await writeFile(
join(GENERATED_DIR, 'key_derivation.json'),
JSON.stringify(derivationData, null, 2)
);
} catch (err) {
console.error('Error saving derivation data:', err);
}
return [address, privateHex, publicHex, derivationPath];
}
@@ -111,6 +144,12 @@ async function initializeAccount(): Promise<IIdentifier> {
console.log(JSON.stringify(accountData, null, 2));
console.log();
// Save account data
await writeFile(
join(GENERATED_DIR, 'account_init.json'),
JSON.stringify(accountData, null, 2)
);
return identity;
}
@@ -210,6 +249,15 @@ async function register(
if (response.status === 200 && response.data.success?.handleId) {
// Return all success details
const registrationData = {
activeDid,
jwtToken,
response: response.data.success
};
await writeFile(
join(GENERATED_DIR, 'registration.json'),
JSON.stringify(registrationData, null, 2)
);
return {
success: true,
handleId: response.data.success.handleId,
@@ -225,11 +273,29 @@ async function register(
// If we have success data but no handleId, it might be a partial success
if (response.data.success) {
const registrationData = {
activeDid,
jwtToken,
response: response.data.success
};
await writeFile(
join(GENERATED_DIR, 'registration.json'),
JSON.stringify(registrationData, null, 2)
);
return {
success: true,
...response.data.success
};
} else {
const registrationData = {
activeDid,
jwtToken,
response: response.data
};
await writeFile(
join(GENERATED_DIR, 'registration.json'),
JSON.stringify(registrationData, null, 2)
);
return { error: "Registration failed", details: response.data };
}
} catch (error: any) {
@@ -247,6 +313,15 @@ async function register(
}
console.error();
const registrationData = {
activeDid,
jwtToken,
response: { error: `Error submitting claim: ${error.message}` }
};
await writeFile(
join(GENERATED_DIR, 'registration.json'),
JSON.stringify(registrationData, null, 2)
);
return { error: `Error submitting claim: ${error.message}` };
}
}
@@ -284,7 +359,24 @@ async function fetchClaim(
}
);
return response.data;
const claimData = response.data;
// Save claim data
try {
await writeFile(
join(GENERATED_DIR, 'claim_details.json'),
JSON.stringify({
claim_id: claimId,
active_did: activeDid,
response: claimData
}, null, 2)
);
} catch (err) {
console.error('Error saving claim data:', err);
}
return claimData;
} catch (error: any) {
console.error("\nError fetching claim:");
if (error.response) {
@@ -293,14 +385,77 @@ async function fetchClaim(
} else {
console.error(error.message);
}
// Save error state
try {
await writeFile(
join(GENERATED_DIR, 'claim_details.json'),
JSON.stringify({
claim_id: claimId,
active_did: activeDid,
error: error.message || 'Unknown error',
response: error.response?.data
}, null, 2)
);
} catch (writeErr) {
console.error('Error saving claim error:', writeErr);
}
throw error;
}
}
/**
* Generate test environment data for deeplink testing
*/
async function generateTestEnv(
identity: IIdentifier,
jwtToken: string,
apiServer: string = API_SERVER
): Promise<void> {
// Create test data structure
const testEnvData = {
CONTACT1_DID: identity.did,
CONTACT1_KEY: identity.keys[0].privateKeyHex,
CONTACT2_DID: `did:ethr:${Wallet.createRandom().address}`, // Generate random DID for contact 2
CONTACT2_KEY: Wallet.createRandom().privateKey.substring(2), // Remove '0x'
ISSUER_DID: ENDORSER_DID,
ISSUER_KEY: ENDORSER_PRIVATE_KEY,
TEST_JWT: jwtToken,
API_SERVER: apiServer
};
// Write test environment variables
const envContent = Object.entries(testEnvData)
.map(([key, value]) => `export ${key}="${value}"`)
.join('\n');
await writeFile(
join(GENERATED_DIR, 'test-env.sh'),
envContent + '\n',
'utf-8'
);
// Write test contacts data
const contactsData = {
contacts: [
{ did: testEnvData.CONTACT1_DID, name: 'Test Contact 1' },
{ did: testEnvData.CONTACT2_DID, name: 'Test Contact 2' }
]
};
await writeFile(
join(GENERATED_DIR, 'contacts.json'),
JSON.stringify(contactsData, null, 2),
'utf-8'
);
}
/**
* Main execution flow
*/
async function main() {
// Initialize directories first
await initializeDirectories();
try {
// Create a new DID
const identity = await initializeAccount();
@@ -321,6 +476,9 @@ async function main() {
);
console.log("\nClaim Details:");
console.log(JSON.stringify(claimDetails, null, 2));
// Generate test environment data
await generateTestEnv(identity, result.claimId);
}
} catch (error: any) {
console.error("Error:", error.message);
@@ -339,5 +497,6 @@ export {
initializeAccount,
createEndorserJwt,
register,
fetchClaim
fetchClaim,
generateTestEnv
};