+
{{-- 本文 --}}
-
+
@{{ whatsnews.post_detail_strip_tags }}
diff --git a/tests/Feature/Plugins/User/Whatsnews/WhatsnewsViewClassesFeatureTest.php b/tests/Feature/Plugins/User/Whatsnews/WhatsnewsViewClassesFeatureTest.php
new file mode 100644
index 000000000..03509920a
--- /dev/null
+++ b/tests/Feature/Plugins/User/Whatsnews/WhatsnewsViewClassesFeatureTest.php
@@ -0,0 +1,180 @@
+renderWhatsnewsTemplate('plugins.user.whatsnews.default.whatsnews');
+
+ $this->assertWhatsnewPartClasses($this->extractInitialDisplayMarkup($html));
+ }
+
+ /**
+ * 1行表示テンプレートで、表示項目の有無に左右されず各要素をクラスで指定できること。
+ */
+ public function testOnerowTemplateRendersClassesForEachWhatsnewPart(): void
+ {
+ $html = $this->renderWhatsnewsTemplate('plugins.user.whatsnews.onerow.whatsnews');
+
+ $this->assertWhatsnewPartClasses($this->extractInitialDisplayMarkup($html));
+ }
+
+ /**
+ * カード表示テンプレートで、既存のカード用HTMLにも各要素のCSS用クラスが維持されること。
+ */
+ public function testCardTemplateRendersClassesForEachWhatsnewPart(): void
+ {
+ $html = $this->renderWhatsnewsTemplate('plugins.user.whatsnews.card_04.whatsnews');
+
+ $this->assertWhatsnewPartClasses($this->extractInitialDisplayMarkup($html));
+ }
+
+ /**
+ * 標準テンプレートの追加表示でも、初期表示と同じCSS用クラスで各要素を指定できること。
+ */
+ public function testDefaultTemplateRendersClassesForEachAsyncWhatsnewPart(): void
+ {
+ $html = $this->renderWhatsnewsTemplate('plugins.user.whatsnews.default.whatsnews', UseType::use);
+
+ $this->assertWhatsnewPartClasses($this->extractAsyncDisplayMarkup($html));
+ }
+
+ /**
+ * 1行表示テンプレートの追加表示でも、初期表示と同じCSS用クラスで各要素を指定できること。
+ */
+ public function testOnerowTemplateRendersClassesForEachAsyncWhatsnewPart(): void
+ {
+ $html = $this->renderWhatsnewsTemplate('plugins.user.whatsnews.onerow.whatsnews', UseType::use);
+
+ $this->assertWhatsnewPartClasses($this->extractAsyncDisplayMarkup($html));
+ }
+
+ /**
+ * カード表示テンプレートの追加表示でも、既存のカード用HTMLのCSS用クラスが維持されること。
+ */
+ public function testCardTemplateRendersClassesForEachAsyncWhatsnewPart(): void
+ {
+ $html = $this->renderWhatsnewsTemplate('plugins.user.whatsnews.card_04.whatsnews', UseType::use);
+
+ $this->assertWhatsnewPartClasses($this->extractAsyncDisplayMarkup($html));
+ }
+
+ /**
+ * 新着情報テンプレートの描画に必要な最小限のデータを用意する。
+ */
+ private function renderWhatsnewsTemplate(string $template, int $async = UseType::not_use): string
+ {
+ $frame = (object) [
+ 'id' => 1,
+ 'bucket_id' => 1,
+ 'frame_design' => 'default',
+ 'classname_body' => '',
+ ];
+
+ $whatsnews_frame = (object) [
+ 'rss' => UseType::not_use,
+ 'whatsnew_name' => 'テスト新着',
+ 'view_posted_at' => UseType::use,
+ 'view_posted_name' => UseType::use,
+ 'read_more_use_flag' => UseType::not_use,
+ 'read_more_btn_transparent_flag' => UseType::not_use,
+ 'read_more_btn_color_type' => 'primary',
+ 'read_more_btn_type' => '',
+ 'read_more_name' => 'もっと見る',
+ 'read_more_fetch_count' => 10,
+ ];
+
+ $whatsnews = collect([
+ (object) [
+ 'posted_at' => Carbon::parse('2026-05-22 10:00:00'),
+ 'category' => 'お知らせ',
+ 'classname' => 'notice',
+ 'plugin_name' => 'blogs',
+ 'page_id' => 1,
+ 'frame_id' => 2,
+ 'post_id' => 3,
+ 'post_title' => 'テストタイトル',
+ 'post_title_strip_tags' => 'テストタイトル',
+ 'post_detail_strip_tags' => 'テスト本文',
+ 'first_image_path' => '/file/10',
+ 'posted_name' => '投稿者名',
+ ],
+ ]);
+
+ return view($template, [
+ 'frame' => $frame,
+ 'frame_id' => $frame->id,
+ 'page' => (object) ['id' => 1],
+ 'whatsnews' => $whatsnews,
+ 'whatsnews_frame' => $whatsnews_frame,
+ 'whatsnews_total_count' => 1,
+ 'link_pattern' => ['blogs' => 'show_page_frame_post'],
+ 'link_base' => ['blogs' => '/plugin/blogs/show'],
+ 'frame_configs' => $this->createVisiblePartFrameConfigs($async),
+ ])->render();
+ }
+
+ /**
+ * 本文・サムネイル・罫線を表示状態にして、対象クラスがHTMLに現れるようにする。
+ */
+ private function createVisiblePartFrameConfigs(int $async): EloquentCollection
+ {
+ return new EloquentCollection([
+ new FrameConfig(['name' => WhatsnewFrameConfig::post_detail, 'value' => UseType::use]),
+ new FrameConfig(['name' => WhatsnewFrameConfig::thumbnail, 'value' => UseType::use]),
+ new FrameConfig(['name' => WhatsnewFrameConfig::border, 'value' => UseType::use]),
+ new FrameConfig(['name' => WhatsnewFrameConfig::async, 'value' => $async]),
+ ]);
+ }
+
+ /**
+ * 追加表示用のVueテンプレートに紛れず、初期表示部分だけを検証できるようにする。
+ */
+ private function extractInitialDisplayMarkup(string $html): string
+ {
+ return preg_replace('/
.*?<\/template>/s', '', $html) ?? $html;
+ }
+
+ /**
+ * 追加表示で差し込まれるHTML断片だけを対象に、初期表示側のクラスで補完されないようにする。
+ */
+ private function extractAsyncDisplayMarkup(string $html): string
+ {
+ $async_markup_position = strpos($html, 'v-for="whatsnews in whatsnewses"');
+
+ $this->assertNotFalse($async_markup_position);
+
+ return substr($html, $async_markup_position);
+ }
+
+ /**
+ * CSS適用対象として公開する6種類のクラスが描画結果に含まれることを確認する。
+ */
+ private function assertWhatsnewPartClasses(string $html): void
+ {
+ $this->assertStringContainsString('whatsnew_posted_at', $html);
+ $this->assertStringContainsString('whatsnew_category', $html);
+ $this->assertStringContainsString('whatsnew_title', $html);
+ $this->assertStringContainsString('whatsnew_posted_name', $html);
+ $this->assertStringContainsString('whatsnew_post_detail', $html);
+ $this->assertStringContainsString('whatsnew_thumbnail', $html);
+ }
+}