Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
a04ae51
feat: add Admin Bar integration for Code Snippets with quick links an…
imantsk Jan 6, 2026
d224342
feat: add Admin Bar integration to the Plugin class
imantsk Jan 6, 2026
e3da8f4
feat: update snippet type labels
imantsk Jan 8, 2026
8f98136
feat: add admin bar snippet limit setting
imantsk Jan 8, 2026
bc77764
feat: enhance admin bar with pagination and snippet limit features
imantsk Jan 8, 2026
ce40ffa
feat: add filtering and sorting options to snippets REST API endpoint
imantsk Jan 8, 2026
1a6bfc0
feat: add admin bar pagination functionality with snippet fetching
imantsk Jan 8, 2026
ce45668
feat: add styles for admin bar code snippets pagination and safe mode
imantsk Jan 8, 2026
d16bc87
feat: refactor admin bar icon styles
imantsk Jan 8, 2026
fd419f4
feat: update admin bar icon handling and remove SVG function
imantsk Jan 8, 2026
4caef68
fix: update snippet response item type handling
imantsk Jan 8, 2026
1cf61b7
feat: enhance admin bar settings with enable option and snippet limit
imantsk Jan 8, 2026
cd2167d
feat: add 'Conditions' tab
imantsk Jan 8, 2026
4e74851
feat: enable admin bar by default in settings
imantsk Jan 9, 2026
680d682
Merge branch 'core/core' into feat/snippets-quicknav
imantsk Jan 17, 2026
f6929f1
fix: eslint @stylistic/quote-props
imantsk Jan 17, 2026
b7e5a74
fix: codestyle clean up and delint
imantsk Jan 17, 2026
be4ad85
fix: simplify snippet filtering logic in get_items method
imantsk Jan 22, 2026
1641d7b
fix: remove `require_once` to rely on composer autoloader
imantsk Jan 22, 2026
87da130
fix: update `register_hooks` to class constructor to register WordPre…
imantsk Jan 22, 2026
4e333b4
fix: export types and interfaces, refactor `getTypeFromScope` to swit…
imantsk Jan 22, 2026
a303ebb
Merge branch 'core-beta' into feat/snippets-quicknav
sheabunge Feb 12, 2026
567f0ac
Merge branch 'core/core-beta' into feat/snippets-quicknav
imantsk Feb 17, 2026
74875f6
tests: Refactor PHPUnit workflow to use a matrix strategy for PHP ver…
imantsk Feb 17, 2026
ecfb2b5
fix: Update WordPress directory paths in PHPUnit workflow
imantsk Feb 17, 2026
f3ffef2
fix: Simplify Composer install command in PHPUnit workflow
imantsk Feb 17, 2026
559b635
fix: Update permissions and improve comment handling in PHPUnit workflow
imantsk Feb 17, 2026
16d3e09
fix: Correct namespace for REST API snippets test
imantsk Feb 17, 2026
ee0f9b4
fix: Add step to delete previous PR failure comment on success in PHP…
imantsk Feb 17, 2026
ee52a47
feat: Enhance PHPUnit workflow with artifact download and error summa…
imantsk Feb 17, 2026
5aa246a
feat: Enhance PHPUnit test execution with result logging and director…
imantsk Feb 17, 2026
0bd4d6e
feat: Add intentional failure tests for CI validation
imantsk Feb 17, 2026
b0096d7
feat: Improve PHPUnit error message handling and deduplication logic
imantsk Feb 17, 2026
e36aabd
feat: Improve error summary formatting in PHPUnit results
imantsk Feb 17, 2026
74600df
feat: Enhance Playwright workflow with error summary and report norma…
imantsk Feb 17, 2026
116b3cc
feat: Enhance Playwright test logging and error reporting
imantsk Feb 17, 2026
66dd59b
feat: Remove intentional failure tests for CI validation
imantsk Feb 17, 2026
348a53a
feat: Update Playwright reporter output paths to use absolute paths
imantsk Feb 17, 2026
49ed6f3
feat: Increase WordPress memory limits and enhance Playwright test lo…
imantsk Feb 17, 2026
f14d80d
feat: Enhance WordPress debugging settings in Playwright workflow
imantsk Feb 17, 2026
c0bfcb0
feat: Add conditional display for admin bar snippets limit setting
imantsk Feb 17, 2026
63a0348
feat: Implement conditional rendering for settings fields based on cu…
imantsk Feb 17, 2026
0502a84
feat: Update Playwright reporter configuration for CI environment
imantsk Feb 17, 2026
714b933
feat: Update caching keys in Playwright workflow for improved depende…
imantsk Feb 17, 2026
501d68a
feat: Adjust Playwright configuration for retries and timeout settings
imantsk Feb 17, 2026
2639901
fix: Update E2E test selectors and snippet type/location constants to…
imantsk Feb 17, 2026
185d55d
refactor: replace hardcoded snippet activation switch selector with `…
imantsk Feb 17, 2026
0ff95b7
fix: Update Playwright test workflow to correctly handle cache keys a…
imantsk Feb 17, 2026
26cd4a5
fix: Update navigation and selector logic in SnippetsTestHelper
imantsk Feb 17, 2026
983a40c
fix: Clean up constants and update selector references
imantsk Feb 17, 2026
e3cb398
fix: Remove redundant method for success message expectation
imantsk Feb 17, 2026
493c090
fix: Update success message expectations and improve snippet deletion…
imantsk Feb 17, 2026
0c29405
fix: Refactor createPageWithShortcode to accept page parameter and en…
imantsk Feb 17, 2026
92e4541
fix: Refactor snippet row locators
imantsk Feb 17, 2026
415d658
fix: Remove outdated comment
imantsk Feb 17, 2026
e8bff9e
test: Improve Playwright selectors and test reliability for UI intera…
imantsk Feb 17, 2026
fb9a4e3
refactor: Increase Playwright test timeouts and enhance selector robu…
imantsk Feb 17, 2026
efa9c3a
refactor: Improve Playwright E2E test reliability by using `getByRole…
imantsk Feb 17, 2026
cd391fa
refactor: Update E2E test to use role-based button click and URL asse…
imantsk Feb 17, 2026
3e772cd
refactor: Enhance snippet activation/deactivation test with visibilit…
imantsk Feb 17, 2026
68182f9
refactor: Update snippet cloning and deletion tests for new React UI …
imantsk Feb 17, 2026
a49f88a
refactor: Standardize formatting in constants file for improved reada…
imantsk Feb 17, 2026
5532361
refactor: Improve code formatting and consistency in SnippetsTestHelper
imantsk Feb 17, 2026
dae01a6
feat: improve Playwright setup script
imantsk Feb 18, 2026
ec7e2fa
fix: correct worker configuration and increase timeout
imantsk Feb 18, 2026
a3eb97e
refactor: standardize formatting and improve regex patterns in consta…
imantsk Feb 18, 2026
c7f57c1
feat: enhance SnippetsTestHelper with improved methods and error hand…
imantsk Feb 18, 2026
fa9a853
feat: refactor and realign Code Snippets List Page tests
imantsk Feb 18, 2026
cbe66e7
feat: realign snippets admin tests for improved snippet handling and …
imantsk Feb 18, 2026
997f752
feat: enhance snippet handling in evaluation tests with dynamic snipp…
imantsk Feb 18, 2026
3ff07c5
fix: does not comply with psr-4 warning
imantsk Feb 18, 2026
a278d1e
feat: improve reliability of file download by appending link to DOM b…
imantsk Feb 18, 2026
829d400
feat: increase timeout for snippet export test and improve download h…
imantsk Feb 18, 2026
5e9aa27
feat: enhance authentication setup by adding user creation and update…
imantsk Feb 18, 2026
5347c22
feat: update .gitignore to include additional Playwright and local files
imantsk Feb 18, 2026
6ccdda6
feat: update ESLint configuration to ignore additional temporary file…
imantsk Feb 18, 2026
d083a4a
fix: stabilize snippet export download
imantsk Feb 18, 2026
14fdd20
chore: apply small type and docblock cleanups
imantsk Feb 18, 2026
eef0f80
fix: harden playwright auth setup
imantsk Feb 18, 2026
503485f
chore: increase playwright per-test timeout
imantsk Feb 18, 2026
09955b1
chore: add phpunit setup and update npm scripts
imantsk Feb 18, 2026
03b1707
chore: move phpunit tests under tests/phpunit
imantsk Feb 18, 2026
462694b
feat: add phpunit coverage for admin bar quicknav
imantsk Feb 18, 2026
6c732fd
docs: update phpunit setup and testing guide
imantsk Feb 18, 2026
350d246
chore: improve phpunit bootstrap discovery
imantsk Feb 18, 2026
7b9c23f
feat: add playwright coverage for admin bar quicknav
imantsk Feb 18, 2026
f866c3f
docs: add playwright setup and testing guide
imantsk Feb 18, 2026
facdb93
chore: update .gitignore
imantsk Feb 18, 2026
b312445
fix: stabilize quicknav e2e fixtures
imantsk Feb 18, 2026
41210a6
fix: restore deps cache reliably
imantsk Feb 18, 2026
a2f8197
fix: avoid deps cache reservation conflicts
imantsk Feb 18, 2026
7746860
fix: sync flat files on snippet field updates
imantsk Feb 18, 2026
f4e7cc1
fix: always build plugin assets in ci
imantsk Feb 18, 2026
cae8cb9
fix: avoid truncating snippets in e2e
imantsk Feb 18, 2026
cef629f
fix: keep default snippets during e2e
imantsk Feb 18, 2026
e6f169e
test: rename E2E tests for Admin Bar Snippets QuickNav functionality
imantsk Feb 18, 2026
5feab78
fix: eslint
imantsk Feb 18, 2026
209d97f
fix: streamline PHP code generation for Safe Mode definition
imantsk Feb 18, 2026
1d982d3
chore: replace if-else structure with switch for test directory assig…
imantsk Feb 18, 2026
75fe453
Merge branch 'core/core-beta' into feat/snippets-quicknav
imantsk Feb 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 38 additions & 6 deletions .github/workflows/phpunit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ jobs:
phpunit-test:
name: PHPUnit tests (PHP ${{ inputs.php-version }})
runs-on: ubuntu-22.04

