indexmap 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -3
- data/lib/indexmap/pinger/google.rb +34 -3
- data/lib/indexmap/pinger/index_now.rb +46 -6
- data/lib/indexmap/version.rb +1 -1
- data/lib/tasks/indexmap_tasks.rake +70 -2
- data/test/indexmap/pinger/google_test.rb +48 -2
- data/test/indexmap/pinger/index_now_test.rb +81 -3
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 513c19d20a8373690c66fa99a0251db934298589a19139c2b77654340ce7006a
|
|
4
|
+
data.tar.gz: '087bd725e6ecaf81ff07510f78f7c5fa1d613730cd7b735c9f0ed60ecb3f4676'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f4065163991559ca5a1df38f1f01aafbdc539936f40aa81d78a3c5aa4abe34bdbc7cdb0df25d970a8a243e1b552c1946ec97c640f8d64350a46ef0d8de36006
|
|
7
|
+
data.tar.gz: d0ebff2036cefb30689a22ebddf313c89ac45a6dda11277a4a5322b6c39c6257e6d05e3615e0167ca876f985b14dc5ac21eba096f947876ab72be32bc6a73c33
|
data/CHANGELOG.md
CHANGED
|
@@ -5,12 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [0.4.
|
|
8
|
+
## [0.4.1] - 2026-04-22
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
###
|
|
11
|
+
### Added
|
|
12
12
|
|
|
13
|
-
-
|
|
13
|
+
- add output to ping tasks (#6)
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
@@ -17,10 +17,13 @@ module Indexmap
|
|
|
17
17
|
def ping
|
|
18
18
|
if google_configuration.credentials.to_s.strip.empty?
|
|
19
19
|
logger.debug("Google sitemap credentials not configured.")
|
|
20
|
-
return
|
|
20
|
+
return {status: :skipped, reason: :missing_credentials}
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
results = sitemap_files.map { |sitemap_file| ping_sitemap(sitemap_file) }
|
|
24
|
+
return {status: :skipped, reason: :no_sitemaps} if results.empty?
|
|
25
|
+
|
|
26
|
+
summarize_results(results)
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
private
|
|
@@ -36,13 +39,26 @@ module Indexmap
|
|
|
36
39
|
|
|
37
40
|
unless authorized?
|
|
38
41
|
logger.error("Google Search Console does not have access to the site: #{root_domain}")
|
|
39
|
-
return
|
|
42
|
+
return {
|
|
43
|
+
status: :failed,
|
|
44
|
+
reason: :unauthorized,
|
|
45
|
+
property: property_identifier,
|
|
46
|
+
root_domain: root_domain
|
|
47
|
+
}
|
|
40
48
|
end
|
|
41
49
|
|
|
42
50
|
webmasters_service.submit_sitemap(property_identifier, sitemap_url)
|
|
43
51
|
logger.debug { "Successfully pinged Google with sitemap: #{sitemap_url}" }
|
|
52
|
+
{status: :submitted, sitemap_url: sitemap_url}
|
|
44
53
|
rescue ::Google::Apis::ClientError => e
|
|
45
54
|
logger.debug { "Failed to ping Google for #{sitemap_url}. Status: #{e.status_code}, Body: #{e.body}" }
|
|
55
|
+
{
|
|
56
|
+
status: :failed,
|
|
57
|
+
reason: :client_error,
|
|
58
|
+
sitemap_url: sitemap_url,
|
|
59
|
+
status_code: e.status_code,
|
|
60
|
+
body: e.body
|
|
61
|
+
}
|
|
46
62
|
end
|
|
47
63
|
|
|
48
64
|
def authorized?
|
|
@@ -73,6 +89,21 @@ module Indexmap
|
|
|
73
89
|
scope: scope
|
|
74
90
|
)
|
|
75
91
|
end
|
|
92
|
+
|
|
93
|
+
def summarize_results(results)
|
|
94
|
+
submitted = results.select { |result| result[:status] == :submitted }
|
|
95
|
+
failures = results.select { |result| result[:status] == :failed }
|
|
96
|
+
|
|
97
|
+
return {status: :submitted, sitemap_count: submitted.count, submitted: submitted} if failures.empty?
|
|
98
|
+
return {status: :failed, sitemap_count: 0, failures: failures} if submitted.empty?
|
|
99
|
+
|
|
100
|
+
{
|
|
101
|
+
status: :partial,
|
|
102
|
+
sitemap_count: submitted.count,
|
|
103
|
+
submitted: submitted,
|
|
104
|
+
failures: failures
|
|
105
|
+
}
|
|
106
|
+
end
|
|
76
107
|
end
|
|
77
108
|
end
|
|
78
109
|
end
|
|
@@ -17,25 +17,27 @@ module Indexmap
|
|
|
17
17
|
api_key = read_api_key
|
|
18
18
|
unless api_key
|
|
19
19
|
logger.debug("IndexNow API key is not configured.")
|
|
20
|
-
return
|
|
20
|
+
return {status: :skipped, reason: :missing_key}
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
entries = entries_to_ping
|
|
24
24
|
if entries.empty?
|
|
25
25
|
logger.debug("IndexNow: no URLs matched the current filter.")
|
|
26
|
-
return
|
|
26
|
+
return {status: :skipped, reason: :no_urls}
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
entries.each_slice(max_urls_per_request) do |batch|
|
|
29
|
+
results = entries.each_slice(max_urls_per_request).map do |batch|
|
|
30
30
|
urls = batch.map(&:loc)
|
|
31
31
|
|
|
32
32
|
if dry_run?
|
|
33
33
|
logger.debug { "IndexNow dry-run: would ping #{urls.count} URLs." }
|
|
34
|
-
next
|
|
34
|
+
next({status: :dry_run, url_count: urls.count})
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
submit_batch(api_key: api_key, urls: urls)
|
|
38
38
|
end
|
|
39
|
+
|
|
40
|
+
summarize_results(results)
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
def write_key_file(key: index_now_configuration.key, path: nil)
|
|
@@ -148,10 +150,10 @@ module Indexmap
|
|
|
148
150
|
|
|
149
151
|
if response.success?
|
|
150
152
|
logger.debug { "Successfully pinged IndexNow with #{urls.count} URLs." }
|
|
151
|
-
|
|
153
|
+
{status: :submitted, url_count: urls.count}
|
|
152
154
|
else
|
|
153
155
|
logger.debug { "Failed to ping IndexNow. Status: #{response.status}, Body: #{response.body}" }
|
|
154
|
-
|
|
156
|
+
{status: :failed, url_count: urls.count, status_code: response.status, body: response.body}
|
|
155
157
|
end
|
|
156
158
|
end
|
|
157
159
|
|
|
@@ -191,6 +193,44 @@ module Indexmap
|
|
|
191
193
|
def generated_key
|
|
192
194
|
SecureRandom.uuid
|
|
193
195
|
end
|
|
196
|
+
|
|
197
|
+
def summarize_results(results)
|
|
198
|
+
dry_runs = results.select { |result| result[:status] == :dry_run }
|
|
199
|
+
submitted = results.select { |result| result[:status] == :submitted }
|
|
200
|
+
failures = results.select { |result| result[:status] == :failed }
|
|
201
|
+
|
|
202
|
+
if dry_runs.any?
|
|
203
|
+
return {
|
|
204
|
+
status: :dry_run,
|
|
205
|
+
url_count: dry_runs.sum { |result| result[:url_count] },
|
|
206
|
+
batch_count: dry_runs.count
|
|
207
|
+
}
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
if failures.empty?
|
|
211
|
+
return {
|
|
212
|
+
status: :submitted,
|
|
213
|
+
url_count: submitted.sum { |result| result[:url_count] },
|
|
214
|
+
batch_count: submitted.count
|
|
215
|
+
}
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
if submitted.empty?
|
|
219
|
+
return {
|
|
220
|
+
status: :failed,
|
|
221
|
+
url_count: 0,
|
|
222
|
+
batch_count: 0,
|
|
223
|
+
failures: failures
|
|
224
|
+
}
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
{
|
|
228
|
+
status: :partial,
|
|
229
|
+
url_count: submitted.sum { |result| result[:url_count] },
|
|
230
|
+
batch_count: submitted.count,
|
|
231
|
+
failures: failures
|
|
232
|
+
}
|
|
233
|
+
end
|
|
194
234
|
end
|
|
195
235
|
end
|
|
196
236
|
end
|
data/lib/indexmap/version.rb
CHANGED
|
@@ -35,14 +35,40 @@ namespace :sitemap do
|
|
|
35
35
|
namespace :google do
|
|
36
36
|
desc "Ping Google Search Console"
|
|
37
37
|
task ping: :environment do
|
|
38
|
-
Indexmap::Pinger::Google.new.ping
|
|
38
|
+
result = Indexmap::Pinger::Google.new.ping
|
|
39
|
+
|
|
40
|
+
case result[:status]
|
|
41
|
+
when :submitted
|
|
42
|
+
puts "Submitted #{result[:sitemap_count]} sitemap #{(result[:sitemap_count] == 1) ? "file" : "files"} to Google Search Console."
|
|
43
|
+
when :partial
|
|
44
|
+
puts "Submitted #{result[:sitemap_count]} sitemap #{(result[:sitemap_count] == 1) ? "file" : "files"} to Google Search Console, with #{result[:failures].count} failure#{"s" unless result[:failures].count == 1}."
|
|
45
|
+
result[:failures].each { |failure| puts format_google_ping_failure(failure) }
|
|
46
|
+
when :failed
|
|
47
|
+
result[:failures].each { |failure| puts format_google_ping_failure(failure) }
|
|
48
|
+
when :skipped
|
|
49
|
+
puts format_google_ping_skip(result)
|
|
50
|
+
end
|
|
39
51
|
end
|
|
40
52
|
end
|
|
41
53
|
|
|
42
54
|
namespace :index_now do
|
|
43
55
|
desc "Ping IndexNow. ENV: SINCE=2026-04-18T10:30:00Z or INDEXNOW_RECENT_HOURS=24"
|
|
44
56
|
task ping: :environment do
|
|
45
|
-
Indexmap::Pinger::IndexNow.new.ping
|
|
57
|
+
result = Indexmap::Pinger::IndexNow.new.ping
|
|
58
|
+
|
|
59
|
+
case result[:status]
|
|
60
|
+
when :submitted
|
|
61
|
+
puts "Submitted #{result[:url_count]} URL#{"s" unless result[:url_count] == 1} to IndexNow in #{result[:batch_count]} request#{"s" unless result[:batch_count] == 1}."
|
|
62
|
+
when :partial
|
|
63
|
+
puts "Submitted #{result[:url_count]} URL#{"s" unless result[:url_count] == 1} to IndexNow in #{result[:batch_count]} request#{"s" unless result[:batch_count] == 1}, with #{result[:failures].count} failure#{"s" unless result[:failures].count == 1}."
|
|
64
|
+
result[:failures].each { |failure| puts format_index_now_ping_failure(failure) }
|
|
65
|
+
when :failed
|
|
66
|
+
result[:failures].each { |failure| puts format_index_now_ping_failure(failure) }
|
|
67
|
+
when :dry_run
|
|
68
|
+
puts "IndexNow dry-run: would submit #{result[:url_count]} URL#{"s" unless result[:url_count] == 1} in #{result[:batch_count]} request#{"s" unless result[:batch_count] == 1}."
|
|
69
|
+
when :skipped
|
|
70
|
+
puts format_index_now_ping_skip(result)
|
|
71
|
+
end
|
|
46
72
|
end
|
|
47
73
|
|
|
48
74
|
desc "Ensure the IndexNow key file exists in public/"
|
|
@@ -64,4 +90,46 @@ namespace :sitemap do
|
|
|
64
90
|
def public_directory(runner)
|
|
65
91
|
runner.public_path
|
|
66
92
|
end
|
|
93
|
+
|
|
94
|
+
def format_google_ping_failure(failure)
|
|
95
|
+
case failure[:reason]
|
|
96
|
+
when :unauthorized
|
|
97
|
+
"Google Search Console does not have access to #{failure[:property]}."
|
|
98
|
+
when :client_error
|
|
99
|
+
"Google ping failed for #{failure[:sitemap_url]} (status #{failure[:status_code]})."
|
|
100
|
+
else
|
|
101
|
+
"Google ping failed."
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def format_google_ping_skip(result)
|
|
106
|
+
case result[:reason]
|
|
107
|
+
when :missing_credentials
|
|
108
|
+
"Google sitemap credentials are not configured; skipped Google submission."
|
|
109
|
+
when :no_sitemaps
|
|
110
|
+
"No sitemap files found; skipped Google submission."
|
|
111
|
+
else
|
|
112
|
+
"Skipped Google submission."
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def format_index_now_ping_failure(failure)
|
|
117
|
+
case failure[:status_code]
|
|
118
|
+
when nil
|
|
119
|
+
"IndexNow submission failed."
|
|
120
|
+
else
|
|
121
|
+
"IndexNow submission failed for #{failure[:url_count]} URL#{"s" unless failure[:url_count] == 1} (status #{failure[:status_code]})."
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def format_index_now_ping_skip(result)
|
|
126
|
+
case result[:reason]
|
|
127
|
+
when :missing_key
|
|
128
|
+
"IndexNow key is not configured and no valid key file was found; skipped IndexNow submission."
|
|
129
|
+
when :no_urls
|
|
130
|
+
"No sitemap URLs matched the current IndexNow filter; skipped IndexNow submission."
|
|
131
|
+
else
|
|
132
|
+
"Skipped IndexNow submission."
|
|
133
|
+
end
|
|
134
|
+
end
|
|
67
135
|
end
|
|
@@ -40,7 +40,7 @@ class IndexmapPingerGoogleTest < Minitest::Test
|
|
|
40
40
|
:fake_authorizer
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
Indexmap::Pinger::Google.new(
|
|
43
|
+
result = Indexmap::Pinger::Google.new(
|
|
44
44
|
configuration: configuration,
|
|
45
45
|
service: service,
|
|
46
46
|
credentials_builder: credentials_builder
|
|
@@ -49,6 +49,8 @@ class IndexmapPingerGoogleTest < Minitest::Test
|
|
|
49
49
|
assert_equal [["{\"type\":\"service_account\"}", "https://www.googleapis.com/auth/webmasters"]], builder_calls
|
|
50
50
|
assert_equal :fake_authorizer, service.authorization
|
|
51
51
|
assert_equal ["sc-domain:example.com", "https://www.example.com/sitemap.xml"], service.submitted
|
|
52
|
+
assert_equal :submitted, result[:status]
|
|
53
|
+
assert_equal 1, result[:sitemap_count]
|
|
52
54
|
end
|
|
53
55
|
end
|
|
54
56
|
|
|
@@ -63,9 +65,53 @@ class IndexmapPingerGoogleTest < Minitest::Test
|
|
|
63
65
|
|
|
64
66
|
service = FakeWebmastersService.new(site_urls: ["sc-domain:example.com"])
|
|
65
67
|
|
|
66
|
-
Indexmap::Pinger::Google.new(configuration: configuration, service: service).ping
|
|
68
|
+
result = Indexmap::Pinger::Google.new(configuration: configuration, service: service).ping
|
|
67
69
|
|
|
68
70
|
assert_nil service.submitted
|
|
71
|
+
assert_equal({status: :skipped, reason: :missing_credentials}, result)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test_reports_missing_sitemap_files
|
|
76
|
+
Dir.mktmpdir do |dir|
|
|
77
|
+
configuration = Indexmap::Configuration.new
|
|
78
|
+
configuration.base_url = "https://www.example.com"
|
|
79
|
+
configuration.public_path = Pathname(dir)
|
|
80
|
+
configuration.google.credentials = "{\"type\":\"service_account\"}"
|
|
81
|
+
|
|
82
|
+
service = FakeWebmastersService.new(site_urls: ["sc-domain:example.com"])
|
|
83
|
+
result = Indexmap::Pinger::Google.new(
|
|
84
|
+
configuration: configuration,
|
|
85
|
+
service: service,
|
|
86
|
+
credentials_builder: ->(**) { :fake_authorizer }
|
|
87
|
+
).ping
|
|
88
|
+
|
|
89
|
+
assert_equal({status: :skipped, reason: :no_sitemaps}, result)
|
|
90
|
+
assert_nil service.submitted
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_reports_google_authorization_failure
|
|
95
|
+
Dir.mktmpdir do |dir|
|
|
96
|
+
public_path = Pathname(dir)
|
|
97
|
+
public_path.join("sitemap.xml").write("<sitemapindex/>")
|
|
98
|
+
|
|
99
|
+
configuration = Indexmap::Configuration.new
|
|
100
|
+
configuration.base_url = "https://www.example.com"
|
|
101
|
+
configuration.public_path = public_path
|
|
102
|
+
configuration.google.credentials = "{\"type\":\"service_account\"}"
|
|
103
|
+
|
|
104
|
+
service = FakeWebmastersService.new(site_urls: ["sc-domain:not-example.org"])
|
|
105
|
+
result = Indexmap::Pinger::Google.new(
|
|
106
|
+
configuration: configuration,
|
|
107
|
+
service: service,
|
|
108
|
+
credentials_builder: ->(**) { :fake_authorizer }
|
|
109
|
+
).ping
|
|
110
|
+
|
|
111
|
+
assert_equal :failed, result[:status]
|
|
112
|
+
assert_equal 1, result[:failures].count
|
|
113
|
+
assert_equal :unauthorized, result[:failures].first[:reason]
|
|
114
|
+
assert_nil service.submitted
|
|
69
115
|
end
|
|
70
116
|
end
|
|
71
117
|
end
|
|
@@ -48,12 +48,15 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
48
48
|
indexnow_url = "https://api.indexnow.org/indexnow"
|
|
49
49
|
stub_request(:post, indexnow_url).to_return(status: 200, body: "", headers: {})
|
|
50
50
|
|
|
51
|
-
Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
51
|
+
result = Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
52
52
|
|
|
53
53
|
assert_requested(:post, indexnow_url, times: 1) do |request|
|
|
54
54
|
payload = JSON.parse(request.body)
|
|
55
55
|
assert_equal "test-key-123", payload.fetch("key")
|
|
56
56
|
end
|
|
57
|
+
assert_equal :submitted, result[:status]
|
|
58
|
+
assert_equal 2, result[:url_count]
|
|
59
|
+
assert_equal 1, result[:batch_count]
|
|
57
60
|
end
|
|
58
61
|
end
|
|
59
62
|
|
|
@@ -74,7 +77,7 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
74
77
|
indexnow_url = "https://api.indexnow.org/indexnow"
|
|
75
78
|
stub_request(:post, indexnow_url).to_return(status: 200, body: "", headers: {})
|
|
76
79
|
|
|
77
|
-
Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
80
|
+
result = Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
78
81
|
|
|
79
82
|
assert_requested(:post, indexnow_url, times: 1) do |request|
|
|
80
83
|
payload = JSON.parse(request.body)
|
|
@@ -83,6 +86,9 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
83
86
|
"https://www.example.com/insights/us/restaurants/overview"
|
|
84
87
|
].sort, payload.fetch("urlList").sort
|
|
85
88
|
end
|
|
89
|
+
assert_equal :submitted, result[:status]
|
|
90
|
+
assert_equal 2, result[:url_count]
|
|
91
|
+
assert_equal 1, result[:batch_count]
|
|
86
92
|
end
|
|
87
93
|
end
|
|
88
94
|
|
|
@@ -104,7 +110,11 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
104
110
|
stub_request(:post, indexnow_url).to_return(status: 200, body: "", headers: {})
|
|
105
111
|
|
|
106
112
|
with_env("SINCE" => "2026-04-15T00:00:00Z") do
|
|
107
|
-
Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
113
|
+
result = Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
114
|
+
|
|
115
|
+
assert_equal :submitted, result[:status]
|
|
116
|
+
assert_equal 1, result[:url_count]
|
|
117
|
+
assert_equal 1, result[:batch_count]
|
|
108
118
|
end
|
|
109
119
|
|
|
110
120
|
assert_requested(:post, indexnow_url, times: 1) do |request|
|
|
@@ -114,6 +124,74 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
114
124
|
end
|
|
115
125
|
end
|
|
116
126
|
|
|
127
|
+
def test_skips_indexnow_ping_when_key_is_missing
|
|
128
|
+
Dir.mktmpdir do |dir|
|
|
129
|
+
public_path = Pathname(dir)
|
|
130
|
+
write_sitemap_files(
|
|
131
|
+
public_path,
|
|
132
|
+
marketing_lastmod: "2026-04-18T00:00:00Z",
|
|
133
|
+
insights_lastmod: "2026-04-10T00:00:00Z"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
configuration = Indexmap::Configuration.new
|
|
137
|
+
configuration.base_url = "https://www.example.com"
|
|
138
|
+
configuration.public_path = public_path
|
|
139
|
+
|
|
140
|
+
result = Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
141
|
+
|
|
142
|
+
assert_equal({status: :skipped, reason: :missing_key}, result)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def test_reports_indexnow_dry_run
|
|
147
|
+
Dir.mktmpdir do |dir|
|
|
148
|
+
public_path = Pathname(dir)
|
|
149
|
+
write_sitemap_files(
|
|
150
|
+
public_path,
|
|
151
|
+
marketing_lastmod: "2026-04-18T00:00:00Z",
|
|
152
|
+
insights_lastmod: "2026-04-10T00:00:00Z"
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
configuration = Indexmap::Configuration.new
|
|
156
|
+
configuration.base_url = "https://www.example.com"
|
|
157
|
+
configuration.public_path = public_path
|
|
158
|
+
configuration.index_now.key = "test-key"
|
|
159
|
+
|
|
160
|
+
with_env("INDEXNOW_DRY_RUN" => "1") do
|
|
161
|
+
result = Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
162
|
+
|
|
163
|
+
assert_equal :dry_run, result[:status]
|
|
164
|
+
assert_equal 2, result[:url_count]
|
|
165
|
+
assert_equal 1, result[:batch_count]
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def test_reports_failed_indexnow_submission
|
|
171
|
+
Dir.mktmpdir do |dir|
|
|
172
|
+
public_path = Pathname(dir)
|
|
173
|
+
write_sitemap_files(
|
|
174
|
+
public_path,
|
|
175
|
+
marketing_lastmod: "2026-04-18T00:00:00Z",
|
|
176
|
+
insights_lastmod: "2026-04-10T00:00:00Z"
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
configuration = Indexmap::Configuration.new
|
|
180
|
+
configuration.base_url = "https://www.example.com"
|
|
181
|
+
configuration.public_path = public_path
|
|
182
|
+
configuration.index_now.key = "test-key"
|
|
183
|
+
|
|
184
|
+
indexnow_url = "https://api.indexnow.org/indexnow"
|
|
185
|
+
stub_request(:post, indexnow_url).to_return(status: 500, body: "boom", headers: {})
|
|
186
|
+
|
|
187
|
+
result = Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
188
|
+
|
|
189
|
+
assert_equal :failed, result[:status]
|
|
190
|
+
assert_equal 1, result[:failures].count
|
|
191
|
+
assert_equal 500, result[:failures].first[:status_code]
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
117
195
|
private
|
|
118
196
|
|
|
119
197
|
def with_env(overrides)
|