indexmap 0.5.0 → 0.7.0

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.
@@ -8,41 +8,49 @@ class IndexmapConfigurationTest < Minitest::Test
8
8
  end
9
9
 
10
10
  def test_writer_builds_from_configured_callables
11
- Dir.mktmpdir do |dir|
12
- public_path = Pathname(dir)
13
-
14
- Indexmap.configure do |config|
15
- config.base_url = -> { "https://example.com" }
16
- config.public_path = -> { public_path }
17
- config.sections = -> do
18
- [Indexmap::Section.new(filename: "sitemap-pages.xml", entries: [Indexmap::Entry.new(loc: "https://example.com/")])]
19
- end
11
+ Indexmap.configure do |config|
12
+ config.base_url = -> { "https://example.com" }
13
+ config.sections = -> do
14
+ [Indexmap::Section.new(filename: "sitemap-pages.xml", entries: [Indexmap::Entry.new(loc: "https://example.com/")])]
20
15
  end
16
+ end
21
17
 
22
- Indexmap.configuration.writer.write
18
+ files = Indexmap.configuration.writer.write
19
+
20
+ assert_includes files.find { |file| file.filename == "sitemap.xml" }.body, "<loc>https://example.com/sitemap-pages.xml</loc>"
21
+ assert_includes files.find { |file| file.filename == "sitemap-pages.xml" }.body, "<loc>https://example.com/</loc>"
22
+ end
23
23
 
24
- assert_includes public_path.join("sitemap.xml").read, "<loc>https://example.com/sitemap-pages.xml</loc>"
25
- assert_includes public_path.join("sitemap-pages.xml").read, "<loc>https://example.com/</loc>"
24
+ def test_create_writes_to_configured_storage
25
+ storage = Indexmap::Storage::Memory.new
26
+
27
+ Indexmap.configure do |config|
28
+ config.base_url = "https://example.com"
29
+ config.storage = storage
30
+ config.sections = [
31
+ Indexmap::Section.new(filename: "sitemap-pages.xml", entries: [Indexmap::Entry.new(loc: "https://example.com/")])
32
+ ]
26
33
  end
34
+
35
+ files = Indexmap.create
36
+
37
+ assert_equal ["sitemap-pages.xml", "sitemap.xml"], files
38
+ assert_includes storage.read("sitemap.xml"), "<loc>https://example.com/sitemap-pages.xml</loc>"
39
+ assert_includes storage.read("sitemap-pages.xml"), "<loc>https://example.com/</loc>"
27
40
  end
28
41
 
29
42
  def test_writer_builds_single_file_writer_from_configured_entries
30
- Dir.mktmpdir do |dir|
31
- public_path = Pathname(dir)
32
-
33
- Indexmap.configure do |config|
34
- config.base_url = "https://example.com"
35
- config.public_path = public_path
36
- config.format = :single_file
37
- config.entries = -> { [Indexmap::Entry.new(loc: "https://example.com/")] }
38
- end
43
+ Indexmap.configure do |config|
44
+ config.base_url = "https://example.com"
45
+ config.format = :single_file
46
+ config.entries = -> { [Indexmap::Entry.new(loc: "https://example.com/")] }
47
+ end
39
48
 
40
- Indexmap.configuration.writer.write
49
+ files = Indexmap.configuration.writer.write
41
50
 
42
- assert_includes public_path.join("sitemap.xml").read, "<urlset"
43
- assert_includes public_path.join("sitemap.xml").read, "<loc>https://example.com/</loc>"
44
- refute public_path.join("sitemap-pages.xml").exist?
45
- end
51
+ assert_equal ["sitemap.xml"], files.map(&:filename)
52
+ assert_includes files.fetch(0).body, "<urlset"
53
+ assert_includes files.fetch(0).body, "<loc>https://example.com/</loc>"
46
54
  end
47
55
 
48
56
  def test_writer_raises_without_base_url
@@ -83,12 +91,107 @@ class IndexmapConfigurationTest < Minitest::Test
83
91
  config.google.credentials = -> { "{\"type\":\"service_account\"}" }
