From f0c1e14f32a4d17a15158f62ef330db1736eeadb Mon Sep 17 00:00:00 2001 From: vic322 Date: Mon, 13 Jul 2026 23:20:20 +0900 Subject: [PATCH 1/9] test: add balloon block fixture round-trip test Establish a WordPress-core full-content style regression net for Gutenberg blocks, verifying block validity and save-output stability before the planned TypeScript/ESM refactor. balloon is the first covered block: each fixture is parsed, asserted valid, and re-serialized to confirm a clean round-trip. Run via @wordpress/scripts test-unit-js. Cocoon-specific global stubs are required because transforms.js and edit.js reference wp.* and gbSettings at module load time; removing that global coupling in the refactor will let the stubs go away. --- blocks/jest-unit.config.js | 17 ++++ blocks/jest/setup-cocoon-globals.js | 25 ++++++ blocks/package.json | 3 +- blocks/src/block/balloon/test/balloon.test.js | 90 +++++++++++++++++++ .../test/fixtures/balloon__default.html | 3 + .../fixtures/balloon__with-inner-blocks.html | 5 ++ 6 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 blocks/jest-unit.config.js create mode 100644 blocks/jest/setup-cocoon-globals.js create mode 100644 blocks/src/block/balloon/test/balloon.test.js create mode 100644 blocks/src/block/balloon/test/fixtures/balloon__default.html create mode 100644 blocks/src/block/balloon/test/fixtures/balloon__with-inner-blocks.html diff --git a/blocks/jest-unit.config.js b/blocks/jest-unit.config.js new file mode 100644 index 000000000..444c2e0df --- /dev/null +++ b/blocks/jest-unit.config.js @@ -0,0 +1,17 @@ +/** + * jest(wp-scripts test-unit-js)用の設定。 + * + * @wordpress/scripts の既定プリセット(@wordpress/jest-preset-default)を土台に、 + * Cocoon 固有のグローバルスタブ(setup-cocoon-globals.js)を setupFiles に追加する。 + */ +const defaultConfig = require( '@wordpress/scripts/config/jest-unit.config.js' ); +const presetSetupFiles = + require( '@wordpress/jest-preset-default/jest-preset.js' ).setupFiles || []; + +module.exports = { + ...defaultConfig, + setupFiles: [ + ...presetSetupFiles, + require.resolve( './jest/setup-cocoon-globals.js' ), + ], +}; diff --git a/blocks/jest/setup-cocoon-globals.js b/blocks/jest/setup-cocoon-globals.js new file mode 100644 index 000000000..bec9d98f3 --- /dev/null +++ b/blocks/jest/setup-cocoon-globals.js @@ -0,0 +1,25 @@ +/** + * Cocoon ブロックのテスト用グローバル定義。 + * + * Cocoon のブロックソースは、WordPress 管理画面から `wp_localize_script` 等で + * 注入されるグローバル変数(`wp`, `gbSettings`, `gbSpeechBalloons` など)に + * モジュール読み込み時点で依存している。jest(jsdom)にはこれらが存在しないため、 + * ここで最小限のスタブを定義する。 + * + * これは実行前セットアップ(jest の setupFiles)であり、テスト対象モジュールが + * import される前に評価される必要がある。 + */ + +// transforms.js が `const { createBlock } = wp.blocks;` をトップレベルで実行するため、 +// 実物の @wordpress/blocks を wp.blocks として供給する。 +const blocks = require( '@wordpress/blocks' ); +global.wp = global.wp || {}; +global.wp.blocks = blocks; + +// edit.js がトップレベルで参照するグローバル(未定義だと ReferenceError)。 +global.gbSettings = global.gbSettings || {}; +global.gbSpeechBalloons = global.gbSpeechBalloons || []; + +// helpers.js は typeof ガード済みだが、明示しておく。 +global.gbColors = global.gbColors || { keyColor: '#19448e' }; +global.gbCodeLanguages = global.gbCodeLanguages || []; diff --git a/blocks/package.json b/blocks/package.json index ed1676600..f19e77599 100644 --- a/blocks/package.json +++ b/blocks/package.json @@ -13,7 +13,8 @@ "lint:php:fix": "phpcbf -d memory_limit=512M --standard=WordPress --ignore=*/node_modules/* --extensions=php .", "format": "wp-scripts format", "format:check": "wp-scripts format --check", - "start": "wp-scripts start" + "start": "wp-scripts start", + "test:unit": "wp-scripts test-unit-js" }, "devDependencies": { "@babel/core": "^7.23.2", diff --git a/blocks/src/block/balloon/test/balloon.test.js b/blocks/src/block/balloon/test/balloon.test.js new file mode 100644 index 000000000..659290c6f --- /dev/null +++ b/blocks/src/block/balloon/test/balloon.test.js @@ -0,0 +1,90 @@ +/** + * balloon ブロックのフィクスチャ回帰テスト。 + * + * WordPress コアの "full-content" フィクスチャ方式に倣い、シリアライズ済みの + * ブロック HTML(fixtures/__.html)を検証する: + * 1. parse() でブロックにパースできる + * 2. isValid === true(save 出力と保存済み HTML が一致する = デシリアライズ健全性) + * 3. validationIssues が空 + * 4. serialize() で元の HTML にラウンドトリップする(再シリアライズ安定性) + * + * これにより save.js / block.json / deprecated.js の変更が保存形を壊した場合に + * 検知できる、JS 側回帰安全網の骨格となる。 + */ +import { readFileSync } from 'fs'; +import path from 'path'; + +import { + registerBlockType, + parse, + serialize, + setCategories, + getCategories, +} from '@wordpress/blocks'; +import { RichText } from '@wordpress/block-editor'; + +import { metadata, name, settings } from '../index'; + +const FIXTURES_DIR = path.join( __dirname, 'fixtures' ); + +const readFixture = ( variant ) => + readFileSync( + path.join( FIXTURES_DIR, `balloon__${ variant }.html` ), + 'utf8' + ).trim(); + +beforeAll( () => { + // block.json の category "cocoon-block" はテスト環境では未登録なので追加する。 + setCategories( [ + ...getCategories(), + { slug: 'cocoon-block', title: 'Cocoon' }, + ] ); + + // innerBlocks に使う core/paragraph の最小スタブ。 + // フィクスチャ内の

の保存形はこのスタブが基準となる。 + registerBlockType( 'core/paragraph', { + title: 'Paragraph', + edit: () => null, + category: 'text', + attributes: { + content: { + type: 'string', + source: 'html', + selector: 'p', + default: '', + }, + }, + save: ( { attributes } ) => ( + + ), + } ); + + // テスト対象。不安定 API(blocks.js の bootstrap)を避け、 + // index.js の export を使って直接登録する。 + registerBlockType( metadata, settings ); +} ); + +describe( 'balloon block fixtures', () => { + it.each( [ 'default', 'with-inner-blocks' ] )( + '%s: パースすると単一の有効な balloon ブロックになる', + ( variant ) => { + const html = readFixture( variant ); + const blocks = parse( html ); + + expect( blocks ).toHaveLength( 1 ); + expect( blocks[ 0 ].name ).toBe( name ); + expect( blocks[ 0 ].isValid ).toBe( true ); + expect( blocks[ 0 ].validationIssues ).toEqual( [] ); + } + ); + + it.each( [ 'default', 'with-inner-blocks' ] )( + '%s: 再シリアライズで元の HTML にラウンドトリップする', + ( variant ) => { + const html = readFixture( variant ); + const blocks = parse( html ); + + expect( serialize( blocks ) ).toBe( html ); + } + ); +} ); diff --git a/blocks/src/block/balloon/test/fixtures/balloon__default.html b/blocks/src/block/balloon/test/fixtures/balloon__default.html new file mode 100644 index 000000000..3deed7b13 --- /dev/null +++ b/blocks/src/block/balloon/test/fixtures/balloon__default.html @@ -0,0 +1,3 @@ + +

+ diff --git a/blocks/src/block/balloon/test/fixtures/balloon__with-inner-blocks.html b/blocks/src/block/balloon/test/fixtures/balloon__with-inner-blocks.html new file mode 100644 index 000000000..c8ab1d1da --- /dev/null +++ b/blocks/src/block/balloon/test/fixtures/balloon__with-inner-blocks.html @@ -0,0 +1,5 @@ + +
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod!

