test: Add certificate generation tests and deployment tools
- Add E2E test for certificate generation functionality - Create deployment configuration script for staging server - Add certificate email testing script - Update composer.lock with TCPDF dependencies 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
964d5f75a8
commit
42138339cb
4 changed files with 393 additions and 28 deletions
10
wordpress-dev/bin/deploy-config.sh
Executable file
10
wordpress-dev/bin/deploy-config.sh
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Deployment Configuration
|
||||
PROJECT_ROOT="/Users/ben/dev/upskill-event-manager"
|
||||
REMOTE_HOST="146.190.76.204"
|
||||
REMOTE_USER="roodev"
|
||||
REMOTE_PATH_BASE="/home/974670.cloudwaysapps.com/uberrxmprk/public_html"
|
||||
PLUGIN_SLUG="hvac-community-events"
|
||||
REMOTE_PLUGIN_PATH="/home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events"
|
||||
LOCAL_PLUGIN_PATH="/Users/ben/dev/upskill-event-manager/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events"
|
||||
149
wordpress-dev/bin/test-certificate-email.sh
Executable file
149
wordpress-dev/bin/test-certificate-email.sh
Executable file
|
|
@ -0,0 +1,149 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Script to test certificate email functionality on staging server
|
||||
|
||||
# Load configuration
|
||||
source bin/deploy-config.sh
|
||||
|
||||
# Set email address to test with
|
||||
TEST_EMAIL="ben@tealmaker.com"
|
||||
|
||||
echo "=== Testing Certificate Email Functionality ==="
|
||||
echo "Remote host: $REMOTE_HOST"
|
||||
echo "Remote user: $REMOTE_USER"
|
||||
echo "WordPress path: $REMOTE_PATH_BASE"
|
||||
echo "Test email: $TEST_EMAIL"
|
||||
echo "==============================="
|
||||
|
||||
# Connect to the remote server and run a WP-CLI command to create a test event, attendee, and certificate
|
||||
ssh $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_PATH_BASE && \
|
||||
wp eval '
|
||||
// Create a test event if needed
|
||||
\$event_exists = get_posts(array(
|
||||
\"post_type\" => \"tribe_events\",
|
||||
\"meta_key\" => \"_test_certificate_event\",
|
||||
\"meta_value\" => \"yes\",
|
||||
\"posts_per_page\" => 1
|
||||
));
|
||||
|
||||
if (empty(\$event_exists)) {
|
||||
\$event_id = wp_insert_post(array(
|
||||
\"post_title\" => \"Test Certificate Event\",
|
||||
\"post_content\" => \"This is a test event for certificate generation\",
|
||||
\"post_status\" => \"publish\",
|
||||
\"post_type\" => \"tribe_events\"
|
||||
));
|
||||
update_post_meta(\$event_id, \"_test_certificate_event\", \"yes\");
|
||||
echo \"Created test event with ID: {\$event_id}\\n\";
|
||||
} else {
|
||||
\$event_id = \$event_exists[0]->ID;
|
||||
echo \"Using existing test event with ID: {\$event_id}\\n\";
|
||||
}
|
||||
|
||||
// Create a test attendee
|
||||
\$attendee_exists = get_posts(array(
|
||||
\"post_type\" => \"tribe_rsvp_attendees\",
|
||||
\"meta_key\" => \"_tribe_tickets_email\",
|
||||
\"meta_value\" => \"$TEST_EMAIL\",
|
||||
\"posts_per_page\" => 1
|
||||
));
|
||||
|
||||
if (empty(\$attendee_exists)) {
|
||||
\$attendee_id = wp_insert_post(array(
|
||||
\"post_title\" => \"Test Attendee\",
|
||||
\"post_status\" => \"publish\",
|
||||
\"post_type\" => \"tribe_rsvp_attendees\"
|
||||
));
|
||||
|
||||
update_post_meta(\$attendee_id, \"_tribe_tickets_email\", \"$TEST_EMAIL\");
|
||||
update_post_meta(\$attendee_id, \"_tribe_tickets_full_name\", \"Test Attendee\");
|
||||
update_post_meta(\$attendee_id, \"_tribe_rsvp_event\", \$event_id);
|
||||
update_post_meta(\$attendee_id, \"_tribe_rsvp_status\", \"yes\");
|
||||
update_post_meta(\$attendee_id, \"_tribe_tickets_attendee_status\", \"yes\");
|
||||
update_post_meta(\$attendee_id, \"check_in\", \"1\");
|
||||
|
||||
echo \"Created test attendee with ID: {\$attendee_id}\\n\";
|
||||
} else {
|
||||
\$attendee_id = \$attendee_exists[0]->ID;
|
||||
echo \"Using existing attendee with ID: {\$attendee_id}\\n\";
|
||||
}
|
||||
|
||||
// Load certificate manager
|
||||
require_once WP_PLUGIN_DIR . \"/hvac-community-events/includes/certificates/class-certificate-manager.php\";
|
||||
require_once WP_PLUGIN_DIR . \"/hvac-community-events/includes/certificates/class-certificate-generator.php\";
|
||||
|
||||
\$certificate_manager = HVAC_Certificate_Manager::instance();
|
||||
\$certificate_generator = HVAC_Certificate_Generator::instance();
|
||||
|
||||
// Generate certificate
|
||||
\$certificate_exists = \$certificate_manager->get_certificate_by_attendee(\$event_id, \$attendee_id);
|
||||
|
||||
if (!\$certificate_exists) {
|
||||
\$result = \$certificate_generator->generate_certificate(\$event_id, \$attendee_id);
|
||||
if (\$result) {
|
||||
\$certificate = \$certificate_manager->get_certificate_by_attendee(\$event_id, \$attendee_id);
|
||||
echo \"Generated certificate with ID: {\$certificate->certificate_id}\\n\";
|
||||
} else {
|
||||
echo \"Failed to generate certificate\\n\";
|
||||
}
|
||||
} else {
|
||||
echo \"Using existing certificate with ID: {\$certificate_exists->certificate_id}\\n\";
|
||||
}
|
||||
|
||||
// Get existing certificate
|
||||
\$certificate = \$certificate_manager->get_certificate_by_attendee(\$event_id, \$attendee_id);
|
||||
if (!\$certificate) {
|
||||
echo \"No certificate found\\n\";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Email certificate
|
||||
require_once WP_PLUGIN_DIR . \"/hvac-community-events/includes/certificates/class-certificate-security.php\";
|
||||
\$certificate_security = HVAC_Certificate_Security::instance();
|
||||
|
||||
// Generate secure download URL
|
||||
\$event = get_post(\$certificate->event_id);
|
||||
\$attendee_name = get_post_meta(\$certificate->attendee_id, \"_tribe_tickets_full_name\", true);
|
||||
|
||||
\$certificate_data = array(
|
||||
\"file_path\" => \$certificate->file_path,
|
||||
\"event_name\" => \$event->post_title,
|
||||
\"attendee_name\" => \$attendee_name
|
||||
);
|
||||
|
||||
\$download_url = \$certificate_security->generate_download_token(\$certificate->certificate_id, \$certificate_data, 7 * DAY_IN_SECONDS);
|
||||
|
||||
if (!\$download_url) {
|
||||
echo \"Failed to generate download URL\\n\";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Email subject
|
||||
\$subject = sprintf(
|
||||
\"Your Certificate for %s\",
|
||||
\$event->post_title
|
||||
);
|
||||
|
||||
// Email body
|
||||
\$message = sprintf(
|
||||
\"Hello %s,\\n\\nThank you for attending %s.\\n\\nYour certificate of completion is now available. Please click the link below to download your certificate:\\n\\n%s\\n\\nThis link will expire in 7 days.\\n\\nRegards,\\nTest System\",
|
||||
\$attendee_name,
|
||||
\$event->post_title,
|
||||
\$download_url
|
||||
);
|
||||
|
||||
// Send email
|
||||
\$headers = array(\"Content-Type: text/plain; charset=UTF-8\");
|
||||
\$sent = wp_mail(\"$TEST_EMAIL\", \$subject, \$message, \$headers);
|
||||
|
||||
if (\$sent) {
|
||||
// Record email sent
|
||||
\$certificate_manager->mark_certificate_emailed(\$certificate->certificate_id);
|
||||
echo \"Certificate email sent successfully to $TEST_EMAIL\\n\";
|
||||
} else {
|
||||
echo \"Failed to send certificate email\\n\";
|
||||
}
|
||||
'
|
||||
"
|
||||
|
||||
echo "Email verification complete. Please check $TEST_EMAIL for the certificate email."
|
||||
127
wordpress-dev/tests/e2e/certificate-generation.test.ts
Normal file
127
wordpress-dev/tests/e2e/certificate-generation.test.ts
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
import { test, expect } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Certificate Generation End-to-End Test
|
||||
*
|
||||
* This test verifies the certificate generation functionality:
|
||||
* - Login as a trainer
|
||||
* - Navigate to an event summary page
|
||||
* - Generate certificates for attendees
|
||||
* - View certificate
|
||||
* - Email certificate to a test email
|
||||
* - Revoke certificate
|
||||
*/
|
||||
|
||||
test.describe('Certificate Generation Tests', () => {
|
||||
const stagingUrl = 'https://wordpress-974670-5399585.cloudwaysapps.com/';
|
||||
const loginUrl = `${stagingUrl}community-login/`;
|
||||
const dashboardUrl = `${stagingUrl}hvac-dashboard/`;
|
||||
const testEmail = 'ben@tealmaker.com';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Login as trainer
|
||||
await page.goto(loginUrl);
|
||||
await page.fill('input[name="log"]', 'test_trainer');
|
||||
await page.fill('input[name="pwd"]', 'Test123!');
|
||||
await page.click('input[type="submit"]');
|
||||
|
||||
// Verify login was successful by checking for dashboard
|
||||
await expect(page).toHaveURL(dashboardUrl);
|
||||
});
|
||||
|
||||
test('Generate and manage certificates for an event', async ({ page }) => {
|
||||
// Navigate to the dashboard to find an event
|
||||
await page.goto(dashboardUrl);
|
||||
|
||||
// Click on the first event summary link
|
||||
await page.click('.hvac-event-title a');
|
||||
|
||||
// Wait for the event summary page to load
|
||||
await expect(page.locator('h1')).toContainText('Summary');
|
||||
|
||||
// Check if we have attendees
|
||||
const hasAttendees = await page.locator('.hvac-transactions-table').isVisible();
|
||||
|
||||
if (hasAttendees) {
|
||||
// Check if any attendee doesn't have a certificate yet
|
||||
const generateButtonExists = await page.locator('.hvac-cert-action:text("Generate")').isVisible();
|
||||
|
||||
if (generateButtonExists) {
|
||||
// Generate a certificate for an attendee
|
||||
await page.click('.hvac-cert-action:text("Generate")');
|
||||
|
||||
// Navigate to the generate certificates page
|
||||
await expect(page.locator('h1')).toContainText('Generate Certificates');
|
||||
|
||||
// Check the 'checked_in_only' checkbox
|
||||
await page.check('#checked-in-only-checkbox');
|
||||
|
||||
// Generate certificates
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Wait for success message
|
||||
await expect(page.locator('.hvac-success-message')).toBeVisible();
|
||||
|
||||
// Go back to the event summary
|
||||
await page.click('a:text("Back to Event Summary")');
|
||||
}
|
||||
|
||||
// Check if there are any generated certificates
|
||||
const viewButtonExists = await page.locator('.hvac-cert-action:text("View")').isVisible();
|
||||
|
||||
if (viewButtonExists) {
|
||||
// View a certificate
|
||||
await page.click('.hvac-cert-action:text("View")', { force: true });
|
||||
|
||||
// Wait for the certificate modal to appear
|
||||
await expect(page.locator('#hvac-certificate-modal')).toBeVisible();
|
||||
|
||||
// Wait for the certificate iframe to load
|
||||
await page.waitForSelector('#hvac-certificate-preview[src^="http"]');
|
||||
|
||||
// Close the modal
|
||||
await page.click('.hvac-modal-close');
|
||||
|
||||
// Email a certificate
|
||||
await page.click('.hvac-cert-action:text("Email")', { force: true });
|
||||
|
||||
// Confirm the email dialog
|
||||
await page.once('dialog', dialog => dialog.accept());
|
||||
|
||||
// Wait for success message
|
||||
await page.waitForTimeout(2000); // Wait for alert to appear and dismiss
|
||||
|
||||
// Revoke a certificate
|
||||
await page.click('.hvac-cert-action:text("Revoke")', { force: true });
|
||||
|
||||
// Enter reason in the prompt
|
||||
await page.once('dialog', dialog => dialog.accept('Revocation test'));
|
||||
|
||||
// Wait for status to update to Revoked
|
||||
await expect(page.locator('td:has-text("Revoked")')).toBeVisible();
|
||||
} else {
|
||||
console.log('No generated certificates available to test with');
|
||||
}
|
||||
} else {
|
||||
console.log('No attendees found for the event');
|
||||
}
|
||||
});
|
||||
|
||||
test('Navigate to Certificate Reports page', async ({ page }) => {
|
||||
// Navigate to certificate reports page
|
||||
await page.goto(`${stagingUrl}certificate-reports/`);
|
||||
|
||||
// Verify the page loaded successfully
|
||||
await expect(page.locator('h1')).toContainText('Certificate Reports');
|
||||
|
||||
// Try filtering certificates
|
||||
await page.selectOption('select[name="filter_status"]', 'all');
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Check for certificate data or empty message
|
||||
const hasReports = await page.locator('.hvac-certificate-table').isVisible();
|
||||
if (!hasReports) {
|
||||
await expect(page.locator('.hvac-no-certificates')).toBeVisible();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "d03d5891db11eabba74e5b9558c9c7b9",
|
||||
"content-hash": "fabbbe60cdbad1e1d198c566db326a4c",
|
||||
"packages": [
|
||||
{
|
||||
"name": "composer/installers",
|
||||
|
|
@ -156,6 +156,77 @@
|
|||
}
|
||||
],
|
||||
"time": "2021-09-13T08:19:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tecnickcom/tcpdf",
|
||||
"version": "6.9.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tecnickcom/TCPDF.git",
|
||||
"reference": "c838d7f7babb0d35763acfb9ecf78c3f45966f83"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/c838d7f7babb0d35763acfb9ecf78c3f45966f83",
|
||||
"reference": "c838d7f7babb0d35763acfb9ecf78c3f45966f83",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"php": ">=7.1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"config",
|
||||
"include",
|
||||
"tcpdf.php",
|
||||
"tcpdf_barcodes_1d.php",
|
||||
"tcpdf_barcodes_2d.php",
|
||||
"include/tcpdf_colors.php",
|
||||
"include/tcpdf_filters.php",
|
||||
"include/tcpdf_font_data.php",
|
||||
"include/tcpdf_fonts.php",
|
||||
"include/tcpdf_images.php",
|
||||
"include/tcpdf_static.php",
|
||||
"include/barcodes/datamatrix.php",
|
||||
"include/barcodes/pdf417.php",
|
||||
"include/barcodes/qrcode.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicola Asuni",
|
||||
"email": "info@tecnick.com",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "TCPDF is a PHP class for generating PDF documents and barcodes.",
|
||||
"homepage": "http://www.tcpdf.org/",
|
||||
"keywords": [
|
||||
"PDFD32000-2008",
|
||||
"TCPDF",
|
||||
"barcodes",
|
||||
"datamatrix",
|
||||
"pdf",
|
||||
"pdf417",
|
||||
"qrcode"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/tecnickcom/TCPDF/issues",
|
||||
"source": "https://github.com/tecnickcom/TCPDF/tree/6.9.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.com/donate/?hosted_button_id=NZUEC5XS8MFBJ",
|
||||
"type": "custom"
|
||||
}
|
||||
],
|
||||
"time": "2025-05-13T11:34:35+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
|
@ -349,20 +420,20 @@
|
|||
},
|
||||
{
|
||||
"name": "hamcrest/hamcrest-php",
|
||||
"version": "v2.0.1",
|
||||
"version": "v2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hamcrest/hamcrest-php.git",
|
||||
"reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3"
|
||||
"reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3",
|
||||
"reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3",
|
||||
"url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
|
||||
"reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3|^7.0|^8.0"
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"replace": {
|
||||
"cordoval/hamcrest-php": "*",
|
||||
|
|
@ -370,8 +441,8 @@
|
|||
"kodova/hamcrest-php": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/php-file-iterator": "^1.4 || ^2.0",
|
||||
"phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0"
|
||||
"phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0",
|
||||
"phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
|
@ -394,9 +465,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/hamcrest/hamcrest-php/issues",
|
||||
"source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1"
|
||||
"source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1"
|
||||
},
|
||||
"time": "2020-07-09T08:09:16+00:00"
|
||||
"time": "2025-04-30T06:54:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
|
|
@ -483,16 +554,16 @@
|
|||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.13.0",
|
||||
"version": "1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "024473a478be9df5fdaca2c793f2232fe788e414"
|
||||
"reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
|
||||
"reference": "024473a478be9df5fdaca2c793f2232fe788e414",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c",
|
||||
"reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -531,7 +602,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/myclabs/DeepCopy/issues",
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -539,7 +610,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-12T12:17:51+00:00"
|
||||
"time": "2025-04-29T12:36:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
|
|
@ -1038,16 +1109,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.6.22",
|
||||
"version": "9.6.23",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c"
|
||||
"reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c",
|
||||
"reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95",
|
||||
"reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1058,7 +1129,7 @@
|
|||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"myclabs/deep-copy": "^1.12.1",
|
||||
"myclabs/deep-copy": "^1.13.1",
|
||||
"phar-io/manifest": "^2.0.4",
|
||||
"phar-io/version": "^3.2.1",
|
||||
"php": ">=7.3",
|
||||
|
|
@ -1121,7 +1192,7 @@
|
|||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.23"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -1132,12 +1203,20 @@
|
|||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://liberapay.com/sebastianbergmann",
|
||||
"type": "liberapay"
|
||||
},
|
||||
{
|
||||
"url": "https://thanks.dev/u/gh/sebastianbergmann",
|
||||
"type": "thanks_dev"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-12-05T13:48:26+00:00"
|
||||
"time": "2025-05-02T06:40:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
|
|
@ -2154,16 +2233,16 @@
|
|||
},
|
||||
{
|
||||
"name": "wp-phpunit/wp-phpunit",
|
||||
"version": "6.7.2",
|
||||
"version": "6.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wp-phpunit/wp-phpunit.git",
|
||||
"reference": "e2bb06bacc92a8e9e405e83f56989e8ed9359db1"
|
||||
"reference": "a33d328dab5a4a9ddf0c560bcadbabb58b5ee67f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/e2bb06bacc92a8e9e405e83f56989e8ed9359db1",
|
||||
"reference": "e2bb06bacc92a8e9e405e83f56989e8ed9359db1",
|
||||
"url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/a33d328dab5a4a9ddf0c560bcadbabb58b5ee67f",
|
||||
"reference": "a33d328dab5a4a9ddf0c560bcadbabb58b5ee67f",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
|
|
@ -2198,7 +2277,7 @@
|
|||
"issues": "https://github.com/wp-phpunit/issues",
|
||||
"source": "https://github.com/wp-phpunit/wp-phpunit"
|
||||
},
|
||||
"time": "2025-02-12T01:22:52+00:00"
|
||||
"time": "2025-04-16T01:40:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "yoast/phpunit-polyfills",
|
||||
|
|
|
|||
Loading…
Reference in a new issue