@@ -96,7 +96,13 @@ class PackageManager final : public Thread
9696 .withConnectionTimeoutMs (10000 )
9797 .withStatusCode (&statusCode));
9898
99- if (instream != nullptr && statusCode == 200 ) {
99+ bool downloadOk = instream != nullptr && statusCode == 200 ;
100+ #if ENABLE_TESTING
101+ // Local file:// archives used by the test suite don't report an
102+ // HTTP status, so accept any readable stream while testing
103+ downloadOk = instream != nullptr ;
104+ #endif
105+ if (downloadOk) {
100106 startThread ();
101107 } else {
102108 finish (Result::fail (" Failed to start download" ));
@@ -228,24 +234,37 @@ class PackageManager final : public Thread
228234
229235 PackageList getAvailablePackages ()
230236 {
237+ MemoryBlock block;
231238
232- // plugdata's deken servers, hosted on GitHub
233- // This will pre-parse the deken repo information to a faster and smaller format
234- // This saves a lot of work that plugdata would have to do on startup!
235-
236- auto const triplet = os + " -" + machine + " -" + floatsize;
237- auto const repoForArchitecture = " https://raw.githubusercontent.com/plugdata-team/plugdata-deken/main/bin/" + triplet + " .bin" ;
238-
239- webstream = std::make_unique<WebInputStream>(URL (repoForArchitecture), false );
240- webstream->connect (nullptr );
241-
242- if (webstream->isError ()) {
239+ #if ENABLE_TESTING
240+ // The test suite injects a serialised package tree (or forces a failure)
241+ // here, so no network request is made during testing
242+ if (mockShouldFail) {
243243 sendActionMessage (" Failed to connect to server" );
244244 return { };
245245 }
246+ if (mockPackageData.getSize () > 0 ) {
247+ block = mockPackageData;
248+ } else
249+ #endif
250+ {
251+ // plugdata's deken servers, hosted on GitHub
252+ // This will pre-parse the deken repo information to a faster and smaller format
253+ // This saves a lot of work that plugdata would have to do on startup!
246254
247- MemoryBlock block;
248- webstream->readIntoMemoryBlock (block);
255+ auto const triplet = os + " -" + machine + " -" + floatsize;
256+ auto const repoForArchitecture = " https://raw.githubusercontent.com/plugdata-team/plugdata-deken/main/bin/" + triplet + " .bin" ;
257+
258+ webstream = std::make_unique<WebInputStream>(URL (repoForArchitecture), false );
259+ webstream->connect (nullptr );
260+
261+ if (webstream->isError ()) {
262+ sendActionMessage (" Failed to connect to server" );
263+ return { };
264+ }
265+
266+ webstream->readIntoMemoryBlock (block);
267+ }
249268
250269 // Parse tree that was downloaded
251270 auto const tree = ValueTree::readFromData (block.getData (), block.getSize ());
@@ -345,7 +364,15 @@ class PackageManager final : public Thread
345364
346365 PackageList allPackages;
347366
367+ #if ENABLE_TESTING
368+ // The test suite installs into a temp dir and injects mock catalog data,
369+ // so neither the network nor the user's real Externals folder is touched
370+ static inline File filesystem = ProjectInfo::appDataDir.getChildFile(" Externals" );
371+ static inline MemoryBlock mockPackageData;
372+ static inline bool mockShouldFail = false ;
373+ #else
348374 static inline File const filesystem = ProjectInfo::appDataDir.getChildFile(" Externals" );
375+ #endif
349376
350377 // Package info file
351378 File pkgInfo = filesystem.getChildFile(" .pkg_info" );
@@ -409,7 +436,9 @@ class PackageManager final : public Thread
409436 JUCE_DECLARE_SINGLETON (PackageManager, false )
410437};
411438
439+ #ifndef PLUGDATA_TEST_TRANSLATION_UNIT // implemented in Dialogs.cpp's TU
412440JUCE_IMPLEMENT_SINGLETON (PackageManager)
441+ #endif
413442
414443class Deken final : public Component
415444 , public ListBoxModel
0 commit comments