@iterable/react-native-sdk
Version:
Iterable SDK for React Native.
438 lines (403 loc) • 11.6 kB
JavaScript
"use strict";
import { renderHook, act } from '@testing-library/react-native';
import { useDeviceOrientation } from "./useDeviceOrientation.js";
describe('useDeviceOrientation', () => {
let useWindowDimensionsSpy;
beforeEach(() => {
jest.clearAllMocks();
// Spy on useWindowDimensions
useWindowDimensionsSpy = jest.spyOn(require('react-native'), 'useWindowDimensions');
});
afterEach(() => {
useWindowDimensionsSpy.mockRestore();
});
describe('initial state', () => {
it('should return portrait orientation for portrait screen dimensions', () => {
// GIVEN screen dimensions in portrait mode
useWindowDimensionsSpy.mockReturnValue({
height: 800,
width: 400,
scale: 1,
fontScale: 1
});
// WHEN the hook is rendered
const {
result
} = renderHook(() => useDeviceOrientation());
// THEN it should return portrait orientation
expect(result.current).toEqual({
height: 800,
width: 400,
isPortrait: true
});
});
it('should return landscape orientation for landscape screen dimensions', () => {
// GIVEN screen dimensions in landscape mode
useWindowDimensionsSpy.mockReturnValue({
height: 400,
width: 800,
scale: 1,
fontScale: 1
});
// WHEN the hook is rendered
const {
result
} = renderHook(() => useDeviceOrientation());
// THEN it should return landscape orientation
expect(result.current).toEqual({
height: 400,
width: 800,
isPortrait: false
});
});
it('should return portrait orientation for square screen dimensions', () => {
// GIVEN square screen dimensions (height >= width should be portrait)
useWindowDimensionsSpy.mockReturnValue({
height: 500,
width: 500,
scale: 1,
fontScale: 1
});
// WHEN the hook is rendered
const {
result
} = renderHook(() => useDeviceOrientation());
// THEN it should return portrait orientation
expect(result.current).toEqual({
height: 500,
width: 500,
isPortrait: true
});
});
it('should handle edge case where height is slightly larger than width', () => {
// GIVEN screen dimensions where height is slightly larger
useWindowDimensionsSpy.mockReturnValue({
height: 401,
width: 400,
scale: 1,
fontScale: 1
});
// WHEN the hook is rendered
const {
result
} = renderHook(() => useDeviceOrientation());
// THEN it should return portrait orientation
expect(result.current).toEqual({
height: 401,
width: 400,
isPortrait: true
});
});
});
describe('orientation changes', () => {
it('should update orientation when screen rotates from portrait to landscape', () => {
// GIVEN initial portrait dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 800,
width: 400,
scale: 1,
fontScale: 1
});
const {
result,
rerender
} = renderHook(() => useDeviceOrientation());
// THEN initial state should be portrait
expect(result.current.isPortrait).toBe(true);
// WHEN screen rotates to landscape
useWindowDimensionsSpy.mockReturnValue({
height: 400,
width: 800,
scale: 1,
fontScale: 1
});
act(() => {
rerender(() => useDeviceOrientation());
});
// THEN orientation should update to landscape
expect(result.current).toEqual({
height: 400,
width: 800,
isPortrait: false
});
});
it('should update orientation when screen rotates from landscape to portrait', () => {
// GIVEN initial landscape dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 400,
width: 800,
scale: 1,
fontScale: 1
});
const {
result,
rerender
} = renderHook(() => useDeviceOrientation());
// THEN initial state should be landscape
expect(result.current.isPortrait).toBe(false);
// WHEN screen rotates to portrait
useWindowDimensionsSpy.mockReturnValue({
height: 800,
width: 400,
scale: 1,
fontScale: 1
});
act(() => {
rerender(() => useDeviceOrientation());
});
// THEN orientation should update to portrait
expect(result.current).toEqual({
height: 800,
width: 400,
isPortrait: true
});
});
it('should handle multiple orientation changes', () => {
// GIVEN initial portrait dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 800,
width: 400,
scale: 1,
fontScale: 1
});
const {
result,
rerender
} = renderHook(() => useDeviceOrientation());
// THEN initial state should be portrait
expect(result.current.isPortrait).toBe(true);
// WHEN rotating to landscape
useWindowDimensionsSpy.mockReturnValue({
height: 400,
width: 800,
scale: 1,
fontScale: 1
});
act(() => {
rerender(() => useDeviceOrientation());
});
expect(result.current.isPortrait).toBe(false);
// WHEN rotating back to portrait
useWindowDimensionsSpy.mockReturnValue({
height: 800,
width: 400,
scale: 1,
fontScale: 1
});
act(() => {
rerender(() => useDeviceOrientation());
});
expect(result.current.isPortrait).toBe(true);
// WHEN rotating to landscape again
useWindowDimensionsSpy.mockReturnValue({
height: 400,
width: 800,
scale: 1,
fontScale: 1
});
act(() => {
rerender(() => useDeviceOrientation());
});
expect(result.current.isPortrait).toBe(false);
});
});
describe('edge cases', () => {
it('should handle zero dimensions', () => {
// GIVEN zero dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 0,
width: 0,
scale: 1,
fontScale: 1
});
// WHEN the hook is rendered
const {
result
} = renderHook(() => useDeviceOrientation());
// THEN it should return portrait (height >= width)
expect(result.current).toEqual({
height: 0,
width: 0,
isPortrait: true
});
});
it('should handle very large dimensions', () => {
// GIVEN very large dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 10000,
width: 5000,
scale: 1,
fontScale: 1
});
// WHEN the hook is rendered
const {
result
} = renderHook(() => useDeviceOrientation());
// THEN it should return portrait
expect(result.current).toEqual({
height: 10000,
width: 5000,
isPortrait: true
});
});
it('should handle negative dimensions', () => {
// GIVEN negative dimensions (edge case)
useWindowDimensionsSpy.mockReturnValue({
height: -100,
width: -200,
scale: 1,
fontScale: 1
});
// WHEN the hook is rendered
const {
result
} = renderHook(() => useDeviceOrientation());
// THEN it should return landscape (height >= width, -100 >= -200)
expect(result.current).toEqual({
height: -100,
width: -200,
isPortrait: true
});
});
it('should handle decimal dimensions', () => {
// GIVEN decimal dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 800.5,
width: 400.3,
scale: 1,
fontScale: 1
});
// WHEN the hook is rendered
const {
result
} = renderHook(() => useDeviceOrientation());
// THEN it should return portrait
expect(result.current).toEqual({
height: 800.5,
width: 400.3,
isPortrait: true
});
});
});
describe('hook behavior', () => {
it('should maintain consistent state across re-renders with same dimensions', () => {
// GIVEN consistent dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 800,
width: 400,
scale: 1,
fontScale: 1
});
const {
result,
rerender
} = renderHook(() => useDeviceOrientation());
const initialResult = result.current;
// WHEN component re-renders with same dimensions
act(() => {
rerender(() => useDeviceOrientation());
});
// THEN state should remain consistent
expect(result.current).toEqual(initialResult);
});
it('should return new object reference when dimensions change', () => {
// GIVEN initial dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 800,
width: 400,
scale: 1,
fontScale: 1
});
const {
result,
rerender
} = renderHook(() => useDeviceOrientation());
const initialResult = result.current;
// WHEN dimensions change
useWindowDimensionsSpy.mockReturnValue({
height: 400,
width: 800,
scale: 1,
fontScale: 1
});
act(() => {
rerender(() => useDeviceOrientation());
});
// THEN new object reference should be returned
expect(result.current).not.toBe(initialResult);
expect(result.current).toEqual({
height: 400,
width: 800,
isPortrait: false
});
});
it('should handle rapid dimension changes', () => {
// GIVEN initial dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 800,
width: 400,
scale: 1,
fontScale: 1
});
const {
result,
rerender
} = renderHook(() => useDeviceOrientation());
// WHEN rapid dimension changes occur
const dimensions = [{
height: 400,
width: 800
},
// landscape
{
height: 800,
width: 400
},
// portrait
{
height: 600,
width: 600
},
// square
{
height: 300,
width: 900
} // landscape
];
dimensions.forEach(dim => {
useWindowDimensionsSpy.mockReturnValue({
...dim,
scale: 1,
fontScale: 1
});
act(() => {
rerender(() => useDeviceOrientation());
});
expect(result.current.height).toBe(dim.height);
expect(result.current.width).toBe(dim.width);
expect(result.current.isPortrait).toBe(dim.height >= dim.width);
});
});
});
describe('type safety', () => {
it('should return correct IterableDeviceOrientation interface', () => {
// GIVEN screen dimensions
useWindowDimensionsSpy.mockReturnValue({
height: 800,
width: 400,
scale: 1,
fontScale: 1
});
// WHEN the hook is rendered
const {
result
} = renderHook(() => useDeviceOrientation());
// THEN it should match the interface
const orientation = result.current;
expect(typeof orientation.height).toBe('number');
expect(typeof orientation.width).toBe('number');
expect(typeof orientation.isPortrait).toBe('boolean');
});
});
});
//# sourceMappingURL=useDeviceOrientation.test.js.map