Tests/FreeLogClass.Tests.ps1

BeforeAll {
    function Get-TempLogPath {
        if ($IsWindows -or (-not $IsLinux -and -not $IsMacOS)) {
            $tempPath = $env:TEMP
        } else {
            $tempPath = $env:TMPDIR ?? '/tmp'
        }

        Join-Path $tempPath "FreeLogClass_Test_$(Get-Random).log"
    }
}

Describe 'FreeLogClass Constructor' {
    It 'Should create instance with valid log file path' {
        $logPath = Get-TempLogPath
        $logger = [FreeLogClass]::new($logPath)
        $logger | Should -Not -BeNullOrEmpty
        $logger.LogFilePath | Should -Be $logPath
        $logger.IsValid | Should -Be $true
    }

    It 'Should throw exception when initialized with null or empty path' {
        { [FreeLogClass]::new('') } | Should -Throw 'LogFilePath cannot be null or empty.'
        { [FreeLogClass]::new($null) } | Should -Throw 'LogFilePath cannot be null or empty.'
    }

    It 'Should create log file with initial CREATED entry' {
        $logPath = Get-TempLogPath
        $logger = [FreeLogClass]::new($logPath)

        Test-Path $logPath | Should -Be $true

        $logContent = Get-Content $logPath -Raw
        $logContent | Should -Not -BeNullOrEmpty

        $logContent | Should -BeLike '*CREATED*'
        $logContent | Should -BeLike '*Log File Created...*'
        $logContent | Should -Match '\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}'
    }

    It 'Should not create duplicate CREATED entry for existing log file' {
        $logPath = Get-TempLogPath
        $logger1 = [FreeLogClass]::new($logPath)
        $logger2 = [FreeLogClass]::new($logPath)

        $logContent = Get-Content $logPath
        $logContent.Count | Should -Be 1
    }
}

Describe 'IsValidParam Method' {
    BeforeAll {
        $logger = [FreeLogClass]::new((Get-TempLogPath))
    }

    It 'Should return false for null or empty parameters' {
        $logger.IsValidParam('') | Should -Be $false
        $logger.IsValidParam($null) | Should -Be $false
    }

    It 'Should return true for valid string parameters' {
        $logger.IsValidParam('valid') | Should -Be $true
        $logger.IsValidParam(' ') | Should -Be $true
    }
}

Describe 'Logging Methods' {
    BeforeEach {
        $logPath = Get-TempLogPath
        $logger = [FreeLogClass]::new($logPath)
    }

    AfterEach {
        if (Test-Path $logPath) {
            Remove-Item $logPath -Force
        }
    }

    It 'Should write LOG entry to file' {
        $testMessage = 'Test log message'
        $logger.Log($testMessage)
        $logContent = Get-Content $logPath
        $logContent.Count | Should -Be 2
        $logContent[1] | Should -Match "LOG - \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} - $testMessage"
    }

    It 'Should write WARN entry to file' {
        $testMessage = 'Test warning message'
        $logger.Warn($testMessage)
        $logContent = Get-Content $logPath
        $logContent[1] | Should -Match "WARN - \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} - $testMessage"
    }

    It 'Should write ERROR entry to file' {
        $testMessage = 'Test error message'
        $logger.Error($testMessage)
        $logContent = Get-Content $logPath
        $logContent[1] | Should -Match "ERROR - \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} - $testMessage"
    }

    It 'Should write FAIL entry to file' {
        $testMessage = 'Test fail message'
        $logger.Fail($testMessage)
        $logContent = Get-Content $logPath
        $logContent[1] | Should -Match "FAIL - \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} - $testMessage"
    }

    It 'Should maintain IsValid = true after successful logging' {
        $logger.Log('Test message')
        $logger.IsValid | Should -Be $true
    }

    It 'Should throw when logging with invalid logger state' {
        $logger.IsValid = $false
        { $logger.Log('test') } | Should -Throw 'Cannot execute LOG method because log file is not writeable.'
        { $logger.Warn('test') } | Should -Throw 'Cannot execute WARN method because log file is not writeable.'
        { $logger.Error('test') } | Should -Throw 'Cannot execute ERROR method because log file is not writeable.'
        { $logger.Fail('test') } | Should -Throw 'Cannot execute FAIL method because log file is not writeable.'
    }
}

Describe 'Multiple Operations' {
    It 'Should handle multiple log entries in sequence' {
        $logPath = Get-TempLogPath
        $logger = [FreeLogClass]::new($logPath)

        $logger.Log('First message')
        $logger.Warn('Second message')
        $logger.Error('Third message')
        $logger.Fail('Fourth message')

        $logContent = Get-Content $logPath
        $logContent.Count | Should -Be 5

        $logContent[0] | Should -Match 'CREATED'
        $logContent[1] | Should -Match 'LOG'
        $logContent[2] | Should -Match 'WARN'
        $logContent[3] | Should -Match 'ERROR'
        $logContent[4] | Should -Match 'FAIL'
    }
}

Describe 'Timestamp Format' {
    It 'Should use correct timestamp format (yyyy-MM-dd HH:mm:ss)' {
        $logPath = Get-TempLogPath
        $logger = [FreeLogClass]::new($logPath)

        $mockDate = Get-Date '2025-01-15 14:30:45'
        Mock Get-Date { return $mockDate }

        $logger.Log('Test message')

        $logContent = Get-Content $logPath
        $logContent[1] | Should -Match 'LOG - 2025-01-15 14:30:45 - Test message'
    }
}