+
+ From d46e1566c5228f24508f364a11614fb5720ce096 Mon Sep 17 00:00:00 2001 From: vic322 Date: Tue, 14 Jul 2026 00:35:48 +0900 Subject: [PATCH 2/9] test: load WP test suite in integration bootstrap The integration bootstrap called tests_add_filter() before requiring the WordPress test suite's functions.php that defines it, so it fatally errored the moment it was actually used. The bug stayed hidden because phpunit.xml still wires every suite to the unit bootstrap, leaving this file dead. Require functions.php first so the file works once wired in. --- tests/Integration/bootstrap.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/Integration/bootstrap.php b/tests/Integration/bootstrap.php index 284462ccf..b5827634d 100644 --- a/tests/Integration/bootstrap.php +++ b/tests/Integration/bootstrap.php @@ -15,7 +15,7 @@ * vendor/bin/phpunit --testsuite integration * * ローカル環境でのセットアップ: - * - Docker を使用する場合は docker/docker-compose.test.yml を参照 + * - Docker を使用する場合は docker/docker-compose.wp7.0-php8.4.yml を参照 * - GitHub Actions では自動的にセットアップされます */ @@ -43,7 +43,7 @@ echo "WP_TESTS_DIR 環境変数を設定するか、WordPress テストスイートをインストールしてください。\n\n"; echo "セットアップ方法:\n"; echo " 1. GitHub Actions: .github/workflows/phpunit.yml に設定済み\n"; - echo " 2. ローカル: bin/install-wp-tests.sh を使用\n"; + echo " 2. ローカル: docker/docker-compose.wp7.0-php8.4.yml を使用\n"; echo " 3. 手動: export WP_TESTS_DIR=/path/to/wordpress-develop/tests/phpunit\n"; exit(1); } @@ -51,6 +51,10 @@ // Composer オートローダー require_once dirname(__DIR__, 2) . '/vendor/autoload.php'; +// WordPress テストスイートの関数群を読み込み(tests_add_filter 等を定義) +// これを先に読み込まないと、下の tests_add_filter() が未定義になる。 +require_once $_tests_dir . '/includes/functions.php'; + // テーマ読み込み関数を WordPress のテストブートストラップ前に登録 $_theme_dir = dirname(__DIR__, 2); tests_add_filter('setup_theme', function() use ($_theme_dir) { From c492ff88dd61dc1ae89fb288ff8ff03cf66c0537 Mon Sep 17 00:00:00 2001 From: vic322 Date: Tue, 14 Jul 2026 00:35:49 +0900 Subject: [PATCH 3/9] chore: add WordPress 7.0 / PHP 8.4 docker compose Add the regression matrix ceiling environment for local integration and render testing. Ports, network subnet, and volumes are isolated from the existing 6.x combos so it can run alongside them. A dedicated wordpress_test database is created on init because the WP test suite drops all tables in its target database. Also ignore .phpunit.result.cache. --- .gitignore | 1 + docker/docker-compose.wp7.0-php8.4.yml | 111 ++++++++++++++++++ .../01-create-test-db.sql | 5 + 3 files changed, 117 insertions(+) create mode 100644 docker/docker-compose.wp7.0-php8.4.yml create mode 100644 docker/mysql-init-wp7.0-php8.4/01-create-test-db.sql diff --git a/.gitignore b/.gitignore index 60f49f4f1..7d1ec4140 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ composer.lock # PHPUnit .phpunit.cache/ +.phpunit.result.cache tests/coverage/ configs/ diff --git a/docker/docker-compose.wp7.0-php8.4.yml b/docker/docker-compose.wp7.0-php8.4.yml new file mode 100644 index 000000000..bd649a5f2 --- /dev/null +++ b/docker/docker-compose.wp7.0-php8.4.yml @@ -0,0 +1,111 @@ +services: + # 権限修正用初期化コンテナ + init-permissions-70-php84: + image: wordpress:7.0-php8.4-apache + user: "root" + command: | + sh -c " + chown -R www-data:www-data /var/www/html/wp-content/uploads && + chmod -R 755 /var/www/html/wp-content/uploads && + mkdir -p /var/www/html/wp-content/uploads/cocoon-resources/css-cache && + chown -R www-data:www-data /var/www/html/wp-content/uploads/cocoon-resources && + chmod -R 755 /var/www/html/wp-content/uploads/cocoon-resources + " + volumes: + - uploads_70_php84:/var/www/html/wp-content/uploads + networks: + cocoon-70-php84-network: + ipv4_address: 192.168.110.5 + + # WordPress 7.0 + PHP 8.4 サービス + wordpress-7-0-php84: + image: wordpress:7.0-php8.4-apache + container_name: cocoon-wordpress-7-0-php84 + restart: unless-stopped + user: "33:33" # www-data user + ports: + - "8090:80" + environment: + WORDPRESS_DB_HOST: mysql-7-0-php84:3306 + WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME:-wordpress_70_php84} + WORDPRESS_DB_USER: ${WORDPRESS_DB_USER:-wordpress} + WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD:-wordpress} + WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX:-wp_} + WORDPRESS_DEBUG: ${WORDPRESS_DEBUG:-true} + # Apache設定 + APACHE_RUN_USER: www-data + APACHE_RUN_GROUP: www-data + volumes: + # Cocoonテーマを WordPress テーマディレクトリにマウント + - ..:/var/www/html/wp-content/themes/cocoon + # WordPress データの永続化 + - wordpress_70_php84_data:/var/www/html + # アップロードディレクトリ(書き込み権限が必要) + - uploads_70_php84:/var/www/html/wp-content/uploads + depends_on: + mysql-7-0-php84: + condition: service_healthy + init-permissions-70-php84: + condition: service_completed_successfully + networks: + cocoon-70-php84-network: + ipv4_address: 192.168.110.10 + + # MySQL データベース (WordPress 7.0 + PHP 8.4用) + mysql-7-0-php84: + image: mysql:8.0 + container_name: cocoon-mysql-7-0-php84 + restart: unless-stopped + environment: + MYSQL_DATABASE: ${WORDPRESS_DB_NAME:-wordpress_70_php84} + MYSQL_USER: ${WORDPRESS_DB_USER:-wordpress} + MYSQL_PASSWORD: ${WORDPRESS_DB_PASSWORD:-wordpress} + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword} + volumes: + - mysql_70_php84_data:/var/lib/mysql + # 本番用DBに加えて統合テスト用DB(wordpress_test)を初期化時に作成 + - ./mysql-init-wp7.0-php8.4:/docker-entrypoint-initdb.d + ports: + - "3090:3306" + networks: + cocoon-70-php84-network: + ipv4_address: 192.168.110.20 + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "wordpress", "--password=wordpress"] + timeout: 20s + retries: 10 + + # phpMyAdmin (WordPress 7.0 + PHP 8.4用) + phpmyadmin-7-0-php84: + image: phpmyadmin/phpmyadmin:latest + container_name: cocoon-phpmyadmin-7-0-php84 + restart: unless-stopped + ports: + - "8190:80" + environment: + PMA_HOST: mysql-7-0-php84 + PMA_PORT: 3306 + PMA_USER: ${WORDPRESS_DB_USER:-wordpress} + PMA_PASSWORD: ${WORDPRESS_DB_PASSWORD:-wordpress} + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword} + depends_on: + - mysql-7-0-php84 + networks: + cocoon-70-php84-network: + ipv4_address: 192.168.110.30 + +volumes: + wordpress_70_php84_data: + driver: local + mysql_70_php84_data: + driver: local + uploads_70_php84: + driver: local + +networks: + cocoon-70-php84-network: + driver: bridge + ipam: + config: + - subnet: 192.168.110.0/24 + gateway: 192.168.110.1 diff --git a/docker/mysql-init-wp7.0-php8.4/01-create-test-db.sql b/docker/mysql-init-wp7.0-php8.4/01-create-test-db.sql new file mode 100644 index 000000000..151ce71e4 --- /dev/null +++ b/docker/mysql-init-wp7.0-php8.4/01-create-test-db.sql @@ -0,0 +1,5 @@ +-- WordPress 統合テスト用データベースの作成 +-- (WP テストスイートは指定 DB の全テーブルを破棄するため、本番用とは別の専用 DB を用意する) +CREATE DATABASE IF NOT EXISTS `wordpress_test` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +GRANT ALL PRIVILEGES ON `wordpress_test`.* TO 'wordpress'@'%'; +FLUSH PRIVILEGES; From ea1f8c683e2cd5937ed98e02ad3064e521e207fc Mon Sep 17 00:00:00 2001 From: vic322 Date: Tue, 14 Jul 2026 00:35:49 +0900 Subject: [PATCH 4/9] test: add new-list block render golden master Add a WordPress-core style render regression test for the dynamic new-list block. Deterministic posts are seeded via the test factory, rendered through do_blocks(), and the volatile parts (ids, dates, urls, version query) are normalized before comparing against a committed golden. Run with UPDATE_GOLDEN=1 to regenerate the golden files. --- tests/Integration/NewListBlockRenderTest.php | 180 ++++++++++++++++++ .../fixtures/new-list-date-snippet.html | 51 +++++ .../fixtures/new-list-default.html | 48 +++++ 3 files changed, 279 insertions(+) create mode 100644 tests/Integration/NewListBlockRenderTest.php create mode 100644 tests/Integration/fixtures/new-list-date-snippet.html create mode 100644 tests/Integration/fixtures/new-list-default.html diff --git a/tests/Integration/NewListBlockRenderTest.php b/tests/Integration/NewListBlockRenderTest.php new file mode 100644 index 000000000..9c2a49a6d --- /dev/null +++ b/tests/Integration/NewListBlockRenderTest.php @@ -0,0 +1,180 @@ +category->create([ + 'name' => 'ゴールデンカテゴリー', + 'slug' => 'golden-category', + ]); + + // 決定的な投稿を seed(固定タイトル・固定日付・固定slug・固定抜粋)。 + // 実DBの既存投稿に依存しないよう、必要な投稿だけをこのテスト内で生成する。 + // 日付降順(order=desc)で新しい順に並ぶ: C > B > A。 + $seeds = [ + [ + 'post_title' => 'ゴールデンマスター記事A', + 'post_name' => 'golden-post-a', + 'post_date' => '2021-01-01 09:00:00', + 'post_content' => 'これは記事Aの本文です。', + 'post_excerpt' => '記事Aの抜粋テキストです。', + ], + [ + 'post_title' => 'ゴールデンマスター記事B', + 'post_name' => 'golden-post-b', + 'post_date' => '2021-02-02 09:00:00', + 'post_content' => 'これは記事Bの本文です。', + 'post_excerpt' => '記事Bの抜粋テキストです。', + ], + [ + 'post_title' => 'ゴールデンマスター記事C', + 'post_name' => 'golden-post-c', + 'post_date' => '2021-03-03 09:00:00', + 'post_content' => 'これは記事Cの本文です。', + 'post_excerpt' => '記事Cの抜粋テキストです。', + ], + ]; + + foreach ($seeds as $seed) { + $post_id = self::factory()->post->create(array_merge($seed, [ + 'post_status' => 'publish', + 'post_type' => 'post', + 'post_category' => [$cat_id], + ])); + $this->post_ids[] = $post_id; + } + } + + /** + * 既定属性(count=3, 日付/抜粋なし)の新着リストが golden と一致すること。 + */ + public function test_新着リストブロックの既定レンダリングが_golden_と一致する(): void + { + $attrs = [ + 'count' => 3, + 'sticky' => false, + 'showAllCats' => true, + ]; + $this->assertRenderMatchesGolden('new-list-default', $attrs); + } + + /** + * 日付・抜粋を有効化した新着リストが golden と一致すること。 + */ + public function test_新着リストブロックの日付抜粋つきレンダリングが_golden_と一致する(): void + { + $attrs = [ + 'count' => 3, + 'sticky' => false, + 'showAllCats' => true, + 'date' => true, + 'snippet' => true, + ]; + $this->assertRenderMatchesGolden('new-list-date-snippet', $attrs); + } + + /** + * 指定属性でブロックをレンダリングし、正規化後 HTML を golden と比較する。 + * UPDATE_GOLDEN=1 のときは golden を書き出す。 + */ + private function assertRenderMatchesGolden(string $name, array $attrs): void + { + $rendered = $this->render_new_list_block($attrs); + $actual = $this->normalize($rendered); + $golden_file = self::FIXTURES_DIR . '/' . $name . '.html'; + + if (getenv('UPDATE_GOLDEN')) { + if (!is_dir(self::FIXTURES_DIR)) { + mkdir(self::FIXTURES_DIR, 0777, true); + } + file_put_contents($golden_file, $actual); + // 生成モードでは書き出しの成否のみ確認する。 + $this->assertFileExists($golden_file); + return; + } + + $this->assertFileExists( + $golden_file, + "golden ファイルがありません: {$golden_file}\n" . + 'UPDATE_GOLDEN=1 を付けて実行すると生成できます。' + ); + $expected = file_get_contents($golden_file); + $this->assertSame($expected, $actual, "レンダリング結果が golden ({$name}) と一致しません。"); + } + + /** + * new-list ブロックを do_blocks() でサーバーサイドレンダリングする。 + */ + private function render_new_list_block(array $attrs): string + { + $json = wp_json_encode($attrs); + $block = ''; + return do_blocks($block); + } + + /** + * 揮発要素を正規化する。 + * + * 正規化ルール: + * - 行末の空白を除去(末尾空白の揺れを吸収) + * - パーマリンク等の投稿ID/タームID (?p=123 / ?cat=1 等) → 0 + * - get_post_class の post-123 クラス → post-0 + * - entry-date 内の日付テキスト (get_the_time 出力) → __DATE__ + * - アセットの ?ver=... キャッシュバスター → ?ver=__VER__ + * + * 固定 seed(固定日付・固定抜粋・固定カテゴリー slug)により、 + * タイトル・抜粋・カテゴリークラスは正規化不要で安定する。 + */ + private function normalize(string $html): string + { + // 行末の空白を整理 + $html = preg_replace('/[ \t]+(\r?\n)/', '$1', $html); + + // パーマリンク中の投稿ID/タームID + $html = preg_replace('/([?&](?:p|page_id|post|cat|tag_id|m)=)\d+/', '${1}0', $html); + + // get_post_class の数値付き投稿クラス + // (post-date/post-update 等は数字を含まないため影響しない) + $html = preg_replace('/\bpost-\d+\b/', 'post-0', $html); + + // entry-date の中身(get_the_time / get_update_time の出力) + $html = preg_replace( + '#()#s', + '${1}__DATE__${2}', + $html + ); + + // アセット URL のバージョンクエリ + $html = preg_replace('/([?&]ver=)[^"\'&\s]+/', '${1}__VER__', $html); + + return $html; + } +} diff --git a/tests/Integration/fixtures/new-list-date-snippet.html b/tests/Integration/fixtures/new-list-date-snippet.html new file mode 100644 index 000000000..a02f84ff7 --- /dev/null +++ b/tests/Integration/fixtures/new-list-date-snippet.html @@ -0,0 +1,51 @@ + \ No newline at end of file diff --git a/tests/Integration/fixtures/new-list-default.html b/tests/Integration/fixtures/new-list-default.html new file mode 100644 index 000000000..6d489620f --- /dev/null +++ b/tests/Integration/fixtures/new-list-default.html @@ -0,0 +1,48 @@ + \ No newline at end of file From c577dbe37a9d49a71cfe3a17a4c576bd5ba5cbe4 Mon Sep 17 00:00:00 2001 From: vic322 Date: Tue, 14 Jul 2026 06:07:58 +0900 Subject: [PATCH 5/9] test: establish PHPUnit 9.6 integration test lane The integration testsuite silently skipped in CI because phpunit.xml wires every suite to the Brain\Monkey unit bootstrap, which never loads WP_UnitTestCase. Real WordPress integration tests must run on PHPUnit 9.x + yoast/phpunit-polyfills ^1.1, since the WordPress 7.0 test suite calls parseTestMethodAnnotations(), removed in PHPUnit 10; the theme root stays on PHPUnit ^11 for the unit lane. Give the integration lane its own isolated toolchain (a dedicated composer manifest with a tracked lock for reproducibility), a PHPUnit 9.6 config that loads the WP-aware bootstrap, and a docker-based local runner that mirrors the CI path. The bootstrap loads the tooling autoloader rather than the theme's PHPUnit 11 vendor to avoid class-version clashes. --- .gitignore | 2 + bin/run-integration-tests.sh | 153 ++ phpunit-integration.xml.dist | 33 + tests/Integration/bootstrap.php | 26 +- tests/integration-tooling/composer.json | 12 + tests/integration-tooling/composer.lock | 1862 +++++++++++++++++++++++ 6 files changed, 2086 insertions(+), 2 deletions(-) create mode 100755 bin/run-integration-tests.sh create mode 100644 phpunit-integration.xml.dist create mode 100644 tests/integration-tooling/composer.json create mode 100644 tests/integration-tooling/composer.lock diff --git a/.gitignore b/.gitignore index 7d1ec4140..14bccfb7f 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,8 @@ claudedocs # Composer vendor/ composer.lock +# 統合テスト用ツールチェーンは再現性のため lock を追跡する +!tests/integration-tooling/composer.lock # PHPUnit .phpunit.cache/ diff --git a/bin/run-integration-tests.sh b/bin/run-integration-tests.sh new file mode 100755 index 000000000..125488c2a --- /dev/null +++ b/bin/run-integration-tests.sh @@ -0,0 +1,153 @@ +#!/usr/bin/env bash +# +# WordPress 統合テスト(integration レーン)をローカルの Docker で実行する。 +# +# 概要: +# ユニットレーン(PHPUnit 11 / Brain\Monkey)とは分離した統合レーンを、 +# 実 WordPress 環境で実行する。統合レーンは WordPress 7.0 テストスイートが +# 要求する PHPUnit 9.6 + yoast/phpunit-polyfills ^1.1(tests/integration-tooling) +# を使い、bootstrap は WP_UnitTestCase をロードする tests/Integration/bootstrap.php。 +# +# 実行経路は .github/workflows/phpunit.yml の integration-tests ジョブと同一: +# 1. WordPress コア + wordpress-develop テストスイートを取得 +# 2. wp-tests-config.php を生成(テスト用 DB を指す) +# 3. tests/integration-tooling で composer install(PHPUnit 9.6 + polyfills) +# 4. phpunit-integration.xml.dist で integration testsuite を実行 +# +# 前提: +# - Docker / Docker Compose が利用可能なこと +# - テスト用 MySQL は docker/docker-compose.wp7.0-php8.4.yml で起動する +# (初期化 SQL で DB "wordpress_test" を作成済み) +# +# 環境変数(すべて任意・上書き可能): +# WP_VERSION テスト対象の WordPress バージョン (default: 7.0.1) +# COCOON_PHP_IMAGE PHP ランタイムとして使う Docker イメージ (default: wordpress:7.0-php8.4-apache) +# COCOON_COMPOSE_FILE MySQL を起動する compose ファイル +# COCOON_MYSQL_SERVICE compose 内の MySQL サービス名 +# COCOON_DOCKER_NETWORK テスト実行コンテナを接続する Docker ネットワーク +# COCOON_DB_HOST/NAME/USER/PASSWORD テスト用 DB 接続情報 +# COCOON_WORK_VOLUME WP コア/テストスイートを保持する Docker ボリューム名 +# http_proxy/https_proxy 設定されていればコンテナへ引き継ぐ(企業プロキシ等) +# +# 追加引数はそのまま phpunit に渡される。例: +# bin/run-integration-tests.sh --filter NoticeTest +# UPDATE_GOLDEN=1 bin/run-integration-tests.sh --filter NewListBlockRenderTest +# +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +# --- 設定 --- +WP_VERSION="${WP_VERSION:-7.0.1}" +PHP_IMAGE="${COCOON_PHP_IMAGE:-wordpress:7.0-php8.4-apache}" +COMPOSE_FILE="${COCOON_COMPOSE_FILE:-$REPO_DIR/docker/docker-compose.wp7.0-php8.4.yml}" +MYSQL_SERVICE="${COCOON_MYSQL_SERVICE:-mysql-7-0-php84}" +DOCKER_NETWORK="${COCOON_DOCKER_NETWORK:-docker_cocoon-70-php84-network}" +DB_HOST="${COCOON_DB_HOST:-$MYSQL_SERVICE}" +DB_NAME="${COCOON_DB_NAME:-wordpress_test}" +DB_USER="${COCOON_DB_USER:-root}" +DB_PASSWORD="${COCOON_DB_PASSWORD:-rootpassword}" +WORK_VOLUME="${COCOON_WORK_VOLUME:-cocoon_integration_work}" + +COMPOSE="docker compose -f $COMPOSE_FILE" + +echo "== [1/4] テスト用 MySQL を起動 ($MYSQL_SERVICE) ==" +$COMPOSE up -d "$MYSQL_SERVICE" + +echo "== MySQL の healthy を待機 ==" +for _ in $(seq 1 30); do + status="$(docker inspect -f '{{.State.Health.Status}}' "$($COMPOSE ps -q "$MYSQL_SERVICE")" 2>/dev/null || echo starting)" + [ "$status" = "healthy" ] && break + sleep 2 +done +echo " MySQL status: ${status:-unknown}" + +# --- コンテナへ渡すプロキシ設定(任意) --- +PROXY_ARGS=() +if [ -n "${http_proxy:-}" ]; then PROXY_ARGS+=(-e "http_proxy=${http_proxy}"); fi +if [ -n "${https_proxy:-}" ]; then PROXY_ARGS+=(-e "https_proxy=${https_proxy}"); fi +PROXY_ARGS+=(-e "no_proxy=${no_proxy:-$DB_HOST,localhost,127.0.0.1}") + +# --- コンテナ内で実行するセットアップ + テスト --- +# 変数はホスト側で展開して埋め込む。 +INNER=$(cat < "\$WP_TESTS_DIR/wp-tests-config.php" <&1 | tail -5 + +# --- 統合レーン実行 --- +echo "== integration テストを実行 ==" +cd /theme +export WP_TESTS_DIR="\$WP_TESTS_DIR" +exec tests/integration-tooling/vendor/bin/phpunit -c phpunit-integration.xml.dist --colors=always $* +INNER_EOF +) + +echo "== [2/4] PHP ランタイムコンテナ ($PHP_IMAGE) で実行 ==" +docker run --rm \ + --network "$DOCKER_NETWORK" \ + "${PROXY_ARGS[@]}" \ + ${UPDATE_GOLDEN:+-e UPDATE_GOLDEN="$UPDATE_GOLDEN"} \ + -v "$REPO_DIR":/theme \ + -v "$WORK_VOLUME":/work \ + -w /theme \ + "$PHP_IMAGE" \ + bash -c "$INNER" diff --git a/phpunit-integration.xml.dist b/phpunit-integration.xml.dist new file mode 100644 index 000000000..ef5d8c462 --- /dev/null +++ b/phpunit-integration.xml.dist @@ -0,0 +1,33 @@ + + + + + + + tests/Integration + + + + diff --git a/tests/Integration/bootstrap.php b/tests/Integration/bootstrap.php index b5827634d..18fa9ecf7 100644 --- a/tests/Integration/bootstrap.php +++ b/tests/Integration/bootstrap.php @@ -48,8 +48,30 @@ exit(1); } -// Composer オートローダー -require_once dirname(__DIR__, 2) . '/vendor/autoload.php'; +// Composer オートローダー(統合レーン専用ツールチェーン: PHPUnit 9.6 + polyfills) +// +// ユニットレーンのテーマ vendor は PHPUnit 11 だが、WordPress 7.0 テストスイートは +// PHPUnit 10 で削除された parseTestMethodAnnotations() を使うため 9.x が必須。 +// ここでテーマ vendor(PHPUnit 11)を読み込むと 9.6 実行系とクラスが混在して fatal に +// なるため、統合レーンは tests/integration-tooling/vendor(PHPUnit 9.6 + polyfills)を用いる。 +$_tooling_autoload = __DIR__ . '/../integration-tooling/vendor/autoload.php'; +if (file_exists($_tooling_autoload)) { + require_once $_tooling_autoload; +} + +// テスト用クラス(Cocoon\Tests\ => tests/)の PSR-4 オートローダー。 +// テーマ本体の関数は WordPress がテーマ切り替え時に読み込むため、ここでは扱わない。 +spl_autoload_register(function ($class) { + $prefix = 'Cocoon\\Tests\\'; + if (strncmp($class, $prefix, strlen($prefix)) !== 0) { + return; + } + $rel = substr($class, strlen($prefix)); + $file = dirname(__DIR__) . '/' . str_replace('\\', '/', $rel) . '.php'; + if (is_file($file)) { + require $file; + } +}); // WordPress テストスイートの関数群を読み込み(tests_add_filter 等を定義) // これを先に読み込まないと、下の tests_add_filter() が未定義になる。 diff --git a/tests/integration-tooling/composer.json b/tests/integration-tooling/composer.json new file mode 100644 index 000000000..467ae7037 --- /dev/null +++ b/tests/integration-tooling/composer.json @@ -0,0 +1,12 @@ +{ + "name": "cocoon/integration-tooling", + "description": "Isolated toolchain for the WordPress integration test lane. Kept separate from the theme's root composer.json (PHPUnit ^11) because the WordPress 7.0 test suite calls PHPUnit\\Util\\Test::parseTestMethodAnnotations(), which was removed in PHPUnit 10. The integration lane therefore requires PHPUnit 9.x + yoast/phpunit-polyfills ^1.1. Install with 'composer install' inside this directory; the resulting vendor/bin/phpunit is the integration runner.", + "license": "GPL-2.0-or-later", + "require-dev": { + "phpunit/phpunit": "^9.6", + "yoast/phpunit-polyfills": "^1.1" + }, + "config": { + "optimize-autoloader": true + } +} diff --git a/tests/integration-tooling/composer.lock b/tests/integration-tooling/composer.lock new file mode 100644 index 000000000..94d227d38 --- /dev/null +++ b/tests/integration-tooling/composer.lock @@ -0,0 +1,1862 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "ad8e1c9397278d5042595fc9e25e454d", + "packages": [], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:23:10+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-08-01T08:46:24+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.8.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/044a6a392ff8ad0d61f14370a5fbbd0a0107152f", + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.8.0" + }, + "time": "2026-07-04T14:30:18+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.32", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.6" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-22T04:23:01+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.35", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "0edba2f3a0c48df3553cb9b640810b30df60302b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0edba2f3a0c48df3553cb9b640810b30df60302b", + "reference": "0edba2f3a0c48df3553cb9b640810b30df60302b", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.5.0 || ^2", + "ext-dom": "*", + "ext-filter": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", + "sebastian/comparator": "^4.0.10", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.8", + "sebastian/global-state": "^5.0.8", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "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.35" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsoring.html", + "type": "other" + } + ], + "time": "2026-07-06T14:48:07+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:27:43+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.10", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10" + }, + "funding": [ + { + "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/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2026-01-24T09:22:56+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:30:58+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" + }, + "funding": [ + { + "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/sebastian/exporter", + "type": "tidelift" + } + ], + "time": "2025-09-24T06:03:27+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.8" + }, + "funding": [ + { + "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/sebastian/global-state", + "type": "tidelift" + } + ], + "time": "2025-08-10T07:10:35+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/539c6691e0623af6dc6f9c20384c120f963465a0", + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.6" + }, + "funding": [ + { + "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/sebastian/recursion-context", + "type": "tidelift" + } + ], + "time": "2025-08-10T06:57:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-14T16:00:52+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2025-11-17T20:03:58+00:00" + }, + { + "name": "yoast/phpunit-polyfills", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", + "reference": "41aaac462fbd80feb8dd129e489f4bbc53fe26b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/41aaac462fbd80feb8dd129e489f4bbc53fe26b0", + "reference": "41aaac462fbd80feb8dd129e489f4bbc53fe26b0", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "yoast/yoastcs": "^3.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.x-dev" + } + }, + "autoload": { + "files": [ + "phpunitpolyfills-autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Team Yoast", + "email": "support@yoast.com", + "homepage": "https://yoast.com" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Yoast/PHPUnit-Polyfills/graphs/contributors" + } + ], + "description": "Set of polyfills for changed PHPUnit functionality to allow for creating PHPUnit cross-version compatible tests", + "homepage": "https://github.com/Yoast/PHPUnit-Polyfills", + "keywords": [ + "phpunit", + "polyfill", + "testing" + ], + "support": { + "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", + "security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy", + "source": "https://github.com/Yoast/PHPUnit-Polyfills" + }, + "time": "2025-08-10T04:54:36+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.9.0" +} From 42bfd2e9c33fcaf608b25481f2357febf3a287de Mon Sep 17 00:00:00 2001 From: vic322 Date: Tue, 14 Jul 2026 06:07:58 +0900 Subject: [PATCH 6/9] chore: run integration tests on PHPUnit 9.6 lane Point the CI integration job at the isolated PHPUnit 9.6 toolchain and the dedicated integration config, and pass the polyfills path to the WP test suite. The job now actually executes the integration tests instead of silently skipping them all. --- .github/workflows/phpunit.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 90709cc1d..78966726d 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -98,8 +98,12 @@ jobs: extensions: mbstring, intl, json, mysqli, pdo_mysql tools: composer:v2 - - name: Install dependencies - run: composer install --prefer-dist --no-progress + # 統合レーン専用ツールチェーン(PHPUnit 9.6 + yoast/phpunit-polyfills ^1.1)。 + # WordPress 7.0 テストスイートは PHPUnit 10 で削除された + # parseTestMethodAnnotations() を使うため、テーマ本体の PHPUnit ^11 とは + # 分離した composer manifest からインストールする。 + - name: Install integration test toolchain (PHPUnit 9.6 + polyfills) + run: composer install --working-dir=tests/integration-tooling --prefer-dist --no-progress - name: Install WordPress test suite run: | @@ -153,6 +157,8 @@ jobs: define('WP_TESTS_TITLE', 'Test Blog'); define('WP_PHP_BINARY', 'php'); define('WPLANG', ''); + // 統合ツールチェーンの polyfills を WP テストスイートに明示(読込順に依存しない) + define('WP_TESTS_PHPUNIT_POLYFILLS_PATH', '$GITHUB_WORKSPACE/tests/integration-tooling/vendor/yoast/phpunit-polyfills'); EOF # テーマをWordPressにシンボリックリンク @@ -164,4 +170,4 @@ jobs: - name: Run integration tests env: WP_TESTS_DIR: /tmp/wordpress-tests-lib - run: vendor/bin/phpunit --testsuite integration --colors=always + run: tests/integration-tooling/vendor/bin/phpunit -c phpunit-integration.xml.dist --colors=always From b7b8a461a774dc994515263762f39b313a6249cc Mon Sep 17 00:00:00 2001 From: vic322 Date: Tue, 14 Jul 2026 08:56:02 +0900 Subject: [PATCH 7/9] chore: bump GitHub Actions to Node 24 runtimes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub is deprecating Node.js 20 on Actions runners, so checkout, cache, and upload-artifact were being force-run on Node 24 with a warning. Bump each to the lowest major that natively targets Node 24 (checkout v5, cache v5, upload-artifact v6 — v5 still ships Node 20) to clear the warning with minimal change; dependabot can advance them further. --- .github/workflows/phpunit.yml | 8 ++++---- .github/workflows/pot_generator.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 78966726d..c76007011 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -35,7 +35,7 @@ jobs: run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache Composer dependencies - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} @@ -54,7 +54,7 @@ jobs: - name: Upload coverage report if: matrix.php-version == '8.3' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: coverage-report path: coverage.xml @@ -89,7 +89,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/pot_generator.yml b/.github/workflows/pot_generator.yml index 943d6f141..cbdb33813 100644 --- a/.github/workflows/pot_generator.yml +++ b/.github/workflows/pot_generator.yml @@ -24,7 +24,7 @@ jobs: WP_POT_Generator: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Wordpress POT Generation shell: bash run: | From ecd83039733cead2a25bf2c785be5bb9ade80170 Mon Sep 17 00:00:00 2001 From: vic322 Date: Tue, 14 Jul 2026 09:14:47 +0900 Subject: [PATCH 8/9] chore: add block regression workflow for JS fixtures phpunit.yml covers only the PHP side; the block JavaScript fixture tests (block.json + edit/save parse-serialize round-trip) had no CI job and ran locally only. Add a Block Regression workflow that installs the blocks toolchain and runs the jest fixture suite, so the JS safety net actually gates on pull requests. --- .github/workflows/block-regression.yml | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/block-regression.yml diff --git a/.github/workflows/block-regression.yml b/.github/workflows/block-regression.yml new file mode 100644 index 000000000..8390b2f64 --- /dev/null +++ b/.github/workflows/block-regression.yml @@ -0,0 +1,40 @@ +name: Block Regression + +# Gutenberg ブロックの JS レーン回帰テスト。 +# phpunit.yml(PHP unit/integration)ではカバーされない、ブロックの +# JavaScript 側(block.json + edit/save のパース・シリアライズ健全性)を +# WordPress コア流の fixture ラウンドトリップで検証する。 + +on: + push: + branches: [ master, main, develop ] + pull_request: + branches: [ master, main, develop ] + +jobs: + js-fixtures: + name: Block JS fixtures (Node ${{ matrix.node-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: ['22'] + defaults: + run: + working-directory: blocks + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.node-version }} + cache: npm + cache-dependency-path: blocks/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Run block fixture tests + run: npm run test:unit From f896b362760bfac667b8f2dad2636b8587075dac Mon Sep 17 00:00:00 2001 From: vic322 Date: Tue, 14 Jul 2026 09:43:07 +0900 Subject: [PATCH 9/9] test: cover all discoverable blocks with fixture harness Generalize the balloon proof-of-concept into a block.json discovery harness that registers every structured block (37: block, block-universal, micro) via its index.js metadata instead of the unstable blocks.js path, then runs the WordPress-core full-content round-trip (parse, assert valid, re-serialize) against a captured fixture per block. Fixtures are generated from each block's example via createBlock/getBlockFromExample + serialize, not hand-guessed. Add @wordpress/block-library as a dev dependency (version-matched to the installed @wordpress packages, no drift) so InnerBlocks serialize through the real core blocks. A single console.error suppression is scoped to the core/list unique-key dev warning; every other error still fails the suite. --- blocks/jest-unit.config.js | 12 +- blocks/jest/block-registry.js | 164 ++++++ blocks/jest/setup-cocoon-globals.js | 57 +- blocks/jest/stubs/wordpress-editor.js | 18 + blocks/package-lock.json | 543 ++++++++++++++++++ blocks/package.json | 1 + blocks/src/test/block-fixtures.test.js | 89 +++ blocks/src/test/fixtures/ad__default.html | 3 + .../amazon-product-link__default.html | 1 + .../src/test/fixtures/balloon__default.html | 5 + .../src/test/fixtures/blank-box__default.html | 5 + .../src/test/fixtures/blogcard__default.html | 5 + .../src/test/fixtures/box-menu__default.html | 1 + .../test/fixtures/button-wrap__default.html | 3 + blocks/src/test/fixtures/button__default.html | 3 + .../src/test/fixtures/campaign__default.html | 5 + .../test/fixtures/caption-box__default.html | 5 + blocks/src/test/fixtures/cta__default.html | 1 + blocks/src/test/fixtures/faq__default.html | 5 + .../src/test/fixtures/icon-box__default.html | 5 + .../src/test/fixtures/icon-list__default.html | 23 + .../src/test/fixtures/info-box__default.html | 5 + .../src/test/fixtures/info-list__default.html | 1 + .../src/test/fixtures/label-box__default.html | 5 + .../fixtures/login-user-only__default.html | 3 + .../test/fixtures/micro-balloon__default.html | 3 + .../test/fixtures/micro-text__default.html | 3 + .../src/test/fixtures/navicard__default.html | 1 + .../src/test/fixtures/new-list__default.html | 1 + .../test/fixtures/popular-list__default.html | 1 + .../src/test/fixtures/profile__default.html | 1 + blocks/src/test/fixtures/radar__default.html | 127 ++++ .../rakuten-product-link__default.html | 1 + .../src/test/fixtures/ranking__default.html | 1 + .../test/fixtures/search-box__default.html | 3 + .../test/fixtures/sticky-box__default.html | 5 + .../src/test/fixtures/tab-box__default.html | 5 + .../fixtures/tab-caption-box__default.html | 5 + .../src/test/fixtures/tab-item__default.html | 3 + blocks/src/test/fixtures/tab__default.html | 3 + .../src/test/fixtures/template__default.html | 1 + .../test/fixtures/timeline-item__default.html | 3 + .../src/test/fixtures/timeline__default.html | 19 + .../test/fixtures/toggle-box__default.html | 5 + 44 files changed, 1151 insertions(+), 8 deletions(-) create mode 100644 blocks/jest/block-registry.js create mode 100644 blocks/jest/stubs/wordpress-editor.js create mode 100644 blocks/src/test/block-fixtures.test.js create mode 100644 blocks/src/test/fixtures/ad__default.html create mode 100644 blocks/src/test/fixtures/amazon-product-link__default.html create mode 100644 blocks/src/test/fixtures/balloon__default.html create mode 100644 blocks/src/test/fixtures/blank-box__default.html create mode 100644 blocks/src/test/fixtures/blogcard__default.html create mode 100644 blocks/src/test/fixtures/box-menu__default.html create mode 100644 blocks/src/test/fixtures/button-wrap__default.html create mode 100644 blocks/src/test/fixtures/button__default.html create mode 100644 blocks/src/test/fixtures/campaign__default.html create mode 100644 blocks/src/test/fixtures/caption-box__default.html create mode 100644 blocks/src/test/fixtures/cta__default.html create mode 100644 blocks/src/test/fixtures/faq__default.html create mode 100644 blocks/src/test/fixtures/icon-box__default.html create mode 100644 blocks/src/test/fixtures/icon-list__default.html create mode 100644 blocks/src/test/fixtures/info-box__default.html create mode 100644 blocks/src/test/fixtures/info-list__default.html create mode 100644 blocks/src/test/fixtures/label-box__default.html create mode 100644 blocks/src/test/fixtures/login-user-only__default.html create mode 100644 blocks/src/test/fixtures/micro-balloon__default.html create mode 100644 blocks/src/test/fixtures/micro-text__default.html create mode 100644 blocks/src/test/fixtures/navicard__default.html create mode 100644 blocks/src/test/fixtures/new-list__default.html create mode 100644 blocks/src/test/fixtures/popular-list__default.html create mode 100644 blocks/src/test/fixtures/profile__default.html create mode 100644 blocks/src/test/fixtures/radar__default.html create mode 100644 blocks/src/test/fixtures/rakuten-product-link__default.html create mode 100644 blocks/src/test/fixtures/ranking__default.html create mode 100644 blocks/src/test/fixtures/search-box__default.html create mode 100644 blocks/src/test/fixtures/sticky-box__default.html create mode 100644 blocks/src/test/fixtures/tab-box__default.html create mode 100644 blocks/src/test/fixtures/tab-caption-box__default.html create mode 100644 blocks/src/test/fixtures/tab-item__default.html create mode 100644 blocks/src/test/fixtures/tab__default.html create mode 100644 blocks/src/test/fixtures/template__default.html create mode 100644 blocks/src/test/fixtures/timeline-item__default.html create mode 100644 blocks/src/test/fixtures/timeline__default.html create mode 100644 blocks/src/test/fixtures/toggle-box__default.html diff --git a/blocks/jest-unit.config.js b/blocks/jest-unit.config.js index 444c2e0df..a24be9638 100644 --- a/blocks/jest-unit.config.js +++ b/blocks/jest-unit.config.js @@ -2,8 +2,10 @@ * jest(wp-scripts test-unit-js)用の設定。 * * @wordpress/scripts の既定プリセット(@wordpress/jest-preset-default)を土台に、 - * Cocoon 固有のグローバルスタブ(setup-cocoon-globals.js)を setupFiles に追加する。 + * Cocoon 固有のグローバルスタブ(setup-cocoon-globals.js)を setupFiles に追加し、 + * 本番ビルドで外部化される `@wordpress/editor` をテスト用スタブに解決する。 */ +const path = require( 'path' ); const defaultConfig = require( '@wordpress/scripts/config/jest-unit.config.js' ); const presetSetupFiles = require( '@wordpress/jest-preset-default/jest-preset.js' ).setupFiles || []; @@ -14,4 +16,12 @@ module.exports = { ...presetSetupFiles, require.resolve( './jest/setup-cocoon-globals.js' ), ], + moduleNameMapper: { + ...( defaultConfig.moduleNameMapper || {} ), + // 本番では wp.editor グローバルに外部化される(devDep に無い)。 + '^@wordpress/editor$': path.resolve( + __dirname, + 'jest/stubs/wordpress-editor.js' + ), + }, }; diff --git a/blocks/jest/block-registry.js b/blocks/jest/block-registry.js new file mode 100644 index 000000000..047407b0a --- /dev/null +++ b/blocks/jest/block-registry.js @@ -0,0 +1,164 @@ +/** + * Cocoon ブロックの自動発見・一括登録ハーネス。 + * + * `blocks.js`(本番の登録経路)は `unstable__bootstrapServerSideBlockDefinitions` + * や大量の `wp.*` グローバル副作用に依存しており、テストには不向き。そこで本 + * モジュールは、各ブロックの `index.js` が公開する `{ metadata, name, settings }` + * を直接 import して `registerBlockType` する、テスト専用の登録経路を提供する。 + * + * 発見方法(block.json 自動発見型): + * src/{block,block-universal,micro}// に block.json と index.js が + * 両方存在するディレクトリを構造化ブロックとみなす。 + * + * innerBlocks(core/paragraph, core/list など)の忠実なシリアライズのため、 + * @wordpress/block-library の registerCoreBlocks() でコアブロックも登録する。 + */ +const fs = require( 'fs' ); +const path = require( 'path' ); + +const { + registerBlockType, + getBlockType, + setCategories, + getCategories, +} = require( '@wordpress/blocks' ); +const { registerCoreBlocks } = require( '@wordpress/block-library' ); + +const SRC_DIR = path.join( __dirname, '..', 'src' ); +const TARGET_DIRS = [ 'block', 'block-universal', 'micro' ]; + +// block.json の category は既定カテゴリーに含まれないため補う。 +const COCOON_CATEGORIES = [ + { slug: 'cocoon-block', title: 'Cocoon' }, + { slug: 'cocoon-universal-block', title: 'Cocoon Universal' }, + { slug: 'cocoon-micro', title: 'Cocoon Micro' }, +]; + +/** + * ディスク上に存在するが本ハーネスの対象外とするブロックと、その理由。 + * blocks.js の登録配列に含まれない(=本番でも未登録の)ブロックはここで除外する。 + */ +const EXCLUDED = { + 'comparison-box': + 'blocks.js の登録配列に含まれず本番でも未登録。加えて、blocks.js から import されない子ブロック cocoon-blocks/comparison-left・comparison-right(items/block.js)に依存する。', +}; + +/** + * 対象ディレクトリを走査し、block.json と index.js を持つブロックを列挙する。 + * + * @return {{dir:string, slug:string, indexPath:string, blockJsonPath:string}[]} + */ +function discoverBlockDirs() { + const found = []; + for ( const dir of TARGET_DIRS ) { + const base = path.join( SRC_DIR, dir ); + if ( ! fs.existsSync( base ) ) { + continue; + } + for ( const slug of fs.readdirSync( base ).sort() ) { + const dirPath = path.join( base, slug ); + if ( ! fs.statSync( dirPath ).isDirectory() ) { + continue; + } + const indexPath = path.join( dirPath, 'index.js' ); + const blockJsonPath = path.join( dirPath, 'block.json' ); + if ( + fs.existsSync( indexPath ) && + fs.existsSync( blockJsonPath ) + ) { + found.push( { dir, slug, indexPath, blockJsonPath } ); + } + } + } + return found; +} + +/** + * 各ブロックの index.js を読み込む。ロード時例外(重い外部依存など)は + * 失敗として捕捉し、除外理由付きで返す。 + * + * @return {{loaded:Object[], excluded:Object[]}} + */ +function loadCocoonBlocks() { + const loaded = []; + const excluded = []; + for ( const info of discoverBlockDirs() ) { + if ( EXCLUDED[ info.slug ] ) { + excluded.push( { ...info, reason: EXCLUDED[ info.slug ] } ); + continue; + } + try { + // eslint-disable-next-line import/no-dynamic-require + const mod = require( info.indexPath ); + const { metadata, name, settings } = mod; + if ( ! metadata || ! name || ! settings ) { + throw new Error( + 'index.js が { metadata, name, settings } を公開していない' + ); + } + loaded.push( { ...info, metadata, name, settings } ); + } catch ( e ) { + excluded.push( { + ...info, + reason: `index.js のロードに失敗: ${ e.message }`, + } ); + } + } + return { loaded, excluded }; +} + +let registrationResult = null; + +/** + * コアブロック+発見した全 Cocoon ブロックを登録する(冪等)。 + * + * @return {{registered:Object[], excluded:Object[]}} + * registered: 登録に成功したブロック({slug,name,blockJsonPath,...}) + * excluded: 対象外・ロード失敗・登録失敗のブロックと理由 + */ +function registerAllBlocks() { + if ( registrationResult ) { + return registrationResult; + } + + // カテゴリー補完(既存を保持しつつ不足分を追加)。 + const existing = getCategories(); + const existingSlugs = new Set( existing.map( ( c ) => c.slug ) ); + setCategories( [ + ...existing, + ...COCOON_CATEGORIES.filter( ( c ) => ! existingSlugs.has( c.slug ) ), + ] ); + + // innerBlocks の忠実化のためコアブロックを登録。 + registerCoreBlocks(); + + const { loaded, excluded } = loadCocoonBlocks(); + const registered = []; + const registerExcluded = [ ...excluded ]; + + for ( const b of loaded ) { + try { + if ( ! getBlockType( b.name ) ) { + // balloon の PoC と同様、metadata を第1引数に渡して登録する。 + registerBlockType( b.metadata, b.settings ); + } + registered.push( b ); + } catch ( e ) { + registerExcluded.push( { + ...b, + reason: `registerBlockType に失敗: ${ e.message }`, + } ); + } + } + + registrationResult = { registered, excluded: registerExcluded }; + return registrationResult; +} + +module.exports = { + SRC_DIR, + TARGET_DIRS, + discoverBlockDirs, + loadCocoonBlocks, + registerAllBlocks, +}; diff --git a/blocks/jest/setup-cocoon-globals.js b/blocks/jest/setup-cocoon-globals.js index bec9d98f3..0923dd468 100644 --- a/blocks/jest/setup-cocoon-globals.js +++ b/blocks/jest/setup-cocoon-globals.js @@ -4,22 +4,65 @@ * Cocoon のブロックソースは、WordPress 管理画面から `wp_localize_script` 等で * 注入されるグローバル変数(`wp`, `gbSettings`, `gbSpeechBalloons` など)に * モジュール読み込み時点で依存している。jest(jsdom)にはこれらが存在しないため、 - * ここで最小限のスタブを定義する。 + * ここで最小限かつ決定的なスタブを定義する。 * * これは実行前セットアップ(jest の setupFiles)であり、テスト対象モジュールが - * import される前に評価される必要がある。 + * import される前に評価される必要がある。golden(フィクスチャ)を安定させるため、 + * すべてのスタブは固定値にする(乱数・時刻・環境依存の値を含めない)。 + * + * 対象ブロック(src/block, src/block-universal, src/micro)がモジュールロード時に + * 参照するグローバルの和集合をカバーする。 */ -// transforms.js が `const { createBlock } = wp.blocks;` をトップレベルで実行するため、 -// 実物の @wordpress/blocks を wp.blocks として供給する。 +// --- wp.* 名前空間 --------------------------------------------------------- +// Cocoon のブロックは一部の依存を ESM import ではなく `wp.*` グローバル経由で +// 参照する。これらは deprecated.js / save.js / edit.js のモジュールトップレベルで +// 分割代入されるため、未定義だと import 時点で ReferenceError になる。 const blocks = require( '@wordpress/blocks' ); +const components = require( '@wordpress/components' ); +const element = require( '@wordpress/element' ); + global.wp = global.wp || {}; +// transforms.js が `const { createBlock } = wp.blocks;` をトップレベルで実行する。 global.wp.blocks = blocks; +// icon-box/info-box/blogcard/sticky-box の deprecated.js が +// `const { PanelBody, SelectControl } = wp.components;` をトップレベルで実行する。 +global.wp.components = components; +// tab/save.js の `const { RawHTML } = wp.element;` と +// timeline-item/deprecated.js の `const { Fragment } = wp.element;` 用。 +global.wp.element = element; + +// radar/edit.js はモジュールトップレベルで `wp.data.subscribe(...)` を呼ぶ。 +// 実ストアの副作用(registerCoreBlocks のディスパッチで購読コールバックが発火し、 +// 未登録の core/block-editor ストアに触れて例外になる)を避けるため、 +// wp.data は決定的なノーオペスタブにする。edit のレンダリングは行わないため、 +// select は空のブロック一覧を返すだけでよい。 +global.wp.data = global.wp.data || { + subscribe: () => () => {}, + select: () => ( { + getBlocks: () => [], + getBlockRootClientId: () => null, + getCurrentPostType: () => null, + } ), + dispatch: () => ( {} ), +}; -// edit.js がトップレベルで参照するグローバル(未定義だと ReferenceError)。 +// --- gb* ローカライズ変数 -------------------------------------------------- +// ほとんどは edit 内で `typeof gbXxx !== 'undefined'` ガード済みだが、 +// 一部(balloon/edit.js の gbSettings / gbSpeechBalloons)はトップレベルで +// 参照される。決定性のためすべて固定の空値で定義する。 global.gbSettings = global.gbSettings || {}; global.gbSpeechBalloons = global.gbSpeechBalloons || []; - -// helpers.js は typeof ガード済みだが、明示しておく。 global.gbColors = global.gbColors || { keyColor: '#19448e' }; global.gbCodeLanguages = global.gbCodeLanguages || []; +global.gbTemplates = global.gbTemplates || []; +global.gbItemRankings = global.gbItemRankings || []; +global.gbNavMenus = global.gbNavMenus || []; +global.gbUsers = global.gbUsers || []; + +// amazon-product-link / rakuten-product-link は window 経由で参照する。 +global.window = global.window || global; +global.window.gbAmazonBlockDefaults = + global.window.gbAmazonBlockDefaults || {}; +global.window.gbRakutenBlockDefaults = + global.window.gbRakutenBlockDefaults || {}; diff --git a/blocks/jest/stubs/wordpress-editor.js b/blocks/jest/stubs/wordpress-editor.js new file mode 100644 index 000000000..29918fa8d --- /dev/null +++ b/blocks/jest/stubs/wordpress-editor.js @@ -0,0 +1,18 @@ +/** + * `@wordpress/editor` のテスト用スタブ。 + * + * 本番ビルドでは wp-scripts が `@wordpress/editor` を外部化し、実行時に + * グローバル `wp.editor` へ解決する(依存 package.json には含まれない)。 + * テストでは実体が無いため、ブロックがモジュールロード時に import する + * 名前付きエクスポートのみを最小スタブで供給する。 + * + * 利用箇所: 8 ブロック(cta/info-list/navicard/new-list/popular-list/ + * profile/ranking/template)が `ServerSideRender` を edit プレビューで使う。 + * save/serialize には一切関与しないため、フィクスチャの決定性に影響しない。 + */ +const ServerSideRender = () => null; + +module.exports = { + ServerSideRender, + default: ServerSideRender, +}; diff --git a/blocks/package-lock.json b/blocks/package-lock.json index 51b3ec21a..c0d8141b0 100644 --- a/blocks/package-lock.json +++ b/blocks/package-lock.json @@ -20,6 +20,7 @@ "@fortawesome/react-fontawesome": "^0.2.0", "@wordpress/api-fetch": "^6.41.0", "@wordpress/block-editor": "^12.12.0", + "@wordpress/block-library": "^8.35.0", "@wordpress/compose": "^6.21.0", "@wordpress/data": "^9.14.0", "@wordpress/dom-ready": "^3.44.0", @@ -4690,6 +4691,34 @@ "dev": true, "license": "MIT" }, + "node_modules/@preact/signals": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-1.3.4.tgz", + "integrity": "sha512-TPMkStdT0QpSc8FpB63aOwXoSiZyIrPsP9Uj347KopdS6olZdAYeeird/5FZv/M1Yc1ge5qstub2o8VDbvkT4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@preact/signals-core": "^1.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact": "10.x" + } + }, + "node_modules/@preact/signals-core": { + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.14.4.tgz", + "integrity": "sha512-HNB6HYeYKhQbJ1aKl+YRjrS4+QWHLKX6qKoUsfS/m0vqzsVaEBiZiaKbG/e+NKk2ch5ALQr/ihWaMHxiCuuWHA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/@prisma/instrumentation": { "version": "6.11.1", "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.11.1.tgz", @@ -6018,6 +6047,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/simple-peer": { + "version": "9.11.9", + "resolved": "https://registry.npmjs.org/@types/simple-peer/-/simple-peer-9.11.9.tgz", + "integrity": "sha512-6Gdl7TSS5oh9nuwKD4Pl8cSmaxWycYeZz9HLnJBNvIwWjZuGVsmHe9RwW3+9RxfhC1aIR9Z83DvaJoMw6rhkbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/sockjs": { "version": "0.3.36", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", @@ -7207,6 +7246,65 @@ "react-dom": "^18.0.0" } }, + "node_modules/@wordpress/block-library": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@wordpress/block-library/-/block-library-8.35.0.tgz", + "integrity": "sha512-Cb0n8gh3wK+aFwbPjhyrJpHoe7mqszi8FsxJtw9e37lxwax323pdc5G2YcsfEpfGs7fJnoJ9CA8GfKPqzpdVAw==", + "dev": true, + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "^7.16.0", + "@wordpress/a11y": "^3.58.0", + "@wordpress/api-fetch": "^6.55.0", + "@wordpress/autop": "^3.58.0", + "@wordpress/blob": "^3.58.0", + "@wordpress/block-editor": "^12.26.0", + "@wordpress/blocks": "^12.35.0", + "@wordpress/components": "^27.6.0", + "@wordpress/compose": "^6.35.0", + "@wordpress/core-data": "^6.35.0", + "@wordpress/data": "^9.28.0", + "@wordpress/date": "^4.58.0", + "@wordpress/deprecated": "^3.58.0", + "@wordpress/dom": "^3.58.0", + "@wordpress/element": "^5.35.0", + "@wordpress/escape-html": "^2.58.0", + "@wordpress/hooks": "^3.58.0", + "@wordpress/html-entities": "^3.58.0", + "@wordpress/i18n": "^4.58.0", + "@wordpress/icons": "^9.49.0", + "@wordpress/interactivity": "^5.7.0", + "@wordpress/interactivity-router": "^1.8.0", + "@wordpress/keyboard-shortcuts": "^4.35.0", + "@wordpress/keycodes": "^3.58.0", + "@wordpress/notices": "^4.26.0", + "@wordpress/patterns": "^1.19.0", + "@wordpress/primitives": "^3.56.0", + "@wordpress/private-apis": "^0.40.0", + "@wordpress/reusable-blocks": "^4.35.0", + "@wordpress/rich-text": "^6.35.0", + "@wordpress/server-side-render": "^4.35.0", + "@wordpress/url": "^3.59.0", + "@wordpress/viewport": "^5.35.0", + "@wordpress/wordcount": "^3.58.0", + "change-case": "^4.1.2", + "clsx": "^2.1.1", + "colord": "^2.7.0", + "escape-html": "^1.0.3", + "fast-average-color": "^9.1.1", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "remove-accents": "^0.5.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/@wordpress/block-serialization-default-parser": { "version": "4.58.0", "resolved": "https://registry.npmjs.org/@wordpress/block-serialization-default-parser/-/block-serialization-default-parser-4.58.0.tgz", @@ -7390,6 +7488,43 @@ "react": "^18.0.0" } }, + "node_modules/@wordpress/core-data": { + "version": "6.35.0", + "resolved": "https://registry.npmjs.org/@wordpress/core-data/-/core-data-6.35.0.tgz", + "integrity": "sha512-VnESF55nkAkKHQVwj0Oo8AU6w/yWjg/RQb+wKqJRnDuHEKHDAF5PI+9lYmcAsbXdnAc2yyf3lwBGk4w8m4uxlA==", + "dev": true, + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "^7.16.0", + "@wordpress/api-fetch": "^6.55.0", + "@wordpress/block-editor": "^12.26.0", + "@wordpress/blocks": "^12.35.0", + "@wordpress/compose": "^6.35.0", + "@wordpress/data": "^9.28.0", + "@wordpress/deprecated": "^3.58.0", + "@wordpress/element": "^5.35.0", + "@wordpress/html-entities": "^3.58.0", + "@wordpress/i18n": "^4.58.0", + "@wordpress/is-shallow-equal": "^4.58.0", + "@wordpress/private-apis": "^0.40.0", + "@wordpress/rich-text": "^6.35.0", + "@wordpress/sync": "^0.20.0", + "@wordpress/undo-manager": "^0.18.0", + "@wordpress/url": "^3.59.0", + "change-case": "^4.1.2", + "equivalent-key-map": "^0.2.2", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/@wordpress/data": { "version": "9.28.0", "resolved": "https://registry.npmjs.org/@wordpress/data/-/data-9.28.0.tgz", @@ -7681,6 +7816,34 @@ "node": ">=12" } }, + "node_modules/@wordpress/interactivity": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@wordpress/interactivity/-/interactivity-5.7.0.tgz", + "integrity": "sha512-zB2CZwj4TWpE5OJtFfpma1OYvrsLTMgWpRJ2ojRuNqBruZfQAUqOXsn6JyTTWs6bgyd4dr/WOZay4Wr4isleUw==", + "dev": true, + "license": "GPL-2.0-or-later", + "dependencies": { + "@preact/signals": "^1.2.2", + "deepsignal": "^1.4.0", + "preact": "^10.19.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@wordpress/interactivity-router": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@wordpress/interactivity-router/-/interactivity-router-1.8.0.tgz", + "integrity": "sha512-i2Lb9008DmPyh/DyCWhvVkwUha2zhLqPfBtMAUQuwes2prDLyl8FnWVS6bwXXYpu6qKkLhFz6hzXt3O988u53Q==", + "dev": true, + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/interactivity": "^5.7.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@wordpress/is-shallow-equal": { "version": "4.58.0", "resolved": "https://registry.npmjs.org/@wordpress/is-shallow-equal/-/is-shallow-equal-4.58.0.tgz", @@ -7796,6 +7959,37 @@ "npm-package-json-lint": ">=6.0.0" } }, + "node_modules/@wordpress/patterns": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@wordpress/patterns/-/patterns-1.19.0.tgz", + "integrity": "sha512-L0NhNn6P2YuZRgZNlZP0IFYKoVjQI5Vf/4edgG8yjYwuXLkanJvBZWglswu4Z8jzlsBN72o0n3K37FO8VzcnmA==", + "dev": true, + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "^7.16.0", + "@wordpress/a11y": "^3.58.0", + "@wordpress/block-editor": "^12.26.0", + "@wordpress/blocks": "^12.35.0", + "@wordpress/components": "^27.6.0", + "@wordpress/compose": "^6.35.0", + "@wordpress/core-data": "^6.35.0", + "@wordpress/data": "^9.28.0", + "@wordpress/element": "^5.35.0", + "@wordpress/html-entities": "^3.58.0", + "@wordpress/i18n": "^4.58.0", + "@wordpress/icons": "^9.49.0", + "@wordpress/notices": "^4.26.0", + "@wordpress/private-apis": "^0.40.0", + "@wordpress/url": "^3.59.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/@wordpress/postcss-plugins-preset": { "version": "5.41.0", "resolved": "https://registry.npmjs.org/@wordpress/postcss-plugins-preset/-/postcss-plugins-preset-5.41.0.tgz", @@ -7917,6 +8111,34 @@ "redux": ">=4" } }, + "node_modules/@wordpress/reusable-blocks": { + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@wordpress/reusable-blocks/-/reusable-blocks-4.35.0.tgz", + "integrity": "sha512-vofZGdVCOljSviar11sJWK+8loVAz53fBqPllcC0MbnSWkj4VPF4L6VWFVus1PQyL2MdkHynWRce9MHpKvN1NQ==", + "dev": true, + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "^7.16.0", + "@wordpress/block-editor": "^12.26.0", + "@wordpress/blocks": "^12.35.0", + "@wordpress/components": "^27.6.0", + "@wordpress/core-data": "^6.35.0", + "@wordpress/data": "^9.28.0", + "@wordpress/element": "^5.35.0", + "@wordpress/i18n": "^4.58.0", + "@wordpress/icons": "^9.49.0", + "@wordpress/notices": "^4.26.0", + "@wordpress/private-apis": "^0.40.0", + "@wordpress/url": "^3.59.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/@wordpress/rich-text": { "version": "6.35.0", "resolved": "https://registry.npmjs.org/@wordpress/rich-text/-/rich-text-6.35.0.tgz", @@ -8059,6 +8281,33 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@wordpress/server-side-render": { + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@wordpress/server-side-render/-/server-side-render-4.35.0.tgz", + "integrity": "sha512-yTbq31iGFc9VaRMtdCLlyZtbwCN+WdiECEqY6MsMXf31/TDmUcdZPxRTORy3Rz2HxEpFfUMjpRz7A8wn1QZmzA==", + "dev": true, + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "^7.16.0", + "@wordpress/api-fetch": "^6.55.0", + "@wordpress/blocks": "^12.35.0", + "@wordpress/components": "^27.6.0", + "@wordpress/compose": "^6.35.0", + "@wordpress/data": "^9.28.0", + "@wordpress/deprecated": "^3.58.0", + "@wordpress/element": "^5.35.0", + "@wordpress/i18n": "^4.58.0", + "@wordpress/url": "^3.59.0", + "fast-deep-equal": "^3.1.3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/@wordpress/shortcode": { "version": "3.58.0", "resolved": "https://registry.npmjs.org/@wordpress/shortcode/-/shortcode-3.58.0.tgz", @@ -8108,6 +8357,28 @@ "stylelint-scss": "^6.4.0" } }, + "node_modules/@wordpress/sync": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@wordpress/sync/-/sync-0.20.0.tgz", + "integrity": "sha512-nEB2UHiSF0PoU5irAmeuljt4OQbqKHpOlJOb0WMiydbDBGTzquxF6I61ax2mFTbSDntL0AUt8pxi6eT9con1sQ==", + "dev": true, + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "^7.16.0", + "@types/simple-peer": "^9.11.5", + "@wordpress/url": "^3.59.0", + "import-locals": "^2.0.0", + "lib0": "^0.2.42", + "simple-peer": "^9.11.0", + "y-indexeddb": "~9.0.11", + "y-protocols": "^1.0.5", + "y-webrtc": "~10.2.5", + "yjs": "~13.6.6" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@wordpress/theme": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@wordpress/theme/-/theme-0.8.0.tgz", @@ -8218,6 +8489,25 @@ "node": ">=12" } }, + "node_modules/@wordpress/viewport": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@wordpress/viewport/-/viewport-5.35.0.tgz", + "integrity": "sha512-iCIVbFcA1CzGXEVu5COoi6DRdh3m3zEMWOYKKqF1C7W/LhZnTNRsHOZbHq0tv7MOkwx0Nl7+hDJlPRM0B3fb7A==", + "dev": true, + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "^7.16.0", + "@wordpress/compose": "^6.35.0", + "@wordpress/data": "^9.28.0", + "@wordpress/element": "^5.35.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, "node_modules/@wordpress/warning": { "version": "2.58.0", "resolved": "https://registry.npmjs.org/@wordpress/warning/-/warning-2.58.0.tgz", @@ -10986,6 +11276,33 @@ "node": ">=0.10.0" } }, + "node_modules/deepsignal": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/deepsignal/-/deepsignal-1.6.0.tgz", + "integrity": "sha512-oplhhOSfBRKmx96B0PzbhRaX2W7iDpH6BEqvyGLIZPO2pdHQD+/P3u4Z8wi/sKXjCE7ht8C7ULTEzLSJbgwccA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@preact/signals": "^1.1.4 || ^2.0.0", + "@preact/signals-core": "^1.5.1", + "@preact/signals-react": "^1.3.8 || ^2.0.0 || ^3.0.0", + "preact": "^10.16.0" + }, + "peerDependenciesMeta": { + "@preact/signals": { + "optional": true + }, + "@preact/signals-core": { + "optional": true + }, + "@preact/signals-react": { + "optional": true + }, + "preact": { + "optional": true + } + } + }, "node_modules/default-gateway": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", @@ -11575,6 +11892,13 @@ "dev": true, "license": "MIT" }, + "node_modules/err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==", + "dev": true, + "license": "MIT" + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -12968,6 +13292,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/fast-average-color": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/fast-average-color/-/fast-average-color-9.5.2.tgz", + "integrity": "sha512-FbaU8iPTPljP7tmnVhXbCyASNw/zxnmaNDf88gn5pTXlNvejl9w4FapeWMh6UNDwIjhJJU28EPfQWwW032YgPA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -13662,6 +13996,13 @@ "node": ">=6.9.0" } }, + "node_modules/get-browser-rtc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", + "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -14668,6 +15009,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-locals": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-locals/-/import-locals-2.0.0.tgz", + "integrity": "sha512-1/bPE89IZhyf7dr5Pkz7b4UyVXy5pEt7PTEfye15UEn3AK8+2zwcDCfKk9Pwun4ltfhOSszOrReSsFcDKw/yoA==", + "dev": true, + "license": "MIT" + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -15442,6 +15790,17 @@ "node": ">=0.10.0" } }, + "node_modules/isomorphic.js": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", + "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -16670,6 +17029,28 @@ "node": ">= 0.8.0" } }, + "node_modules/lib0": { + "version": "0.2.117", + "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz", + "integrity": "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "isomorphic.js": "^0.2.4" + }, + "bin": { + "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", + "0gentesthtml": "bin/gentesthtml.js", + "0serve": "bin/0serve.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/lighthouse": { "version": "12.8.2", "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-12.8.2.tgz", @@ -19560,6 +19941,25 @@ "node": ">=0.10.0" } }, + "node_modules/preact": { + "version": "10.29.7", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.7.tgz", + "integrity": "sha512-DCHYrK/B10yUD3ZjLfhZ3WIE/9Vf9VFUODcRE2dRomTYDpJk6z6L9wecSfhfE6M9ZTHUdyQkoC46arIDhEV84Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact-render-to-string": ">=5" + }, + "peerDependenciesMeta": { + "preact-render-to-string": { + "optional": true + } + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -21631,6 +22031,61 @@ "dev": true, "license": "MIT" }, + "node_modules/simple-peer": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", + "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "debug": "^4.3.2", + "err-code": "^3.0.1", + "get-browser-rtc": "^1.1.0", + "queue-microtask": "^1.2.3", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/simple-peer/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/sirv": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", @@ -24742,6 +25197,76 @@ "node": ">=0.4" } }, + "node_modules/y-indexeddb": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/y-indexeddb/-/y-indexeddb-9.0.12.tgz", + "integrity": "sha512-9oCFRSPPzBK7/w5vOkJBaVCQZKHXB/v6SIT+WYhnJxlEC61juqG0hBrAf+y3gmSMLFLwICNH9nQ53uscuse6Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lib0": "^0.2.74" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "yjs": "^13.0.0" + } + }, + "node_modules/y-protocols": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.7.tgz", + "integrity": "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lib0": "^0.2.85" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "yjs": "^13.0.0" + } + }, + "node_modules/y-webrtc": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/y-webrtc/-/y-webrtc-10.2.6.tgz", + "integrity": "sha512-1kZ4YYwksFZi8+l8mTebVX9vW6Q5MnqxMkvNU700X5dBE38usurt/JgeXSIQRpK3NwUYYb9y63Jn9FMpMH6/vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lib0": "^0.2.42", + "simple-peer": "^9.11.0", + "y-protocols": "^1.0.6" + }, + "bin": { + "y-webrtc-signaling": "bin/server.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "optionalDependencies": { + "ws": "^8.14.2" + }, + "peerDependencies": { + "yjs": "^13.6.8" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -24809,6 +25334,24 @@ "fd-slicer": "~1.1.0" } }, + "node_modules/yjs": { + "version": "13.6.31", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.31.tgz", + "integrity": "sha512-Eq+5BRfbeGyqGVrTJL3bEcr8gKkxPuyuoHmAwpk52fDb8kOVMrfVSTRPd6yiGgX5Fskb96qCRjzjbRjrL4YEnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lib0": "^0.2.99" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/blocks/package.json b/blocks/package.json index f19e77599..0a1474393 100644 --- a/blocks/package.json +++ b/blocks/package.json @@ -25,6 +25,7 @@ "@fortawesome/react-fontawesome": "^0.2.0", "@wordpress/api-fetch": "^6.41.0", "@wordpress/block-editor": "^12.12.0", + "@wordpress/block-library": "^8.35.0", "@wordpress/compose": "^6.21.0", "@wordpress/data": "^9.14.0", "@wordpress/dom-ready": "^3.44.0", diff --git a/blocks/src/test/block-fixtures.test.js b/blocks/src/test/block-fixtures.test.js new file mode 100644 index 000000000..30e13a265 --- /dev/null +++ b/blocks/src/test/block-fixtures.test.js @@ -0,0 +1,89 @@ +/** + * 全 Cocoon 構造化ブロックのフィクスチャ回帰テスト(汎用ハーネス)。 + * + * WordPress コアの "full-content" フィクスチャ方式に倣い、block.json 自動発見で + * 登録した各ブロックについて、シリアライズ済みの保存 HTML + * (fixtures/__default.html)を検証する: + * 1. parse() で単一ブロックにパースできる + * 2. name が block.json の name と一致する + * 3. isValid === true(save 出力と保存済み HTML が一致 = デシリアライズ健全性) + * 4. validationIssues が空 + * 5. serialize() で元の HTML にラウンドトリップする(再シリアライズ安定性) + * + * これにより、いずれかのブロックの save.js / block.json / deprecated.js の変更が + * 保存形を壊した場合に、個別テストを書かずとも 1 ファイルで検知できる。 + * + * フィクスチャは手書き当て推量ではなく、createBlock / getBlockFromExample → + * serialize で実保存形をキャプチャして生成している(jest/block-registry.js と + * scratchpad の generate-fixtures.js を参照)。 + */ +import { readFileSync } from 'fs'; +import path from 'path'; + +import { parse, serialize } from '@wordpress/blocks'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { registerAllBlocks } = require( '../../jest/block-registry' ); + +const FIXTURES_DIR = path.join( __dirname, 'fixtures' ); + +const readFixture = ( slug ) => + readFileSync( + path.join( FIXTURES_DIR, `${ slug }__default.html` ), + 'utf8' + ).trim(); + +// core/list など一部のコアブロック save は子要素に key を付けずにレンダリングする。 +// serialize(内部で renderToString)時に React の dev 警告が出るが、保存出力の +// 正しさとは無関係で決定的。@wordpress/jest-console が console.error で失敗するのを +// 避けるため、この 1 種のみを絞って抑制する(他の console.error は従来どおり失敗)。 +// +// jest-console は setupFilesAfterEnv の beforeEach で毎テスト console.error を +// 張り替えるため、こちらの beforeEach(後に登録=後に実行)で再ラップする。 +let forwardError; +beforeEach( () => { + forwardError = console.error; + jest.spyOn( console, 'error' ).mockImplementation( ( ...args ) => { + const message = String( args[ 0 ] ?? '' ); + if ( message.includes( 'unique "key" prop' ) ) { + return; + } + forwardError( ...args ); + } ); +} ); + +afterEach( () => { + if ( console.error.mockRestore ) { + console.error.mockRestore(); + } +} ); + +const { registered } = registerAllBlocks(); + +// describe.each 用の [表示名, ブロック定義] タプル。 +const cases = registered.map( ( b ) => [ b.slug, b ] ); + +describe( 'Cocoon ブロックのフィクスチャ回帰(全登録ブロック)', () => { + it( '対象ブロックが 1 つ以上発見・登録されている', () => { + expect( registered.length ).toBeGreaterThan( 0 ); + } ); + + describe.each( cases )( '%s', ( slug, block ) => { + it( 'パースすると単一の有効なブロックになる', () => { + const html = readFixture( slug ); + const blocks = parse( html ); + + expect( blocks ).toHaveLength( 1 ); + expect( blocks[ 0 ].name ).toBe( block.name ); + expect( blocks[ 0 ].isValid ).toBe( true ); + expect( blocks[ 0 ].validationIssues ).toEqual( [] ); + } ); + + it( '再シリアライズで元の HTML にラウンドトリップする', () => { + const html = readFixture( slug ); + const blocks = parse( html ); + + expect( serialize( blocks ) ).toBe( html ); + } ); + } ); +} ); diff --git a/blocks/src/test/fixtures/ad__default.html b/blocks/src/test/fixtures/ad__default.html new file mode 100644 index 000000000..5cb990408 --- /dev/null +++ b/blocks/src/test/fixtures/ad__default.html @@ -0,0 +1,3 @@ + +
[ad]
+ diff --git a/blocks/src/test/fixtures/amazon-product-link__default.html b/blocks/src/test/fixtures/amazon-product-link__default.html new file mode 100644 index 000000000..19955a6e1 --- /dev/null +++ b/blocks/src/test/fixtures/amazon-product-link__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/balloon__default.html b/blocks/src/test/fixtures/balloon__default.html new file mode 100644 index 000000000..54d43a9c9 --- /dev/null +++ b/blocks/src/test/fixtures/balloon__default.html @@ -0,0 +1,5 @@ + +
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod!

