Include tutorial landing pages in sitemap and verify notification receipts
This commit is contained in:
parent
ace6d74a18
commit
252e0c38cb
@ -11,3 +11,5 @@ ## AI 文章写作(必读)
|
|||||||
插画完成后按[自动交付](docs/maintenance/ILLUSTRATION_DELIVERY.md)提交批准批次;不要再手工上传发布/编辑图池或把保存草稿当作上线完成。
|
插画完成后按[自动交付](docs/maintenance/ILLUSTRATION_DELIVERY.md)提交批准批次;不要再手工上传发布/编辑图池或把保存草稿当作上线完成。
|
||||||
|
|
||||||
周期文章按[固定发布封装](docs/maintenance/EDITORIAL_RELEASE.md)执行:本机SSH必须经白色机到正式业务服务器,使用服务器进程内API,不临时开放公网接口。每周三篇、每天15:00检查、错过窗口回补及文章随机展示时间见[周期写作](docs/maintenance/WEEKLY_TUTORIALS.md);这一流程替代周期写作中的手动开关API步骤,不扩大其他实例或全站改版权限。
|
周期文章按[固定发布封装](docs/maintenance/EDITORIAL_RELEASE.md)执行:本机SSH必须经白色机到正式业务服务器,使用服务器进程内API,不临时开放公网接口。每周三篇、每天15:00检查、错过窗口回补及文章随机展示时间见[周期写作](docs/maintenance/WEEKLY_TUTORIALS.md);这一流程替代周期写作中的手动开关API步骤,不扩大其他实例或全站改版权限。
|
||||||
|
|
||||||
|
教程SEO、编辑API的IndexNow结果与重试、栏目sitemap的唯一维护说明见[教程SEO通知](docs/maintenance/EDITORIAL_INDEXNOW.md)。`sitemap: done`不代表搜索引擎已收到通知或已收录。
|
||||||
|
|||||||
@ -3,29 +3,33 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Articles;
|
use App\Models\Articles;
|
||||||
|
use App\Models\Categories;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
|
|
||||||
class SitemapController extends Controller
|
class SitemapController extends Controller
|
||||||
{
|
{
|
||||||
public function index(): Response
|
public function index(): Response
|
||||||
{
|
{
|
||||||
// 连表查询分类:按 aOpt['noindexday'] 动态过滤过期文章
|
// Use the same expiry rule as article metadata, including on SQLite in isolated tests.
|
||||||
$cArticles = Articles::where('iStatus', 1)
|
$cArticles = Articles::where('iStatus', 1)
|
||||||
->whereHas('oCategory', function ($q) {
|
->where('created_at', '<=', now())
|
||||||
$q->where(function ($query) {
|
->whereHas('oCategory', fn ($q) => $q->where('iStatus', 1))
|
||||||
// 1. 没有配置 noindexday,或者 noindexday = 0 的文章,一直保留
|
->with('oCategory')
|
||||||
$query->whereNull('aOpt')
|
|
||||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(aOpt, '$.noindexday')) IS NULL")
|
|
||||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(aOpt, '$.noindexday')) = '0'")
|
|
||||||
// 2. 配置了天数的,只取 N 天内创建的新文章
|
|
||||||
->orWhereRaw("articles.created_at >= NOW() - INTERVAL CAST(JSON_UNQUOTE(JSON_EXTRACT(aOpt, '$.noindexday')) AS UNSIGNED) DAY");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
->orderBy('created_at', 'desc')
|
->orderBy('created_at', 'desc')
|
||||||
->get();
|
->get()->reject(fn ($article) => $article->bIsSeoExpired());
|
||||||
|
|
||||||
|
$visible = fn ($q) => $q->where('iStatus', 1)->where('created_at', '<=', now());
|
||||||
|
$cCategories = Categories::whereIn('sSlug', ['client', 'advanced'])
|
||||||
|
->where('iParentId', 0)->where('iStatus', 1)
|
||||||
|
->where(function ($q) use ($visible) {
|
||||||
|
$q->whereHas('aArticles', $visible)->orWhereHas('aChildren', function ($children) use ($visible) {
|
||||||
|
$children->where('iStatus', 1)->whereHas('aArticles', $visible);
|
||||||
|
});
|
||||||
|
})->orderBy('sSlug')->get();
|
||||||
|
|
||||||
$sXmlContent = view('sitemap', [
|
$sXmlContent = view('sitemap', [
|
||||||
'cArticles' => $cArticles
|
'cArticles' => $cArticles,
|
||||||
|
'cCategories' => $cCategories,
|
||||||
])->render();
|
])->render();
|
||||||
|
|
||||||
return response($sXmlContent, 200)->header('Content-Type', 'text/xml');
|
return response($sXmlContent, 200)->header('Content-Type', 'text/xml');
|
||||||
|
|||||||
@ -20,3 +20,16 @@ ## 2026-10-31已部署与验证
|
|||||||
2026-10-31 14:20:55北京时间,通过本机SSH→白色机→业务服务器,由新组件对现有`/a/system-proxy-vs-tun.html`执行一次真实通知验收,HTTP200,密钥文件HTTP200且内容匹配;未改正文、未重新发布、未改旧回执、未批量补推。只证明通知被接收,不代表已收录。已完成服务器侧验收,未做线上页面验收。精确证据见[回执](EDITORIAL_INDEXNOW_2026-10-31.json)。
|
2026-10-31 14:20:55北京时间,通过本机SSH→白色机→业务服务器,由新组件对现有`/a/system-proxy-vs-tun.html`执行一次真实通知验收,HTTP200,密钥文件HTTP200且内容匹配;未改正文、未重新发布、未改旧回执、未批量补推。只证明通知被接收,不代表已收录。已完成服务器侧验收,未做线上页面验收。精确证据见[回执](EDITORIAL_INDEXNOW_2026-10-31.json)。
|
||||||
|
|
||||||
私有恢复点:VPS-003 `/root/backups/cfn-indexnow-20261031/`,包含Git bundle、原HEAD/工作区状态、标签模板、文章核心字段与旧回执快照、真实提交事件和部署记录。回滚可检出基线,保留已有effects状态和内容;单独停推可设`EDITORIAL_INDEXNOW_ENABLED=false`,不要删除pending回执。普通发布继续通过[白色机发布封装](EDITORIAL_RELEASE.md)。
|
私有恢复点:VPS-003 `/root/backups/cfn-indexnow-20261031/`,包含Git bundle、原HEAD/工作区状态、标签模板、文章核心字段与旧回执快照、真实提交事件和部署记录。回滚可检出基线,保留已有effects状态和内容;单独停推可设`EDITORIAL_INDEXNOW_ENABLED=false`,不要删除pending回执。普通发布继续通过[白色机发布封装](EDITORIAL_RELEASE.md)。
|
||||||
|
|
||||||
|
|
||||||
|
## 2026-10-31已部署与验证
|
||||||
|
|
||||||
|
功能提交`574812438338755b160453c4a574557365903506`已Git推送并部署正式cfn,独立分支`codex/editorial-indexnow-publish-20261031`,基线`d981a2aa4fa21abe4512ddd287a2f51f87b11197`。同名旧候选分支另有包含sitemap改动的并行提交415b5f8,保留未覆盖;本任务只部署IndexNow范围,没有捆绑其他SEO工作。
|
||||||
|
|
||||||
|
专项4项测试/52断言通过:新增/更新通知、同UUID去重、无变化跳过、429退避后202成功、旧回执不补推、禁用环境/域名错配拒发、撤下后停止重试。本地相关业务回归合计36项/344断言通过;其中共享工作区的sitemap测试未作为本次部署范围。
|
||||||
|
|
||||||
|
正式站现有188篇文章的核心内容与日期、所有旧编辑发布回执保持;生成标签模板哈希和data.ms并行目录保留。新重试命令以nginx实际运行,空队列返回processed=0/pending=0,已登记每5分钟调度;未为演练制造失败队列,也未宣称已观察到一笔真实失败的自动恢复。公网编辑API仍关闭,首页HTTP200。
|
||||||
|
|
||||||
|
2026-10-31 14:20:55北京时间,通过本机SSH→白色机→业务服务器,由新组件对现有`/a/system-proxy-vs-tun.html`执行一次真实通知验收,HTTP200,密钥文件HTTP200且内容匹配;未改正文、未重新发布、未改旧回执、未批量补推。只证明通知被接收,不代表已收录。已完成服务器侧验收,未做线上页面验收。精确证据见[回执](EDITORIAL_INDEXNOW_2026-10-31.json)。
|
||||||
|
|
||||||
|
私有恢复点:VPS-003 `/root/backups/cfn-indexnow-20261031/`,包含Git bundle、原HEAD/工作区状态、标签模板、文章核心字段与旧回执快照、真实提交事件和部署记录。回滚可检出基线,保留已有effects状态和内容;单独停推可设`EDITORIAL_INDEXNOW_ENABLED=false`,不要删除pending回执。普通发布继续通过[白色机发布封装](EDITORIAL_RELEASE.md)。
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# FNA_V3 SEO 优化建议与执行清单
|
# FNA_V3 SEO 优化建议与执行清单
|
||||||
|
|
||||||
评估日期:2026-10-22,Asia/Shanghai。状态:**分析与建议文档已完成;SEO-001 的部署定位已由用户确认,配置改造尚未实施;SEO-020 于2026-10-27完成本地教程正文更新,设备实测及生产验收未做,D02首页最新免费节点全文展示于2026-10-27本地完成,其余项目尚未实施**。本文件是后续 SEO 工作的唯一执行清单;按 `SEO-001` 至 `SEO-036` 跟踪,实施后在本文件更新结果,不另建重复的“最新版计划”。
|
评估日期:2026-10-22,Asia/Shanghai。状态:**分析与建议文档已完成;SEO-001 的部署定位已由用户确认,配置改造尚未实施;SEO-020 于2026-10-27完成本地教程正文更新,设备实测及生产验收未做,D02首页最新免费节点全文展示于2026-10-27本地完成,其余项目按分项记录;2026-10-31正在实施编辑文章IndexNow通知与两个教程栏目sitemap(见SEO-013/033)**。本文件是后续 SEO 工作的唯一执行清单;按 `SEO-001` 至 `SEO-036` 跟踪,实施后在本文件更新结果,不另建重复的“最新版计划”。
|
||||||
|
|
||||||
本轮依据当前代码、当前本地数据库、重新取得的 HTTP 响应及受限浏览器检查形成结论。网站源码、样式和业务数据未作修改。当前三款 DPL 广告属于已存在的实现,纳入分析基准并保留。网站仍在独立本地副本中开发;用户随后确认未来替换现有 cfn,并支持同一套代码部署多个同类站点,ClashFreeNode 为主力站,尚未实际部署或迁移。
|
本轮依据当前代码、当前本地数据库、重新取得的 HTTP 响应及受限浏览器检查形成结论。网站源码、样式和业务数据未作修改。当前三款 DPL 广告属于已存在的实现,纳入分析基准并保留。网站仍在独立本地副本中开发;用户随后确认未来替换现有 cfn,并支持同一套代码部署多个同类站点,ClashFreeNode 为主力站,尚未实际部署或迁移。
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ ## 5 执行总表
|
|||||||
| [ ] | SEO-010 | 分类、标签、搜索的标题与语义层级 | P1 | 001、004 | 已确认 |
|
| [ ] | SEO-010 | 分类、标签、搜索的标题与语义层级 | P1 | 001、004 | 已确认 |
|
||||||
| [ ] | SEO-011 | 生成真实、干净的页面简介 | P1 | 010 | 已确认 |
|
| [ ] | SEO-011 | 生成真实、干净的页面简介 | P1 | 010 | 已确认 |
|
||||||
| [ ] | SEO-012 | 分离真实内容日期并统一时间基准 | P1 | 003 | 已确认/条件性风险 |
|
| [ ] | SEO-012 | 分离真实内容日期并统一时间基准 | P1 | 003 | 已确认/条件性风险 |
|
||||||
| [ ] | SEO-013 | 统一 sitemap 的集合和 lastmod | P1 | 003、004、008、012 | 已确认 |
|
| [ ] | SEO-013 | 统一 sitemap 的集合和 lastmod | P1 | 003、004、008、012 | 部分实施:教程栏目,见正文 |
|
||||||
| [ ] | SEO-014 | 建立长期内链和内容导航 | P1 | 005、009、018 | 已确认/策略建议 |
|
| [ ] | SEO-014 | 建立长期内链和内容导航 | P1 | 005、009、018 | 已确认/策略建议 |
|
||||||
| [ ] | SEO-015 | 整理标签与重复主题页 | P1 | 002、003 | 策略建议 |
|
| [ ] | SEO-015 | 整理标签与重复主题页 | P1 | 002、003 | 策略建议 |
|
||||||
| [ ] | SEO-016 | 隔离并同步本站搜索索引 | P1 | 008、032 | 已确认 |
|
| [ ] | SEO-016 | 隔离并同步本站搜索索引 | P1 | 008、032 | 已确认 |
|
||||||
@ -202,7 +202,7 @@ ## 5 执行总表
|
|||||||
| [ ] | SEO-030 | 文章接收、更新与删除的发布合同 | P0 发布前 | 003、008、017、029 | 已确认/条件性风险 |
|
| [ ] | SEO-030 | 文章接收、更新与删除的发布合同 | P0 发布前 | 003、008、017、029 | 已确认/条件性风险 |
|
||||||
| [ ] | SEO-031 | 正式主机、HTTPS 与 HTTP 服务质量 | P0 发布前 | 001、004 | 待部署验证 |
|
| [ ] | SEO-031 | 正式主机、HTTPS 与 HTTP 服务质量 | P0 发布前 | 001、004 | 待部署验证 |
|
||||||
| [ ] | SEO-032 | 本地、预发布和生产资源隔离 | P0 发布前 | 001 | 已确认/条件性风险 |
|
| [ ] | SEO-032 | 本地、预发布和生产资源隔离 | P0 发布前 | 001 | 已确认/条件性风险 |
|
||||||
| [ ] | SEO-033 | 规范 IndexNow 及搜索提交 | P2 | 003、004、030、032 | 已确认/待部署验证 |
|
| [ ] | SEO-033 | 规范 IndexNow 及搜索提交 | P2 | 003、004、030、032 | 部分实施:编辑发布通知,见正文 |
|
||||||
| [ ] | SEO-034 | SEO 自动回归与数据样例 | P1 | 跟随各批次 | 当前测试缺口 |
|
| [ ] | SEO-034 | SEO 自动回归与数据样例 | P1 | 跟随各批次 | 当前测试缺口 |
|
||||||
| [ ] | SEO-035 | 搜索平台与业务效果监测 | P1 上线后 | 001、002、036 | 待线上数据 |
|
| [ ] | SEO-035 | 搜索平台与业务效果监测 | P1 上线后 | 001、002、036 | 待线上数据 |
|
||||||
| [ ] | SEO-036 | 发布、迁移、回滚与复核 | P0 发布时 | 前述必需项 | 待发布授权 |
|
| [ ] | SEO-036 | 发布、迁移、回滚与复核 | P0 发布时 | 前述必需项 | 待发布授权 |
|
||||||
@ -352,6 +352,8 @@ ### SEO-013 统一 sitemap 的集合和 lastmod
|
|||||||
|
|
||||||
**验收:** XML 解析、URL 编码、正式 host、状态、canonical、robots、noindex 做交叉校验;新增/撤稿/到期后集合及时变化;集合差异有可解释原因。Google 忽略 priority 与 changefreq,不应将调大这些数字作为优化工作。[Google sitemap 指南](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap)
|
**验收:** XML 解析、URL 编码、正式 host、状态、canonical、robots、noindex 做交叉校验;新增/撤稿/到期后集合及时变化;集合差异有可解释原因。Google 忽略 priority 与 changefreq,不应将调大这些数字作为优化工作。[Google sitemap 指南](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap)
|
||||||
|
|
||||||
|
**2026-10-31定点实施:** 见[教程SEO通知](EDITORIAL_INDEXNOW.md)。仅编辑API新增/实质更新通知、独立回执/退避重试,以及client/advanced非空栏目进入sitemap;未完成本项所有全站建议,发布/验收以该正文为准。
|
||||||
|
|
||||||
### SEO-014 建立长期内链和内容导航
|
### SEO-014 建立长期内链和内容导航
|
||||||
|
|
||||||
**优先级:P1。证据:E03。** 当前资源发现主要依赖列表首屏和“点赞活跃”;动态热门榜并不保证重要教程或可索引资源长期获得入口。
|
**优先级:P1。证据:E03。** 当前资源发现主要依赖列表首屏和“点赞活跃”;动态热门榜并不保证重要教程或可索引资源长期获得入口。
|
||||||
@ -539,6 +541,8 @@ ### SEO-033 规范 IndexNow 及搜索提交
|
|||||||
|
|
||||||
**验收:** 本地使用替身验证,不实际发送;正式获准后单条核验目标主机、验证文件和返回结果;删除事件不因目标已 404 而被本地逻辑永远过滤掉。IndexNow 表示通知采用该协议的搜索引擎,不能当成 Google 通用收录接口。Google Indexing API 仅支持其指定的招聘及直播事件页面,不适用于普通节点文章。[IndexNow 协议](https://www.indexnow.org/documentation)、[Google Indexing API 适用范围](https://developers.google.com/search/apis/indexing-api/v3/using-api)
|
**验收:** 本地使用替身验证,不实际发送;正式获准后单条核验目标主机、验证文件和返回结果;删除事件不因目标已 404 而被本地逻辑永远过滤掉。IndexNow 表示通知采用该协议的搜索引擎,不能当成 Google 通用收录接口。Google Indexing API 仅支持其指定的招聘及直播事件页面,不适用于普通节点文章。[IndexNow 协议](https://www.indexnow.org/documentation)、[Google Indexing API 适用范围](https://developers.google.com/search/apis/indexing-api/v3/using-api)
|
||||||
|
|
||||||
|
**2026-10-31定点实施:** 见[教程SEO通知](EDITORIAL_INDEXNOW.md)。仅编辑API新增/实质更新通知、独立回执/退避重试,以及client/advanced非空栏目进入sitemap;未完成本项所有全站建议,发布/验收以该正文为准。
|
||||||
|
|
||||||
### SEO-034 SEO 自动回归与数据样例
|
### SEO-034 SEO 自动回归与数据样例
|
||||||
|
|
||||||
**优先级:P1,随每批实现。** 当前仓库测试只有首页 200 示例和恒真示例,不能防止 URL、索引和发布规则回退。本轮未执行这些与审计目标无关的示例测试,也没有新增业务测试或修改代码。
|
**优先级:P1,随每批实现。** 当前仓库测试只有首页 200 示例和恒真示例,不能防止 URL、索引和发布规则回退。本轮未执行这些与审计目标无关的示例测试,也没有新增业务测试或修改代码。
|
||||||
|
|||||||
7
resources/views/sitemap.blade.php
Executable file → Normal file
7
resources/views/sitemap.blade.php
Executable file → Normal file
@ -7,6 +7,13 @@
|
|||||||
<changefreq>daily</changefreq>
|
<changefreq>daily</changefreq>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
|
{{-- Only established tutorial landing pages; omit lastmod until a reliable content clock exists. --}}
|
||||||
|
@foreach($cCategories as $oCategory)
|
||||||
|
<url>
|
||||||
|
<loc>{{ rtrim(config('app.url'), '/') }}/{{ $oCategory->sSlug }}</loc>
|
||||||
|
</url>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
{{-- 未过期的文章 --}}
|
{{-- 未过期的文章 --}}
|
||||||
@foreach($cArticles as $oArticles)
|
@foreach($cArticles as $oArticles)
|
||||||
<url>
|
<url>
|
||||||
|
|||||||
@ -477,4 +477,28 @@ public function test_editorial_indexnow_retries_skip_withdrawn_or_expired_articl
|
|||||||
Http::assertSentCount(1);
|
Http::assertSentCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public function test_sitemap_contains_only_active_nonempty_tutorial_roots_and_indexable_articles(): void
|
||||||
|
{
|
||||||
|
config(['app.url' => 'http://localhost']);
|
||||||
|
$this->publish($this->draft([$this->item()]))->assertOk();
|
||||||
|
DB::table('categories')->where('id', 3)->update(['iParentId' => 2]);
|
||||||
|
DB::table('categories')->insert(['id' => 2, 'sSlug' => 'client', 'sName' => '入门教程', 'iStatus' => 1]);
|
||||||
|
$xml = $this->get('/sitemap.xml')->assertOk()->getContent();
|
||||||
|
$this->assertStringContainsString('<loc>http://localhost/client</loc>', $xml);
|
||||||
|
$this->assertStringNotContainsString('<loc>http://localhost/advanced</loc>', $xml);
|
||||||
|
$advanced = $this->item('advanced-test');
|
||||||
|
$advanced['category_slug'] = 'advanced';
|
||||||
|
$this->publish($this->draft([$advanced]))->assertOk();
|
||||||
|
$xml = $this->get('/sitemap.xml')->assertOk()->getContent();
|
||||||
|
$this->assertSame(1, substr_count($xml, '<loc>http://localhost/advanced</loc>'));
|
||||||
|
$this->assertStringContainsString('/a/advanced-test.html</loc>', $xml);
|
||||||
|
$this->assertStringNotContainsString('<loc>http://localhost/windows</loc>', $xml);
|
||||||
|
DB::table('categories')->where('id', 10)->update(['iStatus' => 0]);
|
||||||
|
DB::table('articles')->where('iCategoryId', 3)->update(['iStatus' => 0]);
|
||||||
|
$xml = $this->get('/sitemap.xml')->assertOk()->getContent();
|
||||||
|
$this->assertStringNotContainsString('/advanced</loc>', $xml);
|
||||||
|
$this->assertStringNotContainsString('/client</loc>', $xml);
|
||||||
|
$this->assertStringNotContainsString('/a/advanced-test.html</loc>', $xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -262,4 +262,29 @@ public function test_release_display_time_is_frozen_and_real_publish_time_is_pre
|
|||||||
$this->assertSame($article->sDisplayPublishedAt, DB::table('articles')->value('sDisplayPublishedAt'));
|
$this->assertSame($article->sDisplayPublishedAt, DB::table('articles')->value('sDisplayPublishedAt'));
|
||||||
$this->travelBack();
|
$this->travelBack();
|
||||||
}
|
}
|
||||||
|
public function test_release_tracks_indexnow_pending_and_recovers_without_a_new_publication(): void
|
||||||
|
{
|
||||||
|
config(['editorial.indexnow_enabled' => true, 'editorial.base_url' => 'https://example.org',
|
||||||
|
'app.url' => 'https://example.org', 'app.site_code' => 'example.org', 'key.indexnow' => 'test-key-12345678']);
|
||||||
|
Http::fake(['api.indexnow.org/*' => Http::sequence()->push('', 503)->push('', 200)]);
|
||||||
|
$runner = app(ReleaseRunner::class);
|
||||||
|
$bundle = $this->bundle();
|
||||||
|
$runner->run($bundle);
|
||||||
|
$review = $runner->run(['operation' => 'review', 'release_id' => $bundle['release_id']]);
|
||||||
|
$publish = ['operation' => 'publish', 'release_id' => $bundle['release_id'],
|
||||||
|
'expected_hash' => $review['review']['hash'], 'review_digest' => $review['review']['digest']];
|
||||||
|
$pending = $runner->run($publish);
|
||||||
|
$this->assertSame('published_pending', $pending['phase']);
|
||||||
|
$this->assertSame('pending', $pending['receipt']['effects']['indexnow']['status']);
|
||||||
|
Http::assertSentCount(1);
|
||||||
|
$this->travel(6)->minutes();
|
||||||
|
$this->artisan('editorial:indexnow-retry')->assertExitCode(0);
|
||||||
|
$done = $runner->run(['operation' => 'status', 'release_id' => $bundle['release_id']]);
|
||||||
|
$this->assertSame('complete', $done['phase']);
|
||||||
|
$this->assertSame('done', $done['receipt']['effects']['indexnow']['status']);
|
||||||
|
$this->assertSame(1, DB::table('articles')->count());
|
||||||
|
$this->assertSame(1, DB::table('editorial_publications')->count());
|
||||||
|
Http::assertSentCount(2);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user