env:
WP_CORE_DIR: /tmp/wordpress
WP_TESTS_DIR: /tmp/wordpress-tests-lib

services:
mysql:
image: mysql:8.0
Expand Down Expand Up @@ -59,9 +62,7 @@ jobs:

- name: Install Composer dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: |
cd src
composer install --no-progress --prefer-dist --optimize-autoloader
run: composer install -d src --no-progress --prefer-dist --optimize-autoloader

- name: Save Composer cache
if: steps.composer-cache.outputs.cache-hit != 'true'
Expand All @@ -70,21 +71,52 @@ jobs:
path: src/vendor
key: ${{ runner.os }}-php-${{ inputs.php-version }}-composer-${{ steps.deps-hash.outputs.deps_hash }}

- name: Resolve WordPress version metadata
id: wp-meta
run: |
set -euo pipefail
wp_version=$(curl -s http://api.wordpress.org/core/version-check/1.7/ | grep -o '"version":"[^"]*' | head -1 | sed 's/"version":"//')
if [ -z "$wp_version" ]; then
wp_version="latest-unknown"
fi
echo "wp_version=$wp_version" >> "$GITHUB_OUTPUT"

- name: Get WordPress test suite cache
id: wp-tests-cache
uses: actions/cache/restore@v4
with:
path: |
${{ env.WP_CORE_DIR }}
${{ env.WP_TESTS_DIR }}
key: ${{ runner.os }}-php-${{ inputs.php-version }}-wp-tests-${{ hashFiles('tests/install-wp-tests.sh') }}-wp-${{ steps.wp-meta.outputs.wp_version }}

- name: Install WordPress test suite
run: |
bash tests/install-wp-tests.sh wordpress_test root root 127.0.0.1:3306 latest true

- name: Save WordPress test suite cache
if: steps.wp-tests-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
${{ env.WP_CORE_DIR }}
${{ env.WP_TESTS_DIR }}
key: ${{ steps.wp-tests-cache.outputs.cache-primary-key }}

- name: Run PHPUnit tests
run: |
set -euo pipefail
mkdir -p test-results/phpunit
cd src
vendor/bin/phpunit -c ../phpunit.xml --testdox
vendor/bin/phpunit -c ../phpunit.xml --testdox --log-junit ../test-results/phpunit/phpunit-${{ inputs.php-version }}.xml 2>&1 | tee ../test-results/phpunit/phpunit-${{ inputs.php-version }}.log

- uses: actions/upload-artifact@v4
if: always()
with:
name: phpunit-test-results-php-${{ inputs.php-version }}
path: |
.phpunit.result.cache
src/.phpunit.result.cache
test-results/phpunit/
if-no-files-found: ignore
retention-days: 2

280 changes: 233 additions & 47 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,64 +24,250 @@ concurrency:
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
phpunit-php-7-4:
phpunit:
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run-tests')
strategy:
fail-fast: false
matrix:
php-version: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
uses: ./.github/workflows/phpunit-test.yml
with:
php-version: '7.4'

phpunit-php-8-0:
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run-tests')
uses: ./.github/workflows/phpunit-test.yml
with:
php-version: '8.0'

phpunit-php-8-1:
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run-tests')
uses: ./.github/workflows/phpunit-test.yml
with:
php-version: '8.1'

phpunit-php-8-2:
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run-tests')
uses: ./.github/workflows/phpunit-test.yml
with:
php-version: '8.2'

phpunit-php-8-3:
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run-tests')
uses: ./.github/workflows/phpunit-test.yml
with:
php-version: '8.3'

phpunit-php-8-4:
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run-tests')
uses: ./.github/workflows/phpunit-test.yml
with:
php-version: '8.4'
php-version: ${{ matrix.php-version }}

test-result:
needs: [phpunit-php-7-4, phpunit-php-8-0, phpunit-php-8-1, phpunit-php-8-2, phpunit-php-8-3, phpunit-php-8-4]
if: always() && (needs.phpunit-php-7-4.result != 'skipped' || needs.phpunit-php-8-0.result != 'skipped' || needs.phpunit-php-8-1.result != 'skipped' || needs.phpunit-php-8-2.result != 'skipped' || needs.phpunit-php-8-3.result != 'skipped' || needs.phpunit-php-8-4.result != 'skipped')
needs: [phpunit]
if: always() && needs.phpunit.result != 'skipped'
runs-on: ubuntu-22.04
name: PHPUnit - Test Results Summary
permissions:
pull-requests: write
issues: write
steps:
- name: Test status summary
run: |
echo "PHP 7.4: ${{ needs.phpunit-php-7-4.result }}"
echo "PHP 8.0: ${{ needs.phpunit-php-8-0.result }}"
echo "PHP 8.1: ${{ needs.phpunit-php-8-1.result }}"
echo "PHP 8.2: ${{ needs.phpunit-php-8-2.result }}"
echo "PHP 8.3: ${{ needs.phpunit-php-8-3.result }}"
echo "PHP 8.4: ${{ needs.phpunit-php-8-4.result }}"
echo "PHPUnit matrix result: ${{ needs.phpunit.result }}"

- name: Delete previous PR failure comment on success
if: github.event_name == 'pull_request' && needs.phpunit.result == 'success'
uses: actions/github-script@v7
with:
script: |
const marker = '<!-- phpunit-result-comment -->';

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
per_page: 100,
});