+
+ diff --git a/blocks/src/test/fixtures/blank-box__default.html b/blocks/src/test/fixtures/blank-box__default.html new file mode 100644 index 000000000..d4dea1ad0 --- /dev/null +++ b/blocks/src/test/fixtures/blank-box__default.html @@ -0,0 +1,5 @@ + +
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

+
+ diff --git a/blocks/src/test/fixtures/blogcard__default.html b/blocks/src/test/fixtures/blogcard__default.html new file mode 100644 index 000000000..9a3c2aaf4 --- /dev/null +++ b/blocks/src/test/fixtures/blogcard__default.html @@ -0,0 +1,5 @@ + +
+https://wp-cocoon.com/ +
+ diff --git a/blocks/src/test/fixtures/box-menu__default.html b/blocks/src/test/fixtures/box-menu__default.html new file mode 100644 index 000000000..edb971b7b --- /dev/null +++ b/blocks/src/test/fixtures/box-menu__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/button-wrap__default.html b/blocks/src/test/fixtures/button-wrap__default.html new file mode 100644 index 000000000..72cf58a33 --- /dev/null +++ b/blocks/src/test/fixtures/button-wrap__default.html @@ -0,0 +1,3 @@ + + + diff --git a/blocks/src/test/fixtures/button__default.html b/blocks/src/test/fixtures/button__default.html new file mode 100644 index 000000000..dbfe45a07 --- /dev/null +++ b/blocks/src/test/fixtures/button__default.html @@ -0,0 +1,3 @@ + + + diff --git a/blocks/src/test/fixtures/campaign__default.html b/blocks/src/test/fixtures/campaign__default.html new file mode 100644 index 000000000..fcc2c8b2a --- /dev/null +++ b/blocks/src/test/fixtures/campaign__default.html @@ -0,0 +1,5 @@ + +
+

