- cards: restore the shared card shell, add author follow/message actions, score group, last-reply meta and reference plate header actions - home: desktop left tab rail, widget-only sidebar, reference load-more markup - plate: 1-based tabs, reference defaults (全部/推荐/最新回复/热门/精华) - post: fixed action rail, score footer, author card, h1 article title - quick publish: plate selector moved into the submit row like the reference
104 lines
5.6 KiB
JavaScript
104 lines
5.6 KiB
JavaScript
const test = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
const fs = require('node:fs')
|
|
const path = require('node:path')
|
|
|
|
const root = path.resolve(__dirname, '..', '..')
|
|
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8')
|
|
|
|
test('plate pages render the reference header card, tab bar and list', () => {
|
|
const listing = read('src/Forum/ListingView.php')
|
|
const cards = read('src/Forum/Cards.php')
|
|
const view = read('src/Forum/View.php')
|
|
assert.match(view, /public static function listing\(\): void \{\s*ListingView::plate\(\);/)
|
|
for (const token of ['plate-tab', 'tab-nav-theme', 'affix-header-sm', 'data-forum-tab', 'data-forum-more', 'post_ajax_loader', 'content-wrap', 'content-layout', 'sidebar']) {
|
|
assert.ok(listing.includes(token), `plate page missing ${token}`)
|
|
}
|
|
// Reference header: blurred cover + mask + stats + moderator avatars.
|
|
for (const token of ['plate-header-wrap', 'forum-header blur-header', 'abs-blur-bg', 'forum-mask', 'moderator-btns', 'count-mates']) {
|
|
assert.ok(cards.includes(token), `plate header missing ${token}`)
|
|
}
|
|
// Moderator-only tabs (pending / trash) appear on plate pages.
|
|
assert.match(listing, /'pending'/)
|
|
assert.match(listing, /'trash'/)
|
|
// Topping posts are pulled out of the main loop on the first tab.
|
|
assert.match(listing, /_jio_forum_pinned/)
|
|
assert.match(listing, /post__not_in/)
|
|
})
|
|
|
|
test('post detail pages use the reference article shell', () => {
|
|
const post = read('src/Forum/PostView.php')
|
|
const template = read('templates/pages/page-forum-post.php')
|
|
assert.match(template, /PostView::render\(\)/)
|
|
for (const token of ['fixed-wrap single-wrap', 'fixed-wrap-content', 'forum-single-cover', 'breadcrumb', 'id="article"', 'article jio-panel forum-article', 'article-header clearfix', 'forum-article-meta', 'wp-posts-content', 'article-tags', 'forum-article-footer', 'footer-actions', 'vote-box forum-vote', 'comments-card']) {
|
|
assert.ok(post.includes(token), `post page missing ${token}`)
|
|
}
|
|
// Banners, permissions and actions stay server-side.
|
|
assert.match(post, /Access::can_view\(/)
|
|
assert.match(post, /Cards::title\(\$post, 'article-title'/)
|
|
assert.match(post, /data-forum-action="score"/)
|
|
assert.match(post, /jio_is_show_sidebar\(\)/)
|
|
})
|
|
|
|
test('compose pages mirror the reference editor plus settings sidebar', () => {
|
|
const edit = read('src/Forum/EditView.php')
|
|
const template = read('templates/pages/page-forum-edit.php')
|
|
assert.match(template, /EditView::render\(\)/)
|
|
for (const token of ['editor-main-box', 'edit-posts-featured', 'edit-posts-title', 'line-form-input', 'jio_forum_content', 'bbs-posts-edit', 'but-average', 'bbs-posts-submit', 'data-forum-draft', 'drop-select', 'allow-view-drop', 'plate-drop', 'type-drop', 'forum-type-vote']) {
|
|
assert.ok(edit.includes(token), `compose page missing ${token}`)
|
|
}
|
|
assert.match(edit, /class="sidebar show-sidebar"/)
|
|
assert.match(edit, /wp_editor\(/)
|
|
})
|
|
|
|
test('compose page saves draft state and the cover through the REST contract', () => {
|
|
const rest = read('src/Forum/RestPosts.php')
|
|
const runtime = read('assets/js/forum-runtime.js')
|
|
assert.match(rest, /\$requested === 'draft'/)
|
|
assert.match(rest, /featured_image_id/)
|
|
assert.match(rest, /set_post_thumbnail\(/)
|
|
for (const token of ['data-forum-type-set', 'data-forum-view', 'data-forum-plate', 'data-forum-status', 'data-forum-topics', 'data-forum-tags', 'data-forum-cover-file']) {
|
|
assert.ok(runtime.includes(token), `compose runtime missing ${token}`)
|
|
}
|
|
})
|
|
|
|
test('quick publish mirrors the reference inline composer', () => {
|
|
const quick = read('src/Forum/QuickPost.php')
|
|
for (const token of ['quick-posts-box', 'quick-input-group', 'edit-posts-title', 'line-form-input', 'edit-posts-content', 'quick-upload', 'quick-more-btns', 'plate-drop', 'topic-drop', 'allow-view-drop', 'hide-type-drop', 'quick-posts-submit', 'data-forum-draft']) {
|
|
assert.ok(quick.includes(token), `quick publish missing ${token}`)
|
|
}
|
|
// Guests get the login trigger instead of the editor actions.
|
|
assert.match(quick, /signin-loader/)
|
|
assert.match(quick, /登录后发布/)
|
|
})
|
|
|
|
test('forum publishing is gated by the site captcha scene', () => {
|
|
const rest = read('src/Forum/RestPosts.php')
|
|
const captcha = read('inc/modules/captcha.php')
|
|
const schema = read('src/Admin/Schema/SchemaPermissions.php')
|
|
const vue = read('assets/admin/src/schema/sections/permissions/index.js')
|
|
const quick = read('src/Forum/QuickPost.php')
|
|
const edit = read('src/Forum/EditView.php')
|
|
assert.match(captcha, /'forum_post'\s*=>\s*__\('论坛发帖'/)
|
|
assert.match(schema, /\['label' => '论坛发帖', 'value' => 'forum_post'\]/)
|
|
assert.match(vue, /\{ label: '论坛发帖', value: 'forum_post' \}/)
|
|
assert.match(rest, /jio_require_captcha\('forum_post'/)
|
|
assert.match(rest, /jio_captcha_proof/)
|
|
assert.match(quick, /jio_render_captcha\('forum_post'\)/)
|
|
assert.match(edit, /jio_render_captcha\('forum_post'\)/)
|
|
})
|
|
|
|
test('hidden content becomes the site visibility shortcode on save', () => {
|
|
const rest = read('src/Forum/Rest.php')
|
|
const posts = read('src/Forum/RestPosts.php')
|
|
const quick = read('src/Forum/QuickPost.php')
|
|
const edit = read('src/Forum/EditView.php')
|
|
assert.match(posts, /append_hidden_content\(\$content, \$input\)/)
|
|
assert.match(rest, /'logged' => 'login', 'reply' => 'comment', 'vip1' => 'vip', 'payshow' => 'payshow'/)
|
|
assert.match(rest, /hidecontent type="/)
|
|
assert.match(rest, /payshow/)
|
|
for (const token of ['hide_type', 'hide_content', '登录可见', '评论可见', '会员可见', '付费可见']) {
|
|
assert.ok(quick.includes(token) && edit.includes(token), `hidden content missing ${token}`)
|
|
}
|
|
})
|