const existing = comments.filter(c => typeof c.body === 'string' && c.body.startsWith(marker));

for (const comment of existing) {
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: comment.id,
});
}

- name: Download PHPUnit artifacts
if: github.event_name == 'pull_request' && needs.phpunit.result == 'failure'
uses: actions/download-artifact@v5
with:
pattern: phpunit-test-results-php-*
path: phpunit-artifacts
merge-multiple: true

- name: Build distinct error summary
if: github.event_name == 'pull_request' && needs.phpunit.result == 'failure'
run: |
set -euo pipefail
python3 - <<'PY'
import glob
import os
import re
import xml.etree.ElementTree as ET
from collections import defaultdict

artifacts_dir = 'phpunit-artifacts'

def version_from_path(path: str) -> str:
base = os.path.basename(path)
m = re.search(r'phpunit-([0-9]+\.[0-9]+)\.xml$', base)
if m:
return m.group(1)
m = re.search(r'phpunit-([0-9]+\.[0-9]+)\.log$', base)
if m:
return m.group(1)
return 'unknown'

def add_entry(grouped, key, version, message):
if not message.strip():
return
grouped[key]['versions'].add(version)
# Keep the first representative message we see for this key.
if not grouped[key]['message']:
grouped[key]['message'] = message.strip()

grouped = defaultdict(lambda: {'versions': set(), 'message': ''})
versions_seen = set()