キャンペーン期間中のみ表示されるコンテンツです。

+
+ diff --git a/blocks/src/test/fixtures/caption-box__default.html b/blocks/src/test/fixtures/caption-box__default.html new file mode 100644 index 000000000..cbe5e380d --- /dev/null +++ b/blocks/src/test/fixtures/caption-box__default.html @@ -0,0 +1,5 @@ + +
Lorem ipsum dolor
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

+
+ diff --git a/blocks/src/test/fixtures/cta__default.html b/blocks/src/test/fixtures/cta__default.html new file mode 100644 index 000000000..ee2ee8474 --- /dev/null +++ b/blocks/src/test/fixtures/cta__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/faq__default.html b/blocks/src/test/fixtures/faq__default.html new file mode 100644 index 000000000..5aa25c5d2 --- /dev/null +++ b/blocks/src/test/fixtures/faq__default.html @@ -0,0 +1,5 @@ + +
Q
Lorem ipsum dolor sit amet ?
A
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

+
+ diff --git a/blocks/src/test/fixtures/icon-box__default.html b/blocks/src/test/fixtures/icon-box__default.html new file mode 100644 index 000000000..20d90d514 --- /dev/null +++ b/blocks/src/test/fixtures/icon-box__default.html @@ -0,0 +1,5 @@ + +
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