84
92
  config.google.property = -> { "sc-domain:example.com" }
85
93
  config.index_now.key = -> { "example-key" }
94
+ config.index_now.key_filename = -> { "index-now-key.txt" }
86
95
  config.index_now.max_urls_per_request = -> { 250 }
96
+ config.index_now.write_key_file = -> { false }
87
97
  end
88
98
 
89
99
  assert_equal "{\"type\":\"service_account\"}", Indexmap.configuration.google.credentials
90
100
  assert_equal "sc-domain:example.com", Indexmap.configuration.google.property
91
101
  assert_equal "example-key", Indexmap.configuration.index_now.key
102
+ assert_equal "index-now-key.txt", Indexmap.configuration.index_now.key_filename
92
103
  assert_equal 250, Indexmap.configuration.index_now.max_urls_per_request
104
+ refute Indexmap.configuration.index_now.write_key_file?
105
+ end
106
+
107
+ def test_index_now_key_file_writing_defaults_to_configured_key_presence
108
+ config = Indexmap::Configuration.new
109
+
110
+ refute config.index_now.write_key_file?
111
+
112
+ config.index_now.key = "1234567890abcdef1234567890abcdef"
113
+
114
+ assert config.index_now.write_key_file?
115
+ end
116
+
117
+ def test_index_now_key_file_writing_can_be_disabled_with_a_configured_key
118
+ config = Indexmap::Configuration.new
119
+ config.index_now.key = "1234567890abcdef1234567890abcdef"
120
+ config.index_now.write_key_file = false
121
+
122
+ refute config.index_now.write_key_file?
123
+ end
124
+
125
+ def test_named_outputs_inherit_configuration_defaults
126
+ storage = Indexmap::Storage::Memory.new
127
+
128
+ Indexmap.configure do |config|
129
+ config.base_url = "https://example.com"
130
+ config.storage = storage
131
+ config.output :reports do |output|
132
+ output.sections = [
133
+ Indexmap::Section.new(
134
+ filename: "sitemap-reports.xml",
135
+ entries: [Indexmap::Entry.new(loc: "https://example.com/reports")]
136
+ )
137
+ ]
138
+ end
139
+ end
140
+
141
+ files = Indexmap.create(:reports)
142
+
143
+ assert_equal ["sitemap-reports.xml", "sitemap.xml"], files
144
+ assert_includes storage.read("sitemap.xml"), "https://example.com/sitemap-reports.xml"
145
+ end
146
+
147
+ def test_create_writes_single_file_named_output_without_default_index
148
+ storage = Indexmap::Storage::Memory.new
149
+
150
+ Indexmap.configure do |config|
151
+ config.base_url = "https://example.com"
152
+ config.storage = storage
153
+ config.output :dynamic do |output|
154
+ output.format = :single_file
155
+ output.index_filename = "sitemap-dynamic.xml"
156
+ output.entries = [
157
+ Indexmap::Entry.new(loc: "https://example.com/dynamic")
158
+ ]
159
+ end
160
+ end
161
+
162
+ files = Indexmap.create(:dynamic)
163
+
164
+ assert_equal ["sitemap-dynamic.xml"], files
165
+ refute storage.exist?("sitemap.xml")
166
+ assert_includes storage.read("sitemap-dynamic.xml"), "https://example.com/dynamic"
167
+ end
168
+
169
+ def test_create_preserves_existing_files_when_validation_fails
170
+ storage = Indexmap::Storage::Memory.new
171
+ storage.write("sitemap.xml", "old index")
172
+ storage.write("sitemap-pages.xml", "old child")
173
+
174
+ Indexmap.configure do |config|
175
+ config.base_url = "https://example.com"
176
+ config.storage = storage
177
+ config.sections = [
178
+ Indexmap::Section.new(
179
+ filename: "sitemap-pages.xml",
180
+ entries: [Indexmap::Entry.new(loc: "https://example.com/about?utm_source=test")]
181
+ )
182
+ ]
183
+ end
184
+
185
+ error = assert_raises(Indexmap::ValidationError) { Indexmap.create }
186
+
187
+ assert_match "Parameterized sitemap URLs detected", error.message
188
+ assert_equal "old index", storage.read("sitemap.xml")
189
+ assert_equal "old child", storage.read("sitemap-pages.xml")
190
+ end
191
+
192
+ def test_after_create_requires_a_block
193
+ error = assert_raises(ArgumentError) { Indexmap.configuration.after_create }
194
+
195
+ assert_equal "after_create requires a block", error.message
93
196
  end
