1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 03:50:08 +02:00

👌 Read configuration from JSON file

This allows us to alter the configuration prior to launching the app,
which allows for additional flexibility during testing.
This commit is contained in:
2022-10-16 14:35:19 +02:00
parent 273070ef27
commit 5e3e0c087b
16 changed files with 602 additions and 102 deletions

View File

@ -500,8 +500,6 @@
C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4ACA38E25C754C100060C66 /* PhpExtension.swift */; };
C4AD38B228ECD9D300FA8D83 /* TestableFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AD38B128ECD9D300FA8D83 /* TestableFileSystem.swift */; };
C4AD38B328ECD9D300FA8D83 /* TestableFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AD38B128ECD9D300FA8D83 /* TestableFileSystem.swift */; };
C4AD38B528ECE2DB00FA8D83 /* brew-formula.json in Resources */ = {isa = PBXBuildFile; fileRef = C43A8A1F25D9D1D700591B77 /* brew-formula.json */; };
C4AD38B628ECE56D00FA8D83 /* TestableConfigurations.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40F505428ECA64E004AD45B /* TestableConfigurations.swift */; };
C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C4AF9F70275445FF00D44ED0 /* valet-config.json */; };
C4AF9F78275447F100D44ED0 /* ValetConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F76275447F100D44ED0 /* ValetConfigurationTest.swift */; };
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; };
@ -568,6 +566,30 @@
C4DEB7D427A5D60B00834718 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DEB7D327A5D60B00834718 /* Stats.swift */; };
C4E0F7ED27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */; };
C4E0F7EE27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */; };
C4E2E84828FC1D93003B070C /* TestableConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E84628FC1D8C003B070C /* TestableConfigurationTest.swift */; };
C4E2E84A28FC1E70003B070C /* DataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E84928FC1E70003B070C /* DataExtension.swift */; };
C4E2E84B28FC1E70003B070C /* DataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E84928FC1E70003B070C /* DataExtension.swift */; };
C4E2E84C28FC1E70003B070C /* DataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E84928FC1E70003B070C /* DataExtension.swift */; };
C4E2E84D28FC1E70003B070C /* DataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E84928FC1E70003B070C /* DataExtension.swift */; };
C4E2E84F28FC22E4003B070C /* brew-formula.json in Resources */ = {isa = PBXBuildFile; fileRef = C43A8A1F25D9D1D700591B77 /* brew-formula.json */; };
C4E2E85028FC22E4003B070C /* brew-formula.json in Resources */ = {isa = PBXBuildFile; fileRef = C43A8A1F25D9D1D700591B77 /* brew-formula.json */; };
C4E2E85428FC256B003B070C /* brew-services-sudo.json in Resources */ = {isa = PBXBuildFile; fileRef = C4E2E85128FC256B003B070C /* brew-services-sudo.json */; };
C4E2E85528FC256B003B070C /* brew-services-sudo.json in Resources */ = {isa = PBXBuildFile; fileRef = C4E2E85128FC256B003B070C /* brew-services-sudo.json */; };
C4E2E85628FC256B003B070C /* brew-services-sudo.json in Resources */ = {isa = PBXBuildFile; fileRef = C4E2E85128FC256B003B070C /* brew-services-sudo.json */; };
C4E2E85828FC256B003B070C /* brew-services-normal.json in Resources */ = {isa = PBXBuildFile; fileRef = C4E2E85228FC256B003B070C /* brew-services-normal.json */; };
C4E2E85928FC256B003B070C /* brew-services-normal.json in Resources */ = {isa = PBXBuildFile; fileRef = C4E2E85228FC256B003B070C /* brew-services-normal.json */; };
C4E2E85A28FC256B003B070C /* brew-services-normal.json in Resources */ = {isa = PBXBuildFile; fileRef = C4E2E85228FC256B003B070C /* brew-services-normal.json */; };
C4E2E85C28FC282B003B070C /* TestableConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E85B28FC282B003B070C /* TestableConfiguration.swift */; };
C4E2E85D28FC282B003B070C /* TestableConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E85B28FC282B003B070C /* TestableConfiguration.swift */; };
C4E2E85E28FC282B003B070C /* TestableConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E85B28FC282B003B070C /* TestableConfiguration.swift */; };
C4E2E85F28FC282B003B070C /* TestableConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E85B28FC282B003B070C /* TestableConfiguration.swift */; };
C4E2E86128FC28A6003B070C /* brew-services.json in Resources */ = {isa = PBXBuildFile; fileRef = C4F30B06278E195800755FCE /* brew-services.json */; };
C4E2E86228FC28A6003B070C /* brew-services.json in Resources */ = {isa = PBXBuildFile; fileRef = C4F30B06278E195800755FCE /* brew-services.json */; };
C4E2E86528FC2F1B003B070C /* XCPMApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E86328FC2F1B003B070C /* XCPMApplication.swift */; };
C4E2E86628FC2F1B003B070C /* XCPMApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E86328FC2F1B003B070C /* XCPMApplication.swift */; };
C4E2E86728FC2F1B003B070C /* XCPMApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E2E86328FC2F1B003B070C /* XCPMApplication.swift */; };
C4E2E86928FC3002003B070C /* Utility.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43A8A1925D9CD1000591B77 /* Utility.swift */; };
C4E2E86A28FC3002003B070C /* Utility.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43A8A1925D9CD1000591B77 /* Utility.swift */; };
C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404527C56F4700D225E1 /* ValetSite.swift */; };
C4E4404727C56F4700D225E1 /* ValetSite.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404527C56F4700D225E1 /* ValetSite.swift */; };
C4E49DE728F764050026AC4E /* ActiveCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E49DE628F764050026AC4E /* ActiveCommand.swift */; };
@ -815,6 +837,12 @@
C4D9F24A280B69E100DCD39A /* AddProxyVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddProxyVC.swift; sourceTree = "<group>"; };
C4DEB7D327A5D60B00834718 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = "<group>"; };
C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSWindowExtension.swift; sourceTree = "<group>"; };
C4E2E84628FC1D8C003B070C /* TestableConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestableConfigurationTest.swift; sourceTree = "<group>"; };
C4E2E84928FC1E70003B070C /* DataExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataExtension.swift; sourceTree = "<group>"; };
C4E2E85128FC256B003B070C /* brew-services-sudo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "brew-services-sudo.json"; sourceTree = "<group>"; };
C4E2E85228FC256B003B070C /* brew-services-normal.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "brew-services-normal.json"; sourceTree = "<group>"; };
C4E2E85B28FC282B003B070C /* TestableConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestableConfiguration.swift; sourceTree = "<group>"; };
C4E2E86328FC2F1B003B070C /* XCPMApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCPMApplication.swift; sourceTree = "<group>"; };
C4E4404527C56F4700D225E1 /* ValetSite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetSite.swift; sourceTree = "<group>"; };
C4E49DE628F764050026AC4E /* ActiveCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveCommand.swift; sourceTree = "<group>"; };
C4E49DE928F7643D0026AC4E /* CommandProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandProtocol.swift; sourceTree = "<group>"; };
@ -1176,6 +1204,8 @@
C459B4BF27F6094100E9B4B4 /* brew */ = {
isa = PBXGroup;
children = (
C4E2E85228FC256B003B070C /* brew-services-normal.json */,
C4E2E85128FC256B003B070C /* brew-services-sudo.json */,
C43A8A1F25D9D1D700591B77 /* brew-formula.json */,
C4F30B06278E195800755FCE /* brew-services.json */,
);
@ -1220,6 +1250,7 @@
C471E6DB28F9AFD10021E251 /* Command */,
C471E6DA28F9AFCB0021E251 /* Filesystem */,
C413E43328DA3E8F00AE33C7 /* Shell */,
C4E2E84628FC1D8C003B070C /* TestableConfigurationTest.swift */,
);
path = Testables;
sourceTree = "<group>";
@ -1241,6 +1272,7 @@
C471E79628F9B4260021E251 /* tests */ = {
isa = PBXGroup;
children = (
C4E2E86828FC2FF2003B070C /* Shared */,
C471E79228F9B1D30021E251 /* PHP Monitor.xctestplan */,
C4F7807A25D7F84B000DBC97 /* unit */,
C471E7AE28F9B4940021E251 /* feature */,
@ -1534,6 +1566,16 @@
path = Switcher;
sourceTree = "<group>";
};
C4E2E86828FC2FF2003B070C /* Shared */ = {
isa = PBXGroup;
children = (
C4E2E86328FC2F1B003B070C /* XCPMApplication.swift */,
C40F505428ECA64E004AD45B /* TestableConfigurations.swift */,
C43A8A1925D9CD1000591B77 /* Utility.swift */,
);
path = Shared;
sourceTree = "<group>";
};
C4E49DE528F763E20026AC4E /* Command */ = {
isa = PBXGroup;
children = (
@ -1576,7 +1618,6 @@
C4F7807A25D7F84B000DBC97 /* unit */ = {
isa = PBXGroup;
children = (
C43A8A1925D9CD1000591B77 /* Utility.swift */,
C471E6D928F9AFC20021E251 /* Testables */,
C40C7F1C27720E1400DDDCDC /* Test Files */,
C4C1019927C65A4D001FACC2 /* Commands */,
@ -1599,10 +1640,10 @@
C4F787A728EF812600790735 /* Testables */ = {
isa = PBXGroup;
children = (
C40F505428ECA64E004AD45B /* TestableConfigurations.swift */,
C46EBC4928DB966A007ACC74 /* TestableShell.swift */,
C4AD38B128ECD9D300FA8D83 /* TestableFileSystem.swift */,
C4E49DEC28F764A00026AC4E /* TestableCommand.swift */,
C4E2E85B28FC282B003B070C /* TestableConfiguration.swift */,
);
path = Testables;
sourceTree = "<group>";
@ -1618,6 +1659,7 @@
C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */,
C4EB53E628553117006F9937 /* ArrayExtension.swift */,
C44B3A4528E5C70100718CB1 /* TimeIntervalExtension.swift */,
C4E2E84928FC1E70003B070C /* DataExtension.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -1762,7 +1804,6 @@
54FCFD26276C883F004CE748 /* SelectPreferenceView.xib in Resources */,
C473319F2470923A009A0597 /* Localizable.strings in Resources */,
C4068CA427B0780A00544CD5 /* CheckboxPreferenceView.xib in Resources */,
C4AD38B528ECE2DB00FA8D83 /* brew-formula.json in Resources */,
54FCFD2D276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */,
C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */,
);
@ -1772,6 +1813,10 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C4E2E85528FC256B003B070C /* brew-services-sudo.json in Resources */,
C4E2E85928FC256B003B070C /* brew-services-normal.json in Resources */,
C4E2E84F28FC22E4003B070C /* brew-formula.json in Resources */,
C4E2E86228FC28A6003B070C /* brew-services.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1779,6 +1824,10 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C4E2E85628FC256B003B070C /* brew-services-sudo.json in Resources */,
C4E2E85A28FC256B003B070C /* brew-services-normal.json in Resources */,
C4E2E85028FC22E4003B070C /* brew-formula.json in Resources */,
C4E2E86128FC28A6003B070C /* brew-services.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1794,12 +1843,14 @@
C44F868E2835BD8D005C353A /* phpmon-config.json in Resources */,
C43A8A2025D9D1D700591B77 /* brew-formula.json in Resources */,
C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */,
C4E2E85828FC256B003B070C /* brew-services-normal.json in Resources */,
C44C1992276E44CB0072762D /* ProgressWindow.storyboard in Resources */,
C42F26762805FEE200938AC7 /* nginx-secure-proxy.test in Resources */,
C4F30B08278E195800755FCE /* brew-services.json in Resources */,
54A18D40282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test in Resources */,
C42CFB1627DFDE7900862737 /* nginx-site.test in Resources */,
C459B4BD27F6093700E9B4B4 /* nginx-proxy.test in Resources */,
C4E2E85428FC256B003B070C /* brew-services-sudo.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1866,6 +1917,7 @@
C40C7F2827721FF600DDDCDC /* ActivePhpInstallation+Checks.swift in Sources */,
C463E380284930EE00422731 /* PresetHelper.swift in Sources */,
C41C02A927E61A65009F26CB /* ValetSite+Fake.swift in Sources */,
C4E2E85C28FC282B003B070C /* TestableConfiguration.swift in Sources */,
C4C0E8DF27F88AEB002D32A9 /* FakeSiteScanner.swift in Sources */,
C44B3A4628E5C70100718CB1 /* TimeIntervalExtension.swift in Sources */,
C44264BE2850B86C007400F1 /* SwiftUIHelper.swift in Sources */,
@ -1920,7 +1972,6 @@
C4D9ADBF277610E1007277F4 /* PhpSwitcher.swift in Sources */,
C45E76142854A65300B4FE0C /* ServicesManager.swift in Sources */,
C46EBC4728DB9644007ACC74 /* RealShell.swift in Sources */,
C4AD38B628ECE56D00FA8D83 /* TestableConfigurations.swift in Sources */,
C4068CAA27B0890D00544CD5 /* MenuBarIcons.swift in Sources */,
C44264C02850BD2A007400F1 /* VersionPopoverView.swift in Sources */,
C4C8E81B276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */,
@ -1965,6 +2016,7 @@
C4C3ED412783497000AB15D8 /* MainMenu+Startup.swift in Sources */,
C40508AF28ADA23D008FAC1F /* NoDomainResultsView.swift in Sources */,
C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */,
C4E2E84A28FC1E70003B070C /* DataExtension.swift in Sources */,
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
C42337A3281F19F000459A48 /* Xdebug.swift in Sources */,
C4B97B75275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
@ -1998,12 +2050,14 @@
C471E83A28F9BB650021E251 /* ValetSite+Fake.swift in Sources */,
C471E83B28F9BB650021E251 /* SiteScanner.swift in Sources */,
C471E83C28F9BB650021E251 /* ValetSiteScanner.swift in Sources */,
C4E2E86928FC3002003B070C /* Utility.swift in Sources */,
C471E83D28F9BB650021E251 /* FakeSiteScanner.swift in Sources */,
C471E83F28F9BB650021E251 /* AppDelegate.swift in Sources */,
C471E84028F9BB650021E251 /* AppDelegate+MenuOutlets.swift in Sources */,
C471E84128F9BB650021E251 /* AppDelegate+Notifications.swift in Sources */,
C471E84228F9BB650021E251 /* AppDelegate+InterApp.swift in Sources */,
C471E84328F9BB650021E251 /* App.swift in Sources */,
C4E2E85E28FC282B003B070C /* TestableConfiguration.swift in Sources */,
C471E84428F9BB650021E251 /* App+ActivationPolicy.swift in Sources */,
C471E84528F9BB650021E251 /* App+GlobalHotkey.swift in Sources */,
C471E84628F9BB650021E251 /* InterAppHandler.swift in Sources */,
@ -2031,6 +2085,7 @@
C471E85C28F9BB650021E251 /* DomainListWindowController.swift in Sources */,
C471E85D28F9BB650021E251 /* DomainListVC.swift in Sources */,
C471E85E28F9BB650021E251 /* DomainListVC+ContextMenu.swift in Sources */,
C4E2E86628FC2F1B003B070C /* XCPMApplication.swift in Sources */,
C471E85F28F9BB650021E251 /* DomainListVC+Actions.swift in Sources */,
C471E86028F9BB650021E251 /* SelectionVC.swift in Sources */,
C471E86128F9BB650021E251 /* AddSiteVC.swift in Sources */,
@ -2046,6 +2101,7 @@
C471E86B28F9BB650021E251 /* PreferenceName.swift in Sources */,
C471E86C28F9BB650021E251 /* Preferences.swift in Sources */,
C471E86D28F9BB650021E251 /* CustomPrefs.swift in Sources */,
C4E2E84C28FC1E70003B070C /* DataExtension.swift in Sources */,
C471E86E28F9BB650021E251 /* MenuBarIcons.swift in Sources */,
C471E86F28F9BB650021E251 /* Stats.swift in Sources */,
C471E87028F9BB650021E251 /* GlobalKeybindPreference.swift in Sources */,
@ -2141,6 +2197,7 @@
C471E89528F9BB8F0021E251 /* MenuBarImageGenerator.swift in Sources */,
C471E89628F9BB8F0021E251 /* PMWindowController.swift in Sources */,
C471E89728F9BB8F0021E251 /* VersionExtractor.swift in Sources */,
C4E2E86728FC2F1B003B070C /* XCPMApplication.swift in Sources */,
C471E89828F9BB8F0021E251 /* ValetProxy.swift in Sources */,
C471E89928F9BB8F0021E251 /* ValetProxy+Fake.swift in Sources */,
C471E89A28F9BB8F0021E251 /* ProxyScanner.swift in Sources */,
@ -2179,6 +2236,7 @@
C471E8BC28F9BB8F0021E251 /* DomainListPhpCell.swift in Sources */,
C471E8BD28F9BB8F0021E251 /* DomainListTypeCell.swift in Sources */,
C471E8BE28F9BB8F0021E251 /* DomainListKindCell.swift in Sources */,
C4E2E86A28FC3002003B070C /* Utility.swift in Sources */,
C471E8BF28F9BB8F0021E251 /* DomainListWindowController.swift in Sources */,
C471E8C028F9BB8F0021E251 /* DomainListVC.swift in Sources */,
C471E8C128F9BB8F0021E251 /* DomainListVC+ContextMenu.swift in Sources */,
@ -2196,6 +2254,7 @@
C471E8CD28F9BB8F0021E251 /* PrefsVC.swift in Sources */,
C471E8CE28F9BB8F0021E251 /* PreferenceName.swift in Sources */,
C471E8CF28F9BB8F0021E251 /* Preferences.swift in Sources */,
C4E2E84D28FC1E70003B070C /* DataExtension.swift in Sources */,
C471E8D028F9BB8F0021E251 /* CustomPrefs.swift in Sources */,
C471E8D128F9BB8F0021E251 /* MenuBarIcons.swift in Sources */,
C471E8D228F9BB8F0021E251 /* Stats.swift in Sources */,
@ -2217,6 +2276,7 @@
C471E8E628F9BB8F0021E251 /* VersionPopoverView.swift in Sources */,
C471E8E728F9BB8F0021E251 /* NoDomainResultsView.swift in Sources */,
C471E8E828F9BB8F0021E251 /* ServicesView.swift in Sources */,
C4E2E85F28FC282B003B070C /* TestableConfiguration.swift in Sources */,
C471E8E928F9BB8F0021E251 /* StatsView.swift in Sources */,
C471E8EA28F9BB8F0021E251 /* SectionHeaderView.swift in Sources */,
C471E8EB28F9BB8F0021E251 /* HeaderView.swift in Sources */,
@ -2351,10 +2411,12 @@
C450C8C728C919EC002A2B4B /* PreferenceName.swift in Sources */,
C48D6C75279CD3E400F26D7E /* PhpVersionNumberTest.swift in Sources */,
C485707B28BF458900539B36 /* VersionPopoverView.swift in Sources */,
C4E2E85D28FC282B003B070C /* TestableConfiguration.swift in Sources */,
C485706E28BF451C00539B36 /* OnboardingWindowController.swift in Sources */,
C43603A1275E67610028EFC6 /* AppDelegate+Notifications.swift in Sources */,
C4C3643A28AE4FCE00C0770E /* StatusMenu+Items.swift in Sources */,
C42759682627662800093CAE /* NSMenuExtension.swift in Sources */,
C4E2E84828FC1D93003B070C /* TestableConfigurationTest.swift in Sources */,
C4D936CB27E3EE4A00BD69FE /* DomainListCellProtocol.swift in Sources */,
C4B97B76275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
C4F780CD25D80B75000DBC97 /* Alert.swift in Sources */,
@ -2382,6 +2444,7 @@
54D9E0B327E4F51E003B9AD9 /* HotKeysController.swift in Sources */,
03E36FE828D9219000636F7F /* ActiveShell.swift in Sources */,
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
C4E2E86528FC2F1B003B070C /* XCPMApplication.swift in Sources */,
C4E49DE828F764050026AC4E /* ActiveCommand.swift in Sources */,
C4CE3BBB27B324230086CA49 /* MainMenu+Switcher.swift in Sources */,
C46E20702829D27F00D909D6 /* AppUpdaterCheckTest.swift in Sources */,
@ -2390,6 +2453,7 @@
C44CCD4127AFE2FC00CE40E5 /* AlertableError.swift in Sources */,
C4CDA894288F1A71007CE25F /* Keys.swift in Sources */,
C4D936CA27E3EB6100BD69FE /* PhpHelper.swift in Sources */,
C4E2E84B28FC1E70003B070C /* DataExtension.swift in Sources */,
C449B4F127EE7FC200C47E8A /* DomainListNameCell.swift in Sources */,
C4F780BA25D80B62000DBC97 /* AppDelegate.swift in Sources */,
54FCFD31276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */,

View File

@ -79,12 +79,12 @@
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--configuration:working"
argument = "--configuration:/tmp/pmc_working.json"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--configuration:broken"
isEnabled = "YES">
argument = "--configuration:/tmp/pmc_broken.json"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
<EnvironmentVariables>

View File

@ -0,0 +1,19 @@
//
// DataExtension.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 16/10/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import Foundation
extension Data {
var prettyPrintedJSONString: NSString? {
guard let object = try? JSONSerialization.jsonObject(with: self, options: []),
let data = try? JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted]),
let prettyPrintedString = NSString(data: data, encoding: String.Encoding.utf8.rawValue) else { return nil }
return prettyPrintedString
}
}

View File

@ -47,6 +47,11 @@ extension String {
return !NSArray(object: self).filtered(using: pred).isEmpty
}
static func random(_ length: Int) -> String {
let characters = "0123456789abcdefghijklmnopqrstuvwxyz"
return String((0..<length).map{ _ in characters.randomElement()! })
}
subscript(r: Range<String.Index>) -> String {
let start = r.lowerBound
let end = r.upperBound

View File

@ -48,7 +48,7 @@ protocol ShellProtocol {
) async throws -> (Process, ShellOutput)
}
enum ShellStream {
enum ShellStream: Codable {
case stdOut, stdErr, stdIn
}

View File

@ -0,0 +1,40 @@
//
// TestableConfiguration.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 16/10/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import Foundation
public struct TestableConfiguration: Codable {
var architecture: String
var filesystem: [String: FakeFile]
var shellOutput: [String: BatchFakeShellOutput]
var commandOutput: [String: String]
func apply() {
ActiveShell.useTestable(shellOutput)
ActiveFileSystem.useTestable(filesystem)
ActiveCommand.useTestable(commandOutput)
}
func toJson(pretty: Bool = false) -> String {
let data = try! JSONEncoder().encode(self)
if pretty {
return data.prettyPrintedJSONString! as String
}
return String(data: data, encoding: .utf8)!
}
static func loadFrom(path: String) -> TestableConfiguration {
return try! JSONDecoder().decode(
TestableConfiguration.self,
from: try! String(contentsOf: URL(fileURLWithPath: path), encoding: .utf8)
.data(using: .utf8)!
)
}
}

View File

@ -52,11 +52,11 @@ class TestableFileSystem: FileSystemProtocol {
}
}
enum FakeFileType {
enum FakeFileType: Codable {
case binary, text, directory, symlink
}
struct FakeFile {
struct FakeFile: Codable {
var type: FakeFileType
var content: String?

View File

@ -55,7 +55,7 @@ public class TestableShell: ShellProtocol {
}
}
struct FakeShellOutput {
struct FakeShellOutput: Codable {
let delay: TimeInterval
let output: String
let stream: ShellStream
@ -69,7 +69,7 @@ struct FakeShellOutput {
}
}
struct BatchFakeShellOutput {
struct BatchFakeShellOutput: Codable {
var items: [FakeShellOutput]
static func with(_ items: [FakeShellOutput]) -> BatchFakeShellOutput {

View File

@ -87,19 +87,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
self.phpEnvironment = PhpEnv.shared
}
static func initializeTestingProfile(_ profile: String) {
Log.info("The profile `\(profile)` is being requested...")
switch profile {
case "broken":
Log.info("Applying broken PHP Monitor configuration profile!")
TestableConfigurations.broken.apply()
case "working":
Log.info("Applying working PHP Monitor configuration profile!")
TestableConfigurations.working.apply()
default:
assert(true, "No profile for this name is supported.")
}
static func initializeTestingProfile(_ path: String) {
Log.info("The configuration with path `\(path)` is being requested...")
TestableConfiguration
.loadFrom(path: path)
.apply()
}
// MARK: - Lifecycle

View File

@ -8,37 +8,7 @@
import Foundation
struct TestableConfiguration {
let architecture: String
let filesystem: [String: FakeFile]
let shellOutput: [String: BatchFakeShellOutput]
let commandOutput: [String: String]
func apply() {
ActiveShell.useTestable(shellOutput)
ActiveFileSystem.useTestable(filesystem)
ActiveCommand.useTestable(commandOutput)
}
}
// swiftlint:disable colon trailing_comma
class TestableConfigurations {
/** A broken system, that will not get past initialization due to missing binaries. */
static var broken: TestableConfiguration {
return TestableConfiguration(
architecture: "arm64",
filesystem: [:],
shellOutput: [
"id -un" : .instant("username"),
"php -v" : .instant(""),
"ls /opt/homebrew/opt | grep php" : .instant(""),
"valet --version" : .instant("zsh: command not found: valet")
],
commandOutput: [:]
)
}
/** A functional, working system setup that is compatible with PHP Monitor. */
static var working: TestableConfiguration {
return TestableConfiguration(
@ -59,7 +29,9 @@ class TestableConfigurations {
"/opt/homebrew/Cellar/php/8.1.10_1/bin/php-config"
: .fake(.binary),
"~/.config/valet"
: .fake(.directory)
: .fake(.directory),
"/opt/homebrew/etc/php/8.1/php-fpm.d/valet-fpm.conf"
: .fake(.text)
],
shellOutput: [
"sysctl -n sysctl.proc_translated"
@ -69,13 +41,40 @@ class TestableConfigurations {
"which node"
: .instant("/opt/homebrew/bin/node"),
"php -v"
: .instant(ShellStrings.phpVersion),
: .instant("""
PHP 8.1.10 (cli) (built: Sep 3 2022 12:09:27) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.10, Copyright (c) Zend Technologies
with Zend OPcache v8.1.10, Copyright (c), by Zend Technologies
"""),
"ls /opt/homebrew/opt | grep php"
: .instant("php"),
"ls /opt/homebrew/opt | grep php@"
: .instant("php@8.1"),
"sudo /opt/homebrew/bin/brew services info nginx --json"
: .delayed(0.2, ShellStrings.nginxJson),
: .delayed(0.2, """
[
{
"name": "nginx",
"service_name": "homebrew.mxcl.nginx",
"running": true,
"loaded": true,
"schedulable": false,
"pid": 133,
"exit_code": 0,
"user": "root",
"status": "started",
"file": "/Library/LaunchDaemons/homebrew.mxcl.nginx.plist",
"command": "/opt/homebrew/opt/nginx/bin/nginx -g daemon off;",
"working_dir": "/opt/homebrew",
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
}
]
"""),
"cat /private/etc/sudoers.d/brew"
: .instant("""
Cmnd_Alias BREW = /opt/homebrew/bin/brew *
@ -102,8 +101,6 @@ class TestableConfigurations {
: .instant(""),
"mkdir -p ~/.config/phpmon/bin"
: .instant(""),
"/opt/homebrew/bin/brew info php --json"
: .instant(ShellStrings.brewJson),
"brew info shivammathur/php/php --json"
: .instant("Error: No available formula with the name \"shivammathur/php/php\"."),
"/usr/bin/open -Ra \"PhpStorm\""
@ -116,6 +113,14 @@ class TestableConfigurations {
: .instant("Unable to find application named 'Sublime Merge'", .stdErr),
"/usr/bin/open -Ra \"iTerm\""
: .instant("Unable to find application named 'iTerm'", .stdErr),
"/opt/homebrew/bin/brew info php --json"
: .instant(ShellStrings.shared.brewJson),
"sudo /opt/homebrew/bin/brew services info --all --json"
: .instant(ShellStrings.shared.brewServicesAsRoot),
"/opt/homebrew/bin/brew services info --all --json"
: .instant(ShellStrings.shared.brewServicesAsUser),
"curl -s --max-time 5 '\(Constants.Urls.StableBuildCaskFile.absoluteString)' | grep version"
: .instant("version '5.6.2_976'")
],
commandOutput: [
"/opt/homebrew/bin/php-config --version": "8.1.10",
@ -134,43 +139,24 @@ class TestableConfigurations {
}
}
struct ShellStrings {
class ShellStrings {
static var shared = ShellStrings()
static let phpVersion = """
PHP 8.1.10 (cli) (built: Sep 3 2022 12:09:27) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.10, Copyright (c) Zend Technologies
with Zend OPcache v8.1.10, Copyright (c), by Zend Technologies
"""
var brewJson: String = ""
var brewServicesAsUser: String = ""
var brewServicesAsRoot: String = ""
static let nginxJson = """
[
{
"name": "nginx",
"service_name": "homebrew.mxcl.nginx",
"running": true,
"loaded": true,
"schedulable": false,
"pid": 133,
"exit_code": 0,
"user": "root",
"status": "started",
"file": "/Library/LaunchDaemons/homebrew.mxcl.nginx.plist",
"command": "/opt/homebrew/opt/nginx/bin/nginx -g daemon off;",
"working_dir": "/opt/homebrew",
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
}
]
"""
init() {
self.brewJson = loadFile("brew-formula")
self.brewServicesAsUser = loadFile("brew-services-normal")
self.brewServicesAsRoot = loadFile("brew-services-sudo")
}
static let brewJson: String = {
return try! String(contentsOf: Bundle.main.url(
forResource: "brew-formula",
withExtension: "json"
private func loadFile(_ fileName: String, fileExtension: String = "json") -> String {
let bundle = Bundle(for: type(of: self))
return try! String(contentsOf: bundle.url(
forResource: fileName,
withExtension: fileExtension
)!, encoding: .utf8)
}()
}
}

View File

@ -0,0 +1,23 @@
//
// XCPMApplication.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 16/10/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import XCTest
class XCPMApplication: XCUIApplication {
public func withConfiguration(_ configuration: TestableConfiguration) {
let path = persistTestable(configuration)
self.launchArguments = ["--configuration:\(path)"]
}
private func persistTestable(_ configuration: TestableConfiguration) -> String {
let tempDirectoryURL = NSURL.fileURL(withPath: NSTemporaryDirectory(), isDirectory: true)
let targetURL = tempDirectoryURL.appendingPathComponent("\(UUID().uuidString).json")
try! configuration.toJson().write(toFile: targetURL.path, atomically: true, encoding: .utf8)
return targetURL.path
}
}

View File

@ -1,5 +1,5 @@
//
// UI_Tests.swift
// StartupTest.swift
// UI Tests
//
// Created by Nico Verbruggen on 14/10/2022.
@ -17,14 +17,18 @@ final class StartupTest: UITestCase {
override func tearDownWithError() throws {}
func testApplicationCanLaunchWithTestConfigurationAndIdles() throws {
let app = XCUIApplication()
app.launchArguments = ["--configuration:working"]
let app = XCPMApplication()
app.withConfiguration(TestableConfigurations.working)
app.launch()
sleep(5)
}
func testApplicationCanLaunchWithTestConfigurationAndThrowsAlert() throws {
let app = XCUIApplication()
app.launchArguments = ["--configuration:broken"]
var configuration = TestableConfigurations.working
configuration.filesystem["/opt/homebrew/bin/php"] = nil // PHP binary must be missing
let app = XCPMApplication()
app.withConfiguration(configuration)
app.launch()
// Dialog 1: "PHP is not correctly installed"

View File

@ -0,0 +1,173 @@
[
{
"name": "dnsmasq",
"service_name": "homebrew.mxcl.dnsmasq",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": "root",
"status": "none",
"file": "/Users/nicoverbruggen/Library/LaunchAgents/homebrew.mxcl.dnsmasq.plist",
"command": "/opt/homebrew/opt/dnsmasq/sbin/dnsmasq --keep-in-foreground -C /opt/homebrew/etc/dnsmasq.conf -7 /opt/homebrew/etc/dnsmasq.d,*.conf",
"working_dir": null,
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
},
{
"name": "httpd",
"service_name": "homebrew.mxcl.httpd",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": null,
"status": "none",
"file": "/opt/homebrew/opt/httpd/homebrew.mxcl.httpd.plist",
"command": "/opt/homebrew/opt/httpd/bin/httpd -D FOREGROUND",
"working_dir": null,
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
},
{
"name": "mailhog",
"service_name": "homebrew.mxcl.mailhog",
"running": true,
"loaded": true,
"schedulable": false,
"pid": 686,
"exit_code": 0,
"user": "nicoverbruggen",
"status": "started",
"file": "/Users/nicoverbruggen/Library/LaunchAgents/homebrew.mxcl.mailhog.plist",
"command": "/opt/homebrew/opt/mailhog/bin/MailHog",
"working_dir": null,
"root_dir": null,
"log_path": "/opt/homebrew/var/log/mailhog.log",
"error_log_path": "/opt/homebrew/var/log/mailhog.log",
"interval": null,
"cron": null
},
{
"name": "nginx",
"service_name": "homebrew.mxcl.nginx",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": "root",
"status": "none",
"file": "/Users/nicoverbruggen/Library/LaunchAgents/homebrew.mxcl.nginx.plist",
"command": "/opt/homebrew/opt/nginx/bin/nginx -g daemon off;",
"working_dir": "/opt/homebrew",
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
},
{
"name": "php",
"service_name": "homebrew.mxcl.php",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": "root",
"status": "none",
"file": "/Users/nicoverbruggen/Library/LaunchAgents/homebrew.mxcl.php.plist",
"command": "/opt/homebrew/opt/php/sbin/php-fpm --nodaemonize",
"working_dir": "/opt/homebrew/var",
"root_dir": null,
"log_path": null,
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
"interval": null,
"cron": null
},
{
"name": "php@7.4",
"service_name": "homebrew.mxcl.php@7.4",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": null,
"status": "none",
"file": "/opt/homebrew/opt/php@7.4/homebrew.mxcl.php@7.4.plist",
"command": "/opt/homebrew/opt/php@7.4/sbin/php-fpm --nodaemonize",
"working_dir": "/opt/homebrew/var",
"root_dir": null,
"log_path": null,
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
"interval": null,
"cron": null
},
{
"name": "php@8.0",
"service_name": "homebrew.mxcl.php@8.0",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": null,
"status": "none",
"file": "/opt/homebrew/opt/php@8.0/homebrew.mxcl.php@8.0.plist",
"command": "/opt/homebrew/opt/php@8.0/sbin/php-fpm --nodaemonize",
"working_dir": "/opt/homebrew/var",
"root_dir": null,
"log_path": null,
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
"interval": null,
"cron": null
},
{
"name": "php@8.2",
"service_name": "homebrew.mxcl.php@8.2",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": "root",
"status": "none",
"file": "/Users/nicoverbruggen/Library/LaunchAgents/homebrew.mxcl.php@8.2.plist",
"command": "/opt/homebrew/opt/php@8.2/sbin/php-fpm --nodaemonize",
"working_dir": "/opt/homebrew/var",
"root_dir": null,
"log_path": null,
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
"interval": null,
"cron": null
},
{
"name": "unbound",
"service_name": "homebrew.mxcl.unbound",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": null,
"status": "none",
"file": "/opt/homebrew/opt/unbound/homebrew.mxcl.unbound.plist",
"command": "/opt/homebrew/opt/unbound/sbin/unbound -d -c /opt/homebrew/etc/unbound/unbound.conf",
"working_dir": null,
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
}
]

View File

@ -0,0 +1,173 @@
[
{
"name": "dnsmasq",
"service_name": "homebrew.mxcl.dnsmasq",
"running": true,
"loaded": true,
"schedulable": false,
"pid": 122,
"exit_code": 0,
"user": "root",
"status": "started",
"file": "/Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist",
"command": "/opt/homebrew/opt/dnsmasq/sbin/dnsmasq --keep-in-foreground -C /opt/homebrew/etc/dnsmasq.conf -7 /opt/homebrew/etc/dnsmasq.d,*.conf",
"working_dir": null,
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
},
{
"name": "httpd",
"service_name": "homebrew.mxcl.httpd",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": null,
"status": "none",
"file": "/opt/homebrew/opt/httpd/homebrew.mxcl.httpd.plist",
"command": "/opt/homebrew/opt/httpd/bin/httpd -D FOREGROUND",
"working_dir": null,
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
},
{
"name": "mailhog",
"service_name": "homebrew.mxcl.mailhog",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": "root",
"status": "none",
"file": "/Library/LaunchDaemons/homebrew.mxcl.mailhog.plist",
"command": "/opt/homebrew/opt/mailhog/bin/MailHog",
"working_dir": null,
"root_dir": null,
"log_path": "/opt/homebrew/var/log/mailhog.log",
"error_log_path": "/opt/homebrew/var/log/mailhog.log",
"interval": null,
"cron": null
},
{
"name": "nginx",
"service_name": "homebrew.mxcl.nginx",
"running": true,
"loaded": true,
"schedulable": false,
"pid": 133,
"exit_code": 0,
"user": "root",
"status": "started",
"file": "/Library/LaunchDaemons/homebrew.mxcl.nginx.plist",
"command": "/opt/homebrew/opt/nginx/bin/nginx -g daemon off;",
"working_dir": "/opt/homebrew",
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
},
{
"name": "php",
"service_name": "homebrew.mxcl.php",
"running": true,
"loaded": true,
"schedulable": false,
"pid": 160,
"exit_code": 0,
"user": "root",
"status": "started",
"file": "/Library/LaunchDaemons/homebrew.mxcl.php.plist",
"command": "/opt/homebrew/opt/php/sbin/php-fpm --nodaemonize",
"working_dir": "/opt/homebrew/var",
"root_dir": null,
"log_path": null,
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
"interval": null,
"cron": null
},
{
"name": "php@7.4",
"service_name": "homebrew.mxcl.php@7.4",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": null,
"status": "none",
"file": "/opt/homebrew/opt/php@7.4/homebrew.mxcl.php@7.4.plist",
"command": "/opt/homebrew/opt/php@7.4/sbin/php-fpm --nodaemonize",
"working_dir": "/opt/homebrew/var",
"root_dir": null,
"log_path": null,
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
"interval": null,
"cron": null
},
{
"name": "php@8.0",
"service_name": "homebrew.mxcl.php@8.0",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": null,
"status": "none",
"file": "/opt/homebrew/opt/php@8.0/homebrew.mxcl.php@8.0.plist",
"command": "/opt/homebrew/opt/php@8.0/sbin/php-fpm --nodaemonize",
"working_dir": "/opt/homebrew/var",
"root_dir": null,
"log_path": null,
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
"interval": null,
"cron": null
},
{
"name": "php@8.2",
"service_name": "homebrew.mxcl.php@8.2",
"running": true,
"loaded": true,
"schedulable": false,
"pid": 147,
"exit_code": 0,
"user": "root",
"status": "started",
"file": "/Library/LaunchDaemons/homebrew.mxcl.php@8.2.plist",
"command": "/opt/homebrew/opt/php@8.2/sbin/php-fpm --nodaemonize",
"working_dir": "/opt/homebrew/var",
"root_dir": null,
"log_path": null,
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
"interval": null,
"cron": null
},
{
"name": "unbound",
"service_name": "homebrew.mxcl.unbound",
"running": false,
"loaded": false,
"schedulable": false,
"pid": null,
"exit_code": null,
"user": null,
"status": "none",
"file": "/opt/homebrew/opt/unbound/homebrew.mxcl.unbound.plist",
"command": "/opt/homebrew/opt/unbound/sbin/unbound -d -c /opt/homebrew/etc/unbound/unbound.conf",
"working_dir": null,
"root_dir": null,
"log_path": null,
"error_log_path": null,
"interval": null,
"cron": null
}
]

View File

@ -0,0 +1,21 @@
//
// TestableConfigurationTest.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 16/10/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import XCTest
class TestableConfigurationTest: XCTestCase {
func test_configuration_can_be_saved_as_json() async {
var configuration = TestableConfigurations.working
configuration.filesystem["/opt/homebrew/bin/php"] = nil
print(configuration.filesystem.keys)
let json = configuration.toJson()
try! json.write(toFile: "/tmp/pmc_working.json", atomically: true, encoding: .utf8)
try! json.write(toFile: "/tmp/pmc_broken.json", atomically: true, encoding: .utf8)
}
}