+
+ diff --git a/blocks/src/test/fixtures/icon-list__default.html b/blocks/src/test/fixtures/icon-list__default.html new file mode 100644 index 000000000..0c5629ba3 --- /dev/null +++ b/blocks/src/test/fixtures/icon-list__default.html @@ -0,0 +1,23 @@ + +
Title
+
    +
  • Lorem ipsum dolor sit amet.
  • + + + +
  • Lorem ipsum dolor sit amet.
  • + + + +
  • Lorem ipsum dolor sit amet.
  • + + + +
  • Lorem ipsum dolor sit amet.
  • + + + +
  • Lorem ipsum dolor sit amet.
  • +
+
+ diff --git a/blocks/src/test/fixtures/info-box__default.html b/blocks/src/test/fixtures/info-box__default.html new file mode 100644 index 000000000..5cf75cba6 --- /dev/null +++ b/blocks/src/test/fixtures/info-box__default.html @@ -0,0 +1,5 @@ + +
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

+
+ diff --git a/blocks/src/test/fixtures/info-list__default.html b/blocks/src/test/fixtures/info-list__default.html new file mode 100644 index 000000000..9b914a5e9 --- /dev/null +++ b/blocks/src/test/fixtures/info-list__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/label-box__default.html b/blocks/src/test/fixtures/label-box__default.html new file mode 100644 index 000000000..018b3ef72 --- /dev/null +++ b/blocks/src/test/fixtures/label-box__default.html @@ -0,0 +1,5 @@ + +
Lorem ipsum dolor
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

