feat: add AsyncStorage package and helpers

merge-requests/10/head
Torpenn 2024-10-13 23:17:48 +02:00
parent 1e9cfad86a
commit 397c14d590
4 changed files with 120 additions and 0 deletions

View File

@ -0,0 +1,21 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
export const saveUserSettings = async (key: string, value: string) => {
try {
await AsyncStorage.setItem(key, value);
} catch (e) {
throw new Error('Failed to load the data from AsyncStorage');
}
};
export const loadUserSettings = async (key: string) => {
try {
const value = await AsyncStorage.getItem(key);
if (value !== null) {
return value;
}
} catch (e) {
throw new Error('Failed to load the data from AsyncStorage');
}
};

View File

@ -0,0 +1,64 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import { saveUserSettings, loadUserSettings } from '../AsyncStorage';
// Mock de AsyncStorage
jest.mock('@react-native-async-storage/async-storage', () => ({
setItem: jest.fn(),
getItem: jest.fn(),
}));
describe('UserSettings functions', () => {
afterEach(() => {
jest.clearAllMocks();
});
describe('saveUserSettings', () => {
test('should save data to AsyncStorage', async () => {
const key = 'theme';
const value = 'dark';
await saveUserSettings(key, value);
expect(AsyncStorage.setItem).toHaveBeenCalledWith(key, value);
});
test('should throw an error if AsyncStorage.setItem fails', async () => {
AsyncStorage.setItem.mockRejectedValueOnce(new Error('AsyncStorage error'));
await expect(saveUserSettings('theme', 'dark')).rejects.toThrow(
'Failed to load the data from AsyncStorage'
);
});
});
describe('loadUserSettings', () => {
test('should load data from AsyncStorage', async () => {
const key = 'theme';
const value = 'dark';
AsyncStorage.getItem.mockResolvedValueOnce(value);
const result = await loadUserSettings(key);
expect(result).toBe(value);
expect(AsyncStorage.getItem).toHaveBeenCalledWith(key);
});
test('should return null if the value does not exist in AsyncStorage', async () => {
AsyncStorage.getItem.mockResolvedValueOnce(null);
const result = await loadUserSettings('nonexistent_key');
expect(result).toBeUndefined();
});
test('should throw an error if AsyncStorage.getItem fails', async () => {
AsyncStorage.getItem.mockRejectedValueOnce(new Error('AsyncStorage error'));
await expect(loadUserSettings('theme')).rejects.toThrow(
'Failed to load the data from AsyncStorage'
);
});
});
});

34
package-lock.json generated
View File

@ -11,6 +11,7 @@
"@emotion/native": "^11.11.0", "@emotion/native": "^11.11.0",
"@emotion/react": "^11.13.3", "@emotion/react": "^11.13.3",
"@expo/vector-icons": "^14.0.2", "@expo/vector-icons": "^14.0.2",
"@react-native-async-storage/async-storage": "^2.0.0",
"@react-native-picker/picker": "2.7.5", "@react-native-picker/picker": "2.7.5",
"@react-navigation/native": "^6.0.2", "@react-navigation/native": "^6.0.2",
"@testing-library/react-native": "^12.7.2", "@testing-library/react-native": "^12.7.2",
@ -5085,6 +5086,18 @@
"react": "^16.8 || ^17.0 || ^18.0" "react": "^16.8 || ^17.0 || ^18.0"
} }
}, },
"node_modules/@react-native-async-storage/async-storage": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-2.0.0.tgz",
"integrity": "sha512-af6H9JjfL6G/PktBfUivvexoiFKQTJGQCtSWxMdivLzNIY94mu9DdiY0JqCSg/LyPCLGKhHPUlRQhNvpu3/KVA==",
"license": "MIT",
"dependencies": {
"merge-options": "^3.0.4"
},
"peerDependencies": {
"react-native": "^0.0.0-0 || >=0.65 <1.0"
}
},
"node_modules/@react-native-community/cli": { "node_modules/@react-native-community/cli": {
"version": "13.6.9", "version": "13.6.9",
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-13.6.9.tgz", "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-13.6.9.tgz",
@ -14133,6 +14146,15 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/is-plain-object": { "node_modules/is-plain-object": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -17793,6 +17815,18 @@
"integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==", "integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==",
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/merge-options": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz",
"integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==",
"license": "MIT",
"dependencies": {
"is-plain-obj": "^2.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/merge-stream": { "node_modules/merge-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",

View File

@ -27,6 +27,7 @@
"@emotion/native": "^11.11.0", "@emotion/native": "^11.11.0",
"@emotion/react": "^11.13.3", "@emotion/react": "^11.13.3",
"@expo/vector-icons": "^14.0.2", "@expo/vector-icons": "^14.0.2",
"@react-native-async-storage/async-storage": "^2.0.0",
"@react-native-picker/picker": "2.7.5", "@react-native-picker/picker": "2.7.5",
"@react-navigation/native": "^6.0.2", "@react-navigation/native": "^6.0.2",
"@testing-library/react-native": "^12.7.2", "@testing-library/react-native": "^12.7.2",