# Prefer JUnit XML when present.
for xml_path in sorted(glob.glob(os.path.join(artifacts_dir, '**', '*.xml'), recursive=True)):
version = version_from_path(xml_path)
versions_seen.add(version)
try:
root = ET.parse(xml_path).getroot()
except Exception:
continue

for testcase in root.iter('testcase'):
for tag in ('error', 'failure'):
for node in testcase.findall(tag):
etype = (node.attrib.get('type') or tag).strip()
msg = (node.attrib.get('message') or '').strip()
details = (node.text or '').strip()
combined = f"{etype}: {msg}".strip(': ')
if details:
combined = combined + "\n" + details

testcase_id = (
(testcase.attrib.get('classname') or '').strip() +
'::' +
(testcase.attrib.get('name') or '').strip()
).strip(':')

extracted = ''
if not msg and details:
for line in details.splitlines():
line = line.strip()
if line.startswith('CI demo:'):
extracted = line
break
if not extracted:
extracted = details.splitlines()[0].strip()

# Dedupe key: prefer explicit message; otherwise use extracted details + testcase id.
key_parts = [etype]
if msg:
key_parts.append(msg)
elif extracted:
key_parts.append(extracted)
if testcase_id:
key_parts.append(testcase_id)
key = "\n".join([p for p in key_parts if p]).strip() or (combined.splitlines()[0] if combined else 'unknown')
add_entry(grouped, key, version, combined)

