This commit is contained in:
Ryanba 2026-04-21 08:38:05 +08:00 committed by GitHub
commit f34a890d60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 44 deletions

View file

@ -1,5 +1,6 @@
// usePoseStream is a React hook that uses useEffect, zustand stores, and wsService.
// We test its interface shape and the module export.
import React from 'react';
import { Text } from 'react-native';
import { render, screen } from '@testing-library/react-native';
jest.mock('@/services/ws.service', () => ({
wsService: {
@ -10,36 +11,43 @@ jest.mock('@/services/ws.service', () => ({
},
}));
import { usePoseStream } from '@/hooks/usePoseStream';
import { usePoseStore } from '@/stores/poseStore';
const HookConsumer = () => {
const { connectionStatus, lastFrame, isSimulated } = usePoseStream();
return React.createElement(
React.Fragment,
null,
React.createElement(Text, { testID: 'status' }, connectionStatus),
React.createElement(Text, { testID: 'simulated' }, String(isSimulated)),
React.createElement(Text, { testID: 'frame' }, lastFrame ? 'present' : 'none'),
);
};
describe('usePoseStream', () => {
beforeEach(() => {
usePoseStore.getState().reset();
});
it('module exports usePoseStream function', () => {
const mod = require('@/hooks/usePoseStream');
expect(typeof mod.usePoseStream).toBe('function');
});
it('exports UsePoseStreamResult interface (module shape)', () => {
// Verify the module has the expected named exports
const mod = require('@/hooks/usePoseStream');
expect(mod).toHaveProperty('usePoseStream');
});
it('usePoseStream has the expected return type shape', () => {
// We cannot call hooks outside of React components, but we can verify
// the store provides the data the hook returns.
const state = usePoseStore.getState();
expect(state).toHaveProperty('connectionStatus');
expect(state).toHaveProperty('lastFrame');
expect(state).toHaveProperty('isSimulated');
});
it('wsService.subscribe is callable', () => {
const { wsService } = require('@/services/ws.service');
const unsub = wsService.subscribe(jest.fn());
expect(typeof unsub).toBe('function');
wsService.subscribe.mockClear();
wsService.connect.mockClear();
});
it('returns the expected store-backed values', () => {
render(React.createElement(HookConsumer));
expect(screen.getByTestId('status').props.children).toBe('disconnected');
expect(screen.getByTestId('simulated').props.children).toBe('false');
expect(screen.getByTestId('frame').props.children).toBe('none');
});
it('does not subscribe or reconnect on render', () => {
const { wsService } = require('@/services/ws.service');
render(React.createElement(HookConsumer));
expect(wsService.subscribe).not.toHaveBeenCalled();
expect(wsService.connect).not.toHaveBeenCalled();
});
});

View file

@ -1,7 +1,4 @@
import { useEffect } from 'react';
import { wsService } from '@/services/ws.service';
import { usePoseStore } from '@/stores/poseStore';
import { useSettingsStore } from '@/stores/settingsStore';
export interface UsePoseStreamResult {
connectionStatus: ReturnType<typeof usePoseStore.getState>['connectionStatus'];
@ -13,20 +10,6 @@ export function usePoseStream(): UsePoseStreamResult {
const connectionStatus = usePoseStore((state) => state.connectionStatus);
const lastFrame = usePoseStore((state) => state.lastFrame);
const isSimulated = usePoseStore((state) => state.isSimulated);
const serverUrl = useSettingsStore((state) => state.serverUrl);
useEffect(() => {
const unsubscribe = wsService.subscribe((frame) => {
usePoseStore.getState().handleFrame(frame);
});
// Auto-connect to sensing server on mount
wsService.connect(serverUrl);
return () => {
unsubscribe();
};
}, [serverUrl]);
return { connectionStatus, lastFrame, isSimulated };
}