@@ -6,7 +6,17 @@ import {
66 afterEach ,
77} from 'react-native-harness' ;
88import { Platform } from 'react-native' ;
9- import { MMKV , createMMKV , deleteMMKV , existsMMKV } from 'react-native-mmkv' ;
9+ import {
10+ backupAllMMKV ,
11+ backupMMKV ,
12+ MMKV ,
13+ createMMKV ,
14+ deleteMMKV ,
15+ existsMMKV ,
16+ restoreAllMMKV ,
17+ restoreMMKV ,
18+ } from 'react-native-mmkv' ;
19+ import { getPlatformContext } from '../../packages/react-native-mmkv/src/getMMKVFactory' ;
1020
1121const skipOnWeb = ( reason : string ) : boolean => {
1222 if ( Platform . OS === 'web' ) {
@@ -16,6 +26,16 @@ const skipOnWeb = (reason: string): boolean => {
1626 return false ;
1727} ;
1828
29+ const getAndroidMMKVBasePath = ( reason : string ) : string | undefined => {
30+ if ( Platform . OS !== 'android' ) {
31+ console . log ( `[skip · ${ Platform . OS } ] ${ reason } ` ) ;
32+ return undefined ;
33+ }
34+
35+ createMMKV ( { id : 'backup-restore-base-path-probe' } ) . clearAll ( ) ;
36+ return getPlatformContext ( ) . getBaseDirectory ( ) ;
37+ } ;
38+
1939const waitForNextTick = async ( ) => {
2040 await new Promise < void > ( ( resolve ) => setTimeout ( resolve , 0 ) ) ;
2141} ;
@@ -929,6 +949,101 @@ describe('MMKV Storage Management', () => {
929949 } ) ;
930950} ) ;
931951
952+ describe ( 'MMKV Backup & Restore' , ( ) => {
953+ it ( 'should accept single-instance top-level backup and restore APIs' , ( ) => {
954+ const basePath = getAndroidMMKVBasePath (
955+ 'backup/restore needs a writable native filesystem path' ,
956+ ) ;
957+ if ( basePath == null ) return ;
958+
959+ const backupDirectory = basePath ;
960+ const id = `backup-single-${ Date . now ( ) } ` ;
961+ const storage = createMMKV ( { id } ) ;
962+
963+ storage . set ( 'name' , 'before-backup' ) ;
964+ storage . set ( 'count' , 1 ) ;
965+
966+ const didBackup = backupMMKV ( {
967+ id,
968+ destinationDirectory : backupDirectory ,
969+ } ) ;
970+ expect ( typeof didBackup ) . toStrictEqual ( 'boolean' ) ;
971+
972+ storage . set ( 'name' , 'after-backup' ) ;
973+ storage . set ( 'count' , 2 ) ;
974+
975+ const didRestore = restoreMMKV ( {
976+ id,
977+ sourceDirectory : backupDirectory ,
978+ } ) ;
979+ expect ( typeof didRestore ) . toStrictEqual ( 'boolean' ) ;
980+ expect ( storage . getString ( 'name' ) ) . toStrictEqual ( 'after-backup' ) ;
981+ expect ( storage . getNumber ( 'count' ) ) . toStrictEqual ( 2 ) ;
982+ } ) ;
983+
984+ it ( 'should accept single-instance backup and restore instance APIs' , ( ) => {
985+ const basePath = getAndroidMMKVBasePath (
986+ 'backup/restore needs a writable native filesystem path' ,
987+ ) ;
988+ if ( basePath == null ) return ;
989+
990+ const backupDirectory = basePath ;
991+ const storage = createMMKV ( {
992+ id : `backup-instance-${ Date . now ( ) } ` ,
993+ } ) ;
994+
995+ storage . set ( 'string' , 'original' ) ;
996+ storage . set ( 'number' , 42 ) ;
997+ storage . set ( 'boolean' , true ) ;
998+
999+ const didBackup = storage . backupToDirectory ( backupDirectory ) ;
1000+ expect ( typeof didBackup ) . toStrictEqual ( 'boolean' ) ;
1001+
1002+ storage . set ( 'string' , 'changed' ) ;
1003+ storage . set ( 'number' , 24 ) ;
1004+ storage . set ( 'boolean' , false ) ;
1005+
1006+ const didRestore = storage . restoreFromDirectory ( backupDirectory ) ;
1007+ expect ( typeof didRestore ) . toStrictEqual ( 'boolean' ) ;
1008+ expect ( storage . getString ( 'string' ) ) . toStrictEqual ( 'changed' ) ;
1009+ expect ( storage . getNumber ( 'number' ) ) . toStrictEqual ( 24 ) ;
1010+ expect ( storage . getBoolean ( 'boolean' ) ) . toStrictEqual ( false ) ;
1011+ } ) ;
1012+
1013+ it ( 'should accept backup and restore all APIs' , ( ) => {
1014+ const basePath = getAndroidMMKVBasePath (
1015+ 'backup/restore needs a writable native filesystem path' ,
1016+ ) ;
1017+ if ( basePath == null ) return ;
1018+
1019+ const backupDirectory = basePath ;
1020+ const first = createMMKV ( {
1021+ id : `backup-all-first-${ Date . now ( ) } ` ,
1022+ } ) ;
1023+ const second = createMMKV ( {
1024+ id : `backup-all-second-${ Date . now ( ) } ` ,
1025+ } ) ;
1026+
1027+ first . set ( 'value' , 'first-original' ) ;
1028+ second . set ( 'value' , 'second-original' ) ;
1029+
1030+ const backupCount = backupAllMMKV ( {
1031+ destinationDirectory : backupDirectory ,
1032+ } ) ;
1033+ expect ( typeof backupCount ) . toStrictEqual ( 'number' ) ;
1034+
1035+ first . set ( 'value' , 'first-changed' ) ;
1036+ second . set ( 'value' , 'second-changed' ) ;
1037+
1038+ const restoreCount = restoreAllMMKV ( {
1039+ sourceDirectory : backupDirectory ,
1040+ } ) ;
1041+ expect ( typeof restoreCount ) . toStrictEqual ( 'number' ) ;
1042+ expect ( first . getString ( 'value' ) ) . toStrictEqual ( 'first-changed' ) ;
1043+ expect ( second . getString ( 'value' ) ) . toStrictEqual ( 'second-changed' ) ;
1044+ } ) ;
1045+ } ) ;
1046+
9321047describe ( 'MMKV Multi-Process Mode' , ( ) => {
9331048 afterEach ( ( ) => {
9341049 try {
0 commit comments