-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCheckDOM.py
More file actions
292 lines (211 loc) · 9.86 KB
/
CheckDOM.py
File metadata and controls
292 lines (211 loc) · 9.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
def checkDOM(strParam):
"""
Checks the validity of HTML tags in a given string.
Args:
strParam (str): The input string containing HTML tags.
Returns:
bool or str: Returns False if the HTML tags are invalid or mismatched.
Returns the mismatched tag if there is only one mismatch.
Returns True if all tags are valid and matched.
Examples:
>>> checkDOM("<b>Hello</b>")
True
>>> checkDOM("<b>Hello</i>")
'b'
>>> checkDOM("<b>Hello")
False
"""
stack = []
tags = ('b', 'i', 'em', 'div', 'p')
mismatch_tag = None
mismatch_count = 0
strParam = strParam.lower().replace(" ", "")
if (1 < len(strParam) <= 6 and strParam.count('<') == 1) or strParam.count('<') % 2 == 1:
return False
idx = 0
while idx < len(strParam):
if strParam[idx] == '<':
c = idx + 1
while c < len(strParam) and strParam[c] != '>':
c += 1
if c == len(strParam):
return False # No closing '>'
tag = strParam[idx + 1:c]
if tag[0] == '/': # Closing tag
tag = tag[1:]
if tag not in tags:
return False # Invalid tag
if not stack:
mismatch_count += 1
if mismatch_tag is None:
mismatch_tag = tag
elif stack[-1] != tag:
mismatch_count += 1
if mismatch_tag is None:
mismatch_tag = stack[-1]
stack.pop()
else:
stack.pop()
else: # Opening tag
if tag not in tags:
return False # Invalid tag
stack.append(tag)
idx = c
idx += 1
if stack:
mismatch_count += len(stack)
if mismatch_count == 1:
return False # Return False for a single unmatched opening tag
return False
if mismatch_count == 1:
return mismatch_tag
return mismatch_count == 0
import unittest
class TestCheckDOM(unittest.TestCase):
"""
A test case class for the CheckDOM.py module.
This class contains multiple test methods to validate the behavior of the checkDOM function.
"""
def test_example_1(self):
self.assertTrue(checkDOM("<div><b><p>hello world</p></b></div>"))
def test_example_2(self):
self.assertEqual(checkDOM("<div><i>hello</i>world</b>"), "div")
def test_example_3(self):
self.assertFalse(checkDOM("</div><p></p><div>"))
def test_example_4(self):
self.assertEqual(checkDOM("<em></em><em></em><p></b>"), "p")
def test_example_5(self):
self.assertFalse(checkDOM("<div><p></p><b><p></div>"))
def test_valid_html_nested_correctly(self):
self.assertTrue(checkDOM("<div><b><p>hello world</p></b></div>"))
self.assertTrue(checkDOM("<b><i><em>nested text</em></i></b>"))
self.assertTrue(checkDOM("<p><i>text inside</i></p>"))
self.assertFalse(checkDOM("<b><p>text</b></p>"))
def test_single_tag_change_for_validity(self):
self.assertEqual(checkDOM("<div><i>hello</i>world</b>"), "div")
self.assertEqual(checkDOM("<b><i><em>text</em></i></div>"), "b")
self.assertEqual(checkDOM("<div><p><i>example</i></b></div>"), "p")
def test_invalid_html_multiple_changes_needed(self):
self.assertFalse(checkDOM("</div><p></p><div>"))
self.assertFalse(checkDOM("<b><em>text</em></i></b>"))
self.assertFalse(checkDOM("<b><i>text</i><b>"))
self.assertFalse(checkDOM("<div><p>text</div>"))
def test_valid_html(self):
self.assertTrue(checkDOM("<div><b><p>hello world</p></b></div>"))
def test_mismatched_closing_tag(self):
self.assertEqual(checkDOM("<div><i>hello</i>world</b>"), "div")
def test_invalid_closing_tag(self):
self.assertFalse(checkDOM("</div><p></p><div>"))
def test_single_mismatched_opening_tag(self):
self.assertEqual(checkDOM("<em></em><em></em><p></b>"), "p")
def test_multiple_mismatched_opening_tags(self):
self.assertFalse(checkDOM("<div><p></p><b><p></div>"))
def test_no_tags(self):
self.assertTrue(checkDOM("hello world"))
def test_empty_string(self):
self.assertTrue(checkDOM(""))
def test_nested_valid_tags(self):
self.assertTrue(checkDOM("<div><p><b>text</b></p></div>"))
def test_nested_invalid_tags(self):
self.assertFalse(checkDOM("<div><p></p><b><p></div>"))
def test_single_tag(self):
self.assertEqual(checkDOM("<div>"), False)
def test_single_tag_closed(self):
self.assertEqual(checkDOM("</div>"), False)
def test_mixed_content(self):
self.assertTrue(checkDOM("hello <b>world</b>"))
def two_open(self):
self.assertEqual(checkDOM("<div><div>"), False)
def two_close(self):
self.assertEqual(checkDOM("</div></div>"), False)
def test_valid_combination(self):
self.assertTrue(checkDOM("<div><b><i>text</i></b></div>"))
def test_excessive_closing_tags(self):
self.assertFalse(checkDOM("<div></div></div>"))
def test_nested_invalid_similar_tags(self):
self.assertFalse(checkDOM("<b><i>text</b></i>"))
def test_valid_mixed_content(self):
self.assertTrue(checkDOM("text <b>bold</b> text <i>italic</i>"))
def test_adjacent_mismatched_tags(self):
self.assertFalse(checkDOM("<div><b></div></b>"))
def test_multiple_mismatched_tags(self):
self.assertFalse(checkDOM("<b><i>text</b><p></i></p>"))
def test_case_sensitive_tags(self):
self.assertFalse(checkDOM("<Div><b></DIV>"))
def test_nested_empty_tags(self):
self.assertTrue(checkDOM("<div><b></b></div>"))
def test_valid_no_content(self):
self.assertTrue(checkDOM("<div><b></b></div>"))
def test_invalid_unmatched_multiple(self):
self.assertFalse(checkDOM("<div><b><i></b></div><p>"))
def test_whitespace_between_tags(self):
self.assertTrue(checkDOM("<div> <b>text</b> </div>"))
def test_multiple_valid_nested_tags(self):
self.assertTrue(checkDOM("<div><div><b><i>text</i></b></div></div>"))
# Additional edge cases
def test_tags_with_extra_whitespace(self):
self.assertTrue(checkDOM("<div> <b> text </b> </div>"))
def test_tags_with_text_and_nested_tags(self):
self.assertTrue(checkDOM("<div>hello <b>world</b></div>"))
def test_multiple_nested_tags_with_text(self):
self.assertTrue(checkDOM("<div><p>hello <b>world</b></p></div>"))
def test_empty_tags(self):
self.assertTrue(checkDOM("<div><b></b></div>"))
def test_single_tag_with_text(self):
self.assertTrue(checkDOM("<b>hello</b>"))
def test_multiple_adjacent_tags(self):
self.assertTrue(checkDOM("<b></b><i></i>"))
def test_tags_with_mixed_content(self):
self.assertTrue(checkDOM("<div>hello <b>world</b>!</div>"))
def test_tags_with_only_text(self):
self.assertTrue(checkDOM("hello world"))
def test_tags_with_only_whitespace(self):
self.assertTrue(checkDOM(" "))
def test_tags_with_special_characters(self):
self.assertTrue(checkDOM("<div>@#$%^&*()</div>"))
def test_nested_valid_empty_tags(self):
self.assertTrue(checkDOM("<div><b></b><i></i></div>"))
def test_tags_with_special_html_characters(self):
self.assertTrue(checkDOM("<div>< > & </div>"))
def test_nested_tags_with_text_and_empty_tags(self):
self.assertTrue(checkDOM("<div><b>text</b><i></i></div>"))
def test_adjacent_empty_tags(self):
self.assertTrue(checkDOM("<b></b><i></i>"))
def test_long_string_of_text_with_tags(self):
self.assertTrue(checkDOM("<div>" + "hello " * 1000 + "</div>"))
def test_invalid_tags_with_unmatched_nested_tags(self):
self.assertFalse(checkDOM("<div><b><i></div></b></i>"))
def test_tags_with_numeric_characters(self):
self.assertTrue(checkDOM("<div>123 <b>456</b></div>"))
def test_empty_nested_structure(self):
self.assertTrue(checkDOM("<div><div></div></div>"))
def test_mismatched_tags_with_special_characters(self):
self.assertFalse(checkDOM("<div><b>text</b></i></div>"))
def test_large_input_with_correct_nesting(self):
self.assertTrue(checkDOM("<div>" + "<b><i>nested</i></b>" * 1000 + "</div>"))
def test_large_input_with_incorrect_nesting(self):
self.assertFalse(checkDOM("<div>" + "<b><i>nested</b></i>" * 1000 + "</div>"))
def test_multiple_closing_tags(self):
self.assertFalse(checkDOM("<div></div></div>"))
def test_correctly_nested_with_mixed_content(self):
self.assertTrue(checkDOM("<div><b>Content</b> and <i>more</i></div>"))
def test_tags_with_extra_whitespace(self):
self.assertTrue(checkDOM("<div > <b> text </b> </div>"))
self.assertTrue(checkDOM("<div> <i> text </i> </div>"))
def test_case_insensitive_tags(self):
self.assertTrue(checkDOM("<DIV><b>text</B></DIV>"))
self.assertTrue(checkDOM("<div><B>text</b></DIV>"))
def test_invalid_characters_in_tags(self):
self.assertFalse(checkDOM("<div><b@>text</b@></div>"))
self.assertFalse(checkDOM("<div><i#>text</i#></div>"))
def test_empty_tags(self):
self.assertTrue(checkDOM("<div><b></b></div>"))
self.assertTrue(checkDOM("<div><i></i></div>"))
def test_large_input_with_incorrect_nesting(self):
self.assertFalse(checkDOM("<div>" + "<b><i>nested</b></i>" * 1000 + "</div>"))
def test_multiple_closing_tags(self):
self.assertFalse(checkDOM("<div></div></div>"))
def test_correctly_nested_with_mixed_content(self):
self.assertTrue(checkDOM("<div><b>Content</b> and <i>more</i></div>"))
if __name__ == '__main__':
unittest.main()