Complete Email Sortierer implementation with Appwrite and Stripe integration
This commit is contained in:
268
server/e2e-test.mjs
Normal file
268
server/e2e-test.mjs
Normal file
@@ -0,0 +1,268 @@
|
||||
import { Client, Databases, Query } from 'node-appwrite';
|
||||
import Stripe from 'stripe';
|
||||
|
||||
// Load environment variables
|
||||
const requiredEnvVars = [
|
||||
'APPWRITE_ENDPOINT',
|
||||
'APPWRITE_PROJECT_ID',
|
||||
'APPWRITE_API_KEY',
|
||||
'APPWRITE_DATABASE_ID',
|
||||
'STRIPE_SECRET_KEY'
|
||||
];
|
||||
|
||||
for (const envVar of requiredEnvVars) {
|
||||
if (!process.env[envVar]) {
|
||||
console.error(`❌ Missing required environment variable: ${envVar}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const client = new Client()
|
||||
.setEndpoint(process.env.APPWRITE_ENDPOINT)
|
||||
.setProject(process.env.APPWRITE_PROJECT_ID)
|
||||
.setKey(process.env.APPWRITE_API_KEY);
|
||||
|
||||
const databases = new Databases(client);
|
||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
||||
|
||||
console.log('🧪 Starting End-to-End Test\n');
|
||||
|
||||
// Test 1: Load Questions
|
||||
console.log('Test 1: Loading questions from Appwrite...');
|
||||
try {
|
||||
const productsResponse = await databases.listDocuments(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'products',
|
||||
[Query.equal('slug', 'email-sorter'), Query.equal('isActive', true)]
|
||||
);
|
||||
|
||||
if (productsResponse.documents.length === 0) {
|
||||
console.error('❌ No active product found with slug "email-sorter"');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const product = productsResponse.documents[0];
|
||||
console.log(`✅ Product found: ${product.title} (${product.priceCents / 100} ${product.currency.toUpperCase()})`);
|
||||
|
||||
const questionsResponse = await databases.listDocuments(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'questions',
|
||||
[
|
||||
Query.equal('productId', product.$id),
|
||||
Query.equal('isActive', true),
|
||||
Query.orderAsc('step'),
|
||||
Query.orderAsc('order')
|
||||
]
|
||||
);
|
||||
|
||||
console.log(`✅ Loaded ${questionsResponse.documents.length} questions`);
|
||||
|
||||
// Verify questions are ordered correctly
|
||||
let lastStep = 0;
|
||||
let lastOrder = 0;
|
||||
for (const question of questionsResponse.documents) {
|
||||
if (question.step < lastStep || (question.step === lastStep && question.order < lastOrder)) {
|
||||
console.error('❌ Questions are not properly ordered');
|
||||
process.exit(1);
|
||||
}
|
||||
lastStep = question.step;
|
||||
lastOrder = question.order;
|
||||
}
|
||||
console.log('✅ Questions are properly ordered by step and order');
|
||||
|
||||
// Test 2: Create Submission
|
||||
console.log('\nTest 2: Creating submission with test answers...');
|
||||
|
||||
const testAnswers = {
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
company: 'Test Company',
|
||||
employees: '1-10',
|
||||
emailVolume: '100-500',
|
||||
currentProvider: 'Gmail',
|
||||
painPoints: ['Spam', 'Organization'],
|
||||
budget: '50-100',
|
||||
timeline: 'Sofort',
|
||||
features: ['Auto-Sorting', 'Priority Inbox'],
|
||||
integration: 'Ja',
|
||||
dataPrivacy: 'Sehr wichtig',
|
||||
additionalInfo: 'This is a test submission'
|
||||
};
|
||||
|
||||
const submission = await databases.createDocument(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'submissions',
|
||||
'unique()',
|
||||
{
|
||||
productId: product.$id,
|
||||
status: 'draft',
|
||||
customerEmail: testAnswers.email,
|
||||
customerName: testAnswers.name,
|
||||
finalSummaryJson: JSON.stringify(testAnswers),
|
||||
priceCents: product.priceCents,
|
||||
currency: product.currency
|
||||
}
|
||||
);
|
||||
|
||||
console.log(`✅ Submission created with ID: ${submission.$id}`);
|
||||
|
||||
// Test 3: Save Answers
|
||||
console.log('\nTest 3: Saving answers to Appwrite...');
|
||||
|
||||
const answer = await databases.createDocument(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'answers',
|
||||
'unique()',
|
||||
{
|
||||
submissionId: submission.$id,
|
||||
answersJson: JSON.stringify(testAnswers)
|
||||
}
|
||||
);
|
||||
|
||||
console.log(`✅ Answers saved with ID: ${answer.$id}`);
|
||||
|
||||
// Verify answers can be retrieved
|
||||
const retrievedAnswers = await databases.listDocuments(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'answers',
|
||||
[Query.equal('submissionId', submission.$id)]
|
||||
);
|
||||
|
||||
if (retrievedAnswers.documents.length === 0) {
|
||||
console.error('❌ Failed to retrieve saved answers');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const savedAnswers = JSON.parse(retrievedAnswers.documents[0].answersJson);
|
||||
if (savedAnswers.email !== testAnswers.email) {
|
||||
console.error('❌ Retrieved answers do not match saved answers');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('✅ Answers can be retrieved correctly');
|
||||
|
||||
// Test 4: Create Stripe Checkout Session
|
||||
console.log('\nTest 4: Creating Stripe checkout session...');
|
||||
|
||||
const session = await stripe.checkout.sessions.create({
|
||||
payment_method_types: ['card'],
|
||||
line_items: [
|
||||
{
|
||||
price_data: {
|
||||
currency: submission.currency,
|
||||
product_data: {
|
||||
name: 'Email Sortierer Service',
|
||||
},
|
||||
unit_amount: submission.priceCents,
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
mode: 'payment',
|
||||
success_url: `http://localhost:3000/success.html`,
|
||||
cancel_url: `http://localhost:3000/cancel.html`,
|
||||
metadata: {
|
||||
submissionId: submission.$id
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`✅ Stripe session created: ${session.id}`);
|
||||
console.log(` Checkout URL: ${session.url}`);
|
||||
|
||||
// Test 5: Verify Webhook Signature (simulated)
|
||||
console.log('\nTest 5: Verifying webhook signature validation...');
|
||||
|
||||
if (!process.env.STRIPE_WEBHOOK_SECRET) {
|
||||
console.log('⚠️ STRIPE_WEBHOOK_SECRET not set - skipping webhook signature test');
|
||||
} else {
|
||||
console.log('✅ Webhook secret is configured');
|
||||
console.log(' Note: Actual webhook testing requires Stripe CLI or real webhook events');
|
||||
}
|
||||
|
||||
// Test 6: Simulate Payment Completion (update submission status)
|
||||
console.log('\nTest 6: Simulating payment completion...');
|
||||
|
||||
const updatedSubmission = await databases.updateDocument(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'submissions',
|
||||
submission.$id,
|
||||
{ status: 'paid' }
|
||||
);
|
||||
|
||||
if (updatedSubmission.status !== 'paid') {
|
||||
console.error('❌ Failed to update submission status');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('✅ Submission status updated to "paid"');
|
||||
|
||||
// Create order record
|
||||
const order = await databases.createDocument(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'orders',
|
||||
'unique()',
|
||||
{
|
||||
submissionId: submission.$id,
|
||||
orderDataJson: JSON.stringify({ sessionId: session.id, testOrder: true })
|
||||
}
|
||||
);
|
||||
|
||||
console.log(`✅ Order record created with ID: ${order.$id}`);
|
||||
|
||||
// Test 7: Verify Complete Data Flow
|
||||
console.log('\nTest 7: Verifying complete data flow...');
|
||||
|
||||
const finalSubmission = await databases.getDocument(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'submissions',
|
||||
submission.$id
|
||||
);
|
||||
|
||||
const finalAnswers = await databases.listDocuments(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'answers',
|
||||
[Query.equal('submissionId', submission.$id)]
|
||||
);
|
||||
|
||||
const finalOrders = await databases.listDocuments(
|
||||
process.env.APPWRITE_DATABASE_ID,
|
||||
'orders',
|
||||
[Query.equal('submissionId', submission.$id)]
|
||||
);
|
||||
|
||||
console.log('✅ Data verification:');
|
||||
console.log(` - Submission status: ${finalSubmission.status}`);
|
||||
console.log(` - Answers records: ${finalAnswers.documents.length}`);
|
||||
console.log(` - Order records: ${finalOrders.documents.length}`);
|
||||
|
||||
if (finalSubmission.status !== 'paid') {
|
||||
console.error('❌ Submission status is not "paid"');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (finalAnswers.documents.length === 0) {
|
||||
console.error('❌ No answers found for submission');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (finalOrders.documents.length === 0) {
|
||||
console.error('❌ No orders found for submission');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('\n✅ All tests passed!');
|
||||
console.log('\n📊 Test Summary:');
|
||||
console.log(' ✅ Questions loaded and ordered correctly');
|
||||
console.log(' ✅ Submission created successfully');
|
||||
console.log(' ✅ Answers saved and retrieved correctly');
|
||||
console.log(' ✅ Stripe checkout session created');
|
||||
console.log(' ✅ Webhook configuration verified');
|
||||
console.log(' ✅ Payment completion simulated');
|
||||
console.log(' ✅ Complete data flow verified');
|
||||
console.log('\n🎉 End-to-End test completed successfully!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ Test failed with error:');
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user