# Fallback: scan logs for fatals if XML missing.
fatal_re = re.compile(r'^(PHP\s+Fatal\s+error:.*|Fatal\s+error:.*)$', re.MULTILINE)
for log_path in sorted(glob.glob(os.path.join(artifacts_dir, '**', '*.log'), recursive=True)):
version = version_from_path(log_path)
versions_seen.add(version)
try:
log = open(log_path, 'r', encoding='utf-8', errors='replace').read()
except Exception:
continue
m = fatal_re.search(log)
if m:
msg = m.group(1).strip()
key = 'Fatal error\n' + msg
add_entry(grouped, key, version, msg)

versions = sorted(v for v in versions_seen if v != 'unknown')

def versions_label(affected):
affected = sorted(v for v in affected if v != 'unknown')
if versions and affected == versions:
return 'all'
return ', '.join(affected) if affected else 'unknown'

items = sorted(grouped.items(), key=lambda kv: (-len(kv[1]['versions']), kv[0]))
blocks = []
for idx, (key, info) in enumerate(items):
affected = versions_label(info['versions'])
message = info['message']
block = (
"-----\n"
f"Affected PHP version: `{affected}`\n"
"```php\n"
f"{message}\n"
"```"
)
if idx == len(items) - 1:
block += "\n-----"
blocks.append(block)

if blocks:
details = "\n\n".join(blocks)
else:
details = "No PHPUnit error details could be parsed from artifacts."

md = "\n".join([
"<details>",
"<summary>See all PHPUnit errors (click to expand)</summary>",
"",
details,
"",
"</details>",
"",
])

with open('phpunit-errors.md', 'w', encoding='utf-8') as f:
f.write(md)
PY

- name: Post PR comment on failure
if: github.event_name == 'pull_request' && needs.phpunit.result == 'failure'
uses: actions/github-script@v7
with:
script: |
const marker = '<!-- phpunit-result-comment -->';

const fs = require('fs');
let details = '';
try {
details = fs.readFileSync('phpunit-errors.md', 'utf8').trim();
} catch (e) {
details = '';
}

const body = [
marker,
'## PHPUnit Test Failure',
'',
`One or more PHP version targets failed in [this workflow run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}).`,
'',
details || '_No parsed error details found._',
'',
'Please review the failing jobs and fix the issues before merging.',
].join('\n');

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
per_page: 100,
});

const existing = comments.filter(c => typeof c.body === 'string' && c.body.startsWith(marker));

for (const comment of existing) {
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: comment.id,
});
}

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});

- name: Check overall status
if: |
(needs.phpunit-php-7-4.result != 'success' && needs.phpunit-php-7-4.result != 'skipped') ||
(needs.phpunit-php-8-0.result != 'success' && needs.phpunit-php-8-0.result != 'skipped') ||
(needs.phpunit-php-8-1.result != 'success' && needs.phpunit-php-8-1.result != 'skipped') ||
(needs.phpunit-php-8-2.result != 'success' && needs.phpunit-php-8-2.result != 'skipped') ||
(needs.phpunit-php-8-3.result != 'success' && needs.phpunit-php-8-3.result != 'skipped') ||
(needs.phpunit-php-8-4.result != 'success' && needs.phpunit-php-8-4.result != 'skipped')
if: needs.phpunit.result != 'success'
run: exit 1

Loading