Skip to content

Commit ada862d

Browse files
committed
Improve defaults command
Rename `verboseOutput` to `alwaysVerbose`. It seemed like ELCLI was swallowing commands that had matching prefixes so `--verbose` and `--verboseOutput`` were being captured by the same block when that was not the desired result. Additionally added unit tests for the defaults command around migrations, passing trash values, and its use being applied as expected.
1 parent 7b90d2c commit ada862d

File tree

11 files changed

+177
-24
lines changed

11 files changed

+177
-24
lines changed

ModuloKit/Commands/AddCommand.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ open class AddCommand: NSObject, Command {
3131
}
3232
open var failOnUnrecognizedOptions: Bool { return true }
3333

34-
open var verbose: Bool = State.instance.options.verboseOutput
34+
open var verbose: Bool = State.instance.options.alwaysVerbose
3535
open var quiet: Bool = false
3636

3737
open func configureOptions() {

ModuloKit/Commands/DefaultsCommand.swift

+16-12
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ open class DefaultsCommand: NSObject, Command {
3636

3737
public var failOnUnrecognizedOptions: Bool { return true }
3838

39-
public var verbose: Bool = State.instance.options.verboseOutput
39+
public var verbose: Bool = State.instance.options.alwaysVerbose
4040
public var quiet: Bool = false
4141

4242
public func execute(_ otherParams: Array<String>?) -> Int {
@@ -58,23 +58,27 @@ open class DefaultsCommand: NSObject, Command {
5858
newValue = false
5959
}
6060

61-
spec.options.verboseOutput = newValue
62-
State.instance.options.verboseOutput = newValue
61+
spec.options.alwaysVerbose = newValue
62+
State.instance.options.alwaysVerbose = newValue
6363
}
6464
if let moduleFolderPath = moduleFolderPath,
6565
!moduleFolderPath.isEmpty {
6666
spec.options.depdencyInstallationPath = moduleFolderPath
6767
State.instance.options.depdencyInstallationPath = moduleFolderPath
6868
}
69+
70+
if !toggleVerbose && moduleFolderPath == nil {
71+
writeln(.stderr, """
72+
When `--set` is passed its assumed you want to set a default.
73+
Please specify one of the options
74+
--alwaysVerbose
75+
--moduleFolder
76+
""")
77+
}
6978
spec.save()
7079
} else {
71-
if toggleVerbose {
72-
writeln(.stdout, "VerboseOutput - \(spec.options.verboseOutput)")
73-
}
74-
if moduleFolderPath != nil {
75-
writeln(.stdout, "depdencyInstallationPath - \(spec.options.depdencyInstallationPath)")
76-
}
77-
80+
writeln(.stdout, "alwaysVerbose - \(spec.options.alwaysVerbose)")
81+
writeln(.stdout, "depdencyInstallationPath - \(spec.options.depdencyInstallationPath)")
7882
}
7983

8084
return ErrorCode.success.rawValue
@@ -85,9 +89,9 @@ open class DefaultsCommand: NSObject, Command {
8589
self.setValue = true
8690
}
8791

88-
addOptionValue(["--verboseOutput"],
92+
addOptionValue(["--alwaysVerbose"],
8993
usage: "specify `verbose` for all commands that are run",
90-
valueSignature: "<[true|false}>") { (option, value) in
94+
valueSignature: "<[true|false]>") { (option, value) in
9195
self.toggleVerbose = true
9296
self.verboseValue = value
9397
}

ModuloKit/Commands/InitCommand.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ open class InitCommand: NSObject, Command {
2525
}
2626
open var failOnUnrecognizedOptions: Bool { return true }
2727

28-
open var verbose: Bool = State.instance.options.verboseOutput
28+
open var verbose: Bool = State.instance.options.alwaysVerbose
2929
open var quiet: Bool = false
3030

3131
open func configureOptions() {

ModuloKit/Commands/MapCommand.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ open class MapCommand: NSObject, Command {
2121
}
2222
open var failOnUnrecognizedOptions: Bool { return true }
2323

24-
open var verbose: Bool = State.instance.options.verboseOutput
24+
open var verbose: Bool = State.instance.options.alwaysVerbose
2525
open var quiet: Bool = false
2626

2727
fileprivate var simple = false

ModuloKit/Commands/RemoveCommand.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ open class RemoveCommand: NSObject, Command {
2121
}
2222
open var failOnUnrecognizedOptions: Bool { return true }
2323

24-
open var verbose: Bool = State.instance.options.verboseOutput
24+
open var verbose: Bool = State.instance.options.alwaysVerbose
2525
open var quiet: Bool = false
2626

2727
open func configureOptions() {

ModuloKit/Commands/SetCommand.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ open class SetCommand: NSObject, Command {
2121
}
2222
open var failOnUnrecognizedOptions: Bool { return true }
2323

24-
open var verbose: Bool = State.instance.options.verboseOutput
24+
open var verbose: Bool = State.instance.options.alwaysVerbose
2525
open var quiet: Bool = false
2626

2727
// subcommands

ModuloKit/Commands/StatusCommand.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ open class StatusCommand: NSObject, Command {
2323
open var failOnUnrecognizedOptions: Bool { return true }
2424
open var ignoreMain: Bool = false
2525

26-
open var verbose: Bool = State.instance.options.verboseOutput
26+
open var verbose: Bool = State.instance.options.alwaysVerbose
2727
open var quiet: Bool = false
2828

2929
open func configureOptions() {

ModuloKit/Commands/UpdateCommand.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ open class UpdateCommand: NSObject, Command {
2929
}
3030
open var failOnUnrecognizedOptions: Bool { return true }
3131

32-
open var verbose: Bool = State.instance.options.verboseOutput
32+
open var verbose: Bool = State.instance.options.alwaysVerbose
3333
open var quiet: Bool = false
3434

3535
open func configureOptions() {

ModuloKit/Specs/OptionsSpec.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ import Foundation
1414

1515
public struct OptionsSpec {
1616
/// Should we have `verbose` on all commands
17-
var verboseOutput: Bool = false
17+
var alwaysVerbose: Bool = false
1818
/// Path to store our 'modules'/dependencies in
1919
var depdencyInstallationPath: String = "modules"
2020
}
2121

2222
extension OptionsSpec: ELDecodable {
2323
public static func decode(_ json: JSON?) throws -> OptionsSpec {
2424
return try OptionsSpec(
25-
verboseOutput: json ==> "verboseOutput",
25+
alwaysVerbose: json ==> "alwaysVerbose",
2626
depdencyInstallationPath: json ==> "depdencyInstallationPath"
2727
)
2828
}
@@ -31,7 +31,7 @@ extension OptionsSpec: ELDecodable {
3131
extension OptionsSpec: ELEncodable {
3232
public func encode() throws -> JSON {
3333
return try encodeToJSON([
34-
"verboseOutput" <== verboseOutput,
34+
"alwaysVerbose" <== alwaysVerbose,
3535
"depdencyInstallationPath" <== depdencyInstallationPath
3636
])
3737
}

ModuloKitTests/TestDefaults.swift

+146-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,154 @@
99
import XCTest
1010
import ELCLI
1111
import ELFoundation
12+
import ELCodable // for JSON
1213
@testable import ModuloKit
1314

1415
class TestDefaults: XCTestCase {
1516
let modulo = Modulo()
16-
17+
18+
// MARK: - Setup
19+
override func setUp() {
20+
super.setUp()
21+
22+
moduloReset()
23+
}
24+
25+
// MARK: - Migration
26+
func testMigrationFromNoOptionsInModuloFile() {
27+
let moduleFileJSONDictionary = [
28+
"dependencies": [],
29+
"module": false,
30+
"name": "best project"
31+
] as [String : Any]
32+
do {
33+
let moduleSpec = try spec(from: moduleFileJSONDictionary)
34+
let options = moduleSpec.options
35+
// validate defaults
36+
XCTAssertTrue(options.alwaysVerbose == false)
37+
XCTAssertTrue(options.depdencyInstallationPath == "modules")
38+
} catch {
39+
XCTFail("Failed with error \(error)")
40+
}
41+
}
42+
43+
// MARK: - Bad Input
44+
func testGarbageValuesInModuloFileResultInSaneDefaults() {
45+
let moduleFileJSONDictionary = [
46+
"dependencies": [],
47+
"module": false,
48+
"name": "best project",
49+
"options": [
50+
"alwaysVerbose": "lolgarbage",
51+
"depdencyInstallationPath": ["fart": "toot"],
52+
"invalid_key": true,
53+
]
54+
] as [String : Any]
55+
do {
56+
let moduleSpec = try spec(from: moduleFileJSONDictionary)
57+
let options = moduleSpec.options
58+
// validate defaults since we fed it garbage
59+
XCTAssertTrue(options.alwaysVerbose == false)
60+
XCTAssertTrue(options.depdencyInstallationPath == "modules")
61+
} catch {
62+
XCTFail("Failed with error \(error)")
63+
}
64+
}
65+
66+
// MARK: - Loaded from module file
67+
func testOptionsAreParsedFromModuleFile() {
68+
let directoryPath = "only-the-best-dependencies-live-here"
69+
let moduleFileJSONDictionary = [
70+
"dependencies": [],
71+
"module": false,
72+
"name": "best project",
73+
"options": [
74+
"alwaysVerbose": true,
75+
"depdencyInstallationPath": directoryPath,
76+
]
77+
] as [String : Any]
78+
79+
do {
80+
let moduleSpec = try spec(from: moduleFileJSONDictionary)
81+
let options = moduleSpec.options
82+
XCTAssertTrue(options.alwaysVerbose == true)
83+
XCTAssertTrue(options.depdencyInstallationPath == directoryPath)
84+
} catch {
85+
XCTFail("Failed with error \(error)")
86+
}
87+
}
88+
89+
// MARK: - CLI API
90+
func testReadingAllDefaults() {
91+
_ = Modulo()
92+
moduloReset()
93+
94+
let result = Modulo.run(["defaults"])
95+
96+
// ideally we'd capture output (stdout) somehow
97+
// and verify our output is what we want but since
98+
// i can't see a nice way to do that with ELCLI
99+
// we'll just verify success instead.
100+
101+
XCTAssertTrue(result == .success)
102+
}
103+
104+
func testSettingDefault() {
105+
_ = Modulo()
106+
moduloReset()
107+
XCTAssertFalse(State.instance.options.alwaysVerbose)
108+
let verboseResult = Modulo.run(["defaults", "--set", "--alwaysVerbose", "true"])
109+
XCTAssertTrue(verboseResult == .success)
110+
XCTAssertTrue(State.instance.options.alwaysVerbose)
111+
112+
let directoryResult = Modulo.run(["defaults", "--set", "--moduleFolder", "bestDIR"])
113+
XCTAssertTrue(directoryResult == .success)
114+
XCTAssertTrue(State.instance.options.depdencyInstallationPath == "bestDIR")
115+
}
116+
117+
func testFailsIfSettingBadDefault() {
118+
_ = Modulo()
119+
moduloReset()
120+
121+
xctAssertThrows({
122+
_ = Modulo.run(["defaults", "--set", "--NoTheRightValue", "badValue.BadMe."])
123+
}, "Running `defaults --set` with a bad flag/value did not fail")
124+
}
125+
126+
func testSettingDefaultWithBadValue() {
127+
_ = Modulo()
128+
moduloReset()
129+
State.instance.options.alwaysVerbose = true
130+
131+
let badVerboseResult = Modulo.run(["defaults", "--set", "--alwaysVerbose", "ohSoVerbose"])
132+
XCTAssertTrue(badVerboseResult == .success)
133+
XCTAssertFalse(State.instance.options.alwaysVerbose)
134+
}
135+
136+
func testSettingWithNoKey() {
137+
_ = Modulo()
138+
moduloReset()
139+
140+
let initialVerbose = State.instance.options.alwaysVerbose
141+
let initialPath = State.instance.options.depdencyInstallationPath
142+
let result = Modulo.run(["defaults", "--set"])
143+
XCTAssertTrue(result == .success, "Even though we set nothing, we shoud succeed with some output for the user")
144+
XCTAssertTrue(initialVerbose == State.instance.options.alwaysVerbose)
145+
XCTAssertTrue(initialPath == State.instance.options.depdencyInstallationPath)
146+
}
147+
}
148+
149+
// MARK: - Test Helpers
150+
extension TestDefaults {
151+
func spec(from dictionary: [String: Any]) throws -> ModuleSpec {
152+
let moduleFileJSONData = try JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted)
153+
guard let moduleFileJSON = JSON(data: moduleFileJSONData) else {
154+
throw NSError(domain: "TestDefaults",
155+
code: -1,
156+
userInfo: [
157+
NSLocalizedDescriptionKey: "Failed to create JSON from Data"
158+
])
159+
}
160+
return try ModuleSpec.decode(moduleFileJSON)
161+
}
17162
}

modulo.xcodeproj/xcshareddata/xcschemes/modulo.xcscheme

+5-1
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,17 @@
6767
argument = "update --all --host github.corp.ebay.com"
6868
isEnabled = "NO">
6969
</CommandLineArgument>
70+
<CommandLineArgument
71+
argument = "defaults --set --alwaysVerbose true"
72+
isEnabled = "YES">
73+
</CommandLineArgument>
7074
<CommandLineArgument
7175
argument = "update --verbose"
7276
isEnabled = "NO">
7377
</CommandLineArgument>
7478
<CommandLineArgument
7579
argument = "update"
76-
isEnabled = "YES">
80+
isEnabled = "NO">
7781
</CommandLineArgument>
7882
</CommandLineArguments>
7983
<AdditionalOptions>

0 commit comments

Comments
 (0)