@@ -20,46 +20,44 @@ def runner() -> CliRunner:
20
20
@pytest .fixture
21
21
def temp_config_dir ():
22
22
with tempfile .TemporaryDirectory () as tmpdir :
23
- old_home = os .environ .get (" HOME" )
24
- os .environ [" HOME" ] = tmpdir
23
+ old_home = os .environ .get (' HOME' )
24
+ os .environ [' HOME' ] = tmpdir
25
25
yield Path (tmpdir )
26
26
if old_home :
27
- os .environ [" HOME" ] = old_home
27
+ os .environ [' HOME' ] = old_home
28
28
29
29
30
30
@pytest .fixture
31
31
def sample_configs (temp_config_dir : Path ) -> dict [str , str ]:
32
32
configs = {
33
- " browser.yml" : {
34
- " headless" : True ,
35
- " viewport_width" : 1280 ,
36
- " user_agent_mode" : " random" ,
33
+ ' browser.yml' : {
34
+ ' headless' : True ,
35
+ ' viewport_width' : 1280 ,
36
+ ' user_agent_mode' : ' random'
37
37
},
38
- " crawler.yml" : {
39
- " cache_mode" : " bypass" ,
40
- " wait_until" : " networkidle" ,
41
- " scan_full_page" : True ,
38
+ ' crawler.yml' : {
39
+ ' cache_mode' : ' bypass' ,
40
+ ' wait_until' : ' networkidle' ,
41
+ ' scan_full_page' : True
42
42
},
43
- "extract_css.yml" : {"type" : "json-css" , "params" : {"verbose" : True }},
44
- "css_schema.json" : {
45
- "name" : "ArticleExtractor" ,
46
- "baseSelector" : ".article" ,
47
- "fields" : [
48
- {"name" : "title" , "selector" : "h1.title" , "type" : "text" },
49
- {
50
- "name" : "link" ,
51
- "selector" : "a.read-more" ,
52
- "type" : "attribute" ,
53
- "attribute" : "href" ,
54
- },
55
- ],
43
+ 'extract_css.yml' : {
44
+ 'type' : 'json-css' ,
45
+ 'params' : {'verbose' : True }
56
46
},
47
+ 'css_schema.json' : {
48
+ 'name' : 'ArticleExtractor' ,
49
+ 'baseSelector' : '.article' ,
50
+ 'fields' : [
51
+ {'name' : 'title' , 'selector' : 'h1.title' , 'type' : 'text' },
52
+ {'name' : 'link' , 'selector' : 'a.read-more' , 'type' : 'attribute' , 'attribute' : 'href' }
53
+ ]
54
+ }
57
55
}
58
56
59
57
for filename , content in configs .items ():
60
58
path = temp_config_dir / filename
61
- with open (path , "w" ) as f :
62
- if filename .endswith (" .yml" ):
59
+ with open (path , 'w' ) as f :
60
+ if filename .endswith (' .yml' ):
63
61
yaml .dump (content , f )
64
62
else :
65
63
json .dump (content , f )
@@ -69,25 +67,25 @@ def sample_configs(temp_config_dir: Path) -> dict[str, str]:
69
67
70
68
class TestCLIBasics :
71
69
def test_help (self , runner : CliRunner ):
72
- result : Result = runner .invoke (cli , [" --help" ])
70
+ result : Result = runner .invoke (cli , [' --help' ])
73
71
assert result .exit_code == 0
74
- assert " Crawl4AI CLI" in result .output
72
+ assert ' Crawl4AI CLI' in result .output
75
73
76
74
def test_examples (self , runner : CliRunner ):
77
- result : Result = runner .invoke (cli , [" examples" ])
75
+ result : Result = runner .invoke (cli , [' examples' ])
78
76
assert result .exit_code == 0
79
- assert " Examples" in result .output
77
+ assert ' Examples' in result .output
80
78
81
79
def test_missing_url (self , runner ):
82
- result : Result = runner .invoke (cli , [" crawl" ])
80
+ result : Result = runner .invoke (cli , [' crawl' ])
83
81
assert result .exit_code != 0
84
82
assert "Error: Missing argument 'URL'" in result .output
85
83
86
84
87
85
class TestConfigParsing :
88
86
def test_parse_key_values_basic (self ):
89
- result = parse_key_values (None , None , " key1=value1,key2=true" )
90
- assert result == {" key1" : " value1" , " key2" : True }
87
+ result = parse_key_values (None , None , ' key1=value1,key2=true' )
88
+ assert result == {' key1' : ' value1' , ' key2' : True }
91
89
92
90
def test_parse_key_values_invalid (self ):
93
91
with pytest .raises (click .BadParameter ):
@@ -96,51 +94,50 @@ def test_parse_key_values_invalid(self):
96
94
97
95
class TestConfigLoading :
98
96
def test_load_yaml_config (self , sample_configs ):
99
- config = load_config_file (sample_configs [" browser.yml" ])
100
- assert config [" headless" ] is True
101
- assert config [" viewport_width" ] == 1280
97
+ config = load_config_file (sample_configs [' browser.yml' ])
98
+ assert config [' headless' ] is True
99
+ assert config [' viewport_width' ] == 1280
102
100
103
101
def test_load_json_config (self , sample_configs ):
104
- config = load_config_file (sample_configs [" css_schema.json" ])
105
- assert config [" name" ] == " ArticleExtractor"
106
- assert len (config [" fields" ]) == 2
102
+ config = load_config_file (sample_configs [' css_schema.json' ])
103
+ assert config [' name' ] == ' ArticleExtractor'
104
+ assert len (config [' fields' ]) == 2
107
105
108
106
def test_load_nonexistent_config (self ):
109
107
with pytest .raises (click .BadParameter ):
110
- load_config_file (" nonexistent.yml" )
108
+ load_config_file (' nonexistent.yml' )
111
109
112
110
113
111
class TestLLMConfig :
114
112
def test_llm_config_creation (self , temp_config_dir : Path , runner : CliRunner ):
115
113
def input_simulation (inputs ):
116
- return runner .invoke (
117
- cli ,
118
- ["https://example.com" , "-q" , "test question" ],
119
- input = "\n " .join (inputs ),
120
- )
114
+ return runner .invoke (cli , ['https://example.com' , '-q' , 'test question' ],
115
+ input = '\n ' .join (inputs ))
121
116
122
117
123
118
class TestCrawlingFeatures :
124
119
def test_basic_crawl (self , runner : CliRunner ):
125
- result : Result = runner .invoke (cli , [" crawl" , " https://example.com" ])
120
+ result : Result = runner .invoke (cli , [' crawl' , ' https://example.com' ])
126
121
assert result .exit_code == 0
127
122
128
123
129
124
class TestErrorHandling :
130
125
def test_invalid_config_file (self , runner : CliRunner ):
131
- result : Result = runner .invoke (
132
- cli , ["https://example.com" , "--browser-config" , "nonexistent.yml" ]
133
- )
126
+ result : Result = runner .invoke (cli , [
127
+ 'https://example.com' ,
128
+ '--browser-config' , 'nonexistent.yml'
129
+ ])
134
130
assert result .exit_code != 0
135
131
136
132
def test_invalid_schema (self , runner : CliRunner , temp_config_dir : Path ):
137
- invalid_schema = temp_config_dir / "invalid_schema.json"
138
- with open (invalid_schema , "w" ) as f :
139
- f .write ("invalid json" )
140
-
141
- result : Result = runner .invoke (
142
- cli , ["https://example.com" , "--schema" , str (invalid_schema )]
143
- )
133
+ invalid_schema = temp_config_dir / 'invalid_schema.json'
134
+ with open (invalid_schema , 'w' ) as f :
135
+ f .write ('invalid json' )
136
+
137
+ result : Result = runner .invoke (cli , [
138
+ 'https://example.com' ,
139
+ '--schema' , str (invalid_schema )
140
+ ])
144
141
assert result .exit_code != 0
145
142
146
143
0 commit comments