1
+ const generateHTML = require ( '../src/generateHTML' ) ;
2
+
3
+ describe ( 'generateHTML' , ( ) => {
4
+ describe ( 'with valid geolocation data' , ( ) => {
5
+ const mockResult = {
6
+ ip : '207.97.227.239' ,
7
+ range : [ 3479299072 , 3479299327 ] ,
8
+ country : 'US' ,
9
+ region : 'NY' ,
10
+ eu : '0' ,
11
+ timezone : 'America/New_York' ,
12
+ city : 'New York' ,
13
+ ll : [ 40.7128 , - 74.0060 ] ,
14
+ metro : 501 ,
15
+ area : 1000 ,
16
+ } ;
17
+
18
+ it ( 'should generate valid HTML with DOCTYPE' , ( ) => {
19
+ const html = generateHTML ( mockResult ) ;
20
+ expect ( html ) . toContain ( '<!DOCTYPE html>' ) ;
21
+ expect ( html ) . toContain ( '<html>' ) ;
22
+ expect ( html ) . toContain ( '</html>' ) ;
23
+ } ) ;
24
+
25
+ it ( 'should include proper meta tags' , ( ) => {
26
+ const html = generateHTML ( mockResult ) ;
27
+ expect ( html ) . toContain ( '<meta charset="UTF-8"' ) ;
28
+ expect ( html ) . toContain ( '<meta name="viewport"' ) ;
29
+ expect ( html ) . toContain ( '<meta name="author" content="Ahmed Tokyo">' ) ;
30
+ expect ( html ) . toContain ( '<title>Micro GeoIP Lite - Fast, Free and Open Source IP Geolocation Service</title>' ) ;
31
+ } ) ;
32
+
33
+ it ( 'should include Open Graph meta tags' , ( ) => {
34
+ const html = generateHTML ( mockResult ) ;
35
+ expect ( html ) . toContain ( '<meta property="og:type" content="website">' ) ;
36
+ expect ( html ) . toContain ( '<meta property="og:title"' ) ;
37
+ expect ( html ) . toContain ( '<meta property="og:description"' ) ;
38
+ expect ( html ) . toContain ( '<meta property="og:image"' ) ;
39
+ } ) ;
40
+
41
+ it ( 'should include Twitter meta tags' , ( ) => {
42
+ const html = generateHTML ( mockResult ) ;
43
+ expect ( html ) . toContain ( '<meta property="twitter:card"' ) ;
44
+ expect ( html ) . toContain ( '<meta property="twitter:title"' ) ;
45
+ expect ( html ) . toContain ( '<meta property="twitter:description"' ) ;
46
+ } ) ;
47
+
48
+ it ( 'should display geolocation data in details section' , ( ) => {
49
+ const html = generateHTML ( mockResult ) ;
50
+ expect ( html ) . toContain ( '<h2>Details</h2>' ) ;
51
+ expect ( html ) . toContain ( '<strong>ip:</strong> 207.97.227.239' ) ;
52
+ expect ( html ) . toContain ( '<strong>country:</strong> US' ) ;
53
+ expect ( html ) . toContain ( '<strong>city:</strong> New York' ) ;
54
+ expect ( html ) . toContain ( '<strong>timezone:</strong> America/New_York' ) ;
55
+ } ) ;
56
+
57
+ it ( 'should include JSON data section' , ( ) => {
58
+ const html = generateHTML ( mockResult ) ;
59
+ expect ( html ) . toContain ( '<h2>Raw JSON Data</h2>' ) ;
60
+ expect ( html ) . toContain ( 'class="json-code"' ) ;
61
+ expect ( html ) . toContain ( '"ip": "207.97.227.239"' ) ;
62
+ expect ( html ) . toContain ( '"country": "US"' ) ;
63
+ } ) ;
64
+
65
+ it ( 'should include mobile ad container with ID' , ( ) => {
66
+ const html = generateHTML ( mockResult ) ;
67
+ expect ( html ) . toContain ( 'id="mobile-ad-container"' ) ;
68
+ expect ( html ) . toContain ( 'class="mobile-ad"' ) ;
69
+ } ) ;
70
+
71
+ it ( 'should include desktop ad slot' , ( ) => {
72
+ const html = generateHTML ( mockResult ) ;
73
+ expect ( html ) . toContain ( 'data-ad-slot="8543379979"' ) ;
74
+ expect ( html ) . toContain ( 'data-ad-client="ca-pub-5266987079964279"' ) ;
75
+ expect ( html ) . toContain ( 'data-ad-format="auto"' ) ;
76
+ } ) ;
77
+
78
+ it ( 'should include AdSense script' , ( ) => {
79
+ const html = generateHTML ( mockResult ) ;
80
+ expect ( html ) . toContain ( 'pagead2.googlesyndication.com/pagead/js/adsbygoogle.js' ) ;
81
+ expect ( html ) . toContain ( 'client=ca-pub-5266987079964279' ) ;
82
+ } ) ;
83
+
84
+ it ( 'should include mobile ad injection JavaScript' , ( ) => {
85
+ const html = generateHTML ( mockResult ) ;
86
+ expect ( html ) . toContain ( 'document.addEventListener(\'DOMContentLoaded\'' ) ;
87
+ expect ( html ) . toContain ( 'window.innerWidth < 768' ) ;
88
+ expect ( html ) . toContain ( 'data-ad-slot="9567852882"' ) ;
89
+ expect ( html ) . toContain ( 'window.adsbygoogle.push({})' ) ;
90
+ } ) ;
91
+
92
+ it ( 'should include SEO content section' , ( ) => {
93
+ const html = generateHTML ( mockResult ) ;
94
+ expect ( html ) . toContain ( 'class="seo-content"' ) ;
95
+ expect ( html ) . toContain ( 'Free & Open Source IP Geolocation API' ) ;
96
+ expect ( html ) . toContain ( 'Why Choose Micro GeoIP Lite?' ) ;
97
+ expect ( html ) . toContain ( 'Perfect for Backend Development' ) ;
98
+ expect ( html ) . toContain ( 'Frontend & Client-Side Integration' ) ;
99
+ } ) ;
100
+
101
+ it ( 'should include use cases section' , ( ) => {
102
+ const html = generateHTML ( mockResult ) ;
103
+ expect ( html ) . toContain ( 'class="use-cases"' ) ;
104
+ expect ( html ) . toContain ( 'E-commerce' ) ;
105
+ expect ( html ) . toContain ( 'Security' ) ;
106
+ expect ( html ) . toContain ( 'Analytics' ) ;
107
+ expect ( html ) . toContain ( 'Content' ) ;
108
+ } ) ;
109
+
110
+ it ( 'should include NPM package information' , ( ) => {
111
+ const html = generateHTML ( mockResult ) ;
112
+ expect ( html ) . toContain ( 'npm install micro-geoip-lite' ) ;
113
+ expect ( html ) . toContain ( 'import geodecodeIp from \'micro-geoip-lite\'' ) ;
114
+ expect ( html ) . toContain ( 'https://www.npmjs.com/package/micro-geoip-lite' ) ;
115
+ } ) ;
116
+ } ) ;
117
+
118
+ describe ( 'with error data' , ( ) => {
119
+ const errorResult = {
120
+ error : 'Please only submit valid IPs'
121
+ } ;
122
+
123
+ it ( 'should display error message' , ( ) => {
124
+ const html = generateHTML ( errorResult ) ;
125
+ expect ( html ) . toContain ( '<h2>Error</h2>' ) ;
126
+ expect ( html ) . toContain ( 'class="error-container"' ) ;
127
+ expect ( html ) . toContain ( '❌ Please only submit valid IPs' ) ;
128
+ } ) ;
129
+
130
+ it ( 'should include error help text' , ( ) => {
131
+ const html = generateHTML ( errorResult ) ;
132
+ expect ( html ) . toContain ( 'Please check your IP address and try again' ) ;
133
+ expect ( html ) . toContain ( 'Examples of valid IPs:' ) ;
134
+ expect ( html ) . toContain ( '8.8.8.8 (Google DNS)' ) ;
135
+ expect ( html ) . toContain ( '1.1.1.1 (Cloudflare DNS)' ) ;
136
+ } ) ;
137
+
138
+ it ( 'should still include JSON data section with error' , ( ) => {
139
+ const html = generateHTML ( errorResult ) ;
140
+ expect ( html ) . toContain ( '<h2>Raw JSON Data</h2>' ) ;
141
+ expect ( html ) . toContain ( '"error": "Please only submit valid IPs"' ) ;
142
+ } ) ;
143
+
144
+ it ( 'should still include all meta tags and SEO content' , ( ) => {
145
+ const html = generateHTML ( errorResult ) ;
146
+ expect ( html ) . toContain ( '<title>Micro GeoIP Lite' ) ;
147
+ expect ( html ) . toContain ( 'class="seo-content"' ) ;
148
+ expect ( html ) . toContain ( 'Free & Open Source IP Geolocation API' ) ;
149
+ } ) ;
150
+
151
+ it ( 'should handle error result with additional data properties' , ( ) => {
152
+ const errorWithData = {
153
+ error : 'Lookup failed' ,
154
+ ip : '192.168.1.1' ,
155
+ attempted : true
156
+ } ;
157
+ const html = generateHTML ( errorWithData ) ;
158
+ expect ( html ) . toContain ( '<h2>Error</h2>' ) ;
159
+ expect ( html ) . toContain ( '❌ Lookup failed' ) ;
160
+ expect ( html ) . toContain ( '"error": "Lookup failed"' ) ;
161
+ expect ( html ) . toContain ( '"ip": "192.168.1.1"' ) ;
162
+ expect ( html ) . toContain ( '"attempted": true' ) ;
163
+ } ) ;
164
+ } ) ;
165
+
166
+ describe ( 'with empty/null data' , ( ) => {
167
+ it ( 'should handle null result' , ( ) => {
168
+ const html = generateHTML ( null ) ;
169
+ expect ( html ) . toContain ( 'class="no-data"' ) ;
170
+ expect ( html ) . toContain ( 'No geolocation data available' ) ;
171
+ } ) ;
172
+
173
+ it ( 'should handle empty object' , ( ) => {
174
+ const html = generateHTML ( { } ) ;
175
+ expect ( html ) . toContain ( 'class="no-data"' ) ;
176
+ expect ( html ) . toContain ( 'No geolocation data available' ) ;
177
+ } ) ;
178
+
179
+ it ( 'should handle undefined result' , ( ) => {
180
+ const html = generateHTML ( undefined ) ;
181
+ expect ( html ) . toContain ( 'class="no-data"' ) ;
182
+ expect ( html ) . toContain ( 'No geolocation data available' ) ;
183
+ } ) ;
184
+ } ) ;
185
+
186
+ describe ( 'CSS and styling' , ( ) => {
187
+ const mockResult = { ip : '8.8.8.8' , country : 'US' } ;
188
+
189
+ it ( 'should include responsive CSS grid' , ( ) => {
190
+ const html = generateHTML ( mockResult ) ;
191
+ expect ( html ) . toContain ( '.content-grid' ) ;
192
+ expect ( html ) . toContain ( 'grid-template-columns: 1fr' ) ;
193
+ expect ( html ) . toContain ( '@media (min-width: 768px)' ) ;
194
+ } ) ;
195
+
196
+ it ( 'should include mobile ad CSS rules' , ( ) => {
197
+ const html = generateHTML ( mockResult ) ;
198
+ expect ( html ) . toContain ( '.mobile-ad' ) ;
199
+ expect ( html ) . toContain ( 'display: block' ) ;
200
+ expect ( html ) . toContain ( 'display: none' ) ;
201
+ } ) ;
202
+
203
+ it ( 'should include error container styling' , ( ) => {
204
+ const html = generateHTML ( mockResult ) ;
205
+ expect ( html ) . toContain ( '.error-container' ) ;
206
+ expect ( html ) . toContain ( 'background: #fee' ) ;
207
+ expect ( html ) . toContain ( 'border: 2px solid #e74c3c' ) ;
208
+ } ) ;
209
+
210
+ it ( 'should include JSON container styling' , ( ) => {
211
+ const html = generateHTML ( mockResult ) ;
212
+ expect ( html ) . toContain ( '.json-container' ) ;
213
+ expect ( html ) . toContain ( 'background: #2d3748' ) ;
214
+ expect ( html ) . toContain ( '.json-code' ) ;
215
+ } ) ;
216
+ } ) ;
217
+
218
+ describe ( 'JavaScript functionality' , ( ) => {
219
+ const mockResult = { ip : '8.8.8.8' , country : 'US' } ;
220
+
221
+ it ( 'should include mobile detection logic' , ( ) => {
222
+ const html = generateHTML ( mockResult ) ;
223
+ expect ( html ) . toContain ( 'const isMobile = window.innerWidth < 768' ) ;
224
+ expect ( html ) . toContain ( 'getElementById(\'mobile-ad-container\')' ) ;
225
+ } ) ;
226
+
227
+ it ( 'should include conditional ad injection' , ( ) => {
228
+ const html = generateHTML ( mockResult ) ;
229
+ expect ( html ) . toContain ( 'if (isMobile && mobileAdContainer)' ) ;
230
+ expect ( html ) . toContain ( 'mobileAdContainer.innerHTML =' ) ;
231
+ expect ( html ) . toContain ( 'mobileAdContainer.style.display = \'block\'' ) ;
232
+ expect ( html ) . toContain ( 'mobileAdContainer.style.display = \'none\'' ) ;
233
+ } ) ;
234
+
235
+ it ( 'should include AdSense initialization' , ( ) => {
236
+ const html = generateHTML ( mockResult ) ;
237
+ expect ( html ) . toContain ( 'window.adsbygoogle = window.adsbygoogle || []' ) ;
238
+ expect ( html ) . toContain ( 'window.adsbygoogle.push({})' ) ;
239
+ } ) ;
240
+ } ) ;
241
+ } ) ;
0 commit comments