diff --git a/app/javascript/__tests__/case_contact.test.js b/app/javascript/__tests__/case_contact.test.js
index ba10a0fb3e..0183881988 100644
--- a/app/javascript/__tests__/case_contact.test.js
+++ b/app/javascript/__tests__/case_contact.test.js
@@ -5,6 +5,46 @@
import { convertDateToSystemTimeZone } from '../src/case_contact'
-test('utc date is correctly converted to system date', () => {
- expect(convertDateToSystemTimeZone('2022-06-22 17:14:50 UTC')).toEqual(new Date('2022-06-22 17:14:50 UTC'))
+describe('convertDateToSystemTimeZone', () => {
+ test('converts a UTC date string to a Date object', () => {
+ const dateString = '2022-06-22 17:14:50 UTC'
+ const result = convertDateToSystemTimeZone(dateString)
+
+ expect(result).toBeInstanceOf(Date)
+ expect(result.getTime()).toBe(new Date(dateString).getTime())
+ })
+
+ test('converts a date string without timezone to a Date object', () => {
+ const dateString = '2022-06-22T12:00:00'
+ const result = convertDateToSystemTimeZone(dateString)
+
+ expect(result).toBeInstanceOf(Date)
+ expect(result.getFullYear()).toBe(2022)
+ expect(result.getMonth()).toBe(5) // June is month 5 (0-indexed)
+ expect(result.getDate()).toBe(22)
+ })
+
+ test('creates a copy of an existing Date object', () => {
+ const originalDate = new Date('2022-06-22 17:14:50 UTC')
+ const result = convertDateToSystemTimeZone(originalDate)
+
+ expect(result).toBeInstanceOf(Date)
+ expect(result.getTime()).toBe(originalDate.getTime())
+ expect(result).not.toBe(originalDate) // Should be a different object
+ })
+
+ test('handles ISO 8601 format', () => {
+ const dateString = '2022-06-22T17:14:50.000Z'
+ const result = convertDateToSystemTimeZone(dateString)
+
+ expect(result).toBeInstanceOf(Date)
+ expect(result.toISOString()).toBe(dateString)
+ })
+
+ test('returns Invalid Date for invalid date strings', () => {
+ const result = convertDateToSystemTimeZone('not a valid date')
+
+ expect(result).toBeInstanceOf(Date)
+ expect(isNaN(result.getTime())).toBe(true)
+ })
})
diff --git a/app/javascript/__tests__/case_emancipations.test.js b/app/javascript/__tests__/case_emancipations.test.js
index 2cc2f9619f..9c5b9d9d9f 100644
--- a/app/javascript/__tests__/case_emancipations.test.js
+++ b/app/javascript/__tests__/case_emancipations.test.js
@@ -59,7 +59,7 @@ beforeEach(() => {
})
describe('Function that changes the text of the Toggler based on the state of the parent', () => {
- test('Changes the toggler text to -', () => {
+ test('Changes the toggler text to + when category is closed', () => {
category.attr('data-is-open', 'false')
toggler.manageTogglerText()
diff --git a/app/javascript/__tests__/notifier.test.js b/app/javascript/__tests__/notifier.test.js
index f4b2e96285..2a373ab28f 100644
--- a/app/javascript/__tests__/notifier.test.js
+++ b/app/javascript/__tests__/notifier.test.js
@@ -29,162 +29,120 @@ beforeEach(() => {
`
- $(() => { // JQuery's callback for the DOM loading
- notificationsElement = $('#notifications')
- notifier = new Notifier(notificationsElement)
- })
+ notificationsElement = $('#notifications')
+ notifier = new Notifier(notificationsElement)
})
describe('Notifier', () => {
describe('clicking the minify button', () => {
let minimizeButton
- beforeEach(() => { // Create a notification so the minify button displays
- $(() => {
- notifier.notify('a notification', 'info')
- minimizeButton = notificationsElement.find('#toggle-minimize-notifications')
- })
+ beforeEach(() => {
+ notifier.notify('a notification', 'info')
+ minimizeButton = notificationsElement.find('#toggle-minimize-notifications')
})
- test('should toggle the notifier between the minified and expanded state', (done) => {
- $(() => {
- try {
- const messageNotificationsContainer = notificationsElement.find('.messages')
- const minimizeButtonIcon = minimizeButton.children('i')
- const minimizeButtonText = minimizeButton.children('span').first()
+ test('should toggle the notifier between the minified and expanded state', () => {
+ const messageNotificationsContainer = notificationsElement.find('.messages')
+ const minimizeButtonIcon = minimizeButton.children('i')
+ const minimizeButtonText = minimizeButton.children('span').first()
- expect(minimizeButton.css('display')).not.toBe('none')
- expect(messageNotificationsContainer.css('display')).not.toBe('none')
- expect(minimizeButtonIcon.hasClass('fa-minus')).toBeTruthy()
- expect(minimizeButtonIcon.hasClass('fa-plus')).not.toBeTruthy()
- expect(minimizeButtonText.css('display')).not.toBe('none')
+ expect(minimizeButton.css('display')).not.toBe('none')
+ expect(messageNotificationsContainer.css('display')).not.toBe('none')
+ expect(minimizeButtonIcon.hasClass('fa-minus')).toBe(true)
+ expect(minimizeButtonIcon.hasClass('fa-plus')).toBe(false)
+ expect(minimizeButtonText.css('display')).not.toBe('none')
- minimizeButton.click()
+ minimizeButton.click()
- expect(messageNotificationsContainer.css('display')).toBe('none')
- expect(minimizeButtonIcon.hasClass('fa-minus')).not.toBeTruthy()
- expect(minimizeButtonIcon.hasClass('fa-plus')).toBeTruthy()
- expect(minimizeButtonText.css('display')).toBe('none')
+ expect(messageNotificationsContainer.css('display')).toBe('none')
+ expect(minimizeButtonIcon.hasClass('fa-minus')).toBe(false)
+ expect(minimizeButtonIcon.hasClass('fa-plus')).toBe(true)
+ expect(minimizeButtonText.css('display')).toBe('none')
- minimizeButton.click()
-
- expect(messageNotificationsContainer.css('display')).not.toBe('none')
- expect(minimizeButtonIcon.hasClass('fa-minus')).toBeTruthy()
- expect(minimizeButtonIcon.hasClass('fa-plus')).not.toBeTruthy()
- expect(minimizeButtonText.css('display')).not.toBe('none')
+ minimizeButton.click()
- done()
- } catch (error) {
- done(error)
- }
- })
+ expect(messageNotificationsContainer.css('display')).not.toBe('none')
+ expect(minimizeButtonIcon.hasClass('fa-minus')).toBe(true)
+ expect(minimizeButtonIcon.hasClass('fa-plus')).toBe(false)
+ expect(minimizeButtonText.css('display')).not.toBe('none')
})
- test('should show only badges where there exists at least one notification matching the badge level when minimized', (done) => {
- $(() => {
- try {
- const minimizeButtonBadgeError = minimizeButton.children('.bg-danger')
- const minimizeButtonBadgeInfo = minimizeButton.children('.bg-success')
- const minimizeButtonBadgeWarning = minimizeButton.children('.bg-warning')
+ test('should show only badges where there exists at least one notification matching the badge level when minimized', () => {
+ const minimizeButtonBadgeError = minimizeButton.children('.bg-danger')
+ const minimizeButtonBadgeInfo = minimizeButton.children('.bg-success')
+ const minimizeButtonBadgeWarning = minimizeButton.children('.bg-warning')
- expect(minimizeButton.css('display')).not.toBe('none')
+ expect(minimizeButton.css('display')).not.toBe('none')
- minimizeButton.click()
+ minimizeButton.click()
- expect(minimizeButtonBadgeInfo.css('display')).not.toContain('none')
- expect(minimizeButtonBadgeInfo.text()).toBe('1')
- expect(minimizeButtonBadgeError.css('display')).toContain('none')
- expect(minimizeButtonBadgeWarning.css('display')).toContain('none')
+ expect(minimizeButtonBadgeInfo.css('display')).not.toContain('none')
+ expect(minimizeButtonBadgeInfo.text()).toBe('1')
+ expect(minimizeButtonBadgeError.css('display')).toContain('none')
+ expect(minimizeButtonBadgeWarning.css('display')).toContain('none')
- minimizeButton.click()
- const notification2 = notifier.notify('msg', 'error')
- notifier.notify('msg', 'warn')
+ minimizeButton.click()
+ const notification2 = notifier.notify('msg', 'error')
+ notifier.notify('msg', 'warn')
- minimizeButton.click()
- expect(minimizeButtonBadgeInfo.css('display')).not.toContain('none')
- expect(minimizeButtonBadgeInfo.text()).toBe('1')
- expect(minimizeButtonBadgeError.css('display')).not.toContain('none')
- expect(minimizeButtonBadgeError.text()).toBe('1')
- expect(minimizeButtonBadgeWarning.css('display')).not.toContain('none')
- expect(minimizeButtonBadgeWarning.text()).toBe('1')
+ minimizeButton.click()
+ expect(minimizeButtonBadgeInfo.css('display')).not.toContain('none')
+ expect(minimizeButtonBadgeInfo.text()).toBe('1')
+ expect(minimizeButtonBadgeError.css('display')).not.toContain('none')
+ expect(minimizeButtonBadgeError.text()).toBe('1')
+ expect(minimizeButtonBadgeWarning.css('display')).not.toContain('none')
+ expect(minimizeButtonBadgeWarning.text()).toBe('1')
- minimizeButton.click()
- notification2.dismiss()
+ minimizeButton.click()
+ notification2.dismiss()
- minimizeButton.click()
- expect(minimizeButtonBadgeInfo.css('display')).not.toContain('none')
- expect(minimizeButtonBadgeInfo.text()).toBe('1')
- expect(minimizeButtonBadgeError.css('display')).toContain('none')
- expect(minimizeButtonBadgeWarning.css('display')).not.toContain('none')
- expect(minimizeButtonBadgeWarning.text()).toBe('1')
-
- done()
- } catch (error) {
- done(error)
- }
- })
+ minimizeButton.click()
+ expect(minimizeButtonBadgeInfo.css('display')).not.toContain('none')
+ expect(minimizeButtonBadgeInfo.text()).toBe('1')
+ expect(minimizeButtonBadgeError.css('display')).toContain('none')
+ expect(minimizeButtonBadgeWarning.css('display')).not.toContain('none')
+ expect(minimizeButtonBadgeWarning.text()).toBe('1')
})
})
describe('notify', () => {
- test("displays a green notification when passed a message and level='info'", (done) => {
+ test("displays a green notification when passed a message and level='info'", () => {
const notificationMessage = "'Y$deH[|%ROii]jy"
- $(() => {
- try {
- // Clear any existing notifications from previous tests
- notificationsElement.find('.messages').empty()
+ // Clear any existing notifications from previous tests
+ notificationsElement.find('.messages').empty()
- notifier.notify(notificationMessage, 'info')
+ notifier.notify(notificationMessage, 'info')
- const successMessages = notificationsElement.children('.messages').find('.success-notification')
+ const successMessages = notificationsElement.children('.messages').find('.success-notification')
- expect(successMessages.length).toBe(1)
- expect(successMessages[0].innerHTML).toContain(notificationMessage)
- done()
- } catch (error) {
- done(error)
- }
- })
+ expect(successMessages.length).toBe(1)
+ expect(successMessages[0].innerHTML).toContain(notificationMessage)
})
- test("displays a red notification when passed a message and level='error'", (done) => {
+ test("displays a red notification when passed a message and level='error'", () => {
const notificationMessage = '\\+!h0bbH"yN7dx9.'
- $(() => {
- try {
- notifier.notify(notificationMessage, 'error')
+ notifier.notify(notificationMessage, 'error')
- const failureMessages = notificationsElement.find('.danger-notification')
+ const failureMessages = notificationsElement.find('.danger-notification')
- expect(failureMessages.length).toBe(1)
- expect(failureMessages[0].innerHTML).toContain(notificationMessage)
- done()
- } catch (error) {
- done(error)
- }
- })
+ expect(failureMessages.length).toBe(1)
+ expect(failureMessages[0].innerHTML).toContain(notificationMessage)
})
- test('displays the minimize button after no notifications were present before', (done) => {
- $(() => {
- try {
- const messageNotificationsContainer = notificationsElement.find('.messages')
- const minimizeButton = notificationsElement.find('#toggle-minimize-notifications')
+ test('displays the minimize button after no notifications were present before', () => {
+ const messageNotificationsContainer = notificationsElement.find('.messages')
+ const minimizeButton = notificationsElement.find('#toggle-minimize-notifications')
- expect(minimizeButton.css('display')).toBe('none')
- expect(messageNotificationsContainer.children().length).toBe(0)
+ expect(minimizeButton.css('display')).toBe('none')
+ expect(messageNotificationsContainer.children().length).toBe(0)
- notifier.notify('msg', 'info')
+ notifier.notify('msg', 'info')
- expect(minimizeButton.css('display')).not.toBe('none')
- expect(messageNotificationsContainer.children().length).toBeGreaterThan(0)
-
- done()
- } catch (error) {
- done(error)
- }
- })
+ expect(minimizeButton.css('display')).not.toBe('none')
+ expect(messageNotificationsContainer.children().length).toBeGreaterThan(0)
})
describe('when the notifier is minimized', () => {
diff --git a/app/javascript/__tests__/read_more.test.js b/app/javascript/__tests__/read_more.test.js
new file mode 100644
index 0000000000..7885eb8077
--- /dev/null
+++ b/app/javascript/__tests__/read_more.test.js
@@ -0,0 +1,110 @@
+/* eslint-env jest, browser */
+/**
+ * @jest-environment jsdom
+ */
+
+describe('read_more', () => {
+ beforeEach(() => {
+ document.body.innerHTML = `
+
+
+ Short text...
+
+
+ This is the full text that is initially hidden.
+
+
+
+
+ `
+
+ // Require the module after setting up the DOM
+ jest.isolateModules(() => {
+ require('../src/read_more')
+ })
+
+ // Trigger DOMContentLoaded
+ const event = new Event('DOMContentLoaded')
+ document.dispatchEvent(event)
+ })
+
+ test('shows full text and hides truncated text when Read More is clicked', () => {
+ const readMoreButton = document.querySelector('.js-read-more')
+ const truncatedText = document.querySelector('.js-truncated-text')
+ const fullText = document.querySelector('.js-full-text')
+
+ expect(truncatedText.style.display).toBe('block')
+ expect(fullText.style.display).toBe('none')
+
+ readMoreButton.click()
+
+ expect(truncatedText.style.display).toBe('none')
+ expect(fullText.style.display).toBe('block')
+ })
+
+ test('shows truncated text and hides full text when Read Less is clicked', () => {
+ const readMoreButton = document.querySelector('.js-read-more')
+ const readLessButton = document.querySelector('.js-read-less')
+ const truncatedText = document.querySelector('.js-truncated-text')
+ const fullText = document.querySelector('.js-full-text')
+
+ // First expand
+ readMoreButton.click()
+ expect(fullText.style.display).toBe('block')
+
+ // Then collapse
+ readLessButton.click()
+ expect(truncatedText.style.display).toBe('block')
+ expect(fullText.style.display).toBe('none')
+ })
+
+ test('prevents default event behavior on Read More click', () => {
+ const readMoreButton = document.querySelector('.js-read-more')
+ const event = new MouseEvent('click', { bubbles: true, cancelable: true })
+ const preventDefaultSpy = jest.spyOn(event, 'preventDefault')
+
+ readMoreButton.dispatchEvent(event)
+
+ expect(preventDefaultSpy).toHaveBeenCalled()
+ })
+
+ test('prevents default event behavior on Read Less click', () => {
+ const readLessButton = document.querySelector('.js-read-less')
+ const event = new MouseEvent('click', { bubbles: true, cancelable: true })
+ const preventDefaultSpy = jest.spyOn(event, 'preventDefault')
+
+ readLessButton.dispatchEvent(event)
+
+ expect(preventDefaultSpy).toHaveBeenCalled()
+ })
+
+ test('handles multiple read more/less wrappers independently', () => {
+ document.body.innerHTML = `
+
+
Short 1
+
Full 1
+
+
+
+
Short 2
+
Full 2
+
+
+ `
+
+ jest.isolateModules(() => {
+ require('../src/read_more')
+ })
+ document.dispatchEvent(new Event('DOMContentLoaded'))
+
+ const wrapper1ReadMore = document.querySelector('#wrapper1 .js-read-more')
+ const wrapper1Full = document.querySelector('#wrapper1 .js-full-text')
+ const wrapper2Full = document.querySelector('#wrapper2 .js-full-text')
+
+ wrapper1ReadMore.click()
+
+ // Only wrapper1 should be expanded
+ expect(wrapper1Full.style.display).toBe('block')
+ expect(wrapper2Full.style.display).toBe('none')
+ })
+})
diff --git a/app/javascript/__tests__/time_zone.test.js b/app/javascript/__tests__/time_zone.test.js
new file mode 100644
index 0000000000..6fca7ebbb2
--- /dev/null
+++ b/app/javascript/__tests__/time_zone.test.js
@@ -0,0 +1,37 @@
+/* eslint-env jest */
+/**
+ * @jest-environment jsdom
+ */
+
+import { findTimeZone } from '../src/time_zone'
+
+describe('findTimeZone', () => {
+ test('returns a string timezone name', () => {
+ const timezone = findTimeZone()
+
+ expect(typeof timezone).toBe('string')
+ expect(timezone.length).toBeGreaterThan(0)
+ })
+
+ test('returns a valid timezone string format', () => {
+ const timezone = findTimeZone()
+
+ // Timezone should be in format like "America/New_York" or "Europe/London"
+ // Common formats: Continent/City or UTC
+ expect(timezone).toMatch(/^[A-Za-z_]+\/[A-Za-z_]+$|^UTC$|^[A-Z]{3,4}$/)
+ })
+
+ test('returns consistent result when called multiple times', () => {
+ const timezone1 = findTimeZone()
+ const timezone2 = findTimeZone()
+
+ expect(timezone1).toBe(timezone2)
+ })
+
+ test('handles environments where Intl is available', () => {
+ // This test just verifies the function doesn't throw when Intl exists
+ expect(() => {
+ findTimeZone()
+ }).not.toThrow()
+ })
+})
diff --git a/app/javascript/__tests__/two_minute_warning_session_timeout.test.js b/app/javascript/__tests__/two_minute_warning_session_timeout.test.js
index 69f1bb1948..e70f895235 100644
--- a/app/javascript/__tests__/two_minute_warning_session_timeout.test.js
+++ b/app/javascript/__tests__/two_minute_warning_session_timeout.test.js
@@ -45,14 +45,4 @@ describe('session_timeout_poller', () => {
setIntervalSpy.mockRestore()
})
-
- test('demonstrates timeout logic is testable', () => {
- // This test demonstrates the module loads and can be tested
- // A full integration test would require complex timer manipulation
- // due to how the module uses Date.getTime() and setInterval together
- expect(() => {
- jest.resetModules()
- require('../src/session_timeout_poller')
- }).not.toThrow()
- })
})
diff --git a/app/javascript/__tests__/type_checker.test.js b/app/javascript/__tests__/type_checker.test.js
new file mode 100644
index 0000000000..e7213b294f
--- /dev/null
+++ b/app/javascript/__tests__/type_checker.test.js
@@ -0,0 +1,246 @@
+/* eslint-env jest */
+/**
+ * @jest-environment jsdom
+ */
+
+const TypeChecker = require('../src/type_checker')
+
+describe('TypeChecker', () => {
+ describe('checkNonEmptyJQueryObject', () => {
+ beforeEach(() => {
+ document.body.innerHTML = ''
+ })
+
+ test('accepts a non-empty jQuery object', () => {
+ const element = $('#test-element')
+ expect(() => {
+ TypeChecker.checkNonEmptyJQueryObject(element, 'element')
+ }).not.toThrow()
+ })
+
+ test('throws TypeError when passed a non-jQuery object', () => {
+ expect(() => {
+ TypeChecker.checkNonEmptyJQueryObject('string', 'element')
+ }).toThrow(TypeError)
+ expect(() => {
+ TypeChecker.checkNonEmptyJQueryObject('string', 'element')
+ }).toThrow('Param element must be a jQuery object')
+ })
+
+ test('throws TypeError when passed null', () => {
+ expect(() => {
+ TypeChecker.checkNonEmptyJQueryObject(null, 'element')
+ }).toThrow(TypeError)
+ })
+
+ test('throws TypeError when passed undefined', () => {
+ expect(() => {
+ TypeChecker.checkNonEmptyJQueryObject(undefined, 'element')
+ }).toThrow(TypeError)
+ })
+
+ test('throws TypeError when passed a plain object', () => {
+ expect(() => {
+ TypeChecker.checkNonEmptyJQueryObject({}, 'element')
+ }).toThrow(TypeError)
+ })
+
+ test('throws ReferenceError when jQuery object contains no elements', () => {
+ const emptyElement = $('#non-existent')
+ expect(() => {
+ TypeChecker.checkNonEmptyJQueryObject(emptyElement, 'element')
+ }).toThrow(ReferenceError)
+ expect(() => {
+ TypeChecker.checkNonEmptyJQueryObject(emptyElement, 'element')
+ }).toThrow('Param element contains no elements')
+ })
+ })
+
+ describe('checkNonEmptyString', () => {
+ test('accepts a non-empty string', () => {
+ expect(() => {
+ TypeChecker.checkNonEmptyString('hello', 'myString')
+ }).not.toThrow()
+ })
+
+ test('throws TypeError when passed a non-string', () => {
+ expect(() => {
+ TypeChecker.checkNonEmptyString(123, 'myString')
+ }).toThrow(TypeError)
+ expect(() => {
+ TypeChecker.checkNonEmptyString(123, 'myString')
+ }).toThrow('Param myString must be a string')
+ })
+
+ test('throws TypeError when passed null', () => {
+ expect(() => {
+ TypeChecker.checkNonEmptyString(null, 'myString')
+ }).toThrow(TypeError)
+ })
+
+ test('throws TypeError when passed undefined', () => {
+ expect(() => {
+ TypeChecker.checkNonEmptyString(undefined, 'myString')
+ }).toThrow(TypeError)
+ })
+
+ test('throws RangeError when passed an empty string', () => {
+ expect(() => {
+ TypeChecker.checkNonEmptyString('', 'myString')
+ }).toThrow(RangeError)
+ expect(() => {
+ TypeChecker.checkNonEmptyString('', 'myString')
+ }).toThrow('Param myString cannot be empty string')
+ })
+ })
+
+ describe('checkObject', () => {
+ test('accepts a plain object', () => {
+ expect(() => {
+ TypeChecker.checkObject({}, 'myObject')
+ }).not.toThrow()
+ })
+
+ test('accepts an object with properties', () => {
+ expect(() => {
+ TypeChecker.checkObject({ key: 'value' }, 'myObject')
+ }).not.toThrow()
+ })
+
+ test('throws TypeError when passed a string', () => {
+ expect(() => {
+ TypeChecker.checkObject('string', 'myObject')
+ }).toThrow(TypeError)
+ expect(() => {
+ TypeChecker.checkObject('string', 'myObject')
+ }).toThrow('Param myObject is not an object')
+ })
+
+ test('throws TypeError when passed a number', () => {
+ expect(() => {
+ TypeChecker.checkObject(123, 'myObject')
+ }).toThrow(TypeError)
+ })
+
+ test('throws TypeError when passed an array', () => {
+ expect(() => {
+ TypeChecker.checkObject([1, 2, 3], 'myObject')
+ }).toThrow(TypeError)
+ expect(() => {
+ TypeChecker.checkObject([1, 2, 3], 'myObject')
+ }).toThrow('Param myObject is not an object')
+ })
+
+ test('throws TypeError when passed null', () => {
+ expect(() => {
+ TypeChecker.checkObject(null, 'myObject')
+ }).toThrow(TypeError)
+ })
+
+ test('throws TypeError when passed undefined', () => {
+ expect(() => {
+ TypeChecker.checkObject(undefined, 'myObject')
+ }).toThrow(TypeError)
+ })
+ })
+
+ describe('checkPositiveInteger', () => {
+ test('accepts zero', () => {
+ expect(() => {
+ TypeChecker.checkPositiveInteger(0, 'myNumber')
+ }).not.toThrow()
+ })
+
+ test('accepts positive integers', () => {
+ expect(() => {
+ TypeChecker.checkPositiveInteger(1, 'myNumber')
+ }).not.toThrow()
+ expect(() => {
+ TypeChecker.checkPositiveInteger(100, 'myNumber')
+ }).not.toThrow()
+ })
+
+ test('throws TypeError when passed a float', () => {
+ expect(() => {
+ TypeChecker.checkPositiveInteger(1.5, 'myNumber')
+ }).toThrow(TypeError)
+ expect(() => {
+ TypeChecker.checkPositiveInteger(1.5, 'myNumber')
+ }).toThrow('Param myNumber is not an integer')
+ })
+
+ test('throws TypeError when passed a string', () => {
+ expect(() => {
+ TypeChecker.checkPositiveInteger('123', 'myNumber')
+ }).toThrow(TypeError)
+ })
+
+ test('throws TypeError when passed NaN', () => {
+ expect(() => {
+ TypeChecker.checkPositiveInteger(NaN, 'myNumber')
+ }).toThrow(TypeError)
+ })
+
+ test('throws RangeError when passed a negative integer', () => {
+ expect(() => {
+ TypeChecker.checkPositiveInteger(-1, 'myNumber')
+ }).toThrow(RangeError)
+ expect(() => {
+ TypeChecker.checkPositiveInteger(-1, 'myNumber')
+ }).toThrow('Param myNumber cannot be negative')
+ })
+
+ test('throws RangeError when passed a large negative integer', () => {
+ expect(() => {
+ TypeChecker.checkPositiveInteger(-100, 'myNumber')
+ }).toThrow(RangeError)
+ })
+ })
+
+ describe('checkString', () => {
+ test('accepts a string', () => {
+ expect(() => {
+ TypeChecker.checkString('hello', 'myString')
+ }).not.toThrow()
+ })
+
+ test('accepts an empty string', () => {
+ expect(() => {
+ TypeChecker.checkString('', 'myString')
+ }).not.toThrow()
+ })
+
+ test('throws TypeError when passed a number', () => {
+ expect(() => {
+ TypeChecker.checkString(123, 'myString')
+ }).toThrow(TypeError)
+ expect(() => {
+ TypeChecker.checkString(123, 'myString')
+ }).toThrow('Param myString must be a string')
+ })
+
+ test('throws TypeError when passed null', () => {
+ expect(() => {
+ TypeChecker.checkString(null, 'myString')
+ }).toThrow(TypeError)
+ })
+
+ test('throws TypeError when passed undefined', () => {
+ expect(() => {
+ TypeChecker.checkString(undefined, 'myString')
+ }).toThrow(TypeError)
+ })
+
+ test('throws TypeError when passed an object', () => {
+ expect(() => {
+ TypeChecker.checkString({}, 'myString')
+ }).toThrow(TypeError)
+ })
+
+ test('throws TypeError when passed an array', () => {
+ expect(() => {
+ TypeChecker.checkString([], 'myString')
+ }).toThrow(TypeError)
+ })
+ })
+})
diff --git a/app/javascript/__tests__/validated_form.test.js b/app/javascript/__tests__/validated_form.test.js
index ddc348932b..c82e667835 100644
--- a/app/javascript/__tests__/validated_form.test.js
+++ b/app/javascript/__tests__/validated_form.test.js
@@ -69,13 +69,11 @@ describe('NonDrivingContactMediumWarning', () => {
`
- $(() => { // JQuery's callback for the DOM loading
- checkboxes = $('.contact-medium.form-group input:not([type=hidden])')
- drivingOption = checkboxes.filter('#case_contact_medium_type_in-person')
- milesDrivenInput = $('#case_contact_miles_driven')
- nonDrivingOptions = checkboxes.not(drivingOption)
- notifier = new Notifier($('#notifications'))
- })
+ checkboxes = $('.contact-medium.form-group input:not([type=hidden])')
+ drivingOption = checkboxes.filter('#case_contact_medium_type_in-person')
+ milesDrivenInput = $('#case_contact_miles_driven')
+ nonDrivingOptions = checkboxes.not(drivingOption)
+ notifier = new Notifier($('#notifications'))
})
describe('constructor', () => {
@@ -96,58 +94,40 @@ describe('NonDrivingContactMediumWarning', () => {
let component
beforeEach(() => {
- $(() => {
- component = new NonDrivingContactMediumWarning($('.contact-medium.form-group input:not([type=hidden]), #case_contact_miles_driven'), notifier)
- })
+ component = new NonDrivingContactMediumWarning($('.contact-medium.form-group input:not([type=hidden]), #case_contact_miles_driven'), notifier)
})
- test('returns the warning message if a non driving contact medium is selected and the miles driven count is > 0', (done) => {
- $(() => {
- try {
- expect(nonDrivingOptions.length).toBeGreaterThan(0)
-
- milesDrivenInput.val(1)
+ test('returns the warning message if a non driving contact medium is selected and the miles driven count is > 0', () => {
+ expect(nonDrivingOptions.length).toBeGreaterThan(0)
- nonDrivingOptions.each(function () {
- const option = $(this)
+ milesDrivenInput.val(1)
- option.trigger('click')
+ nonDrivingOptions.each(function () {
+ const option = $(this)
- expect(component.getWarningState()).toBe('You requested driving reimbursement for a contact medium that typically does not involve driving. Are you sure that\'s right?')
- })
+ option.trigger('click')
- done()
- } catch (error) {
- done(error)
- }
+ expect(component.getWarningState()).toBe('You requested driving reimbursement for a contact medium that typically does not involve driving. Are you sure that\'s right?')
})
})
- test('returns a falsy value if the driving contact medium is selected or the miles driven count is 0', (done) => {
- $(() => {
- try {
- expect(nonDrivingOptions.length).toBeGreaterThan(0)
+ test('returns a falsy value if the driving contact medium is selected or the miles driven count is 0', () => {
+ expect(nonDrivingOptions.length).toBeGreaterThan(0)
- milesDrivenInput.val(0)
+ milesDrivenInput.val(0)
- nonDrivingOptions.each(function () {
- const option = $(this)
+ nonDrivingOptions.each(function () {
+ const option = $(this)
- option.trigger('click')
+ option.trigger('click')
- expect(component.getWarningState()).toBeFalsy()
- })
-
- milesDrivenInput.val(1)
- drivingOption.trigger('click')
+ expect(component.getWarningState()).toBeFalsy()
+ })
- expect(component.getWarningState()).toBeFalsy()
+ milesDrivenInput.val(1)
+ drivingOption.trigger('click')
- done()
- } catch (error) {
- done(error)
- }
- })
+ expect(component.getWarningState()).toBeFalsy()
})
})