RepositoryHttpsUpgradeStrategyTest.java
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.cling.invoker.mvnup.goals;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Optional;
import eu.maveniverse.domtrip.Document;
import org.apache.maven.api.cli.mvnup.UpgradeOptions;
import org.apache.maven.cling.invoker.mvnup.UpgradeContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Unit tests for the {@link RepositoryHttpsUpgradeStrategy} class.
* Tests HTTP to HTTPS repository URL upgrades for all POM sections.
*/
@DisplayName("RepositoryHttpsUpgradeStrategy")
class RepositoryHttpsUpgradeStrategyTest {
private RepositoryHttpsUpgradeStrategy strategy;
@BeforeEach
void setUp() {
strategy = new RepositoryHttpsUpgradeStrategy();
}
private UpgradeContext createMockContext() {
return TestUtils.createMockContext();
}
private UpgradeContext createMockContext(UpgradeOptions options) {
return TestUtils.createMockContext(options);
}
@Nested
@DisplayName("Applicability")
class ApplicabilityTests {
@Test
@DisplayName("should be applicable when --model option is true")
void shouldBeApplicableWhenModelOptionTrue() {
UpgradeOptions options = mock(UpgradeOptions.class);
when(options.model()).thenReturn(Optional.of(true));
when(options.all()).thenReturn(Optional.empty());
when(options.infer()).thenReturn(Optional.empty());
when(options.plugins()).thenReturn(Optional.empty());
when(options.modelVersion()).thenReturn(Optional.empty());
UpgradeContext context = createMockContext(options);
assertTrue(strategy.isApplicable(context), "Strategy should be applicable when --model is true");
}
@Test
@DisplayName("should be applicable when --all option is specified")
void shouldBeApplicableWhenAllOptionSpecified() {
UpgradeOptions options = mock(UpgradeOptions.class);
when(options.all()).thenReturn(Optional.of(true));
when(options.model()).thenReturn(Optional.empty());
when(options.infer()).thenReturn(Optional.empty());
when(options.plugins()).thenReturn(Optional.empty());
when(options.modelVersion()).thenReturn(Optional.empty());
UpgradeContext context = createMockContext(options);
assertTrue(strategy.isApplicable(context), "Strategy should be applicable when --all is specified");
}
@Test
@DisplayName("should be applicable by default when no specific options provided")
void shouldBeApplicableByDefaultWhenNoSpecificOptions() {
UpgradeOptions options = TestUtils.createDefaultOptions();
UpgradeContext context = createMockContext(options);
assertTrue(strategy.isApplicable(context), "Strategy should be applicable by default");
}
@Test
@DisplayName("should not be applicable when --model option is false and other options set")
void shouldNotBeApplicableWhenModelOptionFalseAndOtherOptionsSet() {
UpgradeOptions options = mock(UpgradeOptions.class);
when(options.model()).thenReturn(Optional.of(false));
when(options.all()).thenReturn(Optional.empty());
when(options.infer()).thenReturn(Optional.empty());
when(options.plugins()).thenReturn(Optional.of(true));
when(options.modelVersion()).thenReturn(Optional.empty());
UpgradeContext context = createMockContext(options);
assertFalse(strategy.isApplicable(context), "Strategy should not be applicable when --model is false");
}
}
@Nested
@DisplayName("Well-Known URL Mappings")
class WellKnownUrlMappingTests {
@Test
@DisplayName("should map Apache snapshots repository URL")
void shouldMapApacheSnapshotsUrl() {
assertEquals(
"https://repository.apache.org/snapshots",
RepositoryHttpsUpgradeStrategy.mapWellKnownUrl("http://repository.apache.org/snapshots"));
}
@Test
@DisplayName("should map Apache releases repository URL")
void shouldMapApacheReleasesUrl() {
assertEquals(
"https://repository.apache.org/releases",
RepositoryHttpsUpgradeStrategy.mapWellKnownUrl("http://repository.apache.org/releases"));
}
@Test
@DisplayName("should map repo1.maven.org to canonical HTTPS URL")
void shouldMapRepo1MavenOrg() {
assertEquals(
"https://repo.maven.apache.org/maven2",
RepositoryHttpsUpgradeStrategy.mapWellKnownUrl("http://repo1.maven.org/maven2"));
}
@Test
@DisplayName("should map repo.maven.apache.org to canonical HTTPS URL")
void shouldMapRepoMavenApacheOrg() {
assertEquals(
"https://repo.maven.apache.org/maven2",
RepositoryHttpsUpgradeStrategy.mapWellKnownUrl("http://repo.maven.apache.org/maven2"));
}
@Test
@DisplayName("should map central.maven.org to canonical HTTPS URL")
void shouldMapCentralMavenOrg() {
assertEquals(
"https://repo.maven.apache.org/maven2",
RepositoryHttpsUpgradeStrategy.mapWellKnownUrl("http://central.maven.org/maven2"));
}
@Test
@DisplayName("should preserve trailing slash for well-known URLs")
void shouldPreserveTrailingSlash() {
assertEquals(
"https://repo.maven.apache.org/maven2/",
RepositoryHttpsUpgradeStrategy.mapWellKnownUrl("http://repo1.maven.org/maven2/"));
}
@Test
@DisplayName("should return null for unknown URLs")
void shouldReturnNullForUnknownUrls() {
assertNull(RepositoryHttpsUpgradeStrategy.mapWellKnownUrl("http://example.com/repo"));
}
}
@Nested
@DisplayName("Repository URL Upgrades")
class RepositoryUrlUpgradeTests {
@Test
@DisplayName("should upgrade HTTP repository URL to HTTPS")
void shouldUpgradeHttpRepositoryUrl() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>my-repo</id>
<url>http://example.com/maven2</url>
</repository>
</repositories>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(xml.contains("https://example.com/maven2"), "URL should be upgraded to HTTPS");
assertFalse(
xml.contains("http://example.com/maven2"),
"Original HTTP URL should be replaced (excluding xmlns)");
}
@Test
@DisplayName("should upgrade well-known Apache snapshots URL")
void shouldUpgradeWellKnownApacheSnapshotsUrl() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>apache-snapshots</id>
<url>http://repository.apache.org/snapshots</url>
</repository>
</repositories>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(
xml.contains("https://repository.apache.org/snapshots"),
"URL should be upgraded to canonical HTTPS URL");
}
@Test
@DisplayName("should normalize repo1.maven.org to canonical URL")
void shouldNormalizeRepo1MavenOrg() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>central</id>
<url>http://repo1.maven.org/maven2</url>
</repository>
</repositories>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
strategy.doApply(context, pomMap);
String xml = DomUtils.toXml(document);
assertTrue(
xml.contains("https://repo.maven.apache.org/maven2"),
"URL should be normalized to canonical Maven Central HTTPS URL");
}
@Test
@DisplayName("should not modify URLs already using HTTPS")
void shouldNotModifyHttpsUrls() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertEquals(0, result.modifiedCount(), "No POMs should be modified");
String xml = DomUtils.toXml(document);
assertTrue(xml.contains("https://repo.maven.apache.org/maven2"), "HTTPS URL should remain unchanged");
}
@Test
@DisplayName("should handle POM with no repositories")
void shouldHandlePomWithNoRepositories() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertEquals(0, result.modifiedCount(), "No POMs should be modified");
}
}
@Nested
@DisplayName("Plugin Repository URL Upgrades")
class PluginRepositoryUrlUpgradeTests {
@Test
@DisplayName("should upgrade HTTP pluginRepository URL to HTTPS")
void shouldUpgradeHttpPluginRepositoryUrl() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<pluginRepositories>
<pluginRepository>
<id>my-plugin-repo</id>
<url>http://plugins.example.com/maven2</url>
</pluginRepository>
</pluginRepositories>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(xml.contains("https://plugins.example.com/maven2"), "Plugin repository URL should be upgraded");
}
}
@Nested
@DisplayName("Distribution Management URL Upgrades")
class DistributionManagementUrlUpgradeTests {
@Test
@DisplayName("should upgrade distributionManagement repository URL")
void shouldUpgradeDistributionManagementRepositoryUrl() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<distributionManagement>
<repository>
<id>releases</id>
<url>http://repository.apache.org/releases</url>
</repository>
</distributionManagement>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(
xml.contains("https://repository.apache.org/releases"),
"Distribution management repository URL should be upgraded");
}
@Test
@DisplayName("should upgrade distributionManagement snapshotRepository URL")
void shouldUpgradeDistributionManagementSnapshotRepositoryUrl() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<distributionManagement>
<snapshotRepository>
<id>snapshots</id>
<url>http://repository.apache.org/snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(
xml.contains("https://repository.apache.org/snapshots"),
"Snapshot repository URL should be upgraded");
}
@Test
@DisplayName("should upgrade both repository and snapshotRepository in distributionManagement")
void shouldUpgradeBothRepositoryAndSnapshotRepository() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<distributionManagement>
<repository>
<id>releases</id>
<url>http://nexus.example.com/releases</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<url>http://nexus.example.com/snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(xml.contains("https://nexus.example.com/releases"), "Repository URL should be upgraded");
assertTrue(
xml.contains("https://nexus.example.com/snapshots"), "Snapshot repository URL should be upgraded");
}
}
@Nested
@DisplayName("Profile-Scoped Repository URL Upgrades")
class ProfileScopedRepositoryUrlUpgradeTests {
@Test
@DisplayName("should upgrade HTTP repository URLs in profiles")
void shouldUpgradeHttpRepositoryUrlsInProfiles() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<profiles>
<profile>
<id>staging</id>
<repositories>
<repository>
<id>staging-repo</id>
<url>http://staging.example.com/maven2</url>
</repository>
</repositories>
</profile>
</profiles>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(
xml.contains("https://staging.example.com/maven2"),
"Profile repository URL should be upgraded to HTTPS");
}
@Test
@DisplayName("should upgrade HTTP pluginRepository URLs in profiles")
void shouldUpgradeHttpPluginRepositoryUrlsInProfiles() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<profiles>
<profile>
<id>staging</id>
<pluginRepositories>
<pluginRepository>
<id>staging-plugins</id>
<url>http://staging.example.com/plugins</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(
xml.contains("https://staging.example.com/plugins"),
"Profile plugin repository URL should be upgraded to HTTPS");
}
}
@Nested
@DisplayName("Multiple Repositories")
class MultipleRepositoriesTests {
@Test
@DisplayName("should upgrade multiple HTTP repository URLs in a single POM")
void shouldUpgradeMultipleHttpRepositoryUrls() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>central</id>
<url>http://repo1.maven.org/maven2</url>
</repository>
<repository>
<id>custom</id>
<url>http://custom.example.com/repo</url>
</repository>
<repository>
<id>secure</id>
<url>https://secure.example.com/repo</url>
</repository>
</repositories>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
// Well-known URL should be normalized
assertTrue(
xml.contains("https://repo.maven.apache.org/maven2"),
"repo1.maven.org should be normalized to canonical URL");
// Generic HTTP should be upgraded
assertTrue(xml.contains("https://custom.example.com/repo"), "Custom HTTP URL should be upgraded to HTTPS");
// HTTPS should remain unchanged
assertTrue(xml.contains("https://secure.example.com/repo"), "Existing HTTPS URL should remain unchanged");
}
@Test
@DisplayName("should upgrade repositories across all sections")
void shouldUpgradeRepositoriesAcrossAllSections() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>repo1</id>
<url>http://repo.example.com/releases</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>plugin-repo1</id>
<url>http://plugins.example.com/releases</url>
</pluginRepository>
</pluginRepositories>
<distributionManagement>
<repository>
<id>dist-repo</id>
<url>http://dist.example.com/releases</url>
</repository>
</distributionManagement>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(xml.contains("https://repo.example.com/releases"), "Repository URL should be upgraded");
assertTrue(
xml.contains("https://plugins.example.com/releases"), "Plugin repository URL should be upgraded");
assertTrue(
xml.contains("https://dist.example.com/releases"),
"Distribution management repository URL should be upgraded");
}
}
@Nested
@DisplayName("Edge Cases")
class EdgeCaseTests {
@Test
@DisplayName("should handle repository with no URL element")
void shouldHandleRepositoryWithNoUrlElement() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>no-url-repo</id>
</repository>
</repositories>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed without errors");
assertEquals(0, result.modifiedCount(), "No POMs should be modified");
}
@Test
@DisplayName("should handle repository with no id element")
void shouldHandleRepositoryWithNoIdElement() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<url>http://example.com/maven2</url>
</repository>
</repositories>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);
assertTrue(result.success(), "Upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have modified POMs");
String xml = DomUtils.toXml(document);
assertTrue(xml.contains("https://example.com/maven2"), "URL should be upgraded even without id");
}
@Test
@DisplayName("should normalize central.maven.org to canonical URL")
void shouldNormalizeCentralMavenOrg() {
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>central</id>
<url>http://central.maven.org/maven2</url>
</repository>
</repositories>
</project>
""";
Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
UpgradeContext context = createMockContext();
strategy.doApply(context, pomMap);
String xml = DomUtils.toXml(document);
assertTrue(
xml.contains("https://repo.maven.apache.org/maven2"),
"central.maven.org should be normalized to canonical Maven Central URL");
}
}
}