1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-06 11:30:08 +02:00

Improve tests

This commit is contained in:
2023-03-03 23:11:40 +01:00
parent 13ee618d5c
commit 127d5f4494
7 changed files with 166 additions and 69 deletions

View File

@ -587,6 +587,7 @@
C4C8E819276F54D8003AC782 /* App+ConfigWatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C8E817276F54D8003AC782 /* App+ConfigWatch.swift */; };
C4C8E81B276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C8E81A276F54E5003AC782 /* PhpConfigWatcher.swift */; };
C4C8E81C276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C8E81A276F54E5003AC782 /* PhpConfigWatcher.swift */; };
C4CB250529B28BB800CA4492 /* MainMenuTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CB250429B28BB800CA4492 /* MainMenuTest.swift */; };
C4CB6E65292C362C002E9027 /* Homebrew.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CB6E64292C362C002E9027 /* Homebrew.swift */; };
C4CB6E66292C362C002E9027 /* Homebrew.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CB6E64292C362C002E9027 /* Homebrew.swift */; };
C4CB6E67292C362C002E9027 /* Homebrew.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CB6E64292C362C002E9027 /* Homebrew.swift */; };
@ -915,6 +916,7 @@
C4C8900628F0E3EF00CE5E97 /* ActiveFileSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveFileSystem.swift; sourceTree = "<group>"; };
C4C8E817276F54D8003AC782 /* App+ConfigWatch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "App+ConfigWatch.swift"; sourceTree = "<group>"; };
C4C8E81A276F54E5003AC782 /* PhpConfigWatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhpConfigWatcher.swift; sourceTree = "<group>"; };
C4CB250429B28BB800CA4492 /* MainMenuTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainMenuTest.swift; sourceTree = "<group>"; };
C4CB6E64292C362C002E9027 /* Homebrew.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Homebrew.swift; sourceTree = "<group>"; };
C4CCBA6B275C567B008C7055 /* PMWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PMWindowController.swift; sourceTree = "<group>"; };
C4CDA892288F1A71007CE25F /* Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = "<group>"; };
@ -1432,6 +1434,7 @@
C469E702294CFDF700A82AB2 /* DomainsListTest.swift */,
C44E985E29B23EBF0059F773 /* UpdateCheckTest.swift */,
C4181F1028FAF9330042EA28 /* UITestCase.swift */,
C4CB250429B28BB800CA4492 /* MainMenuTest.swift */,
);
path = ui;
sourceTree = "<group>";
@ -2455,6 +2458,7 @@
C471E8DC28F9BB8F0021E251 /* ProgressVC.swift in Sources */,
C471E8DE28F9BB8F0021E251 /* App+ConfigWatch.swift in Sources */,
C471E8DF28F9BB8F0021E251 /* PhpConfigWatcher.swift in Sources */,
C4CB250529B28BB800CA4492 /* MainMenuTest.swift in Sources */,
C471E8E028F9BB8F0021E251 /* Preset.swift in Sources */,
C471E8E128F9BB8F0021E251 /* PresetHelper.swift in Sources */,
C471E8E228F9BB8F0021E251 /* WarningView.swift in Sources */,

View File

@ -28,10 +28,12 @@ class PhpHelper {
Task { // Create the appropriate folders and check if the files exist
do {
if !FileSystem.directoryExists("~/.config/phpmon/bin") {
try FileSystem.createDirectory(
"~/.config/phpmon/bin",
withIntermediateDirectories: true
)
Task { @MainActor in
try FileSystem.createDirectory(
"~/.config/phpmon/bin",
withIntermediateDirectories: true
)
}
}
if FileSystem.fileExists(destination) {
@ -59,10 +61,12 @@ class PhpHelper {
export PATH=\(path):$PATH
"""
try FileSystem.writeAtomicallyToFile(destination, content: script)
Task { @MainActor in
try FileSystem.writeAtomicallyToFile(destination, content: script)
if !FileSystem.isExecutableFile(destination) {
try FileSystem.makeExecutable(destination)
if !FileSystem.isExecutableFile(destination) {
try FileSystem.makeExecutable(destination)
}
}
// Create a symlink if the folder is not in the PATH

View File

@ -15,6 +15,88 @@ public struct TestableConfiguration: Codable {
var commandOutput: [String: String]
var preferenceOverrides: [PreferenceName: Bool]
init(
architecture: String,
filesystem: [String: FakeFile],
shellOutput: [String: BatchFakeShellOutput],
commandOutput: [String: String],
preferenceOverrides: [PreferenceName: Bool],
phpVersions: [VersionNumber]
) {
self.architecture = architecture
self.filesystem = filesystem
self.shellOutput = shellOutput
self.commandOutput = commandOutput
self.preferenceOverrides = preferenceOverrides
phpVersions.enumerated().forEach { (index, version) in
self.addPhpVersion(version, primary: index == 0)
}
}
private enum CodingKeys: String, CodingKey {
case architecture, filesystem, shellOutput, commandOutput, preferenceOverrides
}
// MARK: Add PHP versions
private var primaryPhpVersion: VersionNumber?
private var secondaryPhpVersions: [VersionNumber] = []
mutating func addPhpVersion(_ version: VersionNumber, primary: Bool) {
if primary {
if primaryPhpVersion != nil {
fatalError("You cannot add multiple primary PHP versions to a testable configuration!")
}
primaryPhpVersion = version
} else {
self.secondaryPhpVersions.append(version)
}
self.filesystem = self.filesystem.merging([
"/opt/homebrew/opt/php@\(version.short)/bin/php"
: .fake(.symlink, "/opt/homebrew/Cellar/php/\(version.long)/bin/php"),
"/opt/homebrew/Cellar/php/\(version.long)/bin/php"
: .fake(.binary),
"/opt/homebrew/Cellar/php/\(version.long)/bin/php-config"
: .fake(.binary),
"/opt/homebrew/etc/php/\(version.short)/php-fpm.d/www.conf"
: .fake(.text),
"/opt/homebrew/etc/php/\(version.short)/php-fpm.d/valet-fpm.conf"
: .fake(.text),
"/opt/homebrew/etc/php/\(version.short)/php.ini"
: .fake(.text),
"/opt/homebrew/etc/php/\(version.short)/conf.d/php-memory-limits.ini"
: .fake(.text)
]) { (_, new) in new }
if primary {
self.shellOutput["ls /opt/homebrew/opt | grep php"]
= .instant("php")
self.filesystem["/opt/homebrew/opt/php"]
= .fake(.symlink, "/opt/homebrew/Cellar/php/\(version.long)")
self.filesystem["/opt/homebrew/opt/php/bin/php"]
= .fake(.symlink, "/opt/homebrew/Cellar/php/\(version.long)/bin/php")
self.filesystem["/opt/homebrew/bin/php"]
= .fake(.symlink, "/opt/homebrew/Cellar/php/\(version.long)/bin/php")
self.commandOutput["/opt/homebrew/bin/php-config --version"]
= version.long
self.commandOutput["/opt/homebrew/bin/php -r echo php_ini_scanned_files();"] =
"""
/opt/homebrew/etc/php/\(version.short)/conf.d/php-memory-limits.ini,
"""
} else {
self.shellOutput["ls /opt/homebrew/opt | grep php@"] =
BatchFakeShellOutput.instant(
self.secondaryPhpVersions
.map { "php@\($0.short)" }
.joined(separator: "\n")
)
}
}
// MARK: Interactions
func apply() {
Log.separator()
Log.info("USING TESTABLE CONFIGURATION...")
@ -38,6 +120,8 @@ public struct TestableConfiguration: Codable {
}
}
// MARK: Persist and load
func toJson(pretty: Bool = false) -> String {
let data = try! JSONEncoder().encode(self)

View File

@ -24,16 +24,6 @@ class TestableConfigurations {
: .fake(.binary),
"/opt/homebrew/bin/valet"
: .fake(.binary),
"/opt/homebrew/opt/php"
: .fake(.symlink, "/opt/homebrew/Cellar/php/8.2.0"),
"/opt/homebrew/opt/php@8.2/bin/php"
: .fake(.symlink, "/opt/homebrew/Cellar/php/8.2.0/bin/php"),
"/opt/homebrew/Cellar/php/8.2.0/bin/php"
: .fake(.binary),
"/opt/homebrew/Cellar/php/8.2.0/bin/php-config"
: .fake(.binary),
"/opt/homebrew/etc/php/8.2/php-fpm.d/www.conf"
: .fake(.text),
"~/.config/valet/config.json"
: .fake(.text, """
{
@ -45,12 +35,6 @@ class TestableConfigurations {
"loopback": "127.0.0.1"
}
"""),
"/opt/homebrew/etc/php/8.2/php-fpm.d/valet-fpm.conf"
: .fake(.text),
"/opt/homebrew/etc/php/8.2/php.ini"
: .fake(.text),
"/opt/homebrew/etc/php/8.2/conf.d/php-memory-limits.ini"
: .fake(.text)
],
shellOutput: [
"sysctl -n sysctl.proc_translated"
@ -59,17 +43,6 @@ class TestableConfigurations {
: .instant("user"),
"which node"
: .instant("/opt/homebrew/bin/node"),
"php -v"
: .instant("""
PHP 8.2.0 (cli) (built: Dec XX 20XX XX:XX:XX) (NTS)
Copyright (c) The PHP Group
Zend Engine vX.X, Copyright (c) Zend Technologies
with Zend OPcache vX.X, Copyright (c), by Zend Technologies
"""),
"ls /opt/homebrew/opt | grep php"
: .instant("php"),
"ls /opt/homebrew/opt | grep php@"
: .instant("php@8.2"),
"sudo /opt/homebrew/bin/brew services info dnsmasq --json"
: .delayed(0.2, """
[
@ -176,16 +149,16 @@ class TestableConfigurations {
: .instant("OK"),
],
commandOutput: [
"/opt/homebrew/bin/php-config --version": "8.2.0",
"/opt/homebrew/bin/php -r echo ini_get('memory_limit');": "512M",
"/opt/homebrew/bin/php -r echo ini_get('upload_max_filesize');": "512M",
"/opt/homebrew/bin/php -r echo ini_get('post_max_size');": "512M",
"/opt/homebrew/bin/php -r echo php_ini_scanned_files();"
: """
/opt/homebrew/etc/php/8.2/conf.d/php-memory-limits.ini,
"""
],
preferenceOverrides: [:]
preferenceOverrides: [:],
phpVersions: [
VersionNumber(major: 8, minor: 2, patch: 0),
VersionNumber(major: 8, minor: 1, patch: 0),
VersionNumber(major: 8, minor: 0, patch: 0)
]
)
}
}

View File

@ -0,0 +1,50 @@
//
// MainMenuTest.swift
// UI Tests
//
// Created by Nico Verbruggen on 03/03/2023.
// Copyright © 2023 Nico Verbruggen. All rights reserved.
//
import XCTest
final class MainMenuTest: UITestCase {
override func setUpWithError() throws {
continueAfterFailure = false
}
final func test_can_open_status_menu_item() throws {
let app = launch(openMenu: true)
assertAllExist([
// "Switch to PHP 8.2 (php)" should be visible since it is aliased to `php`
app.menuItems["\("mi_php_switch".localized) 8.2 (php)"],
// "Switch to PHP 8.1" should be the non-disabled option
app.menuItems["\("mi_php_switch".localized) 8.1 (php@8.1)"],
// "Switch to PHP 8.0" should be the non-disabled option
app.menuItems["\("mi_php_switch".localized) 8.0 (php@8.0)"],
// We should see the about and quit items
app.menuItems["mi_about".localized],
app.menuItems["mi_quit".localized]
])
sleep(2)
}
final func test_can_open_about() throws {
let app = launch(openMenu: true)
app.mainMenuItem(withText: "mi_about".localized).click()
}
final func test_can_open_settings() throws {
let app = launch(openMenu: true)
app.mainMenuItem(withText: "mi_preferences".localized).click()
}
final func test_can_quit_app() throws {
let app = launch(openMenu: true)
app.mainMenuItem(withText: "mi_quit".localized).click()
}
}

View File

@ -20,9 +20,7 @@ final class StartupTest: UITestCase {
var configuration = TestableConfigurations.working
configuration.filesystem["/opt/homebrew/bin/php"] = nil // PHP binary must be missing
let app = XCPMApplication()
app.withConfiguration(configuration)
app.launch()
let app = launch(with: configuration)
// Dialog 1: "PHP is not correctly installed"
assertAllExist([
@ -52,9 +50,7 @@ final class StartupTest: UITestCase {
var configuration = TestableConfigurations.working
configuration.filesystem["/opt/homebrew/etc/php/8.2/php-fpm.d/valet-fpm.conf"] = nil
let app = XCPMApplication()
app.withConfiguration(configuration)
app.launch()
let app = launch(with: configuration)
assertExists(app.staticTexts["alert.php_fpm_broken.title".localized], 3.0)
click(app.buttons["generic.ok".localized])
@ -64,30 +60,9 @@ final class StartupTest: UITestCase {
var configuration = TestableConfigurations.working
configuration.shellOutput["valet --version"] = .instant("Laravel Valet 5.0")
let app = XCPMApplication()
app.withConfiguration(configuration)
app.launch()
let app = launch(with: configuration)
assertExists(app.staticTexts["startup.errors.valet_version_not_supported.title".localized], 3.0)
click(app.buttons["generic.ok".localized])
}
final func test_can_open_status_menu_item() throws {
let app = XCPMApplication()
app.withConfiguration(TestableConfigurations.working)
app.launch()
// Note: If this fails here, make sure the menu bar item can be displayed
// If you use Bartender or something like this, this item may be hidden and tests will fail
app.statusItems.firstMatch.click()
assertAllExist([
// "Switch to PHP 8.1 (php)" should be visible since it is aliased to `php`
app.menuItems["\("mi_php_switch".localized) 8.2 (php)"],
// We should see the about and quit items
app.menuItems["mi_about".localized],
app.menuItems["mi_quit".localized]
])
sleep(2)
}
}

View File

@ -9,7 +9,6 @@
import XCTest
class UITestCase: XCTestCase {
/** Launches the app and opens the menu. */
public func launch(
openMenu: Bool = false,
@ -50,7 +49,15 @@ class UITestCase: XCTestCase {
public func click(_ element: XCUIElement) {
element.click()
}
}
extension XCPMApplication {
/**
Opens a given menu item found in the menu bar's status item.
*/
public func mainMenuItem(withText text: String) -> XCUIElement {
self.statusItems.firstMatch.menuItems[text].firstMatch
}
}
extension XCUIElement {