Passed
Pull Request — master (#181)
by Sean
03:09
created

src/tests/local-file.test.ts   A

Complexity

Total Complexity 3
Complexity/F 3

Size

Lines of Code 220
Function Count 1

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 3
eloc 173
mnd 2
bc 2
fnc 1
dl 0
loc 220
rs 10
bpm 2
cpm 3
noi 0
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A local-file.test.ts ➔ isUrl 0 8 2
1
import 'async';
2
import 'assert';
3
import 'should';
4
import fs from 'fs';
5
import path from 'path';
6
import zlib from 'zlib';
7
8
// Simple function to validate URLs using the URL object
9
function isUrl(url: string): boolean {
10
  try {
11
    new URL(url);
12
    return true;
13
  } catch {
14
    return false;
15
  }
16
}
17
18
import Sitemapper from '../../lib/assets/sitemapper.js';
19
import { SitemapperResponse } from '../../sitemapper';
20
let sitemapper: Sitemapper;
21
22
describe('Local File Parsing', function () {
23
  beforeEach(() => {
24
    sitemapper = new Sitemapper();
25
  });
26
27
  describe('isLocalFile method', function () {
28
    it('should return false for HTTP URLs', () => {
29
      sitemapper.isLocalFile('http://example.com/sitemap.xml').should.be.false;
30
    });
31
32
    it('should return false for HTTPS URLs', () => {
33
      sitemapper.isLocalFile('https://example.com/sitemap.xml').should.be.false;
34
    });
35
36
    it('should return false for non-existent file paths', () => {
37
      sitemapper.isLocalFile('/non/existent/file.xml').should.be.false;
38
    });
39
40
    it('should return true for existing local files', () => {
41
      const testFile = path.join(__dirname, 'test-sitemap.xml');
42
      sitemapper.isLocalFile(testFile).should.be.true;
43
    });
44
45
    it('should return false for empty or null input', () => {
46
      sitemapper.isLocalFile('').should.be.false;
47
      sitemapper.isLocalFile(null as any).should.be.false;
48
      sitemapper.isLocalFile(undefined as any).should.be.false;
49
    });
50
  });
51
52
  describe('Local sitemap file parsing', function () {
53
    it('should parse a local sitemap.xml file', function (done) {
54
      const testFile = path.join(__dirname, 'test-sitemap.xml');
55
      sitemapper
56
        .fetch(testFile)
57
        .then((data) => {
58
          data.sites.should.be.Array;
59
          data.url.should.equal(testFile);
60
          data.sites.length.should.equal(3);
61
          data.sites.should.containEql('https://example.com/');
62
          data.sites.should.containEql('https://example.com/page1');
63
          data.sites.should.containEql('https://example.com/page2');
64
          data.sites.forEach((site) => {
65
            isUrl(site as string).should.be.true;
66
          });
67
          done();
68
        })
69
        .catch((error) => {
70
          console.error('Test failed:', error);
71
          done(error);
72
        });
73
    });
74
75
    it('should handle local sitemapindex files', function (done) {
76
      const testFile = path.join(__dirname, 'test-sitemap-index.xml');
77
      sitemapper
78
        .fetch(testFile)
79
        .then((data) => {
80
          data.sites.should.be.Array;
81
          data.url.should.equal(testFile);
82
          // Note: This will attempt to fetch the child sitemaps as URLs
83
          // which may fail, but the structure should be parsed
84
          done();
85
        })
86
        .catch((error) => {
87
          console.error('Test failed:', error);
88
          done(error);
89
        });
90
    });
91
92
    it('should work with fields option for local files', function (done) {
93
      const testFile = path.join(__dirname, 'test-sitemap.xml');
94
      const sitemapperWithFields = new Sitemapper({
95
        fields: {
96
          loc: true,
97
          lastmod: true,
98
          priority: true,
99
          changefreq: true,
100
        },
101
      });
102
      
103
      sitemapperWithFields
104
        .fetch(testFile)
105
        .then((data) => {
106
          data.sites.should.be.Array;
107
          data.sites.length.should.equal(3);
108
          
109
          const firstSite = data.sites[0] as any;
110
          firstSite.should.have.property('loc').which.is.a.String();
111
          firstSite.should.have.property('lastmod').which.is.a.String();
112
          firstSite.should.have.property('priority').which.is.a.String();
113
          firstSite.should.have.property('changefreq').which.is.a.String();
114
          
115
          firstSite.loc.should.equal('https://example.com/');
116
          firstSite.priority.should.equal('1.0');
117
          firstSite.changefreq.should.equal('monthly');
118
          
119
          done();
120
        })
121
        .catch((error) => {
122
          console.error('Test failed:', error);
123
          done(error);
124
        });
125
    });
126
127
    it('should handle lastmod filtering for local files', function (done) {
128
      const testFile = path.join(__dirname, 'test-sitemap.xml');
129
      // Set lastmod to a timestamp after 2023-01-02
130
      const sitemapperWithLastmod = new Sitemapper({
131
        lastmod: new Date('2023-01-02T12:00:00+00:00').getTime(),
132
      });
133
      
134
      sitemapperWithLastmod
135
        .fetch(testFile)
136
        .then((data) => {
137
          data.sites.should.be.Array;
138
          // Should only include URLs with lastmod >= 2023-01-02T12:00:00
139
          data.sites.length.should.equal(1); // Only page2 qualifies
140
          data.sites.should.containEql('https://example.com/page2');
141
          done();
142
        })
143
        .catch((error) => {
144
          console.error('Test failed:', error);
145
          done(error);
146
        });
147
    });
148
149
    it('should handle exclusions for local files', function (done) {
150
      const testFile = path.join(__dirname, 'test-sitemap.xml');
151
      const sitemapperWithExclusions = new Sitemapper({
152
        exclusions: [/page1/],
153
      });
154
      
155
      sitemapperWithExclusions
156
        .fetch(testFile)
157
        .then((data) => {
158
          data.sites.should.be.Array;
159
          data.sites.length.should.equal(2);
160
          data.sites.should.containEql('https://example.com/');
161
          data.sites.should.containEql('https://example.com/page2');
162
          data.sites.should.not.containEql('https://example.com/page1');
163
          done();
164
        })
165
        .catch((error) => {
166
          console.error('Test failed:', error);
167
          done(error);
168
        });
169
    });
170
171
    it('should handle non-existent local files gracefully', function (done) {
172
      const nonExistentFile = path.join(__dirname, 'non-existent.xml');
173
      sitemapper
174
        .fetch(nonExistentFile)
175
        .then((data) => {
176
          data.sites.should.be.Array;
177
          data.sites.length.should.equal(0);
178
          data.errors.should.be.Array;
179
          data.errors.length.should.be.greaterThan(0);
180
          done();
181
        })
182
        .catch((error) => {
183
          console.error('Test failed:', error);
184
          done(error);
185
        });
186
    });
187
188
    it('should handle gzipped local files', function (done) {
189
      // Create a gzipped version of the test sitemap
190
      const testFile = path.join(__dirname, 'test-sitemap.xml');
191
      const gzippedFile = path.join(__dirname, 'test-sitemap.xml.gz');
192
      
193
      const content = fs.readFileSync(testFile);
194
      const gzippedContent = zlib.gzipSync(content);
195
      fs.writeFileSync(gzippedFile, gzippedContent);
196
      
197
      sitemapper
198
        .fetch(gzippedFile)
199
        .then((data) => {
200
          data.sites.should.be.Array;
201
          data.sites.length.should.equal(3);
202
          data.sites.should.containEql('https://example.com/');
203
          data.sites.should.containEql('https://example.com/page1');
204
          data.sites.should.containEql('https://example.com/page2');
205
          
206
          // Clean up
207
          fs.unlinkSync(gzippedFile);
208
          done();
209
        })
210
        .catch((error) => {
211
          // Clean up even on failure
212
          if (fs.existsSync(gzippedFile)) {
213
            fs.unlinkSync(gzippedFile);
214
          }
215
          console.error('Test failed:', error);
216
          done(error);
217
        });
218
    });
219
  });
220
});