94
197
  end
@@ -16,7 +16,7 @@ class IndexmapParserTest < Minitest::Test
16
16
  XML
17
17
  )
18
18
 
19
- parser = Indexmap::Parser.new(path: "https://www.example.com/sitemap.xml")
19
+ parser = Indexmap::Parser.new(source: "https://www.example.com/sitemap.xml")
20
20
 
21
21
  assert_equal ["/", "/pages/features"], parser.paths
22
22
  end
@@ -44,7 +44,7 @@ class IndexmapParserTest < Minitest::Test
44
44
  XML
45
45
  )
46
46
 
47
- parser = Indexmap::Parser.new(path: "https://www.example.com/sitemap.xml")
47
+ parser = Indexmap::Parser.new(source: "https://www.example.com/sitemap.xml")
48
48
 
49
49
  assert_equal ["/tools/google-reviews-calculator"], parser.paths
50
50
  assert_equal ["https://www.reviato.com/tools/google-reviews-calculator"], parser.urls(base_url: "https://www.reviato.com")
@@ -73,9 +73,50 @@ class IndexmapParserTest < Minitest::Test
73
73
  XML
74
74
  )
75
75
 
76
- parser = Indexmap::Parser.new(path: "http://localhost:3001/sitemap.xml", rebase_remote_children: true)
76
+ parser = Indexmap::Parser.new(source: "http://localhost:3001/sitemap.xml", rebase_remote_children: true)
77
77
 
78
78
  assert_equal ["/pages/pricing"], parser.paths
79
79
  assert_equal ["http://localhost:3001/pages/pricing"], parser.urls(base_url: "http://localhost:3001")
80
80
  end
81
+
82
+ def test_parses_storage_sitemap_index_with_directory_keys
83
+ storage = Indexmap::Storage::Memory.new
84
+ storage.write("sitemaps/sitemap.xml", <<~XML)
85
+ <?xml version="1.0" encoding="UTF-8"?>
86
+ <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
87
+ <sitemap><loc>https://www.example.com/sitemaps/content.xml</loc></sitemap>
88
+ </sitemapindex>
89
+ XML
90
+ storage.write("sitemaps/content.xml", <<~XML)
91
+ <?xml version="1.0" encoding="UTF-8"?>
92
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
93
+ <url><loc>https://www.example.com/pages/features</loc></url>
94
+ </urlset>
95
+ XML
96
+
97
+ parser = Indexmap::Parser.new(source: "sitemaps/sitemap.xml", storage: storage)
98
+
99
+ assert_equal ["/pages/features"], parser.paths
100
+ assert_equal ["sitemaps/content.xml"], parser.entries.map(&:source_sitemap)
101
+ end
102
+
103
+ def test_parses_relative_child_sitemaps_from_parent_directory
104
+ storage = Indexmap::Storage::Memory.new
105
+ storage.write("sitemaps/sitemap.xml", <<~XML)
106
+ <?xml version="1.0" encoding="UTF-8"?>
107
+ <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
108
+ <sitemap><loc>content.xml</loc></sitemap>
109
+ </sitemapindex>
110
+ XML
111
+ storage.write("sitemaps/content.xml", <<~XML)
112
+ <?xml version="1.0" encoding="UTF-8"?>
113
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
114
+ <url><loc>https://www.example.com/pages/pricing</loc></url>
115
+ </urlset>
116
+ XML
117
+
118
+ parser = Indexmap::Parser.new(source: "sitemaps/sitemap.xml", storage: storage)
119
+
120
+ assert_equal ["/pages/pricing"], parser.paths
121
+ end
81
122
  end
@@ -8,10 +8,11 @@ class IndexmapPingerGoogleTest < Minitest::Test
8
8
 
9
9
  class FakeWebmastersService
10
10
  attr_accessor :authorization
11
- attr_reader :submitted, :list_sites_calls
11
+ attr_reader :submitted, :submissions, :list_sites_calls
12
12
 
13
13
  def initialize(site_urls:)
14
14
  @site_urls = site_urls
15
+ @submissions = []
15
16
  @list_sites_calls = 0
16
17
  end
17
18
 
@@ -22,122 +23,150 @@ class IndexmapPingerGoogleTest < Minitest::Test
22
23
 
23
24
  def submit_sitemap(property, sitemap_url)
24
25
  @submitted = [property, sitemap_url]
26
+ @submissions << @submitted
25
27
  end
26
28
  end
27
29
 
28
30
  def test_pings_google_for_each_sitemap_file
29
- Dir.mktmpdir do |dir|
30
- public_path = Pathname(dir)
31
- public_path.join("sitemap.xml").write("<sitemapindex/>")
32
-
33
- configuration = Indexmap::Configuration.new
34
- configuration.base_url = "https://www.example.com"
35
- configuration.public_path = public_path
36
- configuration.google.credentials = "{\"type\":\"service_account\"}"
37
-
38
- service = FakeWebmastersService.new(site_urls: ["sc-domain:example.com"])
39
- builder_calls = []
40
- credentials_builder = lambda do |credentials:, scope:|
41
- builder_calls << [credentials, scope]
42
- :fake_authorizer
43
- end
44
-
45
- result = Indexmap::Pinger::Google.new(
46
- configuration: configuration,
47
- service: service,
48
- credentials_builder: credentials_builder
49
- ).ping
50
-
51
- assert_equal [["{\"type\":\"service_account\"}", "https://www.googleapis.com/auth/webmasters"]], builder_calls
52
- assert_equal :fake_authorizer, service.authorization
53
- assert_equal ["sc-domain:example.com", "https://www.example.com/sitemap.xml"], service.submitted
54
- assert_equal :submitted, result[:status]
55
- assert_equal 1, result[:sitemap_count]
56
- assert_equal 1, service.list_sites_calls
31
+ configuration = configuration_with(storage: storage_with("sitemap.xml" => "<sitemapindex/>"))
32
+ configuration.google.credentials = "{\"type\":\"service_account\"}"
33
+
34
+ service = FakeWebmastersService.new(site_urls: ["sc-domain:example.com"])
35
+ builder_calls = []
36
+ credentials_builder = lambda do |credentials:, scope:|
37
+ builder_calls << [credentials, scope]
38
+ :fake_authorizer
57
39
  end
58
- end
59
40
 
60
- def test_skips_google_ping_when_credentials_are_missing
61
- Dir.mktmpdir do |dir|
62
- public_path = Pathname(dir)
63
- public_path.join("sitemap.xml").write("<sitemapindex/>")
41
+ result = Indexmap::Pinger::Google.new(
42
+ configuration: configuration,
43
+ service: service,
44
+ credentials_builder: credentials_builder
45
+ ).ping
46
+
47
+ assert_equal [["{\"type\":\"service_account\"}", "https://www.googleapis.com/auth/webmasters"]], builder_calls
48
+ assert_equal :fake_authorizer, service.authorization
49
+ assert_equal ["sc-domain:example.com", "https://www.example.com/sitemap.xml"], service.submitted
50
+ assert_equal :submitted, result[:status]
51
+ assert_equal 1, result[:sitemap_count]
52
+ assert_equal 0, result[:url_count]
53
+ assert_equal 1, service.list_sites_calls
54
+ end
64
55
 
