mirror of
https://github.com/Jellify-Music/App.git
synced 2025-12-30 15:29:49 -06:00
Fix Playback Reporting, Add QueueProvider Test Coverage (#300)
Addresses regression where playback was not reported
This commit is contained in:
@@ -2,12 +2,8 @@ import 'react-native'
|
||||
import React from 'react'
|
||||
import App from '../App'
|
||||
|
||||
// Note: import explicitly to use the types shipped with jest.
|
||||
import { it } from '@jest/globals'
|
||||
import { render } from '@testing-library/react-native'
|
||||
|
||||
// Note: test renderer must be required after react-native.
|
||||
import renderer from 'react-test-renderer'
|
||||
|
||||
it('renders correctly', () => {
|
||||
renderer.create(<App />)
|
||||
test(`${App.name} renders successfully`, () => {
|
||||
render(<App />)
|
||||
})
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
import 'react-native'
|
||||
import React from 'react'
|
||||
import { render, screen, waitFor } from '@testing-library/react-native'
|
||||
|
||||
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react-native'
|
||||
import TrackPlayer, { Event } from 'react-native-track-player'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { QueueProvider, useQueueContext } from '../player/queue-provider'
|
||||
import { Button, Text } from 'react-native'
|
||||
import { Event } from 'react-native-track-player'
|
||||
|
||||
import { QueueProvider, useQueueContext } from '../player/queue-provider'
|
||||
import { eventHandler } from './setup-rntp'
|
||||
|
||||
const queryClient = new QueryClient()
|
||||
|
||||
const QueueConsumer = () => {
|
||||
const { currentIndex, useSkip } = useQueueContext()
|
||||
const { currentIndex, useSkip, usePrevious } = useQueueContext()
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text testID='current-index'>{currentIndex}</Text>
|
||||
|
||||
<Button title='skip' testID='use-skip' onPress={() => useSkip.mutate(undefined)} />
|
||||
|
||||
<Button title='previous' testID='use-previous' onPress={() => usePrevious.mutate()} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -35,13 +37,27 @@ test(`${QueueProvider.name} renders and functions correctly`, async () => {
|
||||
|
||||
expect(currentIndex.props.children).toBe(-1)
|
||||
|
||||
eventHandler({
|
||||
type: Event.PlaybackActiveTrackChanged,
|
||||
index: 3,
|
||||
act(() => {
|
||||
eventHandler({
|
||||
type: Event.PlaybackActiveTrackChanged,
|
||||
index: 3,
|
||||
})
|
||||
})
|
||||
|
||||
await waitFor(() => {
|
||||
const updatedIndex = screen.getByTestId('current-index')
|
||||
expect(updatedIndex.props.children).toBe(3)
|
||||
})
|
||||
|
||||
act(() => {
|
||||
eventHandler({
|
||||
type: Event.PlaybackActiveTrackChanged,
|
||||
index: 2,
|
||||
})
|
||||
})
|
||||
|
||||
await waitFor(() => {
|
||||
const updatedIndex = screen.getByTestId('current-index')
|
||||
expect(updatedIndex.props.children).toBe(2)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,58 +1,54 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import * as TrackPlayer from 'react-native-track-player'
|
||||
export let eventHandler: any
|
||||
|
||||
// https://github.com/doublesymmetry/react-native-track-player/issues/501
|
||||
jest.mock('react-native-track-player', () => {
|
||||
const listeners = new Map()
|
||||
|
||||
return {
|
||||
__esModule: true,
|
||||
default: {
|
||||
addEventListener: () => ({
|
||||
remove: jest.fn(),
|
||||
}),
|
||||
registerEventHandler: jest.fn(),
|
||||
registerPlaybackService: jest.fn(),
|
||||
setupPlayer: jest.fn().mockResolvedValue(undefined),
|
||||
destroy: jest.fn(),
|
||||
updateOptions: jest.fn(),
|
||||
reset: jest.fn(),
|
||||
add: jest.fn(),
|
||||
addEventListener: () => ({
|
||||
remove: jest.fn(),
|
||||
skip: jest.fn(),
|
||||
skipToNext: jest.fn(),
|
||||
skipToPrevious: jest.fn(),
|
||||
removeUpcomingTracks: jest.fn(),
|
||||
// playback commands
|
||||
play: jest.fn(),
|
||||
pause: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
seekTo: jest.fn(),
|
||||
setVolume: jest.fn(),
|
||||
setRate: jest.fn(),
|
||||
// player getters
|
||||
getQueue: jest.fn(),
|
||||
getTrack: jest.fn(),
|
||||
getActiveTrackIndex: jest.fn(),
|
||||
getActiveTrack: jest.fn(),
|
||||
getCurrentTrack: jest.fn(),
|
||||
getVolume: jest.fn(),
|
||||
getDuration: jest.fn(),
|
||||
getPosition: jest.fn(),
|
||||
getBufferedPosition: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
getRate: jest.fn(),
|
||||
},
|
||||
}),
|
||||
registerEventHandler: jest.fn(),
|
||||
registerPlaybackService: jest.fn(),
|
||||
setupPlayer: jest.fn().mockResolvedValue(undefined),
|
||||
destroy: jest.fn(),
|
||||
updateOptions: jest.fn(),
|
||||
reset: jest.fn(),
|
||||
add: jest.fn(),
|
||||
remove: jest.fn(),
|
||||
skip: jest.fn(),
|
||||
skipToNext: jest.fn(),
|
||||
skipToPrevious: jest.fn(),
|
||||
removeUpcomingTracks: jest.fn(),
|
||||
// playback commands
|
||||
play: jest.fn(),
|
||||
pause: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
seekTo: jest.fn(),
|
||||
setVolume: jest.fn(),
|
||||
setRate: jest.fn(),
|
||||
// player getters
|
||||
getQueue: jest.fn(),
|
||||
getTrack: jest.fn(),
|
||||
getActiveTrackIndex: jest.fn(),
|
||||
getActiveTrack: jest.fn(),
|
||||
getCurrentTrack: jest.fn(),
|
||||
getVolume: jest.fn(),
|
||||
getDuration: jest.fn(),
|
||||
getProgress: jest.fn().mockResolvedValue({ position: 0 }),
|
||||
getBufferedPosition: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
getRate: jest.fn(),
|
||||
useProgress: () => ({
|
||||
position: 100,
|
||||
position: 0,
|
||||
buffered: 150,
|
||||
duration: 200,
|
||||
}),
|
||||
usePlaybackState: () => 'playing',
|
||||
|
||||
// eslint-disable @typescript-eslint/no-explicit-any
|
||||
useTrackPlayerEvents: (events: TrackPlayer.Event[], handler: (variables: any) => void) => {
|
||||
useTrackPlayerEvents: (events: Event[], handler: (variables: any) => void) => {
|
||||
eventHandler = handler
|
||||
},
|
||||
Capability: {
|
||||
@@ -100,13 +96,3 @@ jest.mock('react-native-track-player', () => {
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
export let eventHandler: any
|
||||
|
||||
beforeEach(() => {
|
||||
const player = TrackPlayer as any
|
||||
|
||||
player.useTrackPlayerEvents = (events: Event[], handler: (variables: any) => void) => {
|
||||
eventHandler = handler
|
||||
}
|
||||
})
|
||||
|
||||
244
package.json
244
package.json
@@ -1,123 +1,123 @@
|
||||
{
|
||||
"name": "jellify",
|
||||
"version": "0.11.13",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"init:ios": "yarn install && yarn pod:install",
|
||||
"reinstall": "rm -rf ./node_modules && yarn install",
|
||||
"android": "react-native run-android",
|
||||
"ios": "react-native run-ios",
|
||||
"lint": "eslint .",
|
||||
"start": "react-native start",
|
||||
"test": "jest",
|
||||
"clean:ios": "cd ios && pod deintegrate",
|
||||
"clean:android": "cd android && rm -rf app/ build/",
|
||||
"pod:install": "cd ios && bundle install && RCT_NEW_ARCH_ENABLED=0 bundle exec pod install",
|
||||
"pod:install-new-arch": "cd ios && bundle install && RCT_NEW_ARCH_ENABLED=1 bundle exec pod install",
|
||||
"fastlane:ios:build": "cd ios && bundle exec fastlane build",
|
||||
"fastlane:ios:match": "cd ios && bundle exec fastlane match development",
|
||||
"fastlane:ios:beta": "cd ios && bundle exec fastlane beta",
|
||||
"fastlane:android:build": "cd android && bundle install && bundle exec fastlane build",
|
||||
"androidBuild": "cd android && ./gradlew clean && ./gradlew assembleRelease && cd .. && echo 'find apk in android/app/build/outputs/apk/release'",
|
||||
"prepare": "husky",
|
||||
"format:check": "prettier --check .",
|
||||
"format": "prettier --write .",
|
||||
"postinstall": "patch-package"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jellyfin/sdk": "^0.11.0",
|
||||
"@react-native-community/blur": "^4.4.1",
|
||||
"@react-native-community/cli": "^15.1.3",
|
||||
"@react-native-community/netinfo": "^11.4.1",
|
||||
"@react-native-masked-view/masked-view": "^0.3.2",
|
||||
"@react-navigation/bottom-tabs": "^7.3.10",
|
||||
"@react-navigation/material-top-tabs": "^7.2.10",
|
||||
"@react-navigation/native": "^7.1.6",
|
||||
"@react-navigation/native-stack": "^7.3.10",
|
||||
"@react-navigation/stack": "^7.2.10",
|
||||
"@tamagui/config": "^1.126.1",
|
||||
"@tamagui/toast": "^1.126.1",
|
||||
"@tanstack/query-sync-storage-persister": "^5.74.6",
|
||||
"@tanstack/react-query": "^5.74.4",
|
||||
"@tanstack/react-query-persist-client": "^5.74.6",
|
||||
"@testing-library/react-native": "^13.2.0",
|
||||
"axios": "^1.8.4",
|
||||
"bundle": "^2.1.0",
|
||||
"burnt": "^0.13.0",
|
||||
"expo": "^52.0.46",
|
||||
"expo-image": "^2.0.7",
|
||||
"gem": "^2.4.3",
|
||||
"invert-color": "^2.0.0",
|
||||
"jest-expo": "^52.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"npm-bundle": "^3.0.3",
|
||||
"patch-package": "^8.0.0",
|
||||
"react": "18.3.1",
|
||||
"react-freeze": "^1.0.4",
|
||||
"react-native": "0.77.0",
|
||||
"react-native-background-actions": "^4.0.1",
|
||||
"react-native-blurhash": "^2.1.1",
|
||||
"react-native-boost": "^0.5.6",
|
||||
"react-native-carplay": "^2.4.1-beta.0",
|
||||
"react-native-device-info": "^14.0.4",
|
||||
"react-native-draggable-flatlist": "^4.0.2",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "^2.25.0",
|
||||
"react-native-haptic-feedback": "^2.3.3",
|
||||
"react-native-mmkv": "^2.12.2",
|
||||
"react-native-pager-view": "^6.7.1",
|
||||
"react-native-reanimated": "^3.17.5",
|
||||
"react-native-safe-area-context": "^5.4.0",
|
||||
"react-native-screens": "^4.10.0",
|
||||
"react-native-swipeable-item": "^2.0.9",
|
||||
"react-native-text-ticker": "^1.14.0",
|
||||
"react-native-track-player": "^4.1.1",
|
||||
"react-native-url-polyfill": "^2.0.0",
|
||||
"react-native-uuid": "^2.0.3",
|
||||
"react-native-vector-icons": "^10.2.0",
|
||||
"ruby": "^0.6.1",
|
||||
"tamagui": "^1.126.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/runtime": "^7.25.0",
|
||||
"@react-native-community/cli-platform-android": "15.1.3",
|
||||
"@react-native-community/cli-platform-ios": "15.1.3",
|
||||
"@react-native/babel-preset": "0.77.0",
|
||||
"@react-native/eslint-config": "0.77.0",
|
||||
"@react-native/metro-config": "0.77.0",
|
||||
"@react-native/typescript-config": "0.77.0",
|
||||
"@types/jest": "^29.5.13",
|
||||
"@types/lodash": "^4.17.10",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-native-vector-icons": "^6.4.18",
|
||||
"@types/react-test-renderer": "^18.3.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.29.1",
|
||||
"@typescript-eslint/parser": "^8.29.1",
|
||||
"babel-plugin-module-resolver": "^5.0.2",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^10.1.2",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-native": "^5.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^29.6.3",
|
||||
"jscodeshift": "^0.15.2",
|
||||
"lint-staged": "^15.5.0",
|
||||
"prettier": "^2.8.8",
|
||||
"react-native-cli-bump-version": "^1.5.1",
|
||||
"react-test-renderer": "18.3.1",
|
||||
"typescript": "5.7.3"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
"prettier --write",
|
||||
"eslint --fix"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
"name": "jellify",
|
||||
"version": "0.11.13",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"init:ios": "yarn install && yarn pod:install",
|
||||
"reinstall": "rm -rf ./node_modules && yarn install",
|
||||
"android": "react-native run-android",
|
||||
"ios": "react-native run-ios",
|
||||
"lint": "eslint .",
|
||||
"start": "react-native start",
|
||||
"test": "jest",
|
||||
"clean:ios": "cd ios && pod deintegrate",
|
||||
"clean:android": "cd android && rm -rf app/ build/",
|
||||
"pod:install": "cd ios && bundle install && RCT_NEW_ARCH_ENABLED=0 bundle exec pod install",
|
||||
"pod:install-new-arch": "cd ios && bundle install && RCT_NEW_ARCH_ENABLED=1 bundle exec pod install",
|
||||
"fastlane:ios:build": "cd ios && bundle exec fastlane build",
|
||||
"fastlane:ios:match": "cd ios && bundle exec fastlane match development",
|
||||
"fastlane:ios:beta": "cd ios && bundle exec fastlane beta",
|
||||
"fastlane:android:build": "cd android && bundle install && bundle exec fastlane build",
|
||||
"androidBuild": "cd android && ./gradlew clean && ./gradlew assembleRelease && cd .. && echo 'find apk in android/app/build/outputs/apk/release'",
|
||||
"prepare": "husky",
|
||||
"format:check": "prettier --check .",
|
||||
"format": "prettier --write .",
|
||||
"postinstall": "patch-package"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jellyfin/sdk": "^0.11.0",
|
||||
"@react-native-community/blur": "^4.4.1",
|
||||
"@react-native-community/cli": "^15.1.3",
|
||||
"@react-native-community/netinfo": "^11.4.1",
|
||||
"@react-native-masked-view/masked-view": "^0.3.2",
|
||||
"@react-navigation/bottom-tabs": "^7.3.10",
|
||||
"@react-navigation/material-top-tabs": "^7.2.10",
|
||||
"@react-navigation/native": "^7.1.6",
|
||||
"@react-navigation/native-stack": "^7.3.10",
|
||||
"@react-navigation/stack": "^7.2.10",
|
||||
"@tamagui/config": "^1.126.1",
|
||||
"@tamagui/toast": "^1.126.1",
|
||||
"@tanstack/query-sync-storage-persister": "^5.74.6",
|
||||
"@tanstack/react-query": "^5.74.4",
|
||||
"@tanstack/react-query-persist-client": "^5.74.6",
|
||||
"@testing-library/react-native": "^13.2.0",
|
||||
"axios": "^1.8.4",
|
||||
"bundle": "^2.1.0",
|
||||
"burnt": "^0.13.0",
|
||||
"expo": "^52.0.46",
|
||||
"expo-image": "^2.0.7",
|
||||
"gem": "^2.4.3",
|
||||
"invert-color": "^2.0.0",
|
||||
"jest-expo": "^52.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"npm-bundle": "^3.0.3",
|
||||
"patch-package": "^8.0.0",
|
||||
"react": "18.3.1",
|
||||
"react-freeze": "^1.0.4",
|
||||
"react-native": "0.77.0",
|
||||
"react-native-background-actions": "^4.0.1",
|
||||
"react-native-blurhash": "^2.1.1",
|
||||
"react-native-boost": "^0.5.6",
|
||||
"react-native-carplay": "^2.4.1-beta.0",
|
||||
"react-native-device-info": "^14.0.4",
|
||||
"react-native-draggable-flatlist": "^4.0.2",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "^2.25.0",
|
||||
"react-native-haptic-feedback": "^2.3.3",
|
||||
"react-native-mmkv": "^2.12.2",
|
||||
"react-native-pager-view": "^6.7.1",
|
||||
"react-native-reanimated": "^3.17.5",
|
||||
"react-native-safe-area-context": "^5.4.0",
|
||||
"react-native-screens": "^4.10.0",
|
||||
"react-native-swipeable-item": "^2.0.9",
|
||||
"react-native-text-ticker": "^1.14.0",
|
||||
"react-native-track-player": "^4.1.1",
|
||||
"react-native-url-polyfill": "^2.0.0",
|
||||
"react-native-uuid": "^2.0.3",
|
||||
"react-native-vector-icons": "^10.2.0",
|
||||
"ruby": "^0.6.1",
|
||||
"tamagui": "^1.126.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/runtime": "^7.25.0",
|
||||
"@react-native-community/cli-platform-android": "15.1.3",
|
||||
"@react-native-community/cli-platform-ios": "15.1.3",
|
||||
"@react-native/babel-preset": "0.77.0",
|
||||
"@react-native/eslint-config": "0.77.0",
|
||||
"@react-native/metro-config": "0.77.0",
|
||||
"@react-native/typescript-config": "0.77.0",
|
||||
"@types/jest": "^29.5.13",
|
||||
"@types/lodash": "^4.17.10",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-native-vector-icons": "^6.4.18",
|
||||
"@types/react-test-renderer": "^18.3.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.29.1",
|
||||
"@typescript-eslint/parser": "^8.29.1",
|
||||
"babel-plugin-module-resolver": "^5.0.2",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^10.1.2",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-native": "^5.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^29.6.3",
|
||||
"jscodeshift": "^0.15.2",
|
||||
"lint-staged": "^15.5.0",
|
||||
"prettier": "^2.8.8",
|
||||
"react-native-cli-bump-version": "^1.5.1",
|
||||
"react-test-renderer": "18.3.1",
|
||||
"typescript": "5.7.3"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
"prettier --write",
|
||||
"eslint --fix"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ const PlayerContextInitializer = () => {
|
||||
|
||||
let playStateApi: PlaystateApi | undefined
|
||||
|
||||
if (Client.api) getPlaystateApi(Client.api)
|
||||
if (Client.api) playStateApi = getPlaystateApi(Client.api)
|
||||
|
||||
//#region State
|
||||
const [nowPlaying, setNowPlaying] = useState<JellifyTrack | undefined>(
|
||||
|
||||
@@ -157,7 +157,6 @@ const QueueContextInitailizer = () => {
|
||||
const previous = async () => {
|
||||
trigger('impactMedium')
|
||||
|
||||
setCurrentIndex(-1)
|
||||
const { position } = await TrackPlayer.getProgress()
|
||||
|
||||
console.debug(
|
||||
|
||||
Reference in New Issue
Block a user