Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
SBub committed Sep 23, 2021
2 parents 0922106 + 560baf2 commit a18fae3
Show file tree
Hide file tree
Showing 106 changed files with 2,393 additions and 1,799 deletions.
18 changes: 7 additions & 11 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ module.exports = {
'prefer-const': ['error'],
semi: ['error', 'never'],
'use-isnan': ['error'],
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
'@typescript-eslint/array-type': ['error', 'array-simple'],
'@typescript-eslint/ban-types': [
'error',
{
Expand All @@ -54,27 +54,23 @@ module.exports = {
],
'react/jsx-uses-vars': ['warn'],
// PascalCase for classes
'@typescript-eslint/class-name-casing': ['off'],
'@typescript-eslint/class-name-casing': ['error'],
// don't prefix interface names with 'I'
'@typescript-eslint/interface-name-prefix': ['off'],
'@typescript-eslint/interface-name-prefix': ['error', 'never'],
// don't conflict <Types> and JSX
'@typescript-eslint/no-angle-bracket-type-assertion': ['off'],
'@typescript-eslint/no-angle-bracket-type-assertion': ['error'],
// lose out on typing benefits with any
'@typescript-eslint/no-explicit-any': ['error'],
'@typescript-eslint/no-empty-interface': ['off'],
'@typescript-eslint/no-inferrable-types': ['error'],
// namespaces and modules are outdated, use ES6 style
'@typescript-eslint/no-namespace': ['error'],
// use ES6-style imports instead
'@typescript-eslint/no-triple-slash-reference': ['off'],
'@typescript-eslint/no-triple-slash-reference': ['error'],
'@typescript-eslint/no-var-requires': ['off'],
'@typescript-eslint/no-use-before-define': ['off'],
'@typescript-eslint/explicit-function-return-type': ['off'],
'import/no-duplicates': ['off'],
'import/no-duplicates': ['error'],
},
ignorePatterns: [
'package.json',
'jest.config.js',
'app.json',
],
ignorePatterns: ['package.json', 'jest.config.js', 'app.json'],
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# Sentry auth
sentry.properties
sentry-auth/

# Secrets
android-secrets/
ios-certificates
appcenter-secrets
report.xml
.bundle/
vendor/
poeditor-key/
key.json

# App connect keys
app-store-connect-auth
Expand Down
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
Jolocom SmartWallet - An application to manage your digital identity.

Interested in our vision? Take a look at our [whitepaper](https://jolocom.io/wp-content/uploads/2019/12/Jolocom-Whitepaper-v2.1-A-Decentralized-Open-Source-Solution-for-Digital-Identity-and-Access-Management.pdf).

[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/jolocom/SmartWallet)

## Prerequisites

- Set-up requires [Node.js](https://nodejs.org/en/download/) to be installed on your computer.
- The Jolocom SmartWallet requires `Node.js v12+` to build the project. You can either manually install Node version above 12, or you can delegate it to `Volta` (follow [this link](https://docs.volta.sh/guide/getting-started) to install `Volta`). Node `12.4.1` is pinned to the project
- We use [Yarn](https://yarnpkg.com) as our package manager.
- We use [CocoaPods](https://cocoapods.org/) for `iOS` dependency management.

## Installation

1. Clone the repository to a directory of your choice.
2. `cd` into the cloned repo and run `yarn` from your terminal to install the required depencencies .

### Running a debug version for development

#### Android

3. Please set up an Android development environment and install the required SDKs.
- The [Getting Started](https://facebook.github.io/react-native/docs/getting-started) guide for React Native may come in handy.
- Look for the instructions under React Native CLI Quickstart.
4. Connect an Android device and enable USB debugging **OR** start an Android AVD emulator
5. Run `yarn android` to install the application and run it.
- NOTE: this will start a metro bundler server automatically, with stdout/stderr discarded. You can close this and run `yarn start` to manually start the bundler and receive more detailed output.

### iOS

3. Please set up an appropriate Xcode development environment.
- The [Getting Started](https://facebook.github.io/react-native/docs/getting-started) guide for React Native may come in handy.
- Look for the instructions under React Native CLI Quickstart.
4. `cd` into the `ios` folder, and install the native dependencies using the `pod install` command.
5. Run `yarn ios` to install and run the application in an emulator.
- This will default to an iPhone X emulator.
- The device can be specified by adding `--simulator` and the device name.
- e.g. `yarn ios --simulator "iPhone SE"`
- `NOTE`: this will start a metro bundler server automatically, with stdout/stderr discarded. You can close this and run `yarn start` to manually start the bundler and receive more detailed output.
- `NOTE`: A debug build can also be built through Xcode.

Running a build on a physical device requires the appropriate code signing certificates.

## Testing
We use Jest + [React Native Testing Library](https://testing-library.com/docs/react-native-testing-library/intro/) for unit testing.

To run unit tests with watch and testing coverage:
```bash
yarn test --watch --coverage
```
## Code Style and Formatting

- We use [ESLint](https://eslint.org/) and [Prettier](https://prettier.io/) to keep a consistent style across the codebase.
- There are plugins available for a range of IDEs and text editors; automatic formatting on save is also supported in some editors.
- Check the `yarn lint:fix` and `yarn prettier:format` scripts.

Copyright (C) 2014-2019 JOLOCOM GmbH


15 changes: 14 additions & 1 deletion __tests__/suits/Form/CredentialForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useRoute } from '@react-navigation/native'
import { renderWithSafeArea } from '../../utils/renderWithSafeArea'
import { AttributeTypes, ClaimKeys } from '~/types/credentials'
import { mockSelectorReturn } from '../../mocks/libs/react-redux'
import { fireEvent, waitFor } from '@testing-library/react-native'
import { act, fireEvent, waitFor } from '@testing-library/react-native'
import { editAttr, updateAttrs } from '~/modules/attributes/actions'
import { getMockedDispatch } from '../../mocks/libs/react-redux'
import { mockedAgent } from '../../mocks/agent'
Expand Down Expand Up @@ -51,6 +51,19 @@ jest.mock('../../../src/hooks/sdk', () => ({

const renderCredentialForm = () => {
const queries = renderWithSafeArea(<CredentialForm />)
const headerContainer = queries.getByTestId('collapsable-header-container')

// NOTE: The @Collapsible renders the scroll content only if the header has registered
// the layout
act(() => {
fireEvent(headerContainer, 'onLayout', {
nativeEvent: {
layout: {
height: 100,
},
},
})
})

const emailInput = queries.getByTestId('credential-form-input')
expect(emailInput).toBeDefined()
Expand Down
1 change: 1 addition & 0 deletions __tests__/suits/History/RecordAssembler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const genericOfferArgs = {
...buildSummary({
offerSummary: [{ type: 'test-type', credential: { name: 'test-name' } }],
issued: [{ type: 'test-type', name: 'test-name' }],
credentialsValidity: [true, true],
}),
flowType: FlowType.CredentialOffer,
messageTypes: [
Expand Down
39 changes: 18 additions & 21 deletions __tests__/suits/LocalDeviceAuth/ChangePin.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { waitFor } from '@testing-library/react-native'
import React from 'react'
import * as keychain from 'react-native-keychain'
import { SecureStorage } from 'react-native-jolocom'
import ChangePin from '~/screens/LoggedIn/Settings/ChangePin'
import { strings } from '~/translations'
import { PIN_SERVICE, PIN_USERNAME } from '~/utils/keychainConsts'
import { renderWithSafeArea } from '../../utils/renderWithSafeArea'
import { inputPasscode } from '../../utils/inputPasscode'
import { SecureStorageKeys } from '~/hooks/secureStorage'

const mockNavigation = jest.fn()
const mockNavigationBack = jest.fn()
Expand All @@ -19,12 +19,12 @@ jest.mock('@react-navigation/native', () => ({
}),
}))

jest.mock('react-native-keychain', () => ({
STORAGE_TYPE: {
AES: 'aes',
jest.mock('react-native-jolocom', () => ({
SecureStorage: {
storeValue: jest.fn(),
getValue: jest.fn().mockResolvedValue(null),
removeValue: jest.fn(),
},
setGenericPassword: jest.fn(),
getGenericPassword: jest.fn().mockResolvedValue({ password: '5555' }),
}))

jest.mock('../../../src/hooks/sdk', () => ({
Expand All @@ -47,14 +47,11 @@ jest.mock('../../../src/hooks/loader', () => ({
useLoader: jest
.fn()
.mockImplementation(
() => async (
cb: () => Promise<void>,
_: object,
onSuccess: () => void,
) => {
await cb()
onSuccess()
},
() =>
async (cb: () => Promise<void>, _: object, onSuccess: () => void) => {
await cb()
onSuccess()
},
),
}))

Expand All @@ -65,7 +62,7 @@ jest.mock('../../../src/hooks/navigation', () => ({

xdescribe('Change passcode', () => {
it('should successfully change the passcode', async () => {
const setGenericPasswordSpy = jest.spyOn(keychain, 'setGenericPassword')
const setEncryptedPasswordSpy = jest.spyOn(SecureStorage, 'storeValue')

const { getByText, getByTestId } = await waitFor(() =>
renderWithSafeArea(<ChangePin />),
Expand All @@ -88,11 +85,11 @@ xdescribe('Change passcode', () => {
inputPasscode(getByTestId, [3, 3, 3, 3])

await waitFor(() => {
expect(setGenericPasswordSpy).toHaveBeenCalledTimes(1)
expect(setGenericPasswordSpy).toHaveBeenCalledWith(PIN_USERNAME, '3333', {
service: PIN_SERVICE,
storage: keychain.STORAGE_TYPE.AES,
})
expect(setEncryptedPasswordSpy).toHaveBeenCalledTimes(1)
expect(setEncryptedPasswordSpy).toHaveBeenCalledWith(
SecureStorageKeys.passcode,
'3333',
)
})
})

Expand Down
10 changes: 5 additions & 5 deletions __tests__/suits/LocalDeviceAuth/Lock.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ describe('Without biometry', () => {
isBiometrySelected: false,
})
})
test('Lock screen renders all necessary UI details', () => {
xtest('Lock screen renders all necessary UI details', () => {
const { getByText, getByTestId } = renderWithSafeArea(<Lock />)

mockGetBiometry.mockResolvedValue(undefined)
Expand All @@ -81,7 +81,7 @@ describe('Without biometry', () => {
expect(getByTestId('passcode-keyboard')).toBeDefined()
})

test("The app is locked if pins don't match", async () => {
xtest("The app is locked if pins don't match", async () => {
const { getByText, getByTestId } = renderWithSafeArea(<Lock />)

inputPasscode(getByTestId, [3, 3, 3, 3])
Expand All @@ -91,7 +91,7 @@ describe('Without biometry', () => {
})
})

test('The app is unlocked', () => {
xtest('The app is unlocked', () => {
const useDispatchSpy = jest.spyOn(redux, 'useDispatch')
const mockDispatchFn = jest.fn()
useDispatchSpy.mockReturnValue(mockDispatchFn)
Expand Down Expand Up @@ -119,7 +119,7 @@ describe('With biometry', () => {
})
})

test('unlocks the app', async () => {
xtest('unlocks the app', async () => {
mockBiometryAuthenticate.mockResolvedValue({
success: true,
})
Expand All @@ -140,7 +140,7 @@ describe('With biometry', () => {
})
})

test('do not unlock the app', async () => {
xtest('do not unlock the app', async () => {
mockBiometryAuthenticate.mockResolvedValue({
success: false,
})
Expand Down
38 changes: 26 additions & 12 deletions __tests__/suits/LocalDeviceAuth/RegisterPin.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react'
import { waitFor } from '@testing-library/react-native'
import { setGenericPassword, STORAGE_TYPE } from 'react-native-keychain'
import { SecureStorage } from 'react-native-jolocom'

import RegisterPin from '~/screens/Modals/DeviceAuthentication/RegisterPin'
import { renderWithSafeArea } from '../../utils/renderWithSafeArea'
import { PIN_USERNAME, PIN_SERVICE } from '~/utils/keychainConsts'
import { inputPasscode } from '../../utils/inputPasscode'
import { SecureStorageKeys } from '~/hooks/secureStorage'

const mockNavigation = jest.fn()
const mockNavigationBack = jest.fn()
Expand All @@ -27,16 +27,30 @@ jest.mock('react-redux', () => ({
useDispatch: () => mockedDispatch,
}))

jest.mock('react-native-keychain', () => ({
STORAGE_TYPE: {
AES: 'aes',
jest.mock('react-native-jolocom', () => ({
SecureStorage: {
storeValue: jest.fn(),
getValue: jest.fn().mockResolvedValue(null),
removeValue: jest.fn(),
},
setGenericPassword: jest.fn(() => Promise.resolve(true)),
resetGenericPassword: jest.fn(() => Promise.resolve(true)),
}))

jest.mock('@react-navigation/native', () => ({
useIsFocused: jest.fn().mockReturnValue(true),
useNavigation: () => ({
navigate: jest.fn(),
}),
createNavigatorFactory: jest.fn(),
}))

jest.mock('../../../src/hooks/settings', () => () => ({
get: jest.fn(),
set: jest.fn(),
}))

describe('Register Passcode', () => {
it('User is able to set up pin', async () => {
const setEncryptedPasswordSpy = jest.spyOn(SecureStorage, 'storeValue')
const { getByText, getByTestId, queryByText } = renderWithSafeArea(
<RegisterPin />,
)
Expand All @@ -59,10 +73,10 @@ describe('Register Passcode', () => {

inputPasscode(getByTestId, [1, 1, 1, 1])

expect(setGenericPassword).toHaveBeenCalledTimes(1)
expect(setGenericPassword).toHaveBeenCalledWith(PIN_USERNAME, '1111', {
service: PIN_SERVICE,
storage: STORAGE_TYPE.AES,
})
expect(setEncryptedPasswordSpy).toHaveBeenCalledTimes(1)
expect(setEncryptedPasswordSpy).toHaveBeenCalledWith(
SecureStorageKeys.passcode,
'1111',
)
})
})
11 changes: 11 additions & 0 deletions __tests__/suits/LoggedOut/Recovery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ jest.mock('../../../src/hooks/sdk.ts', () => ({
}),
}))

jest.mock('../../../src/hooks/settings', () => () => ({
get: jest.fn(),
set: jest.fn(),
}))

jest.mock('../../../src/hooks/toasts', () => ({
useToasts: () => ({
scheduleErrorWarning: jest.fn(),
}),
}))

describe('User on a Recovery screen', () => {
test('sees screen with initial state', () => {
const useDispatchSpy = jest.spyOn(redux, 'useDispatch')
Expand Down
8 changes: 7 additions & 1 deletion __tests__/suits/components/Passcode.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ jest.mock('@react-navigation/native', () => ({
...jest.requireActual('@react-navigation/native'),
// eslint-disable-next-line
useFocusEffect: jest.fn().mockImplementation(() => {}),
useIsFocused: jest.fn(() => true),
useNavigation: () => ({
navigate: mockNavigate,
}),
}))

jest.mock('../../../src/hooks/settings', () => () => ({
get: jest.fn(),
set: jest.fn(),
}))

describe('Passcode', () => {
afterEach(cleanup)

Expand Down Expand Up @@ -48,7 +54,7 @@ describe('Passcode', () => {

await waitFor(() => {
expect(mockSubmit).toHaveBeenCalledTimes(1)
expect(mockSubmit).toHaveBeenCalledWith('1111')
expect(mockSubmit).toHaveBeenCalledWith('1111', expect.anything())
})
})

Expand Down
Loading

0 comments on commit a18fae3

Please sign in to comment.