1+ import io
2+ from unittest import mock
3+
14from pytest import mark
25
6+ import shortener # for mocking timestamp()
37from shortener import parse_htaccess , choose , load_redirects
4- from shortener import gen_short , gen_unused_short , shorten_one , ShortenResult
8+ from shortener import gen_short , gen_unused_short , shorten_one , PathURL
9+ from shortener import update_htaccess
510
611
712SAMPLE_HTACCESS = """
2328
2429FROZEN_TIME = '2025-06-07 01:02:03'
2530
26- UPDATED_SAMPLE_HTACCESS = SAMPLE_HTACCESS + f"""
27- # appended: { FROZEN_TIME }
31+ UPDATED_SAMPLE_HTACCESS = (
32+ SAMPLE_HTACCESS
33+ + f"""
34+ # appended { FROZEN_TIME }
2835RedirectTemp /23 https://new.site/
2936RedirectTemp /24 https://other.new.site/
3037"""
38+ )
3139
3240
3341PARSED_SAMPLE_HTACCESS = [
34- ('book' , 'https://www.oreilly.com/.../9781492056348/' ),
35- ('home' , 'https://www.fluentpython.com/' ),
36- ('1-20' , 'https://www.fluentpython.com/' ),
37- ('ora' , 'https://www.oreilly.com/.../9781492056348/' ),
38- ('2-10' , 'http://example.com/' ),
39- ('10-2' , 'http://example.com/' ),
40- ('22' , 'http://firstshortened.co' )
42+ PathURL ('book' , 'https://www.oreilly.com/.../9781492056348/' ),
43+ PathURL ('home' , 'https://www.fluentpython.com/' ),
44+ PathURL ('1-20' , 'https://www.fluentpython.com/' ),
45+ PathURL ('ora' , 'https://www.oreilly.com/.../9781492056348/' ),
46+ PathURL ('2-10' , 'http://example.com/' ),
47+ PathURL ('10-2' , 'http://example.com/' ),
48+ PathURL ('22' , 'http://firstshortened.co' ),
4149]
4250
4351# straightforward mapping of .htaccess; some targets may be duplicated.
6068}
6169
6270
63-
6471def test_parse_htaccess ():
6572 res = list (parse_htaccess (SAMPLE_HTACCESS ))
6673 assert res == PARSED_SAMPLE_HTACCESS
@@ -83,8 +90,8 @@ def test_choose(a, b, expected):
8390
8491
8592def test_load_redirects ():
86- redirects , _ = load_redirects (PARSED_SAMPLE_HTACCESS )
87- assert redirects == SAMPLE_REDIRECTS
93+ redirects , _ = load_redirects (PARSED_SAMPLE_HTACCESS )
94+ assert redirects == SAMPLE_REDIRECTS
8895
8996
9097def test_load_redirect_targets ():
@@ -99,8 +106,8 @@ def test_load_redirect_targets():
99106 ('https://new.site/' , '23' , True ),
100107 ],
101108)
102- def test_shorten (target , path , new ):
103- expected = ShortenResult ( target , path , new )
109+ def test_shorten_one (target , path , new ):
110+ expected = PathURL ( path , target , new )
104111 redirects = dict (SAMPLE_REDIRECTS )
105112 targets = dict (SAMPLE_TARGETS )
106113 result = shorten_one (target , gen_unused_short (redirects ), redirects , targets )
@@ -118,8 +125,23 @@ def test_shorten(target, path, new):
118125 assert targets == SAMPLE_TARGETS
119126
120127
128+ def test_timestamp ():
129+ with mock .patch ('shortener.timestamp' , return_value = FROZEN_TIME ):
130+ assert shortener .timestamp () == FROZEN_TIME
131+
132+
121133def test_update_htaccess ():
122- pass
134+ directives = [
135+ PathURL ('home' , 'https://www.fluentpython.com/' , False ),
136+ PathURL ('23' , 'https://new.site/' , True ),
137+ PathURL ('24' , 'https://other.new.site/' , True )
138+ ]
139+ given = io .StringIO (SAMPLE_HTACCESS )
140+ given .seek (0 , io .SEEK_END ) # emulate append mode
141+ with mock .patch ('shortener.timestamp' , return_value = FROZEN_TIME ):
142+ res = update_htaccess (given , directives )
143+ assert res == 2
144+ assert given .getvalue () == UPDATED_SAMPLE_HTACCESS
123145
124146
125147def test_gen_short ():
0 commit comments