Skip to content

Commit

Permalink
fix: add testable code
Browse files Browse the repository at this point in the history
  • Loading branch information
Inverseit committed Dec 5, 2023
1 parent 7211fea commit 0d679a3
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 26 deletions.
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const customJestConfig = {
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules', '<rootDir>/'],

moduleNameMapper: {
// Handle module aliases (this will be automatically configured for you soon)
'<rootDir>/components/(.*)$': '<rootDir>/components/$1',
Expand Down
33 changes: 33 additions & 0 deletions src/__tests__/random-controller.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { calculateVolumeSteps } from '@/components/header/random-controller'

describe('calculateVolumeSteps tests', () => {
test('calculates volume steps correctly for regular inputs', () => {
const result = calculateVolumeSteps(0.3, 0.8, 5)
const expected = [0.48, 0.62, 0.72, 0.78, 0.8]
expect(result).toHaveLength(expected.length)
result.forEach((val, index) => {
expect(val).toBeCloseTo(expected[index])
})
})

test('handles current and target volume being the same', () => {
const result = calculateVolumeSteps(0.5, 0.5, 5)
expect(result).toEqual([0.5, 0.5, 0.5, 0.5, 0.5])
})

test('handles zero steps', () => {
const result = calculateVolumeSteps(0.3, 0.8, 0)
expect(result).toEqual([])
})

test('handles negative steps', () => {
const result = calculateVolumeSteps(0.3, 0.8, -5)
expect(result).toEqual([])
})

test('handles a large number of steps', () => {
const steps = 1000
const result = calculateVolumeSteps(0.3, 0.8, steps)
expect(result).toHaveLength(steps)
})
})
67 changes: 42 additions & 25 deletions src/components/header/random-controller/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,28 @@ import { soundButton } from './styles'
import { useGlobalRandomModeStore } from '@/stores/random-mode-store'
import { useSoundsStateStore } from '@/stores/sounds-state-store'

// Calculate Target Volumes and out for testing purposes
export const calculateVolumeSteps = (currentVolume, targetVolume, steps) => {
let volumeSteps = []
for (let i = 1; i <= steps; i++) {
// Exponential interpolation factor (ease-out)
const factor = 1 - Math.pow(1 - i / steps, 2)
const newVolume = currentVolume + (targetVolume - currentVolume) * factor
volumeSteps.push(Math.min(newVolume, 1))
}
return volumeSteps
}

export function RandomModeButton() {
// How often the randomization takes place (min and max for the slider)
const MIN_INTERVAL = 10 * 1000 // 10 seconds
const MAX_INTERVAL = 5 * 60 * 1000 // 5 minutes

const [updateInterval, setUpdateInterval] = useState(MAX_INTERVAL)
const TOTAL_TRANSITION = 5000 // 5 seconds
const NUM_STEPS = 5 // Sound moves from 1 state to another in 5 steps

const { randomMode, setRandomMode } = useGlobalRandomModeStore()
const { sounds, setSound } = useSoundsStateStore()
const [updateInterval, setUpdateInterval] = useState(MAX_INTERVAL)
const [isShowing, setIsShowing] = useState(false)

const theme = useThemeStore(set => set.theme)
Expand All @@ -32,34 +46,37 @@ export function RandomModeButton() {
timeoutsRef.current = []
}

function randomizeVolumes() {
const steps = 5
const transitionDuration = 5000 // Total duration for volume change
const stepDuration = transitionDuration / steps

clearAllTimeouts()
// Apply Volumes with Timeouts
function applyVolumeChanges(sounds, stepDuration) {
clearAllTimeouts() // Clears existing timeouts

soundsRef.current
.filter(sound => sound.active)
.forEach(sound => {
const currentVolume = sound.volume
sounds.forEach(sound => {
if (sound.active) {
const targetVolume = Math.random()
const volumeSteps = calculateVolumeSteps(sound.volume, targetVolume, 5)

for (let i = 1; i <= steps; i++) {
const timeoutId = setTimeout(() => {
// Exponential interpolation factor (ease-out)
const factor = 1 - Math.pow(1 - i / steps, 2)
const newVolume =
currentVolume + (targetVolume - currentVolume) * factor
// Update the sound volume in a new object
const updatedSound = { ...sound, volume: Math.min(newVolume, 1) }
// Update the global state with the new sounds array
setSound(updatedSound)
}, i * stepDuration)
volumeSteps.forEach((newVolume, index) => {
const timeoutId = setTimeout(
() => {
const updatedSound = { ...sound, volume: newVolume }
setSound(updatedSound)
},
(index + 1) * stepDuration
)

timeoutsRef.current.push(timeoutId)
}
})
})
}
})
}

function randomizeVolumes() {
// Total duration for volume change
const transitionDuration = TOTAL_TRANSITION
const stepDuration = transitionDuration / NUM_STEPS

const activeSounds = soundsRef.current.filter(sound => sound.active)
applyVolumeChanges(activeSounds, stepDuration)
}

useEffect(() => {
Expand Down

0 comments on commit 0d679a3

Please sign in to comment.