(forTypings = false)
| 176 | }, |
| 177 | |
| 178 | async buildLibWithDocs(forTypings = false) { |
| 179 | // generate documentation for helpers |
| 180 | const files = fs.readdirSync('lib/helper').filter(f => path.extname(f) === '.js') |
| 181 | |
| 182 | const partials = fs.readdirSync('docs/webapi').filter(f => path.extname(f) === '.mustache') |
| 183 | const placeholders = partials.map(file => `{{> ${path.basename(file, '.mustache')} }}`) |
| 184 | const templates = partials |
| 185 | .map(file => fs.readFileSync(`docs/webapi/${file}`).toString()) |
| 186 | .map(template => |
| 187 | template |
| 188 | .replace(/^/gm, ' * ') |
| 189 | .replace(/^/, '\n') |
| 190 | .replace(/\s*\* /, ''), |
| 191 | ) |
| 192 | |
| 193 | for (const file of files) { |
| 194 | const name = path.basename(file, '.js') |
| 195 | console.log(`Building helpers with docs for ${name}`) |
| 196 | copy(`lib/helper/${file}`, `docs/build/${file}`) |
| 197 | replaceInFile(`docs/build/${file}`, cfg => { |
| 198 | for (const i in placeholders) { |
| 199 | cfg.replace(placeholders[i], templates[i]) |
| 200 | } |
| 201 | if (!forTypings) { |
| 202 | cfg.replace(/CodeceptJS.LocatorOrString\?/g, '(string | object)?') |
| 203 | cfg.replace(/LocatorOrString\?/g, '(string | object)?') |
| 204 | cfg.replace(/CodeceptJS.LocatorOrString/g, 'string | object') |
| 205 | cfg.replace(/LocatorOrString/g, 'string | object') |
| 206 | cfg.replace(/CodeceptJS.StringOrSecret/g, 'string | object') |
| 207 | } |
| 208 | // Convert ESM imports to require() for JSDoc compatibility |
| 209 | cfg.replace(/^import\s+([^'"`\s{]+)\s+from\s+['"`]([^'"`]+)['"`]/gm, "const $1 = require('$2')") |
| 210 | cfg.replace(/^import\s*\{\s*([^}]+)\s*\}\s*from\s+['"`]([^'"`]+)['"`]/gm, (match, imports, path) => { |
| 211 | // Handle destructuring imports with aliases - convert to simple require and assign |
| 212 | if (imports.includes(' as ')) { |
| 213 | const parts = imports.split(',').map(i => i.trim()) |
| 214 | const assignments = parts.map(part => { |
| 215 | if (part.includes(' as ')) { |
| 216 | const [original, alias] = part.split(' as ').map(s => s.trim()) |
| 217 | return `const ${alias} = require('${path}').${original}` |
| 218 | } else { |
| 219 | return `const ${part} = require('${path}').${part}` |
| 220 | } |
| 221 | }) |
| 222 | return assignments.join(';\n') |
| 223 | } |
| 224 | return `const { ${imports} } = require('${path}')` |
| 225 | }) |
| 226 | cfg.replace(/^import\s+\*\s+as\s+([^'"`]+)\s+from\s+['"`]([^'"`]+)['"`]/gm, "const $1 = require('$2')") |
| 227 | |
| 228 | // Convert ESM exports to module.exports for JSDoc compatibility |
| 229 | cfg.replace(/^export\s*\{\s*([^}]+)\s+as\s+default\s*\}/gm, 'module.exports = $1') |
| 230 | cfg.replace(/^export\s+default\s+(.+)/gm, 'module.exports = $1') |
| 231 | cfg.replace(/^export\s*\{\s*([^}]+)\s*\}/gm, 'module.exports = { $1 }') |
| 232 | cfg.replace(/^export\s+(class|function|const|let|var)\s+([^\s=]+)/gm, '$1 $2') |
| 233 | }) |
| 234 | } |
| 235 | }, |
nothing calls this directly
no test coverage detected