feat(frontend): replace article system with Zibll 9.0
This commit is contained in:
+31
-7
@@ -8,16 +8,40 @@ $env:ZIBLL_THEME_PATH='C:\Users\Xing\Desktop\zibll'
|
||||
docker compose -f tests/visual/docker-compose.zibll.yml up -d
|
||||
docker compose -f tests/visual/docker-compose.zibll.yml run --rm wp core install --url=https://localhost:9443 --title='Zibll Reference' --admin_user=visual_admin --admin_password='AKSRT-Visual-2026!' --admin_email=visual@example.test --skip-email
|
||||
docker compose -f tests/visual/docker-compose.zibll.yml run --rm wp theme activate zibll
|
||||
docker compose -f tests/visual/docker-compose.zibll.yml run --rm wp eval-file /visual-fixtures/article-fixtures.php create
|
||||
~~~
|
||||
|
||||
Create or clean AKSRT fixtures inside its WordPress container:
|
||||
Run the same theme-neutral article generator inside the AKSRT WordPress
|
||||
container. Mount `tests/visual/` read-only at `/visual-fixtures` in that stack:
|
||||
|
||||
~~~powershell
|
||||
wp eval-file wp-content/themes/AKSRT-theme/tools/wp-cli-visual-fixtures.php create
|
||||
wp eval-file wp-content/themes/AKSRT-theme/tools/wp-cli-visual-fixtures.php cleanup
|
||||
wp eval-file /visual-fixtures/article-fixtures.php create
|
||||
wp eval-file /visual-fixtures/article-fixtures.php cleanup
|
||||
~~~
|
||||
|
||||
Use tests/fixtures/widget-golden-v1.json for the 222 component captures and
|
||||
tests/fixtures/page-visual-matrix-v1.json for page-level captures. Remove
|
||||
the reference stack with docker compose down -v only after fixture cleanup
|
||||
and screenshot verification.
|
||||
The shared generator creates the same authors, category, tag, dates, images,
|
||||
featured/no-image/multi-image/first-image/external-cover posts, slide and video
|
||||
metadata, pay/VIP states, sticky state, and interaction counters in both sites.
|
||||
Fixture-only Zibll and AKSRT metadata are written together so the rendered
|
||||
business state is identical without adding compatibility code to either theme.
|
||||
|
||||
Use `tests/visual/article-visual-matrix-v1.json` for the article-only captures.
|
||||
Every reference/candidate pair must record the screenshot, DOM, computed styles,
|
||||
bounding boxes, console messages, and failed network requests. The matrix pins
|
||||
1440, 1024, 768, 767, 641, 640, and 390 widths across light/dark,
|
||||
sidebar/no-sidebar, list/card modes, media states, and all pagination states.
|
||||
|
||||
The acceptance gate is at most 1 CSS px geometry delta and 1.5% pixel
|
||||
difference, with no visible mismatch, console error, unexpected failed request,
|
||||
or critical/serious accessibility issue.
|
||||
|
||||
Clean the reference fixture before removing its volumes:
|
||||
|
||||
~~~powershell
|
||||
docker compose -f tests/visual/docker-compose.zibll.yml run --rm wp eval-file /visual-fixtures/article-fixtures.php cleanup
|
||||
docker compose -f tests/visual/docker-compose.zibll.yml down -v
|
||||
~~~
|
||||
|
||||
The older `tools/wp-cli-visual-fixtures.php`, widget golden file, and broad page
|
||||
matrix remain dedicated to non-article component regression tests and are not
|
||||
the truth source for this replacement.
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme-neutral article fixtures shared by the Zibll and AKSRT visual sites.
|
||||
*
|
||||
* Usage: wp eval-file /visual-fixtures/article-fixtures.php create|cleanup
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!defined('WP_CLI') || !WP_CLI) {
|
||||
return;
|
||||
}
|
||||
|
||||
$action = sanitize_key((string) ($args[0] ?? ''));
|
||||
$manifest_key = 'zibll_article_visual_fixture_v1';
|
||||
$prefix = 'zibll_article_v1_';
|
||||
|
||||
if (!in_array($action, ['create', 'cleanup'], true)) {
|
||||
WP_CLI::error('Expected create or cleanup.');
|
||||
}
|
||||
|
||||
$cleanup = static function (array $manifest) use ($manifest_key): void {
|
||||
require_once ABSPATH . 'wp-admin/includes/user.php';
|
||||
foreach (array_reverse((array) ($manifest['posts'] ?? [])) as $post_id) {
|
||||
unstick_post((int) $post_id);
|
||||
wp_delete_post((int) $post_id, true);
|
||||
}
|
||||
foreach (array_reverse((array) ($manifest['attachments'] ?? [])) as $attachment_id) {
|
||||
wp_delete_attachment((int) $attachment_id, true);
|
||||
}
|
||||
$upload = wp_upload_dir();
|
||||
$upload_root = wp_normalize_path((string) ($upload['basedir'] ?? ''));
|
||||
foreach (array_reverse((array) ($manifest['files'] ?? [])) as $file) {
|
||||
$file = wp_normalize_path((string) $file);
|
||||
if ($upload_root !== '' && str_starts_with($file, trailingslashit($upload_root)) && is_file($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
foreach (array_reverse((array) ($manifest['terms'] ?? [])) as $term) {
|
||||
wp_delete_term((int) $term['id'], (string) $term['taxonomy']);
|
||||
}
|
||||
foreach (array_reverse((array) ($manifest['users'] ?? [])) as $user_id) {
|
||||
wp_delete_user((int) $user_id);
|
||||
}
|
||||
foreach ((array) ($manifest['options'] ?? []) as $name => $state) {
|
||||
if (!empty($state['exists'])) {
|
||||
update_option((string) $name, $state['value'], false);
|
||||
} else {
|
||||
delete_option((string) $name);
|
||||
}
|
||||
}
|
||||
delete_option($manifest_key);
|
||||
};
|
||||
|
||||
$existing = get_option($manifest_key, []);
|
||||
if ($action === 'cleanup') {
|
||||
if (!is_array($existing) || !$existing) {
|
||||
WP_CLI::success('No article visual fixtures found.');
|
||||
return;
|
||||
}
|
||||
$cleanup($existing);
|
||||
WP_CLI::success('Article visual fixtures removed.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($existing) && $existing) {
|
||||
WP_CLI::error('Fixtures already exist. Run cleanup first.');
|
||||
}
|
||||
|
||||
$manifest = [
|
||||
'created_at' => gmdate('c'),
|
||||
'users' => [],
|
||||
'terms' => [],
|
||||
'attachments' => [],
|
||||
'posts' => [],
|
||||
'files' => [],
|
||||
'options' => [],
|
||||
];
|
||||
foreach (['aksrt_settings', 'zibll_options'] as $option_name) {
|
||||
$manifest['options'][$option_name] = [
|
||||
'exists' => get_option($option_name, null) !== null,
|
||||
'value' => get_option($option_name),
|
||||
];
|
||||
}
|
||||
update_option($manifest_key, $manifest, false);
|
||||
|
||||
try {
|
||||
$visual_options = [
|
||||
'list_type' => 'thumb',
|
||||
'list_show_type' => 'separate',
|
||||
'list_list_option' => ['style' => 'null', 'img_position' => 'left', 'scale' => 70],
|
||||
'list_card_option' => ['style' => 'null', 'scale' => 70],
|
||||
'post_list_author' => true,
|
||||
'post_list_time' => true,
|
||||
'post_time_source' => 'modified',
|
||||
'list_meta_show' => 'like',
|
||||
'list_badge_show' => ['pay', 'cat', 'tag'],
|
||||
'list_thumb_slides_s' => true,
|
||||
'list_thumb_video_s' => true,
|
||||
'list_thumb_video_mute_s' => true,
|
||||
'thumb_postfirstimg_s' => true,
|
||||
'thumb_catimg_s' => true,
|
||||
'list_thumb_fit' => '',
|
||||
'paging_ajax_s' => '1',
|
||||
'paging_ajax_ias_s' => true,
|
||||
'ias_max' => 3,
|
||||
'post_related_s' => true,
|
||||
'post_related_type' => 'img',
|
||||
'post_related_n' => 6,
|
||||
'post_related_orderby' => 'views',
|
||||
'related_title' => '相关推荐',
|
||||
];
|
||||
foreach (['aksrt_settings', 'zibll_options'] as $option_name) {
|
||||
$current = get_option($option_name, []);
|
||||
update_option($option_name, array_merge(is_array($current) ? $current : [], $visual_options), false);
|
||||
}
|
||||
|
||||
$authors = [
|
||||
['login' => $prefix . 'author_a', 'name' => '视觉作者甲'],
|
||||
['login' => $prefix . 'author_b', 'name' => '视觉作者乙'],
|
||||
];
|
||||
$author_ids = [];
|
||||
foreach ($authors as $author) {
|
||||
$user_id = wp_insert_user([
|
||||
'user_login' => $author['login'],
|
||||
'user_pass' => 'AKSRT-Visual-2026!',
|
||||
'user_email' => $author['login'] . '@example.test',
|
||||
'display_name' => $author['name'],
|
||||
'description' => '固定作者简介,用于文章卡片视觉对比。',
|
||||
'role' => 'author',
|
||||
]);
|
||||
if (is_wp_error($user_id)) {
|
||||
throw new RuntimeException($user_id->get_error_message());
|
||||
}
|
||||
$author_ids[] = (int) $user_id;
|
||||
$manifest['users'][] = (int) $user_id;
|
||||
}
|
||||
|
||||
$category = wp_insert_term('视觉文章', 'category', ['slug' => 'zibll-article-fixture']);
|
||||
$tag = wp_insert_term('视觉标签', 'post_tag', ['slug' => 'zibll-visual-tag']);
|
||||
if (is_wp_error($category) || is_wp_error($tag)) {
|
||||
throw new RuntimeException('Unable to create article fixture terms.');
|
||||
}
|
||||
$category_id = (int) $category['term_id'];
|
||||
$tag_id = (int) $tag['term_id'];
|
||||
$manifest['terms'][] = ['id' => $category_id, 'taxonomy' => 'category'];
|
||||
$manifest['terms'][] = ['id' => $tag_id, 'taxonomy' => 'post_tag'];
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
$upload = wp_upload_dir();
|
||||
if (!empty($upload['error'])) {
|
||||
throw new RuntimeException((string) $upload['error']);
|
||||
}
|
||||
$attachment_ids = [];
|
||||
$colors = [
|
||||
[240, 68, 148],
|
||||
[58, 134, 255],
|
||||
[92, 191, 147],
|
||||
[255, 175, 56],
|
||||
[126, 87, 194],
|
||||
];
|
||||
foreach ($colors as $index => $rgb) {
|
||||
$filename = $prefix . 'image-' . ($index + 1) . '.jpg';
|
||||
$filepath = trailingslashit($upload['path']) . $filename;
|
||||
if (function_exists('imagecreatetruecolor')) {
|
||||
$image = imagecreatetruecolor(1200, 800);
|
||||
$background = imagecolorallocate($image, $rgb[0], $rgb[1], $rgb[2]);
|
||||
$foreground = imagecolorallocate($image, 255, 255, 255);
|
||||
imagefill($image, 0, 0, $background);
|
||||
imagestring($image, 5, 48, 48, 'Zibll 9.0 Article Fixture ' . ($index + 1), $foreground);
|
||||
imagejpeg($image, $filepath, 92);
|
||||
imagedestroy($image);
|
||||
} else {
|
||||
$pixel = base64_decode('/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAP//////////////////////////////////////////////////////////////////////////////////////2wBDAf//////////////////////////////////////////////////////////////////////////////////////wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAX/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAEf/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABBQJ//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPwF//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAgEBPwF//8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQAGPwJ//8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABPyF//9oADAMBAAIAAwAAABAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPxB//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAgEBPxB//8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABPxB//9k=', true);
|
||||
file_put_contents($filepath, $pixel);
|
||||
}
|
||||
$attachment_id = wp_insert_attachment([
|
||||
'post_mime_type' => 'image/jpeg',
|
||||
'post_title' => '视觉图片 ' . ($index + 1),
|
||||
'post_status' => 'inherit',
|
||||
], $filepath);
|
||||
if (is_wp_error($attachment_id)) {
|
||||
throw new RuntimeException($attachment_id->get_error_message());
|
||||
}
|
||||
$attachment_id = (int) $attachment_id;
|
||||
wp_update_attachment_metadata($attachment_id, wp_generate_attachment_metadata($attachment_id, $filepath));
|
||||
$attachment_ids[] = $attachment_id;
|
||||
$manifest['attachments'][] = $attachment_id;
|
||||
}
|
||||
|
||||
$image_urls = array_map(static fn(int $id): string => (string) wp_get_attachment_image_url($id, 'full'), $attachment_ids);
|
||||
$video_path = trailingslashit($upload['path']) . $prefix . 'fixture-video.mp4';
|
||||
file_put_contents($video_path, '');
|
||||
$manifest['files'][] = $video_path;
|
||||
$video_url = trailingslashit($upload['url']) . basename($video_path);
|
||||
$term_other = (array) get_term_meta($category_id, 'zib_other_data', true);
|
||||
$term_other['cover_image'] = $image_urls[4];
|
||||
update_term_meta($category_id, 'zib_other_data', $term_other);
|
||||
update_term_meta($category_id, 'cover_image', $image_urls[4]);
|
||||
update_term_meta($category_id, 'aksrt_category_cover_id', $attachment_ids[4]);
|
||||
|
||||
$scenarios = [
|
||||
['slug' => 'featured', 'title' => '特色图文章:标准列表与卡片基线', 'featured' => 0],
|
||||
['slug' => 'no-image', 'title' => '无图长标题文章用于检查纯文字模式与两行截断', 'no_image' => true],
|
||||
['slug' => 'multi', 'title' => '多图文章:四张真实内容图片', 'featured' => 1, 'gallery' => true],
|
||||
['slug' => 'external', 'title' => '自定义外链封面文章', 'external' => 2],
|
||||
['slug' => 'slides', 'title' => '幻灯片封面文章', 'featured' => 3, 'slides' => true],
|
||||
['slug' => 'video', 'title' => '视频悬停封面文章', 'featured' => 4, 'video' => true],
|
||||
['slug' => 'paid', 'title' => '付费阅读文章价格徽章', 'featured' => 0, 'pay' => 'reading'],
|
||||
['slug' => 'vip', 'title' => '会员专属文章 VIP 徽章', 'featured' => 1, 'pay' => 'vip'],
|
||||
['slug' => 'first-image', 'title' => '文章首图作为缩略图', 'first_image' => 3],
|
||||
];
|
||||
foreach ($scenarios as $index => $scenario) {
|
||||
$content = '<p>固定摘要正文,用于 Zibll 与 AKSRT 的文章列表逐像素比较。</p>';
|
||||
if (!empty($scenario['gallery'])) {
|
||||
$content .= implode('', array_map(static fn(string $url): string => '<img src="' . esc_url($url) . '" alt="">', array_slice($image_urls, 0, 4)));
|
||||
} elseif (isset($scenario['first_image'])) {
|
||||
$content .= '<img src="' . esc_url($image_urls[(int) $scenario['first_image']]) . '" alt="">';
|
||||
}
|
||||
$post_id = wp_insert_post([
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'post_author' => $author_ids[$index % 2],
|
||||
'post_title' => $scenario['title'],
|
||||
'post_name' => $prefix . $scenario['slug'],
|
||||
'post_excerpt' => '固定文章摘要用于检查字号、行高、留白和截断。',
|
||||
'post_content' => $content,
|
||||
'post_date' => gmdate('Y-m-d H:i:s', strtotime('2026-07-01 08:00:00') + ($index * DAY_IN_SECONDS)),
|
||||
'post_date_gmt' => gmdate('Y-m-d H:i:s', strtotime('2026-07-01 00:00:00') + ($index * DAY_IN_SECONDS)),
|
||||
], true);
|
||||
if (is_wp_error($post_id)) {
|
||||
throw new RuntimeException($post_id->get_error_message());
|
||||
}
|
||||
$post_id = (int) $post_id;
|
||||
$manifest['posts'][] = $post_id;
|
||||
wp_set_post_terms($post_id, [$category_id], 'category');
|
||||
wp_set_post_terms($post_id, [$tag_id], 'post_tag');
|
||||
if (isset($scenario['featured'])) {
|
||||
set_post_thumbnail($post_id, $attachment_ids[(int) $scenario['featured']]);
|
||||
}
|
||||
if (!empty($scenario['gallery'])) {
|
||||
set_post_format($post_id, 'gallery');
|
||||
}
|
||||
|
||||
$post_meta = [
|
||||
'subtitle' => ' · 固定副标题',
|
||||
];
|
||||
$zib_meta = (array) get_post_meta($post_id, 'zib_other_data', true);
|
||||
$zib_meta['subtitle'] = $post_meta['subtitle'];
|
||||
if (isset($scenario['external'])) {
|
||||
$post_meta['thumbnail_url'] = $image_urls[(int) $scenario['external']];
|
||||
$zib_meta['thumbnail_url'] = $post_meta['thumbnail_url'];
|
||||
}
|
||||
if (!empty($scenario['slides'])) {
|
||||
$post_meta['featured_slide'] = implode(',', array_slice($attachment_ids, 0, 4));
|
||||
$zib_meta['featured_slide'] = $post_meta['featured_slide'];
|
||||
}
|
||||
if (!empty($scenario['video'])) {
|
||||
$post_meta['featured_video'] = $video_url;
|
||||
$zib_meta['featured_video'] = $video_url;
|
||||
}
|
||||
$zib_meta['views'] = 1200 + ($index * 137);
|
||||
$zib_meta['like'] = 30 + ($index * 7);
|
||||
update_post_meta($post_id, 'zib_other_data', $zib_meta);
|
||||
update_post_meta($post_id, 'aksrt_post_meta', $post_meta);
|
||||
update_post_meta($post_id, 'aksrt_post_views', $zib_meta['views']);
|
||||
update_post_meta($post_id, '_aksrt_like_count', $zib_meta['like']);
|
||||
update_post_meta($post_id, '_aksrt_favorite_count', 10 + $index);
|
||||
|
||||
$pay_type = (string) ($scenario['pay'] ?? 'no');
|
||||
$pay_limit = $pay_type === 'vip' ? 2 : 0;
|
||||
$pay_price = $pay_type === 'reading' ? 19.9 : 0;
|
||||
update_post_meta($post_id, '_aksrt_pay', [
|
||||
'pay_type' => $pay_type,
|
||||
'pay_modo' => '0',
|
||||
'price' => $pay_price,
|
||||
'pay_limit' => $pay_limit,
|
||||
]);
|
||||
update_post_meta($post_id, 'posts_zibpay', [
|
||||
'pay_type' => $pay_type,
|
||||
'pay_modo' => '0',
|
||||
'pay_price' => $pay_price,
|
||||
'pay_limit' => $pay_limit,
|
||||
]);
|
||||
}
|
||||
if ($manifest['posts']) {
|
||||
stick_post((int) $manifest['posts'][0]);
|
||||
}
|
||||
update_option($manifest_key, $manifest, false);
|
||||
WP_CLI::success('Created identical Zibll/AKSRT article fixtures.');
|
||||
} catch (Throwable $error) {
|
||||
$cleanup($manifest);
|
||||
WP_CLI::error('Fixture creation rolled back: ' . $error->getMessage());
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"schema": "aksrt.zibll-article-visual-matrix.v1",
|
||||
"reference": "https://localhost:9443",
|
||||
"candidate": "https://localhost",
|
||||
"fixture": "/visual-fixtures/article-fixtures.php",
|
||||
"viewports": [
|
||||
{ "id": "desktop-wide", "width": 1440, "height": 1100 },
|
||||
{ "id": "desktop", "width": 1024, "height": 1000 },
|
||||
{ "id": "tablet", "width": 768, "height": 1000 },
|
||||
{ "id": "breakpoint-767", "width": 767, "height": 1000 },
|
||||
{ "id": "breakpoint-641", "width": 641, "height": 960 },
|
||||
{ "id": "breakpoint-640", "width": 640, "height": 960 },
|
||||
{ "id": "mobile", "width": 390, "height": 844 }
|
||||
],
|
||||
"colorSchemes": ["light", "dark"],
|
||||
"layouts": ["sidebar", "no-sidebar"],
|
||||
"listModes": ["thumb", "text", "thumb_if_has", "card"],
|
||||
"styles": ["default", "style2", "style3"],
|
||||
"routes": [
|
||||
{ "id": "home", "path": "/", "states": ["default", "hover", "loading", "error"] },
|
||||
{ "id": "archive", "path": "/?post_type=post", "states": ["default", "numbered", "load-more", "infinite", "no-more"] },
|
||||
{ "id": "category", "path": "/category/zibll-article-fixture/", "states": ["default", "empty"] },
|
||||
{ "id": "tag", "path": "/tag/zibll-visual-tag/", "states": ["default", "empty"] },
|
||||
{ "id": "search", "path": "/?s=视觉", "states": ["default", "empty"] },
|
||||
{ "id": "author-a", "path": "/author/zibll_article_v1_author_a/", "states": ["default", "numbered", "load-more"] },
|
||||
{ "id": "single-related", "path": "/zibll_article_v1_featured/", "states": ["img", "list", "text"] }
|
||||
],
|
||||
"postScenarios": ["featured", "no-image", "multi", "external", "slides", "video", "paid", "vip", "first-image"],
|
||||
"capture": {
|
||||
"selector": ".posts-row, .profile-list, .relates",
|
||||
"artifacts": ["screenshot", "dom", "computed-style", "bounding-box", "console", "network"],
|
||||
"computedProperties": [
|
||||
"display", "position", "width", "height", "margin", "padding", "gap", "font-size", "line-height",
|
||||
"border-radius", "box-shadow", "background-color", "color", "object-fit"
|
||||
]
|
||||
},
|
||||
"acceptance": {
|
||||
"dimensionDeltaPxMax": 1,
|
||||
"pixelDifferencePercentMax": 1.5,
|
||||
"consoleErrorsMax": 0,
|
||||
"unexpectedNetworkFailuresMax": 0,
|
||||
"a11yCriticalMax": 0,
|
||||
"a11ySeriousMax": 0
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,10 @@ services:
|
||||
source: ${ZIBLL_THEME_PATH}
|
||||
target: /var/www/html/wp-content/themes/zibll
|
||||
read_only: true
|
||||
- type: bind
|
||||
source: .
|
||||
target: /visual-fixtures
|
||||
read_only: true
|
||||
|
||||
caddy:
|
||||
image: caddy:2.8-alpine
|
||||
@@ -62,6 +66,10 @@ services:
|
||||
source: ${ZIBLL_THEME_PATH}
|
||||
target: /var/www/html/wp-content/themes/zibll
|
||||
read_only: true
|
||||
- type: bind
|
||||
source: .
|
||||
target: /visual-fixtures
|
||||
read_only: true
|
||||
entrypoint: ["wp"]
|
||||
|
||||
volumes:
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"schema": "aksrt.zibll-article-baseline.v1",
|
||||
"referencePath": "C:\\Users\\Xing\\Desktop\\zibll",
|
||||
"theme": "Zibll",
|
||||
"version": "9.0",
|
||||
"capturedAt": "2026-08-18",
|
||||
"files": {
|
||||
"style.css": {
|
||||
"bytes": 927,
|
||||
"sha256": "4e9e319d92cea3862aefd520d5519b81ea22f9147b203b77eafedd0447148aea"
|
||||
},
|
||||
"css/main.css": {
|
||||
"bytes": 292331,
|
||||
"sha256": "87ff1aeaf78369934c875422ab3ebc13ad65f30de78f6caabf091c780a27a158"
|
||||
},
|
||||
"inc/functions/zib-posts-list.php": {
|
||||
"bytes": 34255,
|
||||
"sha256": "ced813182c0b0fc5847ca5c04a57fa4379581ace13a6d40dfb7dfabb55e13ae4"
|
||||
},
|
||||
"inc/options/admin-options.php": {
|
||||
"bytes": 700302,
|
||||
"sha256": "3d2cf89bc01a1ec98297d16c14023a820170568e716daedf421fd0386b38486b"
|
||||
},
|
||||
"js/main.min.js": {
|
||||
"bytes": 74446,
|
||||
"sha256": "0fdd02246a5b68480d11ced1dfd2bfa19788fef16ba069eb021fcfb5cfaf60f9"
|
||||
},
|
||||
"js/libs/grade.min.js": {
|
||||
"bytes": 4833,
|
||||
"sha256": "8d74bf6ab34f4c44203766cc639818c4daf0a7c1978ddefb4ebfde9daaa16040"
|
||||
}
|
||||
},
|
||||
"excluded": [
|
||||
"topics taxonomy",
|
||||
"single article body",
|
||||
"comments",
|
||||
"header and footer"
|
||||
]
|
||||
}
|
||||
@@ -7,79 +7,258 @@ const test = require('node:test');
|
||||
|
||||
const root = path.resolve(__dirname, '..', '..');
|
||||
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
|
||||
const join = (files) => files.map(read).join('\n');
|
||||
|
||||
test('post list DOM follows the Zibll flex and multi-image contract', () => {
|
||||
const articleFiles = [
|
||||
'src/Settings/PostDisplay.php',
|
||||
'src/Admin/Schema/PostList/SchemaPostListList.php',
|
||||
'src/Admin/Schema/SchemaPostList.php',
|
||||
'assets/admin/src/schema/sections/post-list/list.js',
|
||||
'assets/admin/src/schema/sections/post-list/thumb.js',
|
||||
'assets/admin/src/schema/sections/post-list/page.js',
|
||||
'inc/helpers/posts-renderer/config.php',
|
||||
'inc/helpers/posts-renderer/post-data.php',
|
||||
'inc/helpers/posts-renderer/markup.php',
|
||||
'inc/helpers/aksrt-archive.php',
|
||||
'inc/helpers/aksrt-single-render.php',
|
||||
];
|
||||
|
||||
test('the article stream exposes only the new typed renderer contract', () => {
|
||||
const markup = read('inc/helpers/posts-renderer/markup.php');
|
||||
const consumers = join([
|
||||
'index.php',
|
||||
'category.php',
|
||||
'tag.php',
|
||||
'search.php',
|
||||
'archive-resources.php',
|
||||
'src/Admin/Admin.php',
|
||||
'src/Admin/GlobalController.php',
|
||||
'src/Core/Shortcodes.php',
|
||||
'src/WidgetSystem/PostRenderer.php',
|
||||
'inc/helpers/homepage/content.php',
|
||||
'templates/parts/user-home/panels-core.php',
|
||||
]);
|
||||
|
||||
assert.match(markup, /function aksrt_render_post_list\(array \$args = \[\], \?WP_Query \$query = null, bool \$echo = true\): string/);
|
||||
assert.doesNotMatch(consumers, /function_exists\(['"]aksrt_render_post_list/);
|
||||
assert.doesNotMatch(consumers, /aksrt_render_post_list\(\s*\$query\s*,/);
|
||||
assert.doesNotMatch(consumers, /content-post-card|aksrt_homepage_render_post_card/);
|
||||
});
|
||||
|
||||
test('settings use Zibll list modes, grouped options, and destructive related keys', () => {
|
||||
const source = join(articleFiles);
|
||||
const listSchema = read('assets/admin/src/schema/sections/post-list/list.js');
|
||||
const pageSchema = read('assets/admin/src/schema/sections/post-list/page.js');
|
||||
const legacyKeys = [
|
||||
'post_card_style',
|
||||
'list_list_style',
|
||||
'list_card_style',
|
||||
'grid-cms',
|
||||
'large_thumb',
|
||||
'multi_thumb',
|
||||
'layout_override',
|
||||
'homepage_card_style',
|
||||
'homepage_multi_thumb',
|
||||
'homepage_default_view',
|
||||
'post_related_enabled',
|
||||
'post_related_count',
|
||||
'post_related_style',
|
||||
'post_related_source',
|
||||
'post_related_title',
|
||||
];
|
||||
|
||||
assert.match(listSchema, /list_type: 'thumb'/);
|
||||
for (const value of ['text', 'thumb', 'thumb_if_has', 'card']) {
|
||||
assert.match(listSchema, new RegExp(`value: '${value}'`));
|
||||
}
|
||||
assert.match(listSchema, /list_list_option: \{ style: 'null', img_position: 'left', scale: 70 \}/);
|
||||
assert.match(listSchema, /list_card_option: \{ style: 'null', scale: 70 \}/);
|
||||
assert.match(pageSchema, /post_related_s: true/);
|
||||
assert.match(pageSchema, /post_related_type: 'img'/);
|
||||
assert.match(pageSchema, /related_title: '相关推荐'/);
|
||||
assert.match(pageSchema, /post_related_n: 6/);
|
||||
assert.match(pageSchema, /post_related_orderby: 'views'/);
|
||||
for (const key of legacyKeys) {
|
||||
assert.equal(source.includes(key), false, `legacy article key remains: ${key}`);
|
||||
}
|
||||
assert.doesNotMatch(source, /list_card_topics|is_topics|\btopics\b/);
|
||||
});
|
||||
|
||||
test('forced mode wins and thumb_if_has ignores spare and lazy placeholders', () => {
|
||||
const config = read('inc/helpers/posts-renderer/config.php');
|
||||
const data = read('inc/helpers/posts-renderer/post-data.php');
|
||||
|
||||
const forced = config.indexOf("$is_forced = in_array($forced_type, ['list', 'card'], true)");
|
||||
const globalCard = config.indexOf("$list_type === 'card'");
|
||||
const contextCard = config.indexOf("$list['list_card_tag']");
|
||||
const categoryCard = config.indexOf("$list['list_card_cat']");
|
||||
assert.ok(forced >= 0 && forced < globalCard && globalCard < contextCard && contextCard < categoryCard);
|
||||
assert.match(config, /\$is_card = \$forced_type === 'card' \|\| \(!\$is_forced/);
|
||||
|
||||
const hasReal = config.indexOf("$has_real = $primary !== '';");
|
||||
const spareCall = config.lastIndexOf('aksrt_renderer_spare_image($thumb)');
|
||||
const lazy = config.lastIndexOf('aksrt_get_lazy_thumb');
|
||||
assert.ok(hasReal >= 0 && hasReal < spareCall && spareCall < lazy);
|
||||
assert.match(data, /'thumb_if_has' && empty\(\$images\['has_real'\]\)/);
|
||||
assert.match(data, /count\(\$gallery\) > 2/);
|
||||
assert.match(data, /has_post_format\(\['image', 'gallery'\]/);
|
||||
});
|
||||
|
||||
test('image resolution counts only content images and applies the configured WordPress size', () => {
|
||||
const config = read('inc/helpers/posts-renderer/config.php');
|
||||
const data = read('inc/helpers/posts-renderer/post-data.php');
|
||||
const thumbSchema = read('assets/admin/src/schema/sections/post-list/thumb.js');
|
||||
const phpSchema = read('src/Admin/Schema/SchemaPostList.php');
|
||||
|
||||
assert.match(config, /function aksrt_renderer_content_images\(int \$post_id, string \$size\)/);
|
||||
assert.match(config, /strip_shortcodes\(\(string\) get_post_field\('post_content'/);
|
||||
assert.match(config, /\$slides = aksrt_renderer_curated_images\(\$post_id, \$size\);\s*\$gallery = aksrt_renderer_content_images\(\$post_id, \$size\);/);
|
||||
assert.match(config, /get_post_thumbnail_id\(\$post_id\).*aksrt_renderer_sized_image\(\(string\) \$thumbnail_id, \$size\)/s);
|
||||
assert.match(config, /aksrt_renderer_category_image\(\$post_id, \$size\)/);
|
||||
assert.doesNotMatch(config, /aksrt_get_post_gallery_images|cover_images|featured_video_episode|_aksrt_featured_video|_video_url|_aksrt_thumbnail_url|_thumbnail_url/);
|
||||
assert.doesNotMatch(config, /\['aksrt_category_cover_id',/);
|
||||
assert.match(data, /'gallery_count'\s*=>\s*count\(\$content_images\)/);
|
||||
assert.match(data, /\(int\) \$data\['gallery_count'\] - 4/);
|
||||
assert.match(thumbSchema, /spareThumbnailDefault = \[\{ img: `\$\{themeRoot\}\/assets\/img\/thumbnail\.svg` \}\]/);
|
||||
assert.match(phpSchema, /'spare_thumbnail'.*'default' => \[\['img' => get_template_directory_uri\(\) \. '\/assets\/img\/thumbnail\.svg'\]\]/);
|
||||
});
|
||||
|
||||
test('list, card, media, badge and Mini DOM follow dedicated Zibll structures', () => {
|
||||
const markup = read('inc/helpers/posts-renderer/markup.php');
|
||||
const data = read('inc/helpers/posts-renderer/post-data.php');
|
||||
const cardStart = markup.indexOf('function aksrt_renderer_card');
|
||||
const miniStart = markup.indexOf('function aksrt_renderer_mini');
|
||||
const card = markup.slice(cardStart, miniStart);
|
||||
const card = markup.slice(markup.indexOf('function aksrt_renderer_card'), markup.indexOf('function aksrt_renderer_mini'));
|
||||
const mini = markup.slice(markup.indexOf('function aksrt_renderer_mini'), markup.indexOf('function aksrt_render_post'));
|
||||
|
||||
assert.match(markup, /\['posts-item', 'list', 'ajax-item', 'flex'/);
|
||||
assert.match(markup, /if \(!empty\(\$data\['is_mult_thumb'\]\)\)[\s\S]*?\$thumb = '';/);
|
||||
assert.doesNotMatch(card, /item-excerpt|renderer_excerpt_markup/);
|
||||
assert.match(data, /&& \$cfg\['mode'\] === 'list'/);
|
||||
assert.match(data, /<a class=\"thumb-items contain\"/);
|
||||
assert.match(markup, /\['posts-item', 'list', 'ajax-item'\]/);
|
||||
assert.match(markup, /\$classes\[\] = .*'flex xx'.*'flex'/s);
|
||||
assert.match(markup, /<posts class=/);
|
||||
assert.match(markup, /<div class="post-graphic/);
|
||||
assert.match(markup, /<div class="item-body flex xx flex1 jsb/);
|
||||
assert.doesNotMatch(card, /item-excerpt|renderer_excerpt_markup|thumb-items/);
|
||||
assert.match(data, /<div class="item-thumbnail/);
|
||||
assert.match(data, /relative zib-slider.*new-swiper item-thumbnail/s);
|
||||
assert.match(data, /swiper-slide.*gradient-bg.*data-opacity="0\.2"/s);
|
||||
assert.match(data, /\$fit = \$is_contain && !\$has_slides \? ' contain gradient-bg' : ''/);
|
||||
assert.match(data, /video-thumb-box.*data-post-thumb-video/s);
|
||||
assert.match(data, /class="thumb-items/);
|
||||
assert.match(data, /empty\(\$cfg\['is_category'\]\).*in_array\('cat'/s);
|
||||
assert.match(data, /empty\(\$cfg\['is_tag'\]\).*in_array\('tag'/s);
|
||||
assert.doesNotMatch(data, /meta-mobile-show/);
|
||||
|
||||
assert.match(mini, /<div class="mr10"><div class="item-thumbnail"><a/);
|
||||
assert.match(mini, /posts-mini-con flex xx flex1 jsb/);
|
||||
assert.match(mini, /\['c-red', 'c-yellow', 'c-purple', 'c-blue', 'c-green'\]/);
|
||||
assert.match(mini, /aksrt_renderer_pay_badge\(\$data, true\)/);
|
||||
assert.match(data, /meta-pay badg badg-sm mr6/);
|
||||
assert.doesNotMatch(mini, /posts-mini-row/);
|
||||
|
||||
assert.doesNotMatch(markup, /--posts-(?:list|card)-scale|<posts[^>]+style=/);
|
||||
assert.match(data, /\['c-blue', 'c-yellow', 'c-green', 'c-purple', 'c-red'\]/);
|
||||
assert.match(data, /查看更多分类文章/);
|
||||
assert.match(data, /usort\(\$tags,.*->count.*->count/s);
|
||||
assert.match(data, /查看此标签更多文章/);
|
||||
|
||||
const commentMeta = data.indexOf("aksrt_renderer_svg_icon('comment')");
|
||||
const viewMeta = data.indexOf("aksrt_renderer_svg_icon('view')", commentMeta);
|
||||
const likeMeta = data.indexOf("aksrt_renderer_svg_icon('like')", viewMeta);
|
||||
assert.ok(commentMeta >= 0 && commentMeta < viewMeta && viewMeta < likeMeta);
|
||||
assert.match(data, /comments_open.*close_comments/s);
|
||||
assert.match(data, /show_like.*post_type.*=== 'post'/s);
|
||||
assert.match(data, /<use xlink:href="#icon-/);
|
||||
});
|
||||
|
||||
test('homepage card mode keeps the Zibll inline-block three-column flow', () => {
|
||||
const css = read('assets/css/frontend/homepage-fixed/base-2.css');
|
||||
const responsive = read('assets/css/frontend/homepage-fixed/ajax-tab-error-state.css');
|
||||
const homepageScript = read('assets/js/homepage-fixed.js');
|
||||
const scripts = read('src/Core/ScriptsPart1b.php');
|
||||
const cardModeStart = css.indexOf('.aksrt-homepage__posts[data-view="card"] {');
|
||||
const cardItemStart = css.indexOf('.aksrt-homepage__posts[data-view="card"] > .posts-item {');
|
||||
const cardMode = css.slice(cardModeStart, cardItemStart);
|
||||
const cardItem = css.slice(cardItemStart, css.indexOf('\n}', cardItemStart) + 2);
|
||||
const visibilityStart = css.indexOf('VISIBILITY LOCK');
|
||||
const visibilityEnd = css.indexOf('/* Minimal flex utilities', visibilityStart);
|
||||
const visibility = css.slice(visibilityStart, visibilityEnd);
|
||||
test('post-card CSS owns the exact desktop and 767/640 responsive matrix', () => {
|
||||
const css = read('assets/css/frontend/post-card.css');
|
||||
const mobile767 = css.slice(css.indexOf('@media (max-width: 767px)'), css.indexOf('@media (max-width: 640px)'));
|
||||
const mobile640 = css.slice(css.indexOf('@media (max-width: 640px)'));
|
||||
|
||||
assert.match(cardMode, /display:\s*block/);
|
||||
assert.match(cardMode, /font-size:\s*0/);
|
||||
assert.match(cardItem, /width:\s*calc\(33\.333% - 16px\)/);
|
||||
assert.match(cardItem, /display:\s*inline-block/);
|
||||
assert.doesNotMatch(visibility, /\.posts-item[\s\S]*?display:\s*block\s*!important/);
|
||||
assert.match(scripts, /\$homepage_style_parts\s*=\s*\[/);
|
||||
assert.match(scripts, /filemtime\(\$part_path\)/);
|
||||
assert.doesNotMatch(scripts, /wp_enqueue_style\(\s*'aksrt-homepage-fixed',\s*\$base_uri\s*\.\s*'\/assets\/css\/frontend\/homepage-fixed\.css'/);
|
||||
|
||||
const tabletStart = responsive.indexOf('@media (max-width: 991.98px)');
|
||||
const mobileStart = responsive.indexOf('@media (max-width: 767px)');
|
||||
const smallMobileStart = responsive.indexOf('@media (max-width: 640px)');
|
||||
const tablet = responsive.slice(tabletStart, mobileStart);
|
||||
const mobile = responsive.slice(mobileStart, smallMobileStart);
|
||||
const smallMobile = responsive.slice(smallMobileStart);
|
||||
|
||||
assert.doesNotMatch(tablet, /data-view="card"/);
|
||||
assert.match(mobile, /data-view="card"[\s\S]*?width:\s*calc\(50% - 10px\)/);
|
||||
assert.match(mobile, /data-view="card"[\s\S]*?margin:\s*-5px/);
|
||||
assert.doesNotMatch(smallMobile, /data-view="card"[\s\S]*?width:\s*100%/);
|
||||
|
||||
assert.match(homepageScript, /var initialMode = getViewMode\(\)/);
|
||||
assert.match(homepageScript, /var renderedMode = activePanel \? activePanel\.getAttribute\('data-view'\)/);
|
||||
assert.match(homepageScript, /renderedMode !== initialMode[\s\S]*?requestHomepagePanel\(activePanel/);
|
||||
assert.match(css, /\.posts-row\s*\{[^}]*margin-right:\s*-8px;[^}]*margin-left:\s*-8px;/s);
|
||||
assert.match(css, /\.posts-item\.card\s*\{[^}]*width:\s*calc\(33\.333% - 16px\)/s);
|
||||
assert.match(css, /\.fluid-widget-wrap \.posts-item\.card,[\s\S]*?\.site-layout-1 \.posts-item\.card\s*\{[^}]*width:\s*calc\(25% - 16px\)/);
|
||||
assert.match(css, /\.site-layout-1 \.posts-item:not\(\.card\)\s*\{[^}]*width:\s*calc\(50% - 16px\)/s);
|
||||
assert.match(mobile767, /\.posts-item\.card\s*\{[^}]*width:\s*calc\(50% - 10px\)/s);
|
||||
assert.doesNotMatch(mobile767, /\.posts-mini\s*\{[^}]*width:\s*100%/s);
|
||||
assert.match(mobile640, /\.posts-mini\s*\{[^}]*width:\s*100%/s);
|
||||
assert.match(mobile640, /\.posts-item:not\(\.no-thumb\) \.meta-right item\s*\{[^}]*display:\s*none/s);
|
||||
assert.doesNotMatch(css, /\.aksrt-|post-card-cms|grid-cms/);
|
||||
});
|
||||
|
||||
test('site shell has one float owner and fluid zones sit outside main', () => {
|
||||
const layout = read('assets/css/frontend/layout.css');
|
||||
const archive = read('inc/helpers/aksrt-archive.php');
|
||||
const shell = layout.slice(layout.indexOf('Site shell'), layout.indexOf('页面标题区'));
|
||||
test('related posts, author page and widgets use their dedicated renderers', () => {
|
||||
const related = read('inc/helpers/aksrt-single-render.php');
|
||||
const relatedCard = read('inc/helpers/aksrt-single-components.php');
|
||||
const resourceRelated = read('templates/parts/resource-related.php');
|
||||
const author = read('templates/parts/user-home/panels-core.php');
|
||||
const authorPosts = author.slice(author.indexOf("in_array('posts'"), author.indexOf("in_array('comments'"));
|
||||
const widgets = read('src/WidgetSystem/PostRenderer.php');
|
||||
|
||||
assert.doesNotMatch(shell, /display:\s*grid/);
|
||||
assert.match(shell, /width:\s*var\(--sidebar-width, 311px\)/);
|
||||
assert.match(shell, /calc\(var\(--sidebar-width, 311px\) \+ 15px\)/);
|
||||
assert.ok(archive.indexOf("$args['top_fluid']") < archive.indexOf('<main id="main-content"'));
|
||||
assert.ok(archive.lastIndexOf("$args['bottom_fluid']") > archive.indexOf('</main>'));
|
||||
assert.match(related, /\['img', 'list', 'text'\]/);
|
||||
assert.match(related, /aksrt_renderer_mini\(\$data, \$mini_cfg\)/);
|
||||
assert.match(related, /aksrt_render_related_graphic_card\(\$post\)/);
|
||||
assert.match(related, /<li><a class="icon-circle"/);
|
||||
assert.doesNotMatch(related, /topics|post_related_source/);
|
||||
assert.match(relatedCard, /aksrt_renderer_resolve_images/);
|
||||
assert.match(resourceRelated, /swiper-container swiper-scroll/);
|
||||
assert.match(resourceRelated, /aksrt_render_related_graphic_card/);
|
||||
assert.doesNotMatch(resourceRelated, /aksrt_render_post_list/);
|
||||
assert.match(authorPosts, /aksrt_render_post_list/);
|
||||
assert.match(authorPosts, /aksrt_render_pagination/);
|
||||
assert.match(authorPosts, /'page_var'\s*=>\s*'posts_page'/);
|
||||
assert.doesNotMatch(authorPosts, /aksrt_render_profile_pagination/);
|
||||
assert.match(widgets, /aksrt_render_mini_list/);
|
||||
assert.match(widgets, /swiper-container swiper-scroll/);
|
||||
});
|
||||
|
||||
test('widget shell uses Zibll wrappers without overriding post link colors', () => {
|
||||
const renderer = read('src/WidgetSystem/FrontendRenderer.php');
|
||||
const css = read('assets/widgets/frontend.css');
|
||||
test('AJAX pagination can recover, caps auto loading and rehydrates appended media', () => {
|
||||
const php = read('inc/helpers/template-tags/pagination-permissions.php');
|
||||
const admin = read('src/Admin/Admin.php');
|
||||
const js = read('assets/js/core/pagination.js');
|
||||
const media = read('assets/js/core/misc.js');
|
||||
|
||||
assert.match(renderer, /'zib-widget-wrap'/);
|
||||
assert.match(renderer, /\$classes\[\] = 'zib-widget'/);
|
||||
assert.match(renderer, /aksrt-widget__inner container/);
|
||||
assert.doesNotMatch(css, /\.aksrt-widget a\s*\{[^}]*color:\s*inherit/);
|
||||
assert.match(css, /\.aksrt-widget\.zib-widget\s*\{/);
|
||||
assert.match(php, /class="text-center theme-pagination ajax-pag"/);
|
||||
assert.match(php, /class="next-page ajax-next/);
|
||||
assert.match(php, /lazyload-action="ias"/);
|
||||
assert.match(php, /class="post_ajax_loader"/);
|
||||
assert.match(php, /data-page-var/);
|
||||
assert.match(admin, /'author', 'author_name'/);
|
||||
assert.match(admin, /'category__in'.*'tag__in'/s);
|
||||
assert.match(admin, /\$query_vars\['paged'\] = \$page/);
|
||||
assert.match(js, /failed = false;\s*loadNextPage\(fromAuto\)/);
|
||||
assert.match(js, /successfulAutoLoads >= iasMax/);
|
||||
assert.match(js, /AksrtFrontend\.rehydrate\(target, "ajax"\)/);
|
||||
assert.match(js, /classList\.add\("lazyload"\)/);
|
||||
assert.match(media, /thumb-dplayer-playing/);
|
||||
assert.match(media, /data-post-thumb-slider/);
|
||||
assert.match(media, /data-post-thumb-video/);
|
||||
assert.match(media, /window\.Grade\(container/);
|
||||
assert.match(media, /linear-gradient\(135deg/);
|
||||
assert.match(media, /aksrtGradientState/);
|
||||
assert.match(read('src/Core/ScriptsPart1c.php'), /'aksrt-grade'/);
|
||||
});
|
||||
|
||||
test('the pinned Zibll baseline records all source checksums', () => {
|
||||
const baseline = JSON.parse(read('tests/visual/zibll-9.0-article-baseline.json'));
|
||||
assert.equal(baseline.theme, 'Zibll');
|
||||
assert.equal(baseline.version, '9.0');
|
||||
const files = Object.values(baseline.files);
|
||||
assert.ok(files.length >= 6);
|
||||
for (const file of files) {
|
||||
assert.match(file.sha256, /^[a-f0-9]{64}$/);
|
||||
}
|
||||
});
|
||||
|
||||
test('article visual matrix pins every breakpoint, state and strict threshold', () => {
|
||||
const matrix = JSON.parse(read('tests/visual/article-visual-matrix-v1.json'));
|
||||
assert.deepEqual(matrix.viewports.map((item) => item.width), [1440, 1024, 768, 767, 641, 640, 390]);
|
||||
assert.deepEqual(matrix.colorSchemes, ['light', 'dark']);
|
||||
assert.deepEqual(matrix.layouts, ['sidebar', 'no-sidebar']);
|
||||
assert.deepEqual(matrix.listModes, ['thumb', 'text', 'thumb_if_has', 'card']);
|
||||
assert.deepEqual(matrix.styles, ['default', 'style2', 'style3']);
|
||||
assert.ok(matrix.routes.some((route) => route.id === 'author-a'));
|
||||
assert.ok(matrix.routes.some((route) => route.states.includes('infinite')));
|
||||
assert.ok(matrix.postScenarios.includes('no-image'));
|
||||
assert.ok(matrix.postScenarios.includes('multi'));
|
||||
assert.ok(matrix.postScenarios.includes('video'));
|
||||
assert.ok(matrix.postScenarios.includes('slides'));
|
||||
assert.equal(matrix.acceptance.dimensionDeltaPxMax, 1);
|
||||
assert.equal(matrix.acceptance.pixelDifferencePercentMax, 1.5);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user