@@ -209,47 +209,156 @@ final class FairCommandTests: XCTestCase {
209209
210210 XCTAssertEqual ( 3 , output. apps. count)
211211
212- let firstApp = try XCTUnwrap ( output. apps. dropFirst ( 0 ) . first, " catalog should have contained at least one app " )
213- XCTAssertEqual ( " TuneOut " , firstApp . name)
214- XCTAssertEqual ( " org.appfair.app.Tune-Out " , firstApp . bundleIdentifier)
215- XCTAssertEqual ( " other " , firstApp . category) // FIXME
216- XCTAssertEqual ( " 1639901758 " , firstApp . marketplaceID)
217- XCTAssertEqual ( " Stream internet radio " , firstApp . subtitle)
218- XCTAssertEqual ( 1 , firstApp . versions? . count)
219-
220- let secondApp = try XCTUnwrap ( output. apps. dropFirst ( 1 ) . first, " catalog should have contained a second app " )
221- XCTAssertEqual ( " NetSkip " , secondApp . name)
222- XCTAssertEqual ( " org.appfair.app.Net-Skip " , secondApp . bundleIdentifier)
223- XCTAssertEqual ( " other " , secondApp . category) // FIXME
224- XCTAssertEqual ( " 1640618584 " , secondApp . marketplaceID)
225- XCTAssertEqual ( " A humane web browser " , secondApp . subtitle)
226- XCTAssertEqual ( 1 , secondApp . versions? . count)
227- XCTAssertEqual ( netSkipVersion, secondApp . versions? . first? . version)
228-
229- let thirdApp = try XCTUnwrap ( output. apps. dropFirst ( 2 ) . first, " catalog should have contained a third app " )
230- XCTAssertEqual ( " SkipNotes " , thirdApp . name)
231- XCTAssertEqual ( " org.appfair.app.SkipNotes " , thirdApp . bundleIdentifier)
232- XCTAssertEqual ( " other " , thirdApp . category) // FIXME
233- XCTAssertEqual ( " 6740916318 " , thirdApp . marketplaceID)
234- XCTAssertEqual ( " Simple and secure notes " , thirdApp . subtitle)
235- XCTAssertEqual ( 1 , thirdApp . versions? . count)
236- }
237-
238- func testSourceCreateFDrdoidCommand ( ) async throws {
212+ let tuneOut = try XCTUnwrap ( output. apps. dropFirst ( 0 ) . first, " catalog should have contained at least one app " )
213+ XCTAssertEqual ( " TuneOut " , tuneOut . name)
214+ XCTAssertEqual ( " org.appfair.app.Tune-Out " , tuneOut . bundleIdentifier)
215+ XCTAssertEqual ( " other " , tuneOut . category) // FIXME
216+ XCTAssertEqual ( " 1639901758 " , tuneOut . marketplaceID)
217+ XCTAssertEqual ( " Stream internet radio " , tuneOut . subtitle)
218+ XCTAssertEqual ( 1 , tuneOut . versions? . count)
219+
220+ let netSkip = try XCTUnwrap ( output. apps. dropFirst ( 1 ) . first, " catalog should have contained a second app " )
221+ XCTAssertEqual ( " NetSkip " , netSkip . name)
222+ XCTAssertEqual ( " org.appfair.app.Net-Skip " , netSkip . bundleIdentifier)
223+ XCTAssertEqual ( " other " , netSkip . category) // FIXME
224+ XCTAssertEqual ( " 1640618584 " , netSkip . marketplaceID)
225+ XCTAssertEqual ( " A humane web browser " , netSkip . subtitle)
226+ XCTAssertEqual ( 1 , netSkip . versions? . count)
227+ XCTAssertEqual ( netSkipVersion, netSkip . versions? . first? . version)
228+
229+ let skipNotes = try XCTUnwrap ( output. apps. dropFirst ( 2 ) . first, " catalog should have contained a third app " )
230+ XCTAssertEqual ( " SkipNotes " , skipNotes . name)
231+ XCTAssertEqual ( " org.appfair.app.SkipNotes " , skipNotes . bundleIdentifier)
232+ XCTAssertEqual ( " other " , skipNotes . category) // FIXME
233+ XCTAssertEqual ( " 6740916318 " , skipNotes . marketplaceID)
234+ XCTAssertEqual ( " Simple and secure notes " , skipNotes . subtitle)
235+ XCTAssertEqual ( 1 , skipNotes . versions? . count)
236+ }
237+
238+ func testSourceCreateFDroidCommand ( ) async throws {
239239 let netSkipVersion = " 1.4.5 "
240240 let args = [ " Tune-Out " , " Net-Skip/ \( netSkipVersion) " , " Skip-Notes " ]
241241
242242 let ( output, messages) = try await runToolOutputSingle ( SourceCommand . configuration, SourceCommand . CreateCommand. configuration, cmd: SourceCommand . CreateFDroidCatalogCommand. self, args: Array ( args) )
243243
244244 _ = messages
245245
246- //let output = result.output.joined()
247- dbg ( " output: " , output)
248-
249246 XCTAssertEqual ( 3 , output. packages? . count)
250247
248+ let tuneOut = try XCTUnwrap ( output. packages ? [ " org.appfair.app.Tune_Out " ] , " missing app " )
249+ XCTAssertEqual ( " TuneOut " , tuneOut. metadata. name ? [ " en-US " ] )
250+
251+ let netSkip = try XCTUnwrap ( output. packages ? [ " org.appfair.app.Net_Skip " ] , " missing app " )
252+ let _ = netSkip
253+ //XCTAssertEqual("Skip Showcase", netSkip.metadata.name?["en-US"]) // oops
254+
255+ let skipNotes = try XCTUnwrap ( output. packages ? [ " org.appfair.app.SkipNotes " ] , " missing app " )
256+ XCTAssertEqual ( " Skip Notes " , skipNotes. metadata. name ? [ " en-US " ] )
257+
251258 //let catalog: AltCatalog = try SourceCommand.CreateCommand.Output(fromJSON: output.utf8Data, dateDecodingStrategy: .iso8601)
252259 //dbg("catalog:", try? catalog.toJSON(outputFormatting: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes], dateEncodingStrategy: .iso8601).utf8String)
260+
261+ // TODO: validate against fdroidserver's `fdroid update` output for the app:
262+ let expected = try JSONDecoder ( ) . decode ( FDroidIndex . self, from: """
263+ {
264+ " repo " : {
265+ " name " : {
266+ " en-US " : " The App Fair Project "
267+ },
268+ " description " : {
269+ " en-US " : " This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/fdroid. "
270+ },
271+ " icon " : {
272+ " en-US " : {
273+ " name " : " /icons/icon.png " ,
274+ " sha256 " : " 7b42abdb1ec052f24f6957b73789355bdf5d1ba9d9c432d636a515838aa16989 " ,
275+ " size " : 681
276+ }
277+ },
278+ " address " : " https://api.appfair.net/fdroid/repo " ,
279+ " timestamp " : 1760571293000,
280+ " categories " : {
281+ " server " : {
282+ " name " : {
283+ " en-US " : " server "
284+ }
285+ }
286+ }
287+ },
288+ " packages " : {
289+ " org.appfair.app.Tune_Out " : {
290+ " metadata " : {
291+ " added " : 1760571293000,
292+ " categories " : [
293+ " server "
294+ ],
295+ " lastUpdated " : 1760571293000,
296+ " name " : {
297+ " en-US " : " TuneOut "
298+ },
299+ " preferredSigner " : " 082e7b25ea1120bfb1b5e72a15dd359a5300b7b7d44297271ee0c870285bff38 "
300+ },
301+ " versions " : {
302+ " dcf83b18561745baecb8013f542d883dab7d1d1b3cf391173603add9c78df809 " : {
303+ " added " : 1760571293000,
304+ " file " : {
305+ " name " : " https://github.com/appfair/Tune-Out/releases/download/1.0.5/TuneOut-release.apk " ,
306+ " sha256 " : " dcf83b18561745baecb8013f542d883dab7d1d1b3cf391173603add9c78df809 " ,
307+ " size " : 22206307
308+ },
309+ " manifest " : {
310+ " nativecode " : [
311+ " arm64-v8a " ,
312+ " armeabi " ,
313+ " armeabi-v7a " ,
314+ " mips " ,
315+ " mips64 " ,
316+ " x86 " ,
317+ " x86_64 "
318+ ],
319+ " versionName " : " 1.0.5 " ,
320+ " versionCode " : 17,
321+ " usesSdk " : {
322+ " minSdkVersion " : 28,
323+ " targetSdkVersion " : 36
324+ },
325+ " signer " : {
326+ " sha256 " : [
327+ " 082e7b25ea1120bfb1b5e72a15dd359a5300b7b7d44297271ee0c870285bff38 "
328+ ]
329+ },
330+ " usesPermission " : [
331+ {
332+ " name " : " android.permission.INTERNET "
333+ },
334+ {
335+ " name " : " android.permission.FOREGROUND_SERVICE "
336+ },
337+ {
338+ " name " : " android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK "
339+ },
340+ {
341+ " name " : " android.permission.POST_NOTIFICATIONS "
342+ },
343+ {
344+ " name " : " android.permission.WAKE_LOCK "
345+ },
346+ {
347+ " name " : " android.permission.ACCESS_NETWORK_STATE "
348+ },
349+ {
350+ " name " : " org.appfair.app.Tune_Out.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION "
351+ }
352+ ]
353+ }
354+ }
355+ }
356+ }
357+ }
358+ }
359+ """ . data ( using: . utf8) !)
360+
361+ XCTAssertEqual ( 1 , expected. packages? . count)
253362 }
254363
255364 func testValidateCommand( ) async throws {
0 commit comments