Skip to content

Commit

Permalink
Access token UI: Update and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jlledom committed Nov 26, 2024
1 parent 4f4690d commit 995530a
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 8 deletions.
20 changes: 12 additions & 8 deletions features/provider/admin/user/access_tokens.feature
Original file line number Diff line number Diff line change
Expand Up @@ -42,33 +42,37 @@ Feature: Provider Admin Access tokens
Then there is a required field "Name"
And there is a required field "Scopes"
And there is a required field "Permission"
And there is a required field "Expires in"
And the submit button is enabled

Scenario: Create access tokens without required fields
When they press "Create Access Token"
Then field "Name" has inline error "can't be blank"
And field "Scopes" has inline error "select at least one scope"
And field "Permission" has no inline error
And field "Expires in" has no inline error

Scenario: Create access token
When they press "Create Access Token"
And the form is submitted with:
| Name | LeToken |
| Analytics API | Yes |
| Permission | Read & Write |
| Name | LeToken |
| Analytics API | Yes |
| Permission | Read & Write |
| Expires in | No expiration |
Then the current page is the personal tokens page
And they should see the flash message "Access token was successfully created"
And should see the following details:
| Name | LeToken |
| Scopes | Analytics API |
| Permission | Read & Write |
| Name | LeToken |
| Scopes | Analytics API |
| Permission | Read & Write |
| Expires at | Never expires |
And there should be a link to "I have copied the token"

Rule: Edit page
Background:
Given the provider has the following access tokens:
| Name | Scopes | Permission |
| LeToken | Billing API, Analytics API | Read Only |
| Name | Scopes | Permission | Expires at |
| LeToken | Billing API, Analytics API | Read Only | 2030-01-01T00:00:00Z |
And they go to the access token's edit page

Scenario: Navigation to edit page
Expand Down
127 changes: 127 additions & 0 deletions spec/javascripts/AccessTokens/components/ExpirationDatePicker.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { mount } from 'enzyme'

import { ExpirationDatePicker } from 'AccessTokens/components/ExpirationDatePicker'

import type { ExpirationItem, Props } from 'AccessTokens/components/ExpirationDatePicker'
import type { ReactWrapper } from 'enzyme'

const defaultProps: Props = {
id: 'expires_at',
label: 'Expires in'
}

const mountWrapper = (props: Partial<Props> = {}) => mount(<ExpirationDatePicker {...{ ...defaultProps, ...props }} />)

const selectItem = (wrapper: ReactWrapper<any, Readonly<object>>, item: ExpirationItem) => {
wrapper.find('select.pf-c-form-control-expiration').simulate('change', { target: { value: item.id.toString() } })
}

const pickDate = (wrapper: ReactWrapper<any, Readonly<object>>) => {
/*
* Pick tomorrow, to do so, we get the date selected by default which is today and click the next one.
* It could happen that today is the last day in the calendar, in that case we pick the previous day, yesterday.
* In any case, we return the picked date to the caller.
*/
const targetDate = new Date()
targetDate.setHours(0)
targetDate.setMinutes(0)
targetDate.setSeconds(0)
targetDate.setMilliseconds(0)

const tomorrowButton = wrapper.find('.pf-m-selected + td > button')

if (tomorrowButton.length === 0) {
// No tomorrow, pick yesterday
const dayButtons = wrapper.find('button.pf-c-calendar-month__date')
const yesterdayButton = dayButtons.at(dayButtons.length - 2)

yesterdayButton.simulate('click')
targetDate.setDate(targetDate.getDate() - 1)
return targetDate
}

tomorrowButton.simulate('click')
targetDate.setDate(targetDate.getDate() + 1)
return targetDate
}

it('should render itself', () => {
const wrapper = mountWrapper()
expect(wrapper.exists()).toEqual(true)
})

describe('select a period', () => {
const targetItem: ExpirationItem = { id: 4, name: '90 days', period: 90 }

it('should update hint to the correct date', () => {
const wrapper = mountWrapper()
const targetDate = new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * targetItem.period)
const expectedHint = `The token will expire on ${targetDate.toLocaleDateString()}`

selectItem(wrapper, targetItem)
const hint = wrapper.find('.pf-c-form-control-expiration-hint').text()

expect(hint).toBe(expectedHint)
})

it('should update hidden input value to the correct timestamp', () => {
const wrapper = mountWrapper()
const targetDate = new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * targetItem.period)
const expectedValue = targetDate.toISOString().replace(/\.\d{3}Z$/, 'Z')

selectItem(wrapper, targetItem)
const value = wrapper.find(`input#${defaultProps.id}`).prop('value')

expect(value).toBe(expectedValue)
})
})

describe('select "Custom"', () => {
const targetItem: ExpirationItem = { id: 5, name: 'Custom...', period: 0 }

it('should show a calendar', () => {
const wrapper = mountWrapper()

selectItem(wrapper, targetItem)
const calendar = wrapper.find('.pf-c-calendar-month')

expect(calendar.exists()).toBe(true)
})

describe('pick a date from the calendar', () => {
it('should update hidden input value to the correct timestamp', () => {
const wrapper = mountWrapper()

selectItem(wrapper, targetItem)
const targetDate = pickDate(wrapper)
const expectedValue = targetDate.toISOString().replace(/\.\d{3}Z$/, 'Z')
const value = wrapper.find(`input#${defaultProps.id}`).prop('value')

expect(value).toBe(expectedValue)
})
})
})

describe('select "No expiration"', () => {
const targetItem: ExpirationItem = { id: 6, name: 'No expiration', period: 0 }

it('should show a warning', () => {
const wrapper = mountWrapper()

selectItem(wrapper, targetItem)
const warning = wrapper.find('.pf-c-alert.pf-m-warning')

expect(warning.exists()).toBe(true)
})

it('should update hidden input value to empty', () => {
const wrapper = mountWrapper()
const expectedValue = ''

selectItem(wrapper, targetItem)
const value = wrapper.find(`input#${defaultProps.id}`).prop('value')

expect(value).toBe(expectedValue)
})
})

0 comments on commit 995530a

Please sign in to comment.