• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

scriptype / writ-cms / 19239028684

10 Nov 2025 04:43PM UTC coverage: 81.329% (+10.6%) from 70.714%
19239028684

push

github

scriptype
Keep tests as .spec files next to relevant modules

- FileSystemParser.spec.js
- pagination.spec.js
- Create an ImmutableStack.spec.js

Update test script to work with this new approach. It looks for all
files ending with .spec.js inside src directory.

42 of 57 branches covered (73.68%)

Branch coverage included in aggregate %.

85 of 85 new or added lines in 2 files covered. (100.0%)

32 existing lines in 2 files now uncovered.

215 of 259 relevant lines covered (83.01%)

16.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

11.11
/src/lib/FileSystemParser.js
1
const { stat, readdir } = require('fs/promises')
9✔
2
const { join, relative, resolve, extname } = require('path')
9✔
3
const { readFileContent, isDirectory } = require('./fileSystemHelpers')
9✔
4

5
module.exports = class FileSystemParser {
9✔
6
  static isTextFile(extension) {
UNCOV
7
    const acceptedExtensions = [
×
8
      'txt',
9
      'md',
10
      'markdown',
11
      'hbs',
12
      'handlebars',
13
      'html',
14
      'xhtml',
15
      'htm',
16
      'rtf',
17
      'rtfd',
18
      'json',
19
      'srt'
20
    ]
UNCOV
21
    return new RegExp(`\.(${acceptedExtensions.join('|')})`, 'i').test(extension)
×
22
  }
23

24
  static lookBack(path, depth) {
25
    return resolve(path, ...Array(depth).fill('..'))
45✔
26
  }
27

28
  static async contentRoot(rootDirectory, contentDirectory) {
UNCOV
29
    if (!rootDirectory) {
×
30
      throw new Error('rootDirectory is a required parameter')
×
31
    }
UNCOV
32
    try {
×
UNCOV
33
      await stat(join(rootDirectory, contentDirectory))
×
UNCOV
34
      return join(rootDirectory, contentDirectory)
×
35
    } catch (ENOENT) {
UNCOV
36
      return rootDirectory
×
37
    }
38
  }
39

40
  constructor(fileSystemParserSettings, logger) {
UNCOV
41
    this.rootDirectory = fileSystemParserSettings.rootDirectory
×
UNCOV
42
    this.contentDirectory = fileSystemParserSettings.contentDirectory
×
UNCOV
43
    this.ignorePattern = fileSystemParserSettings.IGNORE_PATHS_REG_EXP
×
UNCOV
44
    this.logger = logger
×
45
  }
46

47
  shouldIncludePath(path) {
UNCOV
48
    return (
×
49
      !path.startsWith('_') &&
×
50
      !path.startsWith('.') &&
51
      !path.match(this.ignorePattern)
52
    )
53
  }
54

55
  async parse() {
UNCOV
56
    const root = await FileSystemParser.contentRoot(
×
57
      this.rootDirectory,
58
      this.contentDirectory
59
    )
UNCOV
60
    this.logger.debug('contentRoot', root)
×
UNCOV
61
    return this._parse(root)
×
62
  }
63

64
  async _parse(path, depth = 0) {
×
UNCOV
65
    this.logger.debug('exploring', path)
×
UNCOV
66
    return Promise.all(
×
67
      (await readdir(path))
68
      .filter(this.shouldIncludePath.bind(this))
69
      .map(async fileName => {
UNCOV
70
        const accumulatedPath = join(path, fileName)
×
UNCOV
71
        const rootPath = FileSystemParser.lookBack(accumulatedPath, depth + 1)
×
UNCOV
72
        const { birthtime } = await stat(accumulatedPath)
×
UNCOV
73
        const baseProperties = {
×
74
          name: fileName,
75
          path: relative(rootPath, accumulatedPath),
76
          absolutePath: accumulatedPath,
77
          stats: { birthtime },
78
          depth,
79
        }
UNCOV
80
        if (await isDirectory(accumulatedPath)) {
×
UNCOV
81
          return {
×
82
            ...baseProperties,
83
            children: await this._parse(accumulatedPath, depth + 1)
84
          }
85
        }
UNCOV
86
        const extension = extname(fileName)
×
UNCOV
87
        const fileProperties = {
×
88
          ...baseProperties,
89
          extension,
90
        }
UNCOV
91
        if (FileSystemParser.isTextFile(extension)) {
×
UNCOV
92
          const content = await readFileContent(accumulatedPath)
×
UNCOV
93
          return {
×
94
            ...fileProperties,
95
            content
96
          }
97
        } else {
UNCOV
98
          return fileProperties
×
99
        }
100
      })
101
    )
102
  }
103
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc