Skip to content

Commit

Permalink
chore(wallet): add integration test for send flows
Browse files Browse the repository at this point in the history
  • Loading branch information
J-Son89 committed Feb 22, 2024
1 parent fee8ef5 commit 60d0f01
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 21 deletions.
62 changes: 62 additions & 0 deletions modules/react-native-status/nodejs/status.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,36 @@ void _ToChecksumAddress(const FunctionCallbackInfo<Value>& args) {

}

void _LoginAccount(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();

if (args.Length() != 1) {
// Throw an Error that is passed back to JavaScript
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for Login")));
return;
}

// Check the argument types

if (!args[0]->IsString()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'passwords'")));
return;
}

String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
char *arg0 = *arg0Obj;

// Call exported Go function, which returns a C string
char *c = LoginAccount(arg0);

Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
args.GetReturnValue().Set(ret);
delete c;
}

void _Logout(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();

Expand Down Expand Up @@ -844,6 +874,36 @@ void _CreateAccountAndLogin(const FunctionCallbackInfo<Value>& args) {

}

void _RestoreAccountAndLogin(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();

if (args.Length() != 1) {
// Throw an Error that is passed back to JavaScript
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for RestoreAccountAndLogin")));
return;
}

// Check the argument types

if (!args[0]->IsString()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'RestoreAccountAndLogin'")));
return;
}

String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
char *arg0 = *arg0Obj;

// Call exported Go function, which returns a C string
char *c = RestoreAccountAndLogin(arg0);

Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
args.GetReturnValue().Set(ret);
delete c;
}

void _ValidateMnemonic(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
Expand Down Expand Up @@ -1911,11 +1971,13 @@ void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "isAddress", _IsAddress);
NODE_SET_METHOD(exports, "sha3", _Sha3);
NODE_SET_METHOD(exports, "toChecksumAddress", _ToChecksumAddress);
NODE_SET_METHOD(exports, "loginAccount", _LoginAccount);
NODE_SET_METHOD(exports, "logout", _Logout);
NODE_SET_METHOD(exports, "hashMessage", _HashMessage);
NODE_SET_METHOD(exports, "resetChainData", _ResetChainData);
NODE_SET_METHOD(exports, "saveAccountAndLogin", _SaveAccountAndLogin);
NODE_SET_METHOD(exports, "createAccountAndLogin", _CreateAccountAndLogin);
NODE_SET_METHOD(exports, "restoreAccountAndLogin", _RestoreAccountAndLogin);
NODE_SET_METHOD(exports, "validateMnemonic", _ValidateMnemonic);
NODE_SET_METHOD(exports, "multiformatSerializePublicKey", _MultiformatSerializePublicKey);
NODE_SET_METHOD(exports, "saveAccountAndLoginWithKeycard", _SaveAccountAndLoginWithKeycard);
Expand Down
2 changes: 1 addition & 1 deletion src/mocks/js_dependencies.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
(:require-macros [legacy.status-im.utils.slurp :refer [slurp]])
(:require
[legacy.status-im.fleet.default-fleet :refer (default-fleets)])
(:require [legacy.status-im.utils.test :as utils.test]))
(:require [tests.test-utils :as utils.test]))

;; to generate a js Proxy at js/__STATUS_MOBILE_JS_IDENTITY_PROXY__ that accept any (.xxx) call and
;; return itself
Expand Down
2 changes: 1 addition & 1 deletion src/react_native/keychain.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,5 @@

(defn reset-credentials
[server]
(-> (.resetInternetCredentials ^js react-native-keychain (string/lower-case server))
(-> (.resetInternetCredentials ^js react-native-keychain (when server (string/lower-case server)))
(.then #(when-not % (log/error (str "Error while clearing saved password."))))))
14 changes: 13 additions & 1 deletion src/test_helpers/integration.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
(defmacro with-app-initialized
[& body]
`(do
(legacy.status-im.utils.test/init!)
(tests.test/init!)
(if (test-helpers.integration/app-initialized)
(do ~@body)
(do
Expand All @@ -22,3 +22,15 @@
(rf-test/wait-for [:messenger-started]
(test-helpers.integration/assert-messenger-started)
~@body))))

(defmacro with-recovered-account
[& body]
`(if (test-helpers.integration/messenger-started)
(do ~@body)
(do
(test-helpers.integration/recover-multiaccount!)
(rf-test/wait-for
[:messenger-started]
(test-helpers.integration/enable-testnet!)
(test-helpers.integration/assert-messenger-started)
~@body))))
54 changes: 43 additions & 11 deletions src/test_helpers/integration.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,24 @@
legacy.status-im.subs.root
[native-module.core :as native-module]
[re-frame.core :as rf]
status-im.contexts.onboarding.events
status-im.events
status-im.navigation.core
status-im.subs.root
[taoensso.timbre :as log]
[tests.integration-test.constants :as constants]))
[tests.integration-test.constants :as constants]
[utils.security.core :as security]
[utils.transforms :as transforms]))

(defn validate-mnemonic
[mnemonic on-success on-error]
(native-module/validate-mnemonic
(security/safe-unmask-data mnemonic)
(fn [result]
(let [{:keys [error keyUID]} (transforms/json->clj result)]
(if (seq error)
(when on-error (on-error error))
(on-success mnemonic keyUID))))))

(defn initialize-app!
[]
Expand All @@ -21,6 +34,35 @@
(rf/dispatch [:profile.create/create-and-login
{:display-name constants/account-name :password constants/password :color "blue"}]))

(defn recover-and-login
[seed-phrase]
(rf/dispatch [:profile.recover/recover-and-login
{:display-name (:name constants/recovery-account)
:seed-phrase seed-phrase
:password constants/password
:color "blue"}]))

(defn recover-multiaccount!
[]
(let [masked-seed-phrase (security/mask-data (:seed-phrase constants/recovery-account))]
(validate-mnemonic
masked-seed-phrase
(fn [mnemonic key-uid]
(rf/dispatch [:onboarding/seed-phrase-validated
(security/mask-data mnemonic) key-uid])
(rf/dispatch [:pop-to-root :profiles])
(rf/dispatch [:profile/profile-selected key-uid])
(recover-and-login mnemonic))
#())))

(defn enable-testnet!
[]
(rf/dispatch [:profile.settings/profile-update :test-networks-enabled?
true {}])
; can be removed soon
(rf/dispatch [:profile.settings/profile-update :is-sepolia-enabled? true {}])
(rf/dispatch [:wallet/initialize]))

(defn app-initialized
[]
(let [app-state @(rf/subscribe [:app-state])]
Expand All @@ -42,16 +84,6 @@
[]
(is (= @(rf/subscribe [:communities/create]) constants/community)))

(defn create-new-account!
[]
(rf/dispatch-sync [:wallet-legacy.accounts/start-adding-new-account {:type :generate}])
(rf/dispatch-sync [:set-in [:add-account :account :name] constants/account-name])
(rf/dispatch [:wallet-legacy.accounts/add-new-account (native-module/sha3 constants/password)]))

(defn assert-new-account-created
[]
(is (true? (some #(= (:name %) constants/account-name)
@(rf/subscribe [:profile/wallet-accounts])))))

(defn logout
[]
Expand Down
4 changes: 2 additions & 2 deletions src/tests/contract_test/core_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
legacy.status-im.events
[legacy.status-im.multiaccounts.logout.core :as logout]
legacy.status-im.subs.root
[legacy.status-im.utils.test :as utils.test]
[re-frame.core :as rf]
status-im.events
status-im.navigation.core
status-im.subs.root
[test-helpers.integration :as h]))
[test-helpers.integration :as h]
[tests.test-utils :as utils.test]))

(deftest initialize-app-test
(h/log-headline :initialize-app-test)
Expand Down
8 changes: 8 additions & 0 deletions src/tests/integration_test/constants.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@
(def community {:membership 1 :name "foo" :description "bar"})

(def account-name "account-abc")


(def recovery-account
{:name "wallet-abc"
:seed-phrase "destroy end torch puzzle develop note wise island disease chaos kind bus"
:key-uid "0x6827f3d1e21ae723a24e0dcbac1853b5ed4d651c821a2326492ce8f2367ec905"
:public-key "0x48b8b9e2a8f71e1beae729d83bcd385ffc6af0d5"
})
4 changes: 2 additions & 2 deletions src/tests/integration_test/core_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
legacy.status-im.events
[legacy.status-im.multiaccounts.logout.core :as logout]
legacy.status-im.subs.root
[legacy.status-im.utils.test :as utils.test]
[re-frame.core :as rf]
status-im.events
status-im.navigation.core
status-im.subs.root
[test-helpers.integration :as h]))
[test-helpers.integration :as h]
[tests.test-utils :as utils.test]))

(deftest initialize-app-test
(h/log-headline :initialize-app-test)
Expand Down
4 changes: 2 additions & 2 deletions src/tests/integration_test/profile_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
[cljs.test :refer [deftest is]]
[day8.re-frame.test :as rf-test]
[legacy.status-im.multiaccounts.logout.core :as logout]
[legacy.status-im.utils.test :as utils.test]
[status-im.contexts.profile.utils :as profile.utils]
[test-helpers.integration :as h]
[tests.test-utils :as test-utils]
[utils.re-frame :as rf]))

(deftest edit-profile-name-test
Expand All @@ -28,7 +28,7 @@
(deftest edit-profile-picture-test
(h/log-headline :edit-profile-picture-test)
(let [mock-image "resources/images/mock2/monkey.png"
absolute-path (.resolve utils.test/path mock-image)]
absolute-path (.resolve test-utils/path mock-image)]
(rf-test/run-test-async
(h/with-app-initialized
(h/with-account
Expand Down
64 changes: 64 additions & 0 deletions src/tests/integration_test/wallet_test.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
(ns tests.integration-test.wallet-test
(:require
[cljs.test :refer [deftest is]]
[day8.re-frame.test :as rf-test]
legacy.status-im.events
legacy.status-im.subs.root
status-im.events
status-im.navigation.core
status-im.subs.root
[test-helpers.integration :as h]
[tests.integration-test.constants :as test-constants]
[utils.re-frame :as rf]
[utils.security.core :as security]))

(defn get-default-account
[accounts]
(first (filter :wallet accounts)))

(def send-amount "0.00001")

(deftest wallet-send-test
(h/log-headline :wallet-send-test)
(rf-test/run-test-async
(h/with-app-initialized
(h/with-recovered-account
(rf-test/wait-for
[:wallet/get-wallet-token]
(let [accs (rf/sub [:wallet/accounts])
default-account (get-default-account accs)
address (:address default-account)]
;; navigate to account page
(rf/dispatch [:wallet/navigate-to-account (:address default-account)])
(rf-test/wait-for [:wallet/navigate-to-account]
;; set the receipient address (same address as sender to avoid token loss)
(rf/dispatch [:wallet/select-send-address
{:address address
:token true
:receipient address
:stack-id :wallet-select-address}])
(let [filtered-tokens (rf/sub [:wallet/tokens-filtered "eth"])]
(rf/dispatch [:wallet/send-select-token
{:token (first filtered-tokens)
:stack-id :wallet-select-asset}])
(rf-test/wait-for
[:wallet/clean-suggested-routes]
(rf/dispatch
[:wallet/get-suggested-routes send-amount]))
(rf-test/wait-for
[:wallet/suggested-routes-success]
(let [route (rf/sub [:wallet/wallet-send-route])]
(is (true? (some? route)))
(rf/dispatch [:wallet/send-select-amount
{:amount send-amount
:stack-id :wallet-send-input-amount}])
(rf/dispatch
[:wallet/send-transaction
(security/safe-unmask-data (security/hash-masked-password
(security/mask-data test-constants/password)))])
(rf-test/wait-for [:wallet/pending-transaction-status-changed-received]
(let [transaction-details (rf/sub [:wallet/send-transaction-progress])]
(is (= :confirmed (-> transaction-details vals first :status)))
(h/logout)
(rf-test/wait-for
[:legacy.status-im.multiaccounts.logout.core/logout-method])))))))))))))
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(ns legacy.status-im.utils.test
(ns tests.test-utils
(:require
[legacy.status-im.utils.deprecated-types :as types]
[re-frame.core :as re-frame]))
Expand Down Expand Up @@ -70,6 +70,12 @@
(callback (.openAccounts native-status test-dir)))
:createAccountAndLogin
(fn [request] (.createAccountAndLogin native-status request))
:restoreAccountAndLogin
(fn [request]
(prn native-status)
(.restoreAccountAndLogin native-status request))
:loginAccount
(fn [request] (.loginAccount native-status request))
:logout
(fn [] (.logout native-status))
:multiAccountImportMnemonic
Expand Down Expand Up @@ -128,3 +134,4 @@
(fn [] (.fleets native-status))
:startLocalNotifications
identity}))

0 comments on commit 60d0f01

Please sign in to comment.