Skip to content

Commit 4a0956e

Browse files
committed
Add fromBytes, RiveImages, log level, and view method tests (#275)
Adds 7 new tests covering previously untested native code paths: - **fromBytes**: load .riv from raw ArrayBuffer (HybridRiveFileFactory) - **RiveImages.loadFromURLAsync**: load image and verify byteSize (HybridRiveImageFactory + HybridRiveImage) - **RiveLog.setLogLevel**: exercise all 4 log levels (HybridRiveLogger) - **RiveView pause/play/reset**: exercise view control methods with a rendered RiveView (HybridRiveView)
1 parent dc88ec9 commit 4a0956e

2 files changed

Lines changed: 128 additions & 1 deletion

File tree

example/__tests__/rive.harness.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, it, expect } from 'react-native-harness';
22
import { Platform } from 'react-native';
3-
import { RiveFileFactory } from '@rive-app/react-native';
3+
import { RiveFileFactory, RiveImages, RiveLog } from '@rive-app/react-native';
44

55
const QUICK_START = require('../assets/rive/quick_start.riv');
66
const VIEWMODEL = require('../assets/rive/viewmodelproperty.riv');
@@ -20,6 +20,18 @@ describe('RiveFile Loading', () => {
2020
expect(file).toBeDefined();
2121
expect(file.artboardNames.length).toBeGreaterThan(0);
2222
});
23+
24+
it('fromBytes works', async () => {
25+
// Load the file first via fromSource, then get the URL and fetch raw bytes
26+
// Simpler: use fromURL to get a known .riv, then re-load via fromBytes
27+
const response = await fetch(
28+
'https://cdn.rive.app/animations/vehicles.riv'
29+
);
30+
const bytes = await response.arrayBuffer();
31+
const file = await RiveFileFactory.fromBytes(bytes, undefined);
32+
expect(file).toBeDefined();
33+
expect(file.artboardNames.length).toBeGreaterThan(0);
34+
});
2335
});
2436

2537
describe('ViewModel', () => {
@@ -76,3 +88,22 @@ describe('ViewModel', () => {
7688
expect(val).toBe(testValue);
7789
});
7890
});
91+
92+
describe('RiveImages', () => {
93+
it('loadFromURLAsync loads an image', async () => {
94+
const image = await RiveImages.loadFromURLAsync(
95+
'https://picsum.photos/id/237/100/100'
96+
);
97+
expect(image).toBeDefined();
98+
expect(image.byteSize).toBeGreaterThan(0);
99+
});
100+
});
101+
102+
describe('RiveLog.setLogLevel', () => {
103+
it('setLogLevel does not throw for valid levels', () => {
104+
expect(() => RiveLog.setLogLevel('debug')).not.toThrow();
105+
expect(() => RiveLog.setLogLevel('info')).not.toThrow();
106+
expect(() => RiveLog.setLogLevel('warn')).not.toThrow();
107+
expect(() => RiveLog.setLogLevel('error')).not.toThrow();
108+
});
109+
});
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import {
2+
describe,
3+
it,
4+
expect,
5+
render,
6+
waitFor,
7+
cleanup,
8+
} from 'react-native-harness';
9+
import { useEffect } from 'react';
10+
import { View } from 'react-native';
11+
import {
12+
RiveView,
13+
RiveFileFactory,
14+
Fit,
15+
type RiveFile,
16+
type RiveViewRef,
17+
} from '@rive-app/react-native';
18+
19+
const BOUNCING_BALL = require('../assets/rive/bouncing_ball.riv');
20+
21+
type TestContext = {
22+
ref: RiveViewRef | null;
23+
error: string | null;
24+
};
25+
26+
function SimpleRiveView({
27+
file,
28+
context,
29+
}: {
30+
file: RiveFile;
31+
context: TestContext;
32+
}) {
33+
useEffect(() => {
34+
return () => {
35+
context.ref = null;
36+
};
37+
}, [context]);
38+
39+
return (
40+
<View style={{ width: 200, height: 200 }}>
41+
<RiveView
42+
hybridRef={{
43+
f: (ref: RiveViewRef | null) => {
44+
context.ref = ref;
45+
},
46+
}}
47+
style={{ flex: 1 }}
48+
file={file}
49+
autoPlay={true}
50+
fit={Fit.Contain}
51+
onError={(e) => {
52+
context.error = e.message;
53+
}}
54+
/>
55+
</View>
56+
);
57+
}
58+
59+
describe('RiveView methods', () => {
60+
it('pause() does not throw', async () => {
61+
const file = await RiveFileFactory.fromSource(BOUNCING_BALL, undefined);
62+
const context: TestContext = { ref: null, error: null };
63+
64+
await render(<SimpleRiveView file={file} context={context} />);
65+
await waitFor(() => expect(context.ref).not.toBeNull(), { timeout: 5000 });
66+
67+
await context.ref!.pause();
68+
expect(context.error).toBeNull();
69+
cleanup();
70+
});
71+
72+
it('play() after pause() does not throw', async () => {
73+
const file = await RiveFileFactory.fromSource(BOUNCING_BALL, undefined);
74+
const context: TestContext = { ref: null, error: null };
75+
76+
await render(<SimpleRiveView file={file} context={context} />);
77+
await waitFor(() => expect(context.ref).not.toBeNull(), { timeout: 5000 });
78+
79+
await context.ref!.pause();
80+
await context.ref!.play();
81+
expect(context.error).toBeNull();
82+
cleanup();
83+
});
84+
85+
it('reset() does not throw', async () => {
86+
const file = await RiveFileFactory.fromSource(BOUNCING_BALL, undefined);
87+
const context: TestContext = { ref: null, error: null };
88+
89+
await render(<SimpleRiveView file={file} context={context} />);
90+
await waitFor(() => expect(context.ref).not.toBeNull(), { timeout: 5000 });
91+
92+
await context.ref!.reset();
93+
expect(context.error).toBeNull();
94+
cleanup();
95+
});
96+
});

0 commit comments

Comments
 (0)