Skip to content

Commit

Permalink
Merge pull request #37 from Readify/satisfaction
Browse files Browse the repository at this point in the history
Add `Get-SatisfactionRating` & `New-SatisfactionRating` +semver: feature
  • Loading branch information
RobFaie authored Mar 30, 2020
2 parents 59fc94d + c9cbcc5 commit e810063
Show file tree
Hide file tree
Showing 4 changed files with 296 additions and 0 deletions.
2 changes: 2 additions & 0 deletions PwshZendesk.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
'Get-OrganizationMembership', 'Get-ZendeskOrganizationMembership'
'Get-OrganizationRelated', 'Get-ZendeskOrganizationRelated'
'Get-Problem', 'Get-ZendeskProblem'
'Get-SatisfactionRating', 'Get-ZendeskSatisfactionRating'
'Get-SearchCount', 'Get-ZendeskSearchCount'
'Get-SharingAgreement', 'Get-ZendeskSharingAgreement'
'Get-SuspendedTicket', 'Get-ZendeskSuspendedTicket'
Expand All @@ -119,6 +120,7 @@
'New-GroupMembership', 'New-ZendeskGroupMembership'
'New-Organization', 'New-ZendeskOrganization'
'New-OrganizationMembership', 'New-ZendeskOrganizationMembership'
'New-SatisfactionRating', 'New-ZendeskSatisfactionRating'
'New-SharingAgreement', 'New-ZendeskSharingAgreement'
'New-Ticket', 'New-ZendeskTicket'
'New-UserIdentity', 'New-ZendeskUserIdentity'
Expand Down
102 changes: 102 additions & 0 deletions functions/Get-SatisfactionRating.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
function Get-SatisfactionRating {
<#
.SYNOPSIS
Retrieves Satisfaction Ratings
.DESCRIPTION
Retrieves Satisfaction Ratings
.EXAMPLE
PS C:\> Get-ZendeskSatisfactionRating
Retrieves all satisfaction ratings
.EXAMPLE
PS C:\> Get-ZendeskSatisfactionRating -Id 1
Retrieves satisfaction rating with id 1
.EXAMPLE
PS C:\> Get-ZendeskSatisfactionRating -Score 'good_with_comment'
Retrieves all good satisfaction ratings that include a comment
.EXAMPLE
PS C:\> Get-ZendeskSatisfactionRating -Score 'good'
Retrieves all good satisfaction ratings regardless of whether a comment was included
.EXAMPLE
PS C:\> Get-ZendeskSatisfactionRating -Score 'received'
Retrieves all satisfaction ratings that have been received whether the rating is good or bad.
.EXAMPLE
PS C:\> Get-ZendeskSatisfactionRating -Score 'offered'
Retrieves all satisfaction ratings that have been offered but not responded to.
.EXAMPLE
PS C:\> Get-ZendeskSatisfactionRating -StartTime [DateTime]::Now.AddHours(-1)
Retrieves all satisfaction ratings from the past hour.
.NOTES
If you specify an unqualified score such as good, the results include all the records with and without comments.
#>
[CmdletBinding(DefaultParameterSetName = 'Filter')]
Param (
# Unique Id of the satisfaction rating to retrieve
[Parameter(Mandatory = $false,
ParameterSetName = 'Id')]
[ValidateRange(1, [Int64]::MaxValue)]
[Int64]
$Id,

# Parameter help description
[Parameter(Mandatory = $false,
ParameterSetName = 'Filter')]
[ValidateSet('offered', 'unoffered',
'received', 'received_with_comment', 'received_without_comment',
'good', 'good_with_comment', 'good_without_comment',
'bad', 'bad_with_comment', 'bad_without_comment')]
[String]
$Score,

# Time of the oldest satisfaction rating, as a Unix epoch time
[Parameter(Mandatory = $false,
ParameterSetName = 'Filter')]
[DateTimeOffset]
$StartTime,

# Time of the most recent satisfaction rating, as a Unix epoch time
[Parameter(Mandatory = $false,
ParameterSetName = 'Filter')]
[DateTimeOffset]
$EndTime,

# Zendesk Connection Context from `Get-ZendeskConnection`
[Parameter(Mandatory = $false)]
[PSTypeName('ZendeskContext')]
[PSCustomObject]
$Context = $null
)

Assert-IsAdmin -Context $Context

if ($PSBoundParameters.ContainsKey('Id')) {
$path = "/api/v2/satisfaction_ratings/$Id.json"
$key = 'satisfaction_rating'
} else {
$path = '/api/v2/satisfaction_ratings.json'
$key = 'satisfaction_ratings'
}

$parameters = @()
if ($PSBoundParameters.ContainsKey('Score')) {
$parameters += "score=$Score"
}
if ($PSBoundParameters.ContainsKey('StartTime')) {
$parameters += 'start_time={0}' -f $StartTime.ToUnixTimeSeconds()
}
if ($PSBoundParameters.ContainsKey('EndTime')) {
$parameters += 'end_time={0}' -f $EndTime.ToUnixTimeSeconds()
}
if ($parameters.Count -gt 0) {
$path += '?' + $parameters -join '&'
}

$result = Invoke-Method -Context $Context -Path $path -Verbose:$VerbosePreference
$result | Select-Object -Expand $key
}
75 changes: 75 additions & 0 deletions functions/New-SatisfactionRating.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
function New-SatisfactionRating {
<#
.SYNOPSIS
Creates a CSAT rating for a solved ticket, or for a ticket that was previously solved and then reopened.
.DESCRIPTION
Creates a CSAT rating for a solved ticket, or for a ticket that was previously solved and then reopened.
.EXAMPLE
PS C:\> New-ZendeskSatisfactionRating -TicketId 1 -Score 'good'
Creates a good satisfaction rating for ticket with id 1
.EXAMPLE
PS C:\> New-ZendeskSatisfactionRating -TicketId 1 -Score 'good' -Comment 'fast'
Creates a good satisfaction rating for ticket with id 1 including a comment.
.EXAMPLE
PS C:\> New-ZendeskSatisfactionRating -TicketId 1 -Score 'bad' -ReasonCode 5
Creates a bad satisfaction rating for ticket with id 1 including a reason for the bad rating.
.NOTES
Only the end user listed as the ticket requester can create a satisfaction rating for the ticket.
#>
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
param (
# The internal id of the ticket to create a rating for
[Parameter(Mandatory = $true)]
[ValidateRange(1, [Int64]::MaxValue)]
[Int64]
$TicketId,

# The rating
[Parameter(Mandatory = $true)]
[ValidateSet('good', 'bad')]
[String]
$Score,

# The comment
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[String]
$Comment,

# The reason for a bad rating given by the requester
[Parameter(Mandatory = $false)]
[Int]
$ReasonCode = 0,

# Zendesk Connection Context from `Get-ZendeskConnection`
[Parameter(Mandatory = $false)]
[PSTypeName('ZendeskContext')]
[PSCustomObject]
$Context = $null
)

Assert-IsEndUser -Context $Context

$path = "/api/v2/tickets/$TicketId/satisfaction_rating.json"
$body = @{
satisfaction_rating = @{
score = $Score
}
}

if ($PSBoundParameters.ContainsKey('Comment')) {
$body.satisfaction_rating.comment = $Comment
}

if ($Score -eq 'bad') {
$body.satisfaction_rating.reason_code = $ReasonCode
}

if ($PSCmdlet.ShouldProcess($TicketId, 'Create Group')) {
$result = Invoke-Method -Context $Context -Method 'Post' -Path $path -Body $body -Verbose:$VerbosePreference
$result
}
}
117 changes: 117 additions & 0 deletions tests/Routes-SatisfactionRatings.tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]
Param()

Import-Module "$PSScriptRoot/../PwshZendesk.psm1" -Force

Describe 'Satisfaction Rating Routes' {

InModuleScope PwshZendesk {

$IsInteractive = [Environment]::GetCommandLineArgs() -join ' ' -notmatch '-NonI'

$context = @{
Organization = 'company'
BaseUrl = 'https://company.testdesk.com'
Credential = [System.Management.Automation.PSCredential]::New('email', ('api-key' | ConvertTo-SecureString -AsPlainText -Force))
User = [PSCustomObject]@{ role = '' }
}
$context | Add-Member -TypeName 'ZendeskContext'

Mock -ModuleName PwshZendesk Invoke-RestMethod { [PSCustomObject]@{ satisfaction_rating = $null; satisfaction_ratings = $null } }

Context 'List Satisfaction Ratings' {
It 'Matches the endpoint' {
if ($IsInteractive) {
throw 'Please run test in non-interactive mode'
}

$context.User.role = 'admin'

{ Get-SatisfactionRating -Context $context } | Should -Not -Throw
Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { $Method -eq 'Get' -and $Uri -match '/api/v2/satisfaction_ratings\.json' } -Scope It
}

It 'Does not allow end users to call' {
$context.User.role = 'end-user'

{ Get-SatisfactionRating -Context $context } | Should -Throw 'Authenticated user must have role'
}

It 'Does not allow agents to call' {
$context.User.role = 'agent'

{ Get-SatisfactionRating -Context $context } | Should -Throw 'Authenticated user must have role'
}

It 'Allows admins to call' {
$context.User.role = 'admin'

{ Get-SatisfactionRating -Context $context } | Should -Not -Throw
}
}

Context 'Show Satisfaction Rating' {
It 'Matches the endpoint' {
if ($IsInteractive) {
throw 'Please run test in non-interactive mode'
}

$context.User.role = 'admin'

{ Get-SatisfactionRating -Context $context -Id 1 } | Should -Not -Throw
Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { $Method -eq 'Get' -and $Uri -match '/api/v2/satisfaction_ratings/\d+\.json' } -Scope It
}

It 'Does not allow end users to call' {
$context.User.role = 'end-user'

{ Get-SatisfactionRating -Context $context -Id 1 } | Should -Throw 'Authenticated user must have role'
}

It 'Does not allow agents to call' {
$context.User.role = 'agent'

{ Get-SatisfactionRating -Context $context -Id 1 } | Should -Throw 'Authenticated user must have role'
}

It 'Allows admins to call' {
$context.User.role = 'admin'

{ Get-SatisfactionRating -Context $context -Id 1 } | Should -Not -Throw
}
}

Context 'Create a Satisfaction Rating' {
It 'Matches the endpoint' {
if ($IsInteractive) {
throw 'Please run test in non-interactive mode'
}

$context.User.role = 'end-user'

{ New-SatisfactionRating -Context $context -TicketId 1 -Score 'good' -Confirm:$false } | Should -Not -Throw
Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { $Method -eq 'Post' -and $Uri -match '/api/v2/tickets/\d+/satisfaction_rating\.json' } -Scope It
}

It 'Allows end users to call' {
$context.User.role = 'end-user'

{ New-SatisfactionRating -Context $context -TicketId 1 -Score 'good' -Confirm:$false } | Should -Not -Throw
}

It 'Does not allow agents to call' {
$context.User.role = 'agent'

{ New-SatisfactionRating -Context $context -TicketId 1 -Score 'good' -Confirm:$false } | Should -Throw 'Authenticated user must have role'
}

It 'Does not allow admins to call' {
$context.User.role = 'admin'

{ New-SatisfactionRating -Context $context -TicketId 1 -Score 'good' -Confirm:$false } | Should -Throw 'Authenticated user must have role'
}
}

}

}

0 comments on commit e810063

Please sign in to comment.