1
0
mirror of synced 2025-12-19 18:10:59 -05:00
Files
docs/src/data-directory/tests/orphaned-features.ts
2025-10-14 20:50:09 +00:00

187 lines
7.7 KiB
TypeScript

import { fileURLToPath } from 'url'
import path from 'path'
import fs from 'fs'
import { describe, expect, test } from 'vitest'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const fixturesDir = path.join(__dirname, 'orphaned-features', 'fixtures')
// Import the actual helper functions from the orphaned features script
const { getVariableFiles, getReusableFiles } = await import(
'@/data-directory/scripts/find-orphaned-features/find.js'
)
describe('orphaned features detection', () => {
test('getVariableFiles finds all yml files in variables directory', () => {
const variablesDir = path.join(fixturesDir, 'data', 'variables')
const variableFiles = getVariableFiles(variablesDir)
// Should find our test.yml file
expect(variableFiles).toHaveLength(1)
expect(variableFiles[0]).toMatch(/test\.yml$/)
// Verify the file exists and contains expected content
const testVariableContent = fs.readFileSync(variableFiles[0], 'utf-8')
expect(testVariableContent).toContain('used-in-variables')
expect(testVariableContent).toContain('ifversion')
})
test('getReusableFiles finds all md files in reusables directory', () => {
const reusablesDir = path.join(fixturesDir, 'data', 'reusables')
const reusableFiles = getReusableFiles(reusablesDir)
// Should find our test.md file
expect(reusableFiles).toHaveLength(1)
expect(reusableFiles[0]).toMatch(/test\.md$/)
// Verify the file exists and contains expected content
const testReusableContent = fs.readFileSync(reusableFiles[0], 'utf-8')
expect(testReusableContent).toContain('used-in-reusables')
expect(testReusableContent).toContain('ifversion')
})
test('variables files contain feature references that should be detected', () => {
const variablesDir = path.join(fixturesDir, 'data', 'variables')
const testVariableFile = path.join(variablesDir, 'test.yml')
expect(fs.existsSync(testVariableFile)).toBe(true)
const content = fs.readFileSync(testVariableFile, 'utf-8')
// Verify the test file has the expected feature usage patterns
expect(content).toContain('{% ifversion used-in-variables %}')
expect(content).toContain('test_variable_with_feature')
expect(content).toContain('complex_variable')
})
test('helper functions handle nested directories', () => {
// Create a temporary nested structure to test
const tempDir = path.join(__dirname, 'temp-nested-test')
const nestedVariablesDir = path.join(tempDir, 'variables', 'nested')
const nestedReusablesDir = path.join(tempDir, 'reusables', 'nested')
// Create directories
fs.mkdirSync(nestedVariablesDir, { recursive: true })
fs.mkdirSync(nestedReusablesDir, { recursive: true })
// Create test files
fs.writeFileSync(path.join(nestedVariablesDir, 'nested.yml'), 'test: value')
fs.writeFileSync(path.join(nestedReusablesDir, 'nested.md'), '# Test content')
fs.writeFileSync(path.join(tempDir, 'variables', 'root.yml'), 'root: value')
fs.writeFileSync(path.join(tempDir, 'reusables', 'root.md'), '# Root content')
try {
// Test getVariableFiles with nested structure
const variableFiles = getVariableFiles(path.join(tempDir, 'variables'))
expect(variableFiles).toHaveLength(2)
expect(variableFiles.some((f) => f.includes('nested.yml'))).toBe(true)
expect(variableFiles.some((f) => f.includes('root.yml'))).toBe(true)
// Test getReusableFiles with nested structure
const reusableFiles = getReusableFiles(path.join(tempDir, 'reusables'))
expect(reusableFiles).toHaveLength(2)
expect(reusableFiles.some((f) => f.includes('nested.md'))).toBe(true)
expect(reusableFiles.some((f) => f.includes('root.md'))).toBe(true)
} finally {
// Clean up
fs.rmSync(tempDir, { recursive: true, force: true })
}
})
test('helper functions ignore non-target files', () => {
// Create a temporary directory with mixed file types
const tempDir = path.join(__dirname, 'temp-mixed-files')
fs.mkdirSync(tempDir, { recursive: true })
// Create various file types
fs.writeFileSync(path.join(tempDir, 'test.yml'), 'yml: content')
fs.writeFileSync(path.join(tempDir, 'test.md'), '# MD content')
fs.writeFileSync(path.join(tempDir, 'test.json'), '{"json": true}')
fs.writeFileSync(path.join(tempDir, 'test.txt'), 'text content')
fs.writeFileSync(path.join(tempDir, 'README.yml'), 'readme: content')
fs.writeFileSync(path.join(tempDir, 'README.md'), '# README')
try {
// getVariableFiles should only find .yml files (excluding README.yml)
const variableFiles = getVariableFiles(tempDir)
expect(variableFiles).toHaveLength(1)
expect(variableFiles[0]).toMatch(/test\.yml$/)
// getReusableFiles should only find .md files (excluding README.md)
const reusableFiles = getReusableFiles(tempDir)
expect(reusableFiles).toHaveLength(1)
expect(reusableFiles[0]).toMatch(/test\.md$/)
} finally {
// Clean up
fs.rmSync(tempDir, { recursive: true, force: true })
}
})
test('verify fix addresses the original issue scenario', () => {
// This test simulates the original issue where features were used only in variables
// but not detected by the orphaned features script
const variablesDir = path.join(fixturesDir, 'data', 'variables')
const featuresDir = path.join(fixturesDir, 'data', 'features')
// Verify our test setup has the scenario described in the issue
expect(fs.existsSync(path.join(featuresDir, 'used-in-variables.yml'))).toBe(true)
expect(fs.existsSync(path.join(featuresDir, 'truly-orphaned.yml'))).toBe(true)
// Check that the variable file references the feature
const variableContent = fs.readFileSync(path.join(variablesDir, 'test.yml'), 'utf-8')
expect(variableContent).toContain('used-in-variables')
// Verify that the getVariableFiles function would find this file
const variableFiles = getVariableFiles(variablesDir)
expect(variableFiles.length).toBeGreaterThan(0)
// This proves that the fix would catch features used in variables files
// because the orphaned features script now scans these files
const foundFeatureUsage = variableFiles.some((filePath) => {
const content = fs.readFileSync(filePath, 'utf-8')
return content.includes('used-in-variables')
})
expect(foundFeatureUsage).toBe(true)
})
test('functions correctly identify different file types in same directory', () => {
// Create a directory with both .yml and .md files to ensure each function
// only picks up its target file types
const tempDir = path.join(__dirname, 'temp-mixed-target-files')
fs.mkdirSync(tempDir, { recursive: true })
// Create files that both functions might encounter
fs.writeFileSync(
path.join(tempDir, 'variables.yml'),
'var: {% ifversion test-feature %}enabled{% endif %}',
)
fs.writeFileSync(
path.join(tempDir, 'reusable.md'),
'{% ifversion test-feature %}Reusable content{% endif %}',
)
fs.writeFileSync(path.join(tempDir, 'other.txt'), 'other content')
try {
// Each function should only find its target file type
const variableFiles = getVariableFiles(tempDir)
const reusableFiles = getReusableFiles(tempDir)
expect(variableFiles).toHaveLength(1)
expect(variableFiles[0]).toMatch(/variables\.yml$/)
expect(reusableFiles).toHaveLength(1)
expect(reusableFiles[0]).toMatch(/reusable\.md$/)
// Verify no cross-contamination
expect(variableFiles.some((f) => f.endsWith('.md'))).toBe(false)
expect(reusableFiles.some((f) => f.endsWith('.yml'))).toBe(false)
} finally {
// Clean up
fs.rmSync(tempDir, { recursive: true, force: true })
}
})
})