Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,36 @@ Describe "Export-Csv" -Tags "CI" {
BeforeAll {
$testObject = @("test","object","array")
$testCsv = Join-Path -Path $TestDrive -ChildPath "output.csv"
$newLine = [environment]::NewLine
$P1 = [pscustomobject]@{"P1" = "first"}
$P2 = [pscustomobject]@{"P2" = "second"}
$P11 = [pscustomobject]@{"P1" = "eleventh"}
}

AfterEach {
Remove-Item $testCsv -Force -ErrorAction SilentlyContinue
Remove-Item -Path $testCsv -Force -ErrorAction SilentlyContinue
}

It "Should be able to be called without error" {
{ $testObject | Export-Csv $testCsv -ErrorAction Stop } | Should -Not -Throw
{ $testObject | Export-Csv -Path $testCsv -ErrorAction Stop } | Should -Not -Throw
}

It "Should throw if an output file isn't specified" {
{ $testObject | Export-Csv -ErrorAction Stop } | ShouldBeErrorId "CannotSpecifyPathAndLiteralPath,Microsoft.PowerShell.Commands.ExportCsvCommand"
{ $testObject | Export-Csv -ErrorAction Stop } | Should -Throw -ErrorId "CannotSpecifyPathAndLiteralPath,Microsoft.PowerShell.Commands.ExportCsvCommand"
}

It "Should be a string when exporting via pipe" {
$testObject | Export-Csv $testCsv -IncludeTypeInformation

$piped = Get-Content $testCsv
$testObject | Export-Csv -Path $testCsv -IncludeTypeInformation
$results = Get-Content -Path $testCsv

$piped[0] | Should -BeExactly "#TYPE System.String"
$results[0] | Should -BeExactly "#TYPE System.String"
}

It "Should be an object when exporting via the inputObject switch" {
Export-Csv -InputObject $testObject -Path $testCsv -IncludeTypeInformation
$results = Get-Content -Path $testCsv

$switch = Get-Content $testCsv

$switch[0] | Should -BeExactly "#TYPE System.Object[]"
$results[0] | Should -BeExactly "#TYPE System.Object[]"
}

It "Should output a csv file containing a string of all the lengths of each element when piped input is used" {
Expand All @@ -43,81 +45,186 @@ Describe "Export-Csv" -Tags "CI" {
$expected = @("#TYPE System.String", "`"Length`"", $first , $second, $third)

for ($i = 0; $i -lt $expected.Count; $i++) {
$(Get-Content $testCsv)[$i] | Should -Be $expected[$i]
$(Get-Content -Path $testCsv)[$i] | Should -Be $expected[$i]
}
}

It "Does not include type information by default" {
$testObject | Export-Csv -Path $testCsv
$results = Get-Content -Path $testCsv

$(Get-Content $testCsv)[0] | Should -Not -Match ([regex]::Escape("System.String"))
$(Get-Content $testCsv)[0] | Should -Not -Match ([regex]::Escape("#TYPE"))
$results[0] | Should -Not -Match ([regex]::Escape("System.String"))
$results[0] | Should -Not -Match ([regex]::Escape("#TYPE"))
}

It "Does not include type information with -NoTypeInformation" {
$testObject | Export-Csv -Path $testCsv -NoTypeInformation
$results = Get-Content -Path $testCsv

$(Get-Content $testCsv)[0] | Should -Not -Match ([regex]::Escape("System.String"))
$(Get-Content $testCsv)[0] | Should -Not -Match ([regex]::Escape("#TYPE"))
$results[0] | Should -Not -Match ([regex]::Escape("System.String"))
$results[0] | Should -Not -Match ([regex]::Escape("#TYPE"))
}

It "Includes type information when -IncludeTypeInformation is supplied" {
$testObject | Export-Csv -Path $testCsv -IncludeTypeInformation
$results = Get-Content -Path $testCsv

$(Get-Content $testCsv)[0] | Should -BeExactly "#TYPE System.String"
$results[0] | Should -BeExactly "#TYPE System.String"
}

It "Does not support -IncludeTypeInformation and -NoTypeInformation at the same time" {
{ $testObject | Export-Csv -Path $testCsv -IncludeTypeInformation -NoTypeInformation } |
ShouldBeErrorId "CannotSpecifyIncludeTypeInformationAndNoTypeInformation,Microsoft.PowerShell.Commands.ExportCsvCommand"
{ $testObject | Export-Csv -Path $testCsv -IncludeTypeInformation -NoTypeInformation } | Should -Throw -ErrorId "CannotSpecifyIncludeTypeInformationAndNoTypeInformation,Microsoft.PowerShell.Commands.ExportCsvCommand"
}
}

Describe "Export-Csv DRT Unit Tests" -Tags "CI" {
BeforeAll {
$filePath = Join-Path $TestDrive -ChildPath "test.csv"
$newLine = [environment]::NewLine
It "Should support -LiteralPath parameter" {
$testObject | Export-Csv -LiteralPath $testCsv
$results = Import-Csv -Path $testCsv

$results | Should -HaveCount 3
}

It "Should overwrite file without -NoClobber parameter" {
$P1 | Export-Csv -Path $testCsv
$P2 | Export-Csv -Path $testCsv
$results = Import-Csv -Path $testCsv

$results.P2 | Should -BeExactly "second"
}

It "Should not overwrite file with -NoClobber parameter" {
$P1 | Export-Csv -Path $testCsv
{ $P2 | Export-Csv -Path $testCsv -NoClobber} | Should -Throw -ErrorId "NoClobber,Microsoft.PowerShell.Commands.ExportCsvCommand"
$results = Import-Csv -Path $testCsv

$results.P1 | Should -BeExactly "first"
}

It "Should not overwrite read-only file without -Force parameter" {
$P1 | Export-Csv -Path $testCsv
Set-ItemProperty -Path $testCsv -Name IsReadOnly -Value $true

{ $P2 | Export-Csv -Path $testCsv } | Should -Throw -ErrorId "FileOpenFailure,Microsoft.PowerShell.Commands.ExportCsvCommand"
$results = Import-Csv -Path $testCsv

$results.P1 | Should -BeExactly "first"
}

It "Should overwrite read-only file with -Force parameter" {
$P1 | Export-Csv -Path $testCsv
Set-ItemProperty -Path $testCsv -Name IsReadOnly -Value $true

$P2 | Export-Csv -Path $testCsv -Force
$results = Import-Csv -Path $testCsv

$results.P2 | Should -BeExactly "second"
}

It "Should not export to file if -WhatIf parameter specified" {
$P1 | Export-Csv -Path $testCsv -WhatIf
$testCsv | Should -Not -Exist
}

It "Should append to file if -Append parameter specified" {
$P1 | Export-Csv -Path $testCsv
$P11 | Export-Csv -Path $testCsv -Append
$results = Import-Csv -Path $testCsv

$results[0].P1 | Should -BeExactly "first"
$results[1].P1 | Should -BeExactly "eleventh"
}

# This test is not a duplicate of the previous one, since it covers a separate branch in code.
It "Should append to empty file if -Append parameter specified" {
New-Item -Path $testCsv -ItemType File | Out-Null

$P11 | Export-Csv -Path $testCsv -Append
$results = Import-Csv -Path $testCsv

$results[0].P1 | Should -BeExactly "eleventh"
}

It "Should throw when appended property does not exist in existing .csv file" {
$P1 | Export-Csv -Path $testCsv
{ $P2 | Export-Csv -Path $testCsv -Append -ErrorAction Stop } | Should -Throw -ErrorId "CannotAppendCsvWithMismatchedPropertyNames,Microsoft.PowerShell.Commands.ExportCsvCommand"
$results = Import-Csv -Path $testCsv

$results[0].P1 | Should -BeExactly "first"
}

It "Should append existing properties, add missing properties with empty value, and skip extra properties" {
$object1 = [PSCustomObject]@{first = 1; second = 2}
$object2 = [PSCustomObject]@{first = 11; third = 13}

$object1 | Export-Csv -Path $testCsv
$object2 | Export-Csv -Path $testCsv -Append -Force

$results = Import-Csv -Path $testCsv

$results[0].first | Should -BeExactly "1"
$results[0].second | Should -BeExactly "2"
$results[1].first | Should -BeExactly "11"
$results[1].second | Should -BeNullOrEmpty
$results[1].PSObject.properties.Name | Should -Not -Contain 'third'
}

It "First line should be #TYPE if -IncludeTypeInformation used and pstypenames object property is empty" {
$object = [PSCustomObject]@{first = 1}
$pstypenames = $object.pstypenames | ForEach-Object -Process {$_}
$pstypenames | ForEach-Object -Process {$object.pstypenames.Remove($_)}
$object | Export-Csv -Path $testCsv -IncludeTypeInformation
$content = Get-Content -Path $testCsv

$content[0] | Should -BeExactly '#TYPE'
}

# If type starts with CSV: Export-CSV should remove it. This would happen when you export
# an imported object. Import-Csv adds CSV: prefix to the type.
It "Should remove 'CSV:' from the type name" {
$object = [PSCustomObject]@{first = 1}
$object.pstypenames.Insert(0, "CSV:TheType")
$object | Export-Csv -Path $testCsv -IncludeTypeInformation
$result = Get-Content -Path $testCsv

$result[0] | Should -BeExactly "#TYPE TheType"
}

It "Should escape double quote with another double quote" {
$object = [PSCustomObject]@{first = 'Double quote " in the middle.'}
$object | Export-Csv -Path $testCsv
$result = Get-Content -Path $testCsv

$result[1] | Should -BeExactly '"Double quote "" in the middle."'
}

It "Test basic function works well" {
$input = [pscustomobject]@{ "P1" = "V11"; "P2" = "V12"; "P3" = "V13" }
$input | Export-Csv -Path $filePath -NoTypeInformation
$results = Import-Csv $filePath
$in = [pscustomobject]@{ "P1" = "V11"; "P2" = "V12"; "P3" = "V13" }
$in | Export-Csv -Path $testCsv -NoTypeInformation
$results = Import-Csv -Path $testCsv

$results.P1 | Should -BeExactly "V11"
$results.P2 | Should -BeExactly "V12"
$results.P3 | Should -BeExactly "V13"
}

It "Test if it works with special character" {
$v3 = "abc" + $newLine + "foo"
$input = [pscustomobject]@{ "P1" = " "; "P2" = "abc,foo"; "P3" = $v3}
$input | Export-Csv -Path $filePath -NoTypeInformation
$results = Import-Csv $filePath
$in = [pscustomobject]@{ "P1" = " "; "P2" = "abc,foo"; "P3" = $v3}
$in | Export-Csv -Path $testCsv -NoTypeInformation
$results = Import-Csv -Path $testCsv

$results.P1 | Should -BeExactly " "
$results.P2 | Should -BeExactly "abc,foo"
$results.P3 | Should -Be $v3
}

It "Test force switch works well" {
$input = [pscustomobject]@{ "P1" = "first" }
$input | Export-Csv -Path $filePath

$input = [pscustomobject]@{ "P2" = "second" }
$input | Export-Csv -Path $filePath -Force
$results = Import-Csv $filePath

$results.P2 | Should -BeExactly "second"
$property = $results | Get-Member | Where-Object { $_.MemberType -eq "NoteProperty" } | ForEach-Object { $_.Name }
$property | Should -Not -Be P1
$results.P3 | Should -BeExactly $v3
}

It "Test export-csv with a useculture flag" {
$outputFilesDir = Join-Path $TestDrive -ChildPath "Monad"
$fileToGenerate = Join-Path $outputFilesDir -ChildPath "CSVTests.csv"
$outputFilesDir = Join-Path -Path $TestDrive -ChildPath "Monad"
$fileToGenerate = Join-Path -Path $outputFilesDir -ChildPath "CSVTests.csv"
$delimiter = (Get-Culture).TextInfo.ListSeparator
New-Item -Path $outputFilesDir -ItemType Directory -Force
Get-Item -Path $outputFilesDir| Export-Csv -Path $fileToGenerate -UseCulture -NoTypeInformation
Get-Item -Path $outputFilesDir | Export-Csv -Path $fileToGenerate -UseCulture -NoTypeInformation
$contents = Get-Content -Path $fileToGenerate

$contents.Count | Should -Be 2
$contents[0].Contains($delimiter) | Should -BeTrue
$contents[1].Contains($delimiter) | Should -BeTrue
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use Should -Contain

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. If the delimiter is comma, Should treats input as array, so $contents[0] | Should -Contain $delimiter will fail.

Copy link
Copy Markdown
Collaborator

@iSazonov iSazonov May 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$contents[0] is a string not a language operator.
I think it is passed:
"," | Should -Contain ","

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It "Test export-csv with a useculture flag" {
    $outputFilesDir = Join-Path -Path $TestDrive -ChildPath "Monad"
    $fileToGenerate = Join-Path -Path $outputFilesDir -ChildPath "CSVTests.csv"
    $delimiter = (Get-Culture).TextInfo.ListSeparator
    New-Item -Path $outputFilesDir -ItemType Directory -Force
    Get-Item -Path $outputFilesDir | Export-Csv -Path $fileToGenerate -UseCulture -NoTypeInformation
    $contents = Get-Content -Path $fileToGenerate

    $contents.Count | Should -Be 2
    $contents[0] | Should -Contain $delimiter
}


  [-] Test export-csv with a useculture flag 144ms
    Expected ',' to be found in collection "PSPath","PSParentPath","PSChildName","PSDrive","PSProvider","PSIsContainer","Mode","BaseName","Target","LinkType","Name","Parent","Exists","Root","FullName","Extension","CreationTime","CreationTimeUtc","LastAccessTime","LastAccessTimeUtc","LastWriteTime","LastWriteTimeUtc","Attributes", but it was not found.
    186:         $contents[0] | Should -Contain $delimiter

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the repo! This is my misconception. Closed.

Expand Down