+
+ diff --git a/blocks/src/test/fixtures/login-user-only__default.html b/blocks/src/test/fixtures/login-user-only__default.html new file mode 100644 index 000000000..c8f3a3213 --- /dev/null +++ b/blocks/src/test/fixtures/login-user-only__default.html @@ -0,0 +1,3 @@ + + + diff --git a/blocks/src/test/fixtures/micro-balloon__default.html b/blocks/src/test/fixtures/micro-balloon__default.html new file mode 100644 index 000000000..f63d23d48 --- /dev/null +++ b/blocks/src/test/fixtures/micro-balloon__default.html @@ -0,0 +1,3 @@ + +
microcopy balloon
+ diff --git a/blocks/src/test/fixtures/micro-text__default.html b/blocks/src/test/fixtures/micro-text__default.html new file mode 100644 index 000000000..fc16ab89e --- /dev/null +++ b/blocks/src/test/fixtures/micro-text__default.html @@ -0,0 +1,3 @@ + +
microcopy text
+ diff --git a/blocks/src/test/fixtures/navicard__default.html b/blocks/src/test/fixtures/navicard__default.html new file mode 100644 index 000000000..c13af968e --- /dev/null +++ b/blocks/src/test/fixtures/navicard__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/new-list__default.html b/blocks/src/test/fixtures/new-list__default.html new file mode 100644 index 000000000..1fce9dc64 --- /dev/null +++ b/blocks/src/test/fixtures/new-list__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/popular-list__default.html b/blocks/src/test/fixtures/popular-list__default.html new file mode 100644 index 000000000..c51787dea --- /dev/null +++ b/blocks/src/test/fixtures/popular-list__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/profile__default.html b/blocks/src/test/fixtures/profile__default.html new file mode 100644 index 000000000..baf65f213 --- /dev/null +++ b/blocks/src/test/fixtures/profile__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/radar__default.html b/blocks/src/test/fixtures/radar__default.html new file mode 100644 index 000000000..1be853c01 --- /dev/null +++ b/blocks/src/test/fixtures/radar__default.html @@ -0,0 +1,127 @@ + +
+ diff --git a/blocks/src/test/fixtures/rakuten-product-link__default.html b/blocks/src/test/fixtures/rakuten-product-link__default.html new file mode 100644 index 000000000..4ec206446 --- /dev/null +++ b/blocks/src/test/fixtures/rakuten-product-link__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/ranking__default.html b/blocks/src/test/fixtures/ranking__default.html new file mode 100644 index 000000000..33c082316 --- /dev/null +++ b/blocks/src/test/fixtures/ranking__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/search-box__default.html b/blocks/src/test/fixtures/search-box__default.html new file mode 100644 index 000000000..1580e0a5d --- /dev/null +++ b/blocks/src/test/fixtures/search-box__default.html @@ -0,0 +1,3 @@ + + + diff --git a/blocks/src/test/fixtures/sticky-box__default.html b/blocks/src/test/fixtures/sticky-box__default.html new file mode 100644 index 000000000..8b3a29fcf --- /dev/null +++ b/blocks/src/test/fixtures/sticky-box__default.html @@ -0,0 +1,5 @@ + +
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