65
- configuration = Indexmap::Configuration.new
66
- configuration.base_url = "https://www.example.com"
67
- configuration.public_path = public_path
56
+ def test_reports_unique_url_count_from_submitted_sitemaps
57
+ storage = storage_with(
58
+ "sitemap.xml" => <<~XML,
59
+ <?xml version="1.0" encoding="UTF-8"?>
60
+ <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
61
+ <sitemap><loc>https://www.example.com/sitemap-pages.xml</loc></sitemap>
62
+ <sitemap><loc>https://www.example.com/sitemap-posts.xml</loc></sitemap>
63
+ </sitemapindex>
64
+ XML
65
+ "sitemap-pages.xml" => <<~XML,
66
+ <?xml version="1.0" encoding="UTF-8"?>
67
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
68
+ <url><loc>https://www.example.com/</loc></url>
69
+ <url><loc>https://www.example.com/about</loc></url>
70
+ </urlset>
71
+ XML
72
+ "sitemap-posts.xml" => <<~XML
73
+ <?xml version="1.0" encoding="UTF-8"?>
74
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
75
+ <url><loc>https://www.example.com/about</loc></url>
76
+ <url><loc>https://www.example.com/blog</loc></url>
77
+ </urlset>
78
+ XML
79
+ )
80
+ configuration = configuration_with(storage: storage)
81
+ configuration.google.credentials = "{\"type\":\"service_account\"}"
82
+
83
+ service = FakeWebmastersService.new(site_urls: ["sc-domain:example.com"])
84
+ result = Indexmap::Pinger::Google.new(
85
+ configuration: configuration,
86
+ service: service,
87
+ credentials_builder: ->(**) { :fake_authorizer }
88
+ ).ping
89
+
90
+ assert_equal :submitted, result[:status]
91
+ assert_equal 3, result[:sitemap_count]
92
+ assert_equal 3, result[:url_count]
93
+ assert_equal [
94
+ ["sc-domain:example.com", "https://www.example.com/sitemap-pages.xml"],
95
+ ["sc-domain:example.com", "https://www.example.com/sitemap-posts.xml"],
96
+ ["sc-domain:example.com", "https://www.example.com/sitemap.xml"]
97
+ ], service.submissions
98
+ end
68
99
 
69
- service = FakeWebmastersService.new(site_urls: ["sc-domain:example.com"])
100
+ def test_skips_google_ping_when_credentials_are_missing
101
+ configuration = configuration_with(storage: storage_with("sitemap.xml" => "<sitemapindex/>"))
102
+ service = FakeWebmastersService.new(site_urls: ["sc-domain:example.com"])
70
103
 
71
- result = Indexmap::Pinger::Google.new(configuration: configuration, service: service).ping
104
+ result = Indexmap::Pinger::Google.new(configuration: configuration, service: service).ping
72
105
 
73
- assert_nil service.submitted
74
- assert_equal({status: :skipped, reason: :missing_credentials}, result)
75
- end
106
+ assert_nil service.submitted
107
+ assert_equal({status: :skipped, reason: :missing_credentials}, result)
76
108
  end
77
109
 
78
110
  def test_reports_missing_sitemap_files
79
- Dir.mktmpdir do |dir|
80
- configuration = Indexmap::Configuration.new
81
- configuration.base_url = "https://www.example.com"
82
- configuration.public_path = Pathname(dir)
83
- configuration.google.credentials = "{\"type\":\"service_account\"}"
84
-
85
- service = FakeWebmastersService.new(site_urls: ["sc-domain:example.com"])
86
- result = Indexmap::Pinger::Google.new(
87
- configuration: configuration,
88
- service: service,
89
- credentials_builder: ->(**) { :fake_authorizer }
90
- ).ping
91
-
92
- assert_equal({status: :skipped, reason: :no_sitemaps}, result)
93
- assert_nil service.submitted
94
- end
111
+ configuration = configuration_with
112
+ configuration.google.credentials = "{\"type\":\"service_account\"}"
113
+
114
+ service = FakeWebmastersService.new(site_urls: ["sc-domain:example.com"])
115
+ result = Indexmap::Pinger::Google.new(
116
+ configuration: configuration,
117
+ service: service,
118
+ credentials_builder: ->(**) { :fake_authorizer }
119
+ ).ping
120
+
121
+ assert_equal({status: :skipped, reason: :no_sitemaps}, result)
122
+ assert_nil service.submitted
95
123
  end
