Tests/UKG.Tests.ps1
|
#Requires -Modules Pester <# .SYNOPSIS Pester unit tests for the UKG PowerShell module. .DESCRIPTION Tests all cmdlets with mocked API responses to verify correct behavior without requiring actual API credentials. #> BeforeAll { # Import the module $ModulePath = Split-Path -Parent $PSScriptRoot Import-Module $ModulePath -Force # Mock response data $Script:MockEmployee = @{ id = 'emp123' email = 'john.doe@company.com' first_name = 'John' last_name = 'Doe' employee_number = 'EMP001' status = 'active' organization_id = 'org123' created_at = '2024-01-01T00:00:00Z' updated_at = '2024-01-15T00:00:00Z' } $Script:MockUser = @{ id = 'user123' email = 'admin@company.com' first_name = 'Admin' last_name = 'User' role_id = 'role123' active = $true } $Script:MockOrganization = @{ id = 'org123' name = 'Engineering' code = 'ENG' parent_id = $null } $Script:MockRole = @{ id = 'role123' name = 'HR Administrator' description = 'Full HR access' } # Helper function to create mock session function Get-MockSession { return [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' Region = 'EU' Environment = 'Production' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenType = 'Bearer' TokenExpiry = (Get-Date).AddHours(1) ConnectedAt = Get-Date } } } Describe 'Module Structure' { It 'Should have a module manifest' { $ModulePath = Split-Path -Parent $PSScriptRoot Test-Path "$ModulePath\PSUKG.psd1" | Should -Be $true } It 'Should have a root module' { $ModulePath = Split-Path -Parent $PSScriptRoot Test-Path "$ModulePath\PSUKG.psm1" | Should -Be $true } It 'Should export expected functions' { $Module = Get-Module PSUKG $Module.ExportedFunctions.Keys | Should -Contain 'Connect-UKG' $Module.ExportedFunctions.Keys | Should -Contain 'Get-UKGEmployee' $Module.ExportedFunctions.Keys | Should -Contain 'Get-UKGUser' } } Describe 'Connect-UKG' { BeforeAll { Mock Invoke-RestMethod { return @{ access_token = 'mock-token' token_type = 'Bearer' expires_in = 3600 } } -ModuleName PSUKG } It 'Should connect with valid credentials' { $secret = ConvertTo-SecureString 'test-secret' -AsPlainText -Force $result = Connect-UKG -ApplicationId 'app123' -ApplicationSecret $secret -ClientId 'client123' -Region EU $result | Should -Not -BeNullOrEmpty $result.ClientId | Should -Be 'client123' $result.Region | Should -Be 'EU' } It 'Should accept plain text secret' { $result = Connect-UKG -ApplicationId 'app123' -ApplicationSecretPlainText 'test-secret' -ClientId 'client123' -Region US $result | Should -Not -BeNullOrEmpty $result.Region | Should -Be 'US' } It 'Should use correct base URL for each region' { $secret = ConvertTo-SecureString 'test-secret' -AsPlainText -Force $result = Connect-UKG -ApplicationId 'app123' -ApplicationSecret $secret -ClientId 'client123' -Region EU -Environment Production $result.BaseUrl | Should -Be 'https://apis.eu.people-doc.com/api/v2' $result = Connect-UKG -ApplicationId 'app123' -ApplicationSecret $secret -ClientId 'client123' -Region US -Environment Production $result.BaseUrl | Should -Be 'https://apis.us.people-doc.com/api/v2' $result = Connect-UKG -ApplicationId 'app123' -ApplicationSecret $secret -ClientId 'client123' -Region UKG_ATL -Environment Production $result.BaseUrl | Should -Be 'https://apis.hrsd.ultipro.com/api/v2' } } Describe 'Get-UKGSession' { It 'Should return session info when connected' { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' Region = 'EU' Environment = 'Production' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenType = 'Bearer' TokenExpiry = (Get-Date).AddHours(1) ConnectedAt = Get-Date } } $result = Get-UKGSession $result | Should -Not -BeNullOrEmpty $result.ClientId | Should -Be 'client123' } It 'Should return null when not connected' { InModuleScope PSUKG { $Script:UKGSession = $null } $result = Get-UKGSession $result | Should -BeNullOrEmpty } } Describe 'Disconnect-UKG' { It 'Should clear the session' { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' AccessToken = 'mock-token' } } Disconnect-UKG InModuleScope PSUKG { $Script:UKGSession | Should -BeNullOrEmpty } } } Describe 'Get-UKGEmployee' { BeforeAll { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenExpiry = (Get-Date).AddHours(1) } } $mockEmp = @{ id = 'emp123' email = 'john.doe@company.com' first_name = 'John' last_name = 'Doe' employee_number = 'EMP001' status = 'active' } Mock Invoke-WebRequest { $response = [PSCustomObject]@{ Content = ($mockEmp | ConvertTo-Json) Headers = @{ 'X-Total-Count' = '1' } StatusCode = 200 } return $response } -ModuleName PSUKG } It 'Should get employee by ID' { $result = Get-UKGEmployee -Id 'emp123' $result | Should -Not -BeNullOrEmpty $result.id | Should -Be 'emp123' $result.email | Should -Be 'john.doe@company.com' } It 'Should have correct type name' { $result = Get-UKGEmployee -Id 'emp123' $result.PSObject.TypeNames | Should -Contain 'UKG.Employee' } } Describe 'New-UKGEmployee' { BeforeAll { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenExpiry = (Get-Date).AddHours(1) } } $mockEmp = @{ id = 'emp123' email = 'john.doe@company.com' first_name = 'John' last_name = 'Doe' } Mock Invoke-WebRequest { $response = [PSCustomObject]@{ Content = ($mockEmp | ConvertTo-Json) Headers = @{} StatusCode = 201 } return $response } -ModuleName PSUKG } It 'Should create employee with required parameters' { $result = New-UKGEmployee -Email 'new@company.com' -FirstName 'New' -LastName 'Employee' -Confirm:$false $result | Should -Not -BeNullOrEmpty } It 'Should create employee from InputObject' { $empData = @{ email = 'input@company.com' first_name = 'Input' last_name = 'Object' } $result = New-UKGEmployee -InputObject $empData -Confirm:$false $result | Should -Not -BeNullOrEmpty } } Describe 'Set-UKGEmployee' { BeforeAll { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenExpiry = (Get-Date).AddHours(1) } } $mockEmp = @{ id = 'emp123'; email = 'john.doe@company.com' } Mock Invoke-WebRequest { $response = [PSCustomObject]@{ Content = ($mockEmp | ConvertTo-Json) Headers = @{} StatusCode = 200 } return $response } -ModuleName PSUKG } It 'Should update employee by ID' { $result = Set-UKGEmployee -Id 'emp123' -Title 'Senior Developer' -Confirm:$false $result | Should -Not -BeNullOrEmpty } It 'Should update employee by ExternalId' { $result = Set-UKGEmployee -ExternalId 'EXT001' -Department 'Engineering' -Confirm:$false $result | Should -Not -BeNullOrEmpty } } Describe 'Search-UKGEmployee' { BeforeAll { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenExpiry = (Get-Date).AddHours(1) } } $mockEmps = @(@{ id = 'emp123'; email = 'john.doe@company.com' }) Mock Invoke-WebRequest { $response = [PSCustomObject]@{ Content = ($mockEmps | ConvertTo-Json) Headers = @{ 'X-Total-Count' = '1'; 'Next-Cursor' = $null } StatusCode = 200 } return $response } -ModuleName PSUKG } It 'Should search employees by email' { $result = Search-UKGEmployee -Email 'john.doe@company.com' $result | Should -Not -BeNullOrEmpty } It 'Should search employees with filter hashtable' { $result = Search-UKGEmployee -Filter @{ status = @{ eq = 'active' } } $result | Should -Not -BeNullOrEmpty } } Describe 'Get-UKGUser' { BeforeAll { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenExpiry = (Get-Date).AddHours(1) } } $mockUser = @{ id = 'user123'; email = 'admin@company.com' } Mock Invoke-WebRequest { $response = [PSCustomObject]@{ Content = ($mockUser | ConvertTo-Json) Headers = @{ 'X-Total-Count' = '1' } StatusCode = 200 } return $response } -ModuleName PSUKG } It 'Should get user by ID' { $result = Get-UKGUser -Id 'user123' $result | Should -Not -BeNullOrEmpty $result.id | Should -Be 'user123' } It 'Should have correct type name' { $result = Get-UKGUser -Id 'user123' $result.PSObject.TypeNames | Should -Contain 'UKG.User' } } Describe 'Get-UKGOrganization' { BeforeAll { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenExpiry = (Get-Date).AddHours(1) } } $mockOrg = @{ id = 'org123'; name = 'Engineering' } Mock Invoke-WebRequest { $response = [PSCustomObject]@{ Content = ($mockOrg | ConvertTo-Json) Headers = @{} StatusCode = 200 } return $response } -ModuleName PSUKG } It 'Should get organization by ID' { $result = Get-UKGOrganization -Id 'org123' $result | Should -Not -BeNullOrEmpty $result.id | Should -Be 'org123' $result.name | Should -Be 'Engineering' } } Describe 'Get-UKGRole' { BeforeAll { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenExpiry = (Get-Date).AddHours(1) } } $mockRole = @{ id = 'role123'; name = 'HR Administrator' } Mock Invoke-WebRequest { $response = [PSCustomObject]@{ Content = ($mockRole | ConvertTo-Json) Headers = @{} StatusCode = 200 } return $response } -ModuleName PSUKG } It 'Should get role by ID' { $result = Get-UKGRole -Id 'role123' $result | Should -Not -BeNullOrEmpty $result.id | Should -Be 'role123' $result.name | Should -Be 'HR Administrator' } } Describe 'Error Handling' { It 'Should throw when not connected' { InModuleScope PSUKG { $Script:UKGSession = $null } { Get-UKGEmployee -Id 'emp123' } | Should -Throw } } Describe 'Pagination Helpers' { It 'Should parse Next-Cursor header' { InModuleScope PSUKG { $headers = @{ 'Next-Cursor' = 'abc123' 'X-Total-Count' = '100' 'X-Per-Page' = '25' } $result = Get-UKGNextPage -Headers $headers $result.NextCursor | Should -Be 'abc123' $result.TotalCount | Should -Be 100 $result.PerPage | Should -Be 25 $result.HasNextPage | Should -Be $true } } It 'Should handle empty pagination' { InModuleScope PSUKG { $headers = @{} $result = Get-UKGNextPage -Headers $headers $result.NextCursor | Should -BeNullOrEmpty $result.HasNextPage | Should -Be $false } } } Describe 'ConvertTo-UKGError' { It 'Should convert API error response' { InModuleScope PSUKG { $response = @{ code = 'validation_error' message = 'Validation failed' errors = @( @{ field = 'email'; message = 'Email is required' } ) } $result = ConvertTo-UKGError -Response $response -StatusCode 422 $result | Should -BeOfType [System.Management.Automation.ErrorRecord] $result.CategoryInfo.Category | Should -Be 'InvalidData' } } It 'Should map status codes to error categories' { InModuleScope PSUKG { $result401 = ConvertTo-UKGError -Response @{} -StatusCode 401 $result401.CategoryInfo.Category | Should -Be 'AuthenticationError' $result403 = ConvertTo-UKGError -Response @{} -StatusCode 403 $result403.CategoryInfo.Category | Should -Be 'PermissionDenied' $result404 = ConvertTo-UKGError -Response @{} -StatusCode 404 $result404.CategoryInfo.Category | Should -Be 'ObjectNotFound' } } } Describe 'Pipeline Support' { BeforeAll { InModuleScope PSUKG { $Script:UKGSession = [PSCustomObject]@{ PSTypeName = 'UKG.Session' ApplicationId = 'app123' ApplicationSecret = (ConvertTo-SecureString 'secret' -AsPlainText -Force) ClientId = 'client123' BaseUrl = 'https://apis.eu.people-doc.com/api/v2' TokenUrl = 'https://apis.eu.people-doc.com/oauth/token' AccessToken = 'mock-access-token' TokenExpiry = (Get-Date).AddHours(1) } } $mockEmp = @{ id = 'emp123'; email = 'john.doe@company.com' } Mock Invoke-WebRequest { $response = [PSCustomObject]@{ Content = ($mockEmp | ConvertTo-Json) Headers = @{} StatusCode = 200 } return $response } -ModuleName PSUKG } It 'Should accept pipeline input for Set-UKGEmployee' { $emp = [PSCustomObject]@{ Id = 'emp123' } $result = $emp | Set-UKGEmployee -Title 'Manager' -Confirm:$false $result | Should -Not -BeNullOrEmpty } } AfterAll { # Clean up Remove-Module PSUKG -Force -ErrorAction SilentlyContinue } |