Testing your integration¶
The core ships test doubles in IndexNowKit\Testing (part of the package, not dev-only): FakeTransport,
ArrayLogger, FrozenClock, RecordingDispatcher. Bind them into the container before the first submission.
use IndexNowKit\Http\TransportInterface;
use IndexNowKit\Laravel\IndexNowKitServiceProvider;
use IndexNowKit\Testing\{ArrayLogger, FakeTransport};
final class PostPublishingTest extends TestCase
{
private FakeTransport $transport;
protected function setUp(): void
{
parent::setUp();
$this->app->instance(TransportInterface::class, $this->transport = new FakeTransport());
$this->app->instance(IndexNowKitServiceProvider::LOGGER, new ArrayLogger());
config(['indexnow.dispatch' => 'sync', 'indexnow.debounce.store' => 'memory', 'indexnow.debounce.per_url' => 0]);
}
public function test_publishing_a_post_notifies_the_engines(): void
{
$this->post('/posts', ['title' => 'Hello'])->assertCreated(); // the batch leaves on terminate, inside ->post()
self::assertSame(['https://www.example.com/posts/hello'], $this->transport->posts[0]['body']['urlList']);
self::assertSame('www.example.com', $this->transport->posts[0]['body']['host']);
}
}
Every entry of $transport->posts is ['url' => ..., 'json' => ..., 'headers' => ..., 'body' => ...], so you assert
on host, key, keyLocation and urlList directly. FakeTransport::onGet($url, $response) stubs key file
fetches for indexnow:check; willRespond(new Response(429, '', 30)) queues engine answers.
Without HTTP at all¶
IndexNowKit::urlsFor($post) and IndexNowKit::explain($post) resolve the rules of one model without sending;
ObjectChangeHandler::updatedEvents() (via IndexNowKit::kit()->changes()) tells which rule classified an update as
created / updated / deleted before any URL exists.
Queue¶
Queue::fake() then Queue::assertPushed(SubmitUrlsJob::class, fn ($job) => $job->urls === [...]). To run the
worker logic in a test, call $job->handle($submitter, $logger) with a mocked Illuminate\Contracts\Queue\Job set
through $job->setJob($mock); release() and fail() land on the mock.
Transactions in tests¶
RefreshDatabase / DatabaseTransactions wrap each test in a transaction and swap Laravel's transaction manager for
the testing one, which runs afterCommit callbacks at the test's wrapping level. Submissions therefore behave as in
production: they leave when your code's own transaction commits.
dry_run¶
Outside production_environments a missing INDEXNOW_KEY switches dry_run on: the whole pipeline runs
(normalization, deduplication, grouping, key lookup) and stops before the POST, with the body in the info log.
Set INDEXNOW_KEY and INDEXNOW_DRY_RUN=false in phpunit.xml to exercise the transport in tests.
Conformance¶
The package's own suite runs the core conformance kits (IndexNowKit\Testing\Conformance\CoreConformanceTestCase,
OrmConformanceTestCase) against the container on orchestra/testbench; tests/Conformance/* shows the driver an
adapter implements.