+
+ diff --git a/blocks/src/test/fixtures/tab-box__default.html b/blocks/src/test/fixtures/tab-box__default.html new file mode 100644 index 000000000..699019229 --- /dev/null +++ b/blocks/src/test/fixtures/tab-box__default.html @@ -0,0 +1,5 @@ + +
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

+
+ diff --git a/blocks/src/test/fixtures/tab-caption-box__default.html b/blocks/src/test/fixtures/tab-caption-box__default.html new file mode 100644 index 000000000..affb1a787 --- /dev/null +++ b/blocks/src/test/fixtures/tab-caption-box__default.html @@ -0,0 +1,5 @@ + +
Lorem ipsum dolor
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

+
+ diff --git a/blocks/src/test/fixtures/tab-item__default.html b/blocks/src/test/fixtures/tab-item__default.html new file mode 100644 index 000000000..1abcb7442 --- /dev/null +++ b/blocks/src/test/fixtures/tab-item__default.html @@ -0,0 +1,3 @@ + +
+ diff --git a/blocks/src/test/fixtures/tab__default.html b/blocks/src/test/fixtures/tab__default.html new file mode 100644 index 000000000..effc7f120 --- /dev/null +++ b/blocks/src/test/fixtures/tab__default.html @@ -0,0 +1,3 @@ + +
  • Tab 1
  • Tab 2
