Skip to content

Commit 560574b

Browse files
committed
updating to step 4
1 parent 111d88c commit 560574b

File tree

1 file changed

+364
-0
lines changed

1 file changed

+364
-0
lines changed
Lines changed: 364 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,364 @@
1+
#!/usr/bin/env python
2+
3+
4+
import os
5+
from io import StringIO
6+
7+
from html_render import Element, Body, P, Html, Head, Title
8+
9+
10+
# test utilities
11+
12+
def render_element_file(element, filename='temp_render_file.html',
13+
remove=False):
14+
"""
15+
renders an element, and returns what got rendered
16+
17+
This version uses an actual file on disk -- yu may want to use it so you
18+
can see the file afterward.
19+
20+
:param element: the element to be rendered (its render() method will be
21+
called)
22+
23+
:param filename='temp_render_file.html': the name of the temporary file
24+
to be used.
25+
26+
:param remove=True: Whether to remove the file after using it to render.
27+
Set this to True if you want to be able to look at
28+
after the tests run.
29+
30+
NOTE: - this could be refactored, and still used everywhere.
31+
"""
32+
with open(filename, 'w') as out_file:
33+
element.render(out_file)
34+
with open(filename, 'r') as in_file:
35+
contents = in_file.read()
36+
if remove:
37+
os.remove(filename)
38+
return contents
39+
40+
41+
def render_element(element, cur_ind=""):
42+
# this version uses a StringIO object, to keep it all in memory
43+
"""
44+
renders an element, and returns what got rendered
45+
46+
This can be used by multiple tests.
47+
48+
:param element: the element to be rendered (its render() method will
49+
be called)
50+
51+
:param filename='temp_render_file.html': the name of the temporary file
52+
to be used.
53+
54+
:param remove=True: Whether to remove the file after using it to render.
55+
Set this to True if you want to be able to look at
56+
after the tests run.
57+
58+
NOTE: - this could be refactored, and still used everywhere.
59+
"""
60+
sio = StringIO()
61+
element.render(sio, cur_indent=cur_ind)
62+
# if remove:
63+
# os.remove(filename)
64+
return sio.getvalue()
65+
66+
67+
def test_new_element():
68+
"""
69+
not much here, but it shows Elements can be initialized
70+
"""
71+
el_object = Element()
72+
el_object2 = Element('content')
73+
74+
75+
# careful here -- this is testing internal implimentations
76+
# sometimes helpful as you are developing, but you may want to remove
77+
# these tests once you have more working.
78+
def test_add_content():
79+
el_object = Element('content')
80+
assert hasattr(el_object.content[0], 'render') is True
81+
82+
el_object = Element()
83+
assert el_object.content == []
84+
85+
86+
def test_adding_empty_string():
87+
el_object = Element('')
88+
assert el_object.content == []
89+
90+
91+
# adding content and appending should
92+
# give a list of two render.TextWrappers
93+
def test_append_string():
94+
el_object = Element('spam, spam, spam')
95+
el_object.append(', wonderful spam')
96+
assert len(el_object.content) == 2
97+
assert hasattr(el_object.content[0], 'render')
98+
assert hasattr(el_object.content[1], 'render')
99+
100+
101+
def test_tag_exists():
102+
assert Element.tag == 'html'
103+
el_object = Element('spam, spam, spam')
104+
assert el_object.tag == 'html'
105+
106+
107+
def test_indent_exists():
108+
assert Element.indent == ' '
109+
110+
111+
# Now we get tot he real "meat" of the tests --does the code do what
112+
# it is supposed to do?
113+
def test_render():
114+
my_stuff = 'spam, spam, spam'
115+
el_object = Element(my_stuff)
116+
more_stuff = 'eggs, eggs, eggs'
117+
el_object.append(more_stuff)
118+
contents = render_element(el_object).strip()
119+
print(contents)
120+
assert contents.startswith('<html>')
121+
assert contents.endswith('</html>')
122+
assert my_stuff in contents
123+
assert more_stuff in contents
124+
125+
126+
# you want to be careful with these:
127+
# It is testing an implementation detail, which is less than ideal.
128+
# sometimes in TDD, it's helpful to have quickies tests of
129+
# implementation details so you can see that partially written code
130+
# is working -- but if/when you can test actual functionality, that's
131+
# better. In this case, once we have a render() method, we can test
132+
# that the tag gets rendered properly, so don't need to test if the
133+
# tag attribute is correct.
134+
135+
# def test_body_tag():
136+
# assert Body.tag == 'body'
137+
138+
# def test_p_tag():
139+
# assert Para.tag == 'p'
140+
141+
142+
# def test_html_tag():
143+
# assert HTML.tag == 'html'
144+
145+
# finally! a really good test.
146+
# This is an actual element that we want to render
147+
# so whatever the implimentation deatails, it's working.
148+
def test_render_body():
149+
my_stuff = 'spam, spam, spam'
150+
el_object = Body(my_stuff)
151+
more_stuff = 'eggs, eggs, eggs'
152+
el_object.append(more_stuff)
153+
contents = render_element(el_object).strip()
154+
assert contents.startswith('<body>')
155+
assert contents.endswith('</body>')
156+
assert my_stuff in contents
157+
assert more_stuff in contents
158+
159+
160+
def test_render_para():
161+
my_stuff = 'spam, spam, spam'
162+
p = P(my_stuff)
163+
more_stuff = 'eggs, eggs, eggs'
164+
p.append(more_stuff)
165+
contents = render_element(p).strip()
166+
assert contents.startswith('<p>')
167+
assert contents.endswith('</p>')
168+
assert my_stuff in contents
169+
assert more_stuff in contents
170+
171+
172+
def test_render_html():
173+
my_stuff = 'spam, spam, spam'
174+
el_object = Html(my_stuff)
175+
more_stuff = 'eggs, eggs, eggs'
176+
el_object.append(more_stuff)
177+
contents = render_element(el_object)
178+
assert contents.startswith('<html>')
179+
assert contents.endswith('</html>')
180+
assert my_stuff in contents
181+
assert more_stuff in contents
182+
183+
184+
def test_render_non_strings():
185+
# this is creating a html page with a single body() element in it
186+
# and a string inside that.
187+
el_object = Html(Body('any string I like'))
188+
189+
contents = render_element(el_object)
190+
# make sure extra whitespace at beginning or end doesn't mess things up.
191+
contents = contents.strip()
192+
193+
print(contents) # so we can see what's going on if a test fails
194+
195+
# so what should the results be?
196+
# the html tag is the outer tag, so the contents should start and end
197+
# with that.
198+
assert contents.startswith('<html>')
199+
assert contents.endswith('</html>')
200+
201+
# the body tags had better be there too
202+
assert '<body>' in contents
203+
assert '</body' in contents
204+
205+
# we want the tesxt, too:
206+
assert 'any string I like' in contents
207+
208+
# now lets get pretty specific:
209+
# the opening tag should come before the ending tag
210+
assert contents.index('<body>') < contents.index('</body>')
211+
# the opening tag should come before the content
212+
assert contents.index('<body>') < contents.index('any string')
213+
214+
215+
def test_render_non_strings2():
216+
"""
217+
Testing nested elements and text, in a more complex way
218+
"""
219+
html = Html()
220+
body = Body()
221+
html.append(body)
222+
p = P('any string I like')
223+
p.append('even more random text')
224+
body.append(p)
225+
body.append(P('and this is a different string'))
226+
contents = render_element(html).strip()
227+
228+
print(contents) # so we can see what's going on if a test fails
229+
230+
# so what should the results be?
231+
# the html tag is the outer tag, so the contents should start and
232+
# end with that.
233+
assert contents.startswith('<html>')
234+
assert contents.endswith('</html>')
235+
236+
# the body tags had better be there too
237+
assert '<body>' in contents
238+
assert '</body' in contents
239+
240+
# and two <p> tags
241+
assert contents.count('<p>')
242+
243+
# we want the text, too:
244+
assert 'any string I like' in contents
245+
assert 'even more random text' in contents
246+
assert 'and this is a different string' in contents
247+
248+
# you could, of course, test much more..but hopefully other things
249+
# are tested, too.
250+
251+
252+
def test_indent():
253+
"""
254+
Tests that the indentation gets passed through to the renderer
255+
"""
256+
html = Html("some content")
257+
file_contents = render_element(html, cur_ind=" ")
258+
259+
print(file_contents)
260+
lines = file_contents.split("\n")
261+
262+
assert lines[0].startswith(" <")
263+
assert lines[-1].startswith(" <")
264+
265+
266+
def test_indent_contents():
267+
"""
268+
The contents in a element should be indented more than the tag
269+
by the amount in the indent class attribute
270+
"""
271+
html = Html("some content")
272+
file_contents = render_element(html, cur_ind="")
273+
274+
print(file_contents)
275+
lines = file_contents.split("\n")
276+
assert lines[1].startswith(Element.indent)
277+
278+
279+
def test_multiple_indent():
280+
"""
281+
make sure multiple levels get indented properly
282+
"""
283+
body = Body()
284+
body.append(P("some text"))
285+
body.append(P("even more text"))
286+
html = Html(body)
287+
288+
file_contents = render_element(html)
289+
290+
print(file_contents)
291+
lines = file_contents.split("\n")
292+
for i in range(3):
293+
assert lines[i].startswith(i * Element.indent + "<")
294+
assert lines[3].startswith(3 * Element.indent + "some")
295+
assert lines[4].startswith(2 * Element.indent + "</p>")
296+
assert lines[5].startswith(2 * Element.indent + "<p>")
297+
assert lines[6].startswith(3 * Element.indent + "even ")
298+
for i in range(3):
299+
assert lines[-(i + 1)].startswith(i * Element.indent + "<")
300+
301+
302+
def test_title():
303+
"""
304+
This will implicitly test the OneLineTag element
305+
"""
306+
t = Title("Isn't this a nice title?")
307+
308+
# making sure indentation still works
309+
file_contents = render_element(t, cur_ind=" ")
310+
311+
print(file_contents)
312+
# no "strip()" -- making sure there are no extra newlines
313+
assert file_contents.startswith(" <title>I")
314+
assert file_contents.endswith("?</title>")
315+
# the only newline should be at the end
316+
317+
318+
def test_head():
319+
"""
320+
testing Head with a title in it -- it should never be blank
321+
"""
322+
h = Head()
323+
h.append(Title("A nifty title for the page"))
324+
file_contents = render_element(h, cur_ind=' ')
325+
326+
print(file_contents)
327+
assert file_contents.startswith(" <head>")
328+
assert file_contents.endswith(" </head>")
329+
330+
assert "<title>" in file_contents
331+
assert "</title>" in file_contents
332+
assert "A nifty title for the page" in file_contents
333+
334+
335+
def test_full_page_with_title():
336+
"""
337+
not much to actually test here, but good to see it put together.
338+
339+
everything should have already been tested.
340+
"""
341+
page = Html()
342+
343+
head = Head()
344+
head.append(Title("PythonClass Example"))
345+
346+
page.append(head)
347+
348+
body = Body()
349+
350+
body.append(P(
351+
"Here is a paragraph of text -- there could be more of them, "
352+
"but this is enough to show that we can do some text"))
353+
body.append(P(
354+
"And here is another piece of text -- you should be able to add any"
355+
"number"))
356+
357+
page.append(body)
358+
359+
file_contents = render_element(page)
360+
361+
print(file_contents)
362+
363+
# uncomment this to see results
364+
# assert False

0 commit comments

Comments
 (0)