96
124
 
97
125
  def test_reports_google_authorization_failure
98
- Dir.mktmpdir do |dir|
99
- public_path = Pathname(dir)
100
- public_path.join("sitemap.xml").write("<sitemapindex/>")
101
-
102
- configuration = Indexmap::Configuration.new
103
- configuration.base_url = "https://www.example.com"
104
- configuration.public_path = public_path
105
- configuration.google.credentials = "{\"type\":\"service_account\"}"
106
-
107
- service = FakeWebmastersService.new(site_urls: ["sc-domain:not-example.org"])
108
- result = Indexmap::Pinger::Google.new(
109
- configuration: configuration,
110
- service: service,
111
- credentials_builder: ->(**) { :fake_authorizer }
112
- ).ping
113
-
114
- assert_equal :failed, result[:status]
115
- assert_equal 1, result[:failures].count
116
- assert_equal :unauthorized, result[:failures].first[:reason]
117
- assert_nil service.submitted
118
- end
126
+ configuration = configuration_with(storage: storage_with("sitemap.xml" => "<sitemapindex/>"))
127
+ configuration.google.credentials = "{\"type\":\"service_account\"}"
128
+
129
+ service = FakeWebmastersService.new(site_urls: ["sc-domain:not-example.org"])
130
+ result = Indexmap::Pinger::Google.new(
131
+ configuration: configuration,
132
+ service: service,
133
+ credentials_builder: ->(**) { :fake_authorizer }
134
+ ).ping
135
+
136
+ assert_equal :failed, result[:status]
137
+ assert_equal 1, result[:failures].count
138
+ assert_equal :unauthorized, result[:failures].first[:reason]
139
+ assert_nil service.submitted
119
140
  end
120
141
 
121
142
  def test_google_authorization_requires_exact_property_match
122
- Dir.mktmpdir do |dir|
123
- public_path = Pathname(dir)
124
- public_path.join("sitemap.xml").write("<sitemapindex/>")
143
+ configuration = configuration_with(storage: storage_with("sitemap.xml" => "<sitemapindex/>"))
144
+ configuration.google.credentials = "{\"type\":\"service_account\"}"
145
+
146
+ service = FakeWebmastersService.new(site_urls: ["sc-domain:myexample.com"])
147
+ result = Indexmap::Pinger::Google.new(
148
+ configuration: configuration,
149
+ service: service,
150
+ credentials_builder: ->(**) { :fake_authorizer }
151
+ ).ping
152
+
153
+ assert_equal :failed, result[:status]
154
+ assert_equal :unauthorized, result[:failures].first[:reason]
155
+ assert_nil service.submitted
156
+ end
125
157
 
126
- configuration = Indexmap::Configuration.new
158
+ private
159
+
160
+ def configuration_with(storage: Indexmap::Storage::Memory.new(public_url: "https://www.example.com"))
161
+ Indexmap::Configuration.new.tap do |configuration|
127
162
  configuration.base_url = "https://www.example.com"
128
- configuration.public_path = public_path
129
- configuration.google.credentials = "{\"type\":\"service_account\"}"
130
-
131
- service = FakeWebmastersService.new(site_urls: ["sc-domain:myexample.com"])
132
- result = Indexmap::Pinger::Google.new(
133
- configuration: configuration,
134
- service: service,
135
- credentials_builder: ->(**) { :fake_authorizer }
136
- ).ping
137
-
138
- assert_equal :failed, result[:status]
139
- assert_equal :unauthorized, result[:failures].first[:reason]
140
- assert_nil service.submitted
163
+ configuration.storage = storage
164
+ end
165
+ end
166
+
167
+ def storage_with(files)
168
+ Indexmap::Storage::Memory.new(public_url: "https://www.example.com").tap do |storage|
169
+ files.each { |filename, body| storage.write(filename, body) }
141
170
  end
142
171
  end
143
172
  end