+ diff --git a/blocks/src/test/fixtures/template__default.html b/blocks/src/test/fixtures/template__default.html new file mode 100644 index 000000000..ba7dc0e88 --- /dev/null +++ b/blocks/src/test/fixtures/template__default.html @@ -0,0 +1 @@ + diff --git a/blocks/src/test/fixtures/timeline-item__default.html b/blocks/src/test/fixtures/timeline-item__default.html new file mode 100644 index 000000000..a93c62153 --- /dev/null +++ b/blocks/src/test/fixtures/timeline-item__default.html @@ -0,0 +1,3 @@ + +
  • ラベル
    タイトル
  • + diff --git a/blocks/src/test/fixtures/timeline__default.html b/blocks/src/test/fixtures/timeline__default.html new file mode 100644 index 000000000..6bb05e527 --- /dev/null +++ b/blocks/src/test/fixtures/timeline__default.html @@ -0,0 +1,19 @@ + +
    Title
      +
    • STEP 1
      Volutpat consequat mauris nunc congue
      +

      Adipiscing enim eu turpis egestas pretium aenean pharetra magna ac.

      +
    • + + + +
    • STEP 2
      Elementum curabitur vitae nunc sed
      +

      Suspendisse in est ante in nibh mauris cursus mattis molestie.

      +
    • + + + +
    • STEP 3
      Adipiscing bibendum est ultricies integer
      +

      Donec ac odio tempor orci dapibus ultrices in iaculis nunc.

      +
    • +
    + diff --git a/blocks/src/test/fixtures/toggle-box__default.html b/blocks/src/test/fixtures/toggle-box__default.html new file mode 100644 index 000000000..430c83846 --- /dev/null +++ b/blocks/src/test/fixtures/toggle-box__default.html @@ -0,0 +1,5 @@ + +
    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius facilis in molestiae quod! Aut doloribus est illum iure porro sunt. Eius illo iusto maxime nihil possimus quae tempora voluptas voluptates.

    +
    +