11package me .itzg .helpers .curseforge ;
22
3+ import static com .github .tomakehurst .wiremock .client .WireMock .*;
34import static com .github .tomakehurst .wiremock .core .WireMockConfiguration .wireMockConfig ;
5+ import static java .util .Collections .singletonList ;
46import static org .assertj .core .api .Assertions .assertThat ;
57
8+ import com .github .tomakehurst .wiremock .client .WireMock ;
69import com .github .tomakehurst .wiremock .extension .responsetemplating .ResponseTemplateTransformer ;
710import com .github .tomakehurst .wiremock .junit5 .WireMockExtension ;
811import java .io .IOException ;
12+ import java .nio .charset .StandardCharsets ;
913import java .nio .file .Files ;
1014import java .nio .file .Path ;
1115import java .util .Arrays ;
16+ import java .util .Collections ;
17+ import me .itzg .helpers .curseforge .model .CurseForgeFile ;
18+ import me .itzg .helpers .curseforge .model .CurseForgeMod ;
19+ import me .itzg .helpers .curseforge .model .FileIndex ;
20+ import me .itzg .helpers .curseforge .model .ModsSearchResponse ;
21+ import me .itzg .helpers .files .Manifests ;
1222import org .junit .jupiter .api .Test ;
1323import org .junit .jupiter .api .extension .RegisterExtension ;
1424import org .junit .jupiter .api .io .TempDir ;
@@ -107,4 +117,83 @@ void usingListingFile() throws IOException {
107117 assertThat (tempDir .resolve ("plugins/worldguard-bukkit-7.0.7-dist.jar" )).exists ();
108118
109119 }
120+
121+ @ Test
122+ void handlesDuplicateManifestEntries () throws IOException {
123+ final Path manifestFile = Files .write (tempDir .resolve (Manifests .buildManifestPath (tempDir , CurseForgeFilesManifest .ID )), ("{\n "
124+ + " \" @type\" : \" me.itzg.helpers.curseforge.CurseForgeFilesManifest\" ,\n "
125+ + " \" timestamp\" : \" 2024-04-27T17:48:56.529386300Z\" ,\n "
126+ + " \" files\" : null,\n "
127+ + " \" entries\" : [\n "
128+ + " {\n "
129+ + " \" ids\" : {\n "
130+ + " \" modId\" : 667389,\n "
131+ + " \" fileId\" : 4802504\n "
132+ + " },\n "
133+ + " \" filePath\" : \" mods\\ \\ goblintraders-fabric-1.20.1-1.9.3.jar\" \n "
134+ + " },\n "
135+ + " {\n "
136+ + " \" ids\" : {\n "
137+ + " \" modId\" : 667389,\n "
138+ + " \" fileId\" : 4802504\n "
139+ + " },\n "
140+ + " \" filePath\" : \" mods\\ \\ goblintraders-fabric-1.20.1-1.9.3.jar\" \n "
141+ + " }\n "
142+ + " ]\n "
143+ + "}" ).getBytes (StandardCharsets .UTF_8 ));
144+
145+ wm .stubFor (get (urlPathEqualTo ("/v1/mods/search" ))
146+ .withQueryParam ("gameId" , WireMock .equalTo ("432" ))
147+ .withQueryParam ("slug" , WireMock .equalTo ("goblintraders-fabric" ))
148+ .withQueryParam ("classId" , WireMock .equalTo ("6" ))
149+ .willReturn (
150+ jsonResponse (new ModsSearchResponse ()
151+ .setData (singletonList (
152+ new CurseForgeMod ()
153+ .setId (667389 )
154+ .setClassId (6 )
155+ .setGameId (432 )
156+ .setLatestFilesIndexes (singletonList (
157+ new FileIndex ()
158+ .setGameVersion ("1.20.1" )
159+ .setFileId (4802504 )
160+ ))
161+ .setLatestFiles (singletonList (
162+ new CurseForgeFile ()
163+ .setId (4802504 )
164+ .setModId (667389 )
165+ .setDependencies (Collections .emptyList ())
166+ // reference cdn.json declaration
167+ .setDownloadUrl (wm .baseUrl () + "/files/goblintraders-fabric-1.20.1-1.9.3.jar" )
168+ .setFileName ("goblintraders-fabric-1.20.1-1.9.3.jar" )
169+ ))
170+ )), 200 )
171+ )
172+ );
173+
174+ int exitCode = new CommandLine (
175+ new CurseForgeFilesCommand ()
176+ )
177+ .setCaseInsensitiveEnumValuesAllowed (true )
178+ .execute (
179+ "--api-base-url" , wm .baseUrl (),
180+ "--api-key" , "test" ,
181+ "--output-directory" , tempDir .toString (),
182+ "--default-category" , "mc-mods" ,
183+ "--game-version=1.20.1" ,
184+ "--mod-loader=fabric" ,
185+ "https://www.curseforge.com/minecraft/mc-mods/goblintraders-fabric" ,
186+ "https://www.curseforge.com/minecraft/mc-mods/goblintraders-fabric"
187+ );
188+
189+ assertThat (exitCode ).isEqualTo (0 );
190+
191+ assertThat (manifestFile )
192+ .exists ();
193+
194+ final CurseForgeFilesManifest manifest = Manifests .load (tempDir , CurseForgeFilesManifest .ID , CurseForgeFilesManifest .class );
195+ assertThat (manifest ).isNotNull ();
196+ assertThat (manifest .getEntries ()).hasSize (1 );
197+ assertThat (manifest .getEntries ().get (0 ).getIds ()).isEqualTo (new ModFileIds (667389 , 4802504 ));
198+ }
110199}
0 commit comments