Skip to content

Commit f2f4d44

Browse files
authored
Merge pull request #4 from heinrichb/develop-verbose
feat: Add verbose flag (-v, --verbose) for enhanced system messages
2 parents 94c3550 + d21ef3b commit f2f4d44

4 files changed

Lines changed: 343 additions & 73 deletions

File tree

cmd/scrapeycli/main.go

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// File: cmd/scrapeycli/main.go
2-
31
package main
42

53
import (
@@ -16,34 +14,51 @@ Global variables for storing command-line arguments.
1614
1715
- configPath: The path to the configuration file.
1816
- url: The URL to be scraped, which may override the URL in the config.
17+
- maxDepth: Overrides the scraping depth if set.
18+
- rateLimit: Overrides the request rate limit.
19+
- verbose: Enables verbose output.
1920
*/
2021
var (
2122
configPath string
2223
url string
24+
maxDepth int
25+
rateLimit float64
26+
verbose bool
2327
)
2428

2529
/*
2630
init registers command-line flags for configuration.
2731
28-
It sets up two flags for the config file ("config" and its shorthand "c")
29-
and a flag for the URL override.
32+
It sets up flags for:
33+
- The config file ("config" and its shorthand "c").
34+
- URL override.
35+
- Scraping depth override.
36+
- Rate limit override.
37+
- Verbose output ("verbose" and its shorthand "v").
3038
*/
3139
func init() {
3240
flag.StringVar(&configPath, "config", "", "Path to config file")
3341
flag.StringVar(&configPath, "c", "", "Path to config file (shorthand)")
3442
flag.StringVar(&url, "url", "", "URL to scrape (overrides config)")
43+
flag.IntVar(&maxDepth, "maxDepth", 0, "Override max crawl depth")
44+
flag.Float64Var(&rateLimit, "rateLimit", 0, "Override request rate limit (seconds)")
45+
flag.BoolVar(&verbose, "verbose", false, "Enable verbose output")
46+
flag.BoolVar(&verbose, "v", false, "Enable verbose output (shorthand)")
3547
}
3648

3749
/*
3850
main is the entry point of Scrapey CLI.
3951
4052
It parses command-line flags, prints a welcome message, loads the configuration,
41-
handles URL overrides, and prints confirmation messages for each step.
53+
handles overrides, and prints confirmation messages for each step.
4254
*/
4355
func main() {
4456
// Parse CLI flags.
4557
flag.Parse()
4658

59+
// Store the verbose flag in global state
60+
config.Verbose = verbose
61+
4762
// Print a welcome message in cyan using our PrintColored utility.
4863
utils.PrintColored("Welcome to Scrapey CLI!", "", color.FgCyan)
4964

@@ -60,16 +75,28 @@ func main() {
6075
os.Exit(1)
6176
}
6277

63-
// If a URL is provided via the command line, override the configuration's base URL.
78+
// Construct a partial Config struct for CLI overrides.
79+
cliOverrides := config.Config{}
80+
81+
// Apply URL override if provided.
6482
if url != "" {
65-
utils.PrintColored("Overriding config with URL flag: ", url, color.FgHiMagenta)
66-
cfg.URL.Base = url
83+
cliOverrides.URL.Base = url
6784
}
6885

69-
// Print confirmation of loaded config.
70-
utils.PrintColored("Loaded config from: ", configPath, color.FgHiGreen)
86+
// Apply maxDepth override if provided.
87+
if maxDepth > 0 {
88+
cliOverrides.ScrapingOptions.MaxDepth = maxDepth
89+
}
7190

72-
// Indicate that initialization is complete by printing a success message in green.
91+
// Apply rateLimit override if provided.
92+
if rateLimit > 0 {
93+
cliOverrides.ScrapingOptions.RateLimit = rateLimit
94+
}
95+
96+
// Apply all CLI overrides dynamically.
97+
cfg.OverrideWithCLI(cliOverrides)
98+
99+
// Print confirmation of loaded config.
73100
utils.PrintColored("Scrapey CLI initialization complete.", "", color.FgGreen)
74101

75102
// Print which routes will be scraped.

cmd/scrapeycli/main_test.go

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ It sets the working directory to the project root (two levels up from cmd/scrape
1515
and returns the combined output along with any error.
1616
1717
Parameters:
18-
- t: The current testing context (not used directly, but conforms to typical test helper function signatures).
18+
- t: The current testing context.
1919
- args: A variadic list of arguments to be passed to the go run command.
2020
2121
Usage:
@@ -31,39 +31,39 @@ func runMainCommand(_ *testing.T, args ...string) (string, error) {
3131

3232
/*
3333
TestFlagRegistration verifies that all necessary command-line flags are properly registered.
34-
The application depends on these flags for configuration input and URL overrides.
35-
36-
Checks:
37-
- "config" and "c" flags
38-
- "url" flag
34+
The application depends on these flags for configuration input and CLI overrides.
3935
*/
4036
func TestFlagRegistration(t *testing.T) {
41-
if f := flag.Lookup("config"); f == nil {
42-
t.Error("Expected flag 'config' to be registered")
43-
}
44-
if f := flag.Lookup("c"); f == nil {
45-
t.Error("Expected shorthand flag 'c' to be registered")
46-
}
47-
if f := flag.Lookup("url"); f == nil {
48-
t.Error("Expected flag 'url' to be registered")
37+
expectedFlags := []string{"config", "c", "url", "maxDepth", "rateLimit"}
38+
for _, flagName := range expectedFlags {
39+
if f := flag.Lookup(flagName); f == nil {
40+
t.Errorf("Expected flag '%s' to be registered", flagName)
41+
}
4942
}
5043
}
5144

5245
/*
53-
TestMainExecution runs the main program with a valid configuration file and checks for the expected output.
46+
TestMainExecution runs the main program with a valid configuration file
47+
and ensures it initializes correctly.
5448
*/
5549
func TestMainExecution(t *testing.T) {
56-
output, err := runMainCommand(t, "--config", "configs/default.json")
50+
output, err := runMainCommand(t)
5751
if err != nil {
5852
t.Fatalf("Failed to run main.go: %v\nOutput: %s", err, output)
5953
}
6054

61-
if !strings.Contains(output, "Welcome to Scrapey CLI!") {
62-
t.Errorf("Expected welcome message not found in output.\nOutput: %s", output)
55+
// Define expected phrases used multiple times
56+
requiredPhrases := []string{
57+
"Welcome to Scrapey CLI!",
58+
"Scrapey CLI initialization complete.",
59+
"Base URL: https://example.com",
6360
}
6461

65-
if !strings.Contains(output, "Base URL: https://example.com") {
66-
t.Errorf("Expected base URL output not found.\nOutput: %s", output)
62+
// Validate presence of required phrases
63+
for _, phrase := range requiredPhrases {
64+
if !strings.Contains(output, phrase) {
65+
t.Errorf("Expected output to contain '%s'.\nOutput: %s", phrase, output)
66+
}
6767
}
6868
}
6969

@@ -77,6 +77,7 @@ func TestMainConfigFailure(t *testing.T) {
7777
t.Fatalf("Expected failure due to config load error, but got success")
7878
}
7979

80+
// Validate correct exit behavior
8081
if exitErr, ok := err.(*exec.ExitError); ok {
8182
if exitErr.ExitCode() != 1 {
8283
t.Errorf("Expected exit code 1, got %d", exitErr.ExitCode())
@@ -87,17 +88,42 @@ func TestMainConfigFailure(t *testing.T) {
8788
}
8889

8990
/*
90-
TestURLOverride verifies that specifying a URL via CLI correctly overrides the Base URL.
91+
TestCLIOverrides verifies that CLI arguments correctly override the configuration.
92+
93+
It ensures that:
94+
- The base URL can be overridden.
95+
- Scraping depth (maxDepth) can be overridden.
96+
- Rate limit can be overridden.
97+
98+
The test **does not rely on exact print statements** to avoid fragility.
9199
*/
92-
func TestURLOverride(t *testing.T) {
93-
output, err := runMainCommand(t, "--config", "configs/default.json", "--url", "https://example.org")
100+
func TestCLIOverrides(t *testing.T) {
101+
// CLI argument values (used multiple times)
102+
newBaseURL := "https://cli-example.com"
103+
newMaxDepth := "10"
104+
newRateLimit := "2.5"
105+
106+
// Run command
107+
output, err := runMainCommand(t,
108+
"--url", newBaseURL,
109+
"--maxDepth", newMaxDepth,
110+
"--rateLimit", newRateLimit,
111+
)
94112
if err != nil {
95-
t.Fatalf("Failed to run main.go with URL override: %v\nOutput: %s", err, output)
113+
t.Fatalf("Failed to run main.go with CLI overrides: %v\nOutput: %s", err, output)
96114
}
97-
if !strings.Contains(output, "Overriding config with URL flag:") {
98-
t.Errorf("Expected URL override message not found in output.\nOutput: %s", output)
115+
116+
// Expected CLI override outputs (used multiple times)
117+
expectedOutputs := map[string]string{
118+
"Base URL: ": newBaseURL,
119+
"ScrapingOptions.MaxDepth: ": newMaxDepth,
120+
"ScrapingOptions.RateLimit: ": newRateLimit,
99121
}
100-
if !strings.Contains(output, "Base URL: https://example.org") {
101-
t.Errorf("Expected overridden URL not found in output.\nOutput: %s", output)
122+
123+
// Validate overrides dynamically
124+
for key, expected := range expectedOutputs {
125+
if !strings.Contains(output, key+expected) {
126+
t.Errorf("Expected override '%s%s' not found in output.\nOutput: %s", key, expected, output)
127+
}
102128
}
103129
}

0 commit comments

Comments
 (0)