MALINKA-1004 Node actions model unit tests"

This commit is contained in:
Андрей Геращенко
2023-01-17 15:09:45 +03:00
committed by Никита Чирухин
parent b9d5305ef6
commit edcc3274da
11 changed files with 5699 additions and 42 deletions
@@ -18,9 +18,16 @@ public struct AccountService: NetworkService {
}
let environment: NetworkEnvironment
let session: Session
public init(environment: NetworkEnvironment) {
self.environment = environment
if let configuration = environment.configuration {
configuration.headers = HTTPHeaders.default
self.session = Session(configuration: configuration)
} else {
self.session = AF
}
}
// Methods
@@ -35,7 +42,7 @@ public struct AccountService: NetworkService {
decoder.dateDecodingStrategy = .formatted(dateFormatter)
let variables = AccountCreateRequest.Variables(username: username, pubKey: pubKey, deviceId: deviceId)
let result = try? await AF.request(
let result = try? await self.session.request(
self.environment.usernames.url,
method: .post,
parameters: AccountCreateRequest(variables: variables),
@@ -64,7 +71,7 @@ public struct AccountService: NetworkService {
decoder.dateDecodingStrategy = .formatted(dateFormatter)
let variables = AccountOrderRequest.Variables(uid: id)
let result = try? await AF.request(
let result = try? await self.session.request(
self.environment.usernames.url,
method: .post,
parameters: AccountOrderRequest(variables: variables),
@@ -95,7 +102,7 @@ public struct AccountService: NetworkService {
let variables = AccountCheckNameRequest.Variables(username: username)
let response = try? await AF.request(
let response = try? await self.session.request(
self.environment.usernames.url,
method: .post,
parameters: AccountCheckNameRequest(variables: variables),
@@ -134,7 +141,7 @@ public struct AccountService: NetworkService {
application: "MALINKA"
)
let result = try? await AF.request(
let result = try? await self.session.request(
self.environment.backend.url,
method: .post,
parameters: AccountNotificationTokenRequest(variables: variables),
@@ -146,30 +153,4 @@ public struct AccountService: NetworkService {
print(result ?? "")
}
public func fetchNodeActions(account: String,
limit: Int,
skip: Int? = nil) async throws -> [NodeAction] {
guard let url = URL(string: "https://eos.greymass.com") else { return [] } //self.environment.hyperion.url()
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return [] }
components.path = "/v1/history/get_actions"
components.queryItems = [URLQueryItem(name: "account_name", value: account),
URLQueryItem(name: "offset", value: "\(-limit)")]
if let skip {
components.queryItems?.append(URLQueryItem(name: "pos", value: "\(skip)"))
}
let response = AF.request(
components,
method: .get
)
do {
let result = try await response.serializingDecodable(NodeResponse.self)
.value
return result.actions
} catch {
throw error
}
}
}
@@ -0,0 +1,50 @@
//
// AccountNodeService.swift
//
//
// Created by Nut.Tech on 16.01.2023.
//
import Alamofire
import Foundation
public struct NodeService: NetworkService {
let environment: NetworkEnvironment
let session: Session
public init(environment: NetworkEnvironment) {
self.environment = environment
if let configuration = environment.configuration {
configuration.headers = HTTPHeaders.default
self.session = Session(configuration: configuration)
} else {
self.session = AF
}
}
public func fetchActions(account: String,
limit: Int,
skip: Int? = nil) async throws -> [NodeAction] {
guard let url = URL(string: "https://eos.greymass.com") else { return [] } //self.environment.hyperion.url()
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return [] }
components.path = "/v1/history/get_actions"
components.queryItems = [URLQueryItem(name: "account_name", value: account),
URLQueryItem(name: "offset", value: "\(-limit)")]
if let skip {
components.queryItems?.append(URLQueryItem(name: "pos", value: "\(skip)"))
}
do {
let result = try await self.session.request(
components,
method: .get
).serializingDecodable(NodeResponse.self)
.value
return result.actions
} catch {
throw error
}
}
}
@@ -9,23 +9,20 @@ import Foundation
final class DeviceServiceData {
static let module = Bundle(for: DeviceServiceData.self)
static let bundle = Bundle(url: module.url(forResource: "WalletNetwork_WalletNetworkTests",
withExtension: "bundle")!)!
static let createDeviceTrusted = try! Data(contentsOf: bundle.url(forResource: "CreateDeviceSuccessTrusted",
static let createDeviceTrusted = try! Data(contentsOf: Bundle.module.url(forResource: "CreateDeviceSuccessTrusted",
withExtension: "json")!)
static let createDeviceDecodeFailed = try! Data(contentsOf: bundle.url(forResource: "CreateDeviceSuccessNull",
static let createDeviceDecodeFailed = try! Data(contentsOf: Bundle.module.url(forResource: "CreateDeviceSuccessNull",
withExtension: "json")!)
static let queryDeviceStateNull = try! Data(contentsOf: bundle.url(forResource: "QueryDeviceSuccessNull",
static let queryDeviceStateNull = try! Data(contentsOf: Bundle.module.url(forResource: "QueryDeviceSuccessNull",
withExtension: "json")!)
static let queryDeviceStateUntrusted = try! Data(contentsOf: bundle.url(forResource: "QueryDeviceSuccessUntrusted",
static let queryDeviceStateUntrusted = try! Data(contentsOf: Bundle.module.url(forResource: "QueryDeviceSuccessUntrusted",
withExtension: "json")!)
static let queryDeviceStateTrusted = try! Data(contentsOf: bundle.url(forResource: "QueryDeviceSuccessTrusted",
static let queryDeviceStateTrusted = try! Data(contentsOf: Bundle.module.url(forResource: "QueryDeviceSuccessTrusted",
withExtension: "json")!)
static let nodeActionsExample = try! Data(contentsOf: Bundle.module.url(forResource: "v1historyTestmalinka1",
withExtension: "json")!)
}
@@ -28,4 +28,17 @@ struct NetworkEnvironmentImpl: NetworkEnvironment {
hyperion: NetworkDynamicAPIRecord(url: { dumpUrl }, headers: nil),
node: NetworkDynamicAPIRecord(url: { dumpUrl }, headers: nil))
}
static func createStubNodes(configuration: URLSessionConfiguration,
url: URL,
headers: NetworkStaticAPIRecord.Headers? = nil) -> NetworkEnvironment {
let record = NetworkDynamicAPIRecord(url: { url }, headers: headers)
let dumpUrl = URL(string: "Empty")!
return NetworkEnvironmentImpl(configuration: configuration,
usernames: NetworkStaticAPIRecord(url: dumpUrl, headers: nil),
backend: NetworkStaticAPIRecord(url: dumpUrl, headers: nil),
hyperion: NetworkDynamicAPIRecord(url: { dumpUrl }, headers: nil),
node: record)
}
}
@@ -0,0 +1,120 @@
//
// NodeActionModelsTests.swift
//
//
// Created by Nut.Tech on 13.01.2023.
//
import WalletNetwork
import Foundation
import XCTest
final class NodeActionModelsTests: XCTestCase {
func testNodeActAuthorization() {
let data = """
{
"actor": "testmalinka1",
"permission": "owner"
}
""".data(using: .utf8)!
let nodeAct = try? JSONDecoder().decode(NodeActAuthorization.self, from: data)
XCTAssertNotNil(nodeAct, "Error parsing NodeActAuthorization object")
XCTAssertEqual(nodeAct?.actor, "testmalinka1", "Error parsing NodeActAuthorization.actor value")
XCTAssertEqual(nodeAct?.permission, "owner", "Error parsing NodeActAuthorization.owner value")
}
func testNodeData() {
let data = """
{
"from": "testmalinka1",
"memo": "buyram:testmalinka1",
"quantity": "0.1000 EOS",
"to": "malinkawallt"
}
""".data(using: .utf8)!
let nodeData = try? JSONDecoder().decode(NodeData.self, from: data)
XCTAssertNotNil(nodeData, "Error parsing NodeData object")
guard let parsedData = nodeData?.data else {
XCTFail("Error parsing data value")
return
}
XCTAssertEqual(parsedData["from"] as? String, "testmalinka1", "Error parsing data value")
XCTAssertEqual(parsedData["memo"] as? String, "buyram:testmalinka1", "Error parsing data value")
XCTAssertEqual(parsedData["quantity"] as? String, "0.1000 EOS", "Error parsing data value")
XCTAssertEqual(parsedData["to"] as? String, "malinkawallt", "Error parsing data value")
}
func testNodeAct() {
let data = """
{
"account": "eosio.token",
"authorization": [
{
"actor": "testmalinka1",
"permission": "owner"
}
],
"data": {
"from": "testmalinka1",
"memo": "buyram:testmalinka1",
"quantity": "0.1000 EOS",
"to": "malinkawallt"
},
"hex_data": "100c9c2e1a99b1ca906334dcc0e9a291e80300000000000004454f53000000001362757972616d3a746573746d616c696e6b6131",
"name": "transfer"
}
""".data(using: .utf8)!
let nodeAct = try? JSONDecoder().decode(NodeAct.self, from: data)
XCTAssertNotNil(nodeAct, "Error parsing NodeAct object")
XCTAssertNotNil(nodeAct?.data, "Error parsing NodeAct.data object")
XCTAssertNotNil(nodeAct?.authorization, "buyram:testmalinka1", file: "Error parsing NodeAct.authorization objects")
XCTAssertEqual(nodeAct?.authorization.count, 1, "Error parsing NodeAct.authorization objects")
XCTAssertEqual(nodeAct?.name, "transfer", "Error parsing NodeAct.name value")
XCTAssertEqual(nodeAct?.account, "eosio.token", "Error parsing NodeAct.account value")
}
func testNodeActionTrace() {
guard let url = Bundle.module.url(forResource: "NodeActionTrace", withExtension: "json"),
let data = try? Data(contentsOf: url),
let result = try? JSONDecoder().decode(NodeActionTrace.self, from: data)
else {
XCTFail("Error reading JSON file")
return
}
XCTAssertNotNil(result.act, "Error parsing NodeActionTrace.act object")
XCTAssertEqual(result.blockNum, 288713481, "Error parsing NodeActionTrace.blockNum value")
XCTAssertEqual(result.blockTime, "2023-01-12T15:27:01.500", "Error parsing NodeActionTrace.blockTime value")
XCTAssertEqual(result.receiver, "malinkawallt", "Error parsing NodeActionTrace.receiver value")
XCTAssertEqual(result.trxId, "233cb97fcc9a6c8cc7943e021cd9705dd5ff7b82b1fa3a93afaf240f35f2c31c", "Error parsing NodeActionTrace.trxId value")
}
func testNodeAction() {
guard let url = Bundle.module.url(forResource: "NodeAction", withExtension: "json"),
let data = try? Data(contentsOf: url),
let result = try? JSONDecoder().decode(NodeAction.self, from: data)
else {
XCTFail("Error reading JSON file")
return
}
XCTAssertNotNil(result.actionTrace, "Error parsing NodeAction.actionTrace value")
XCTAssertEqual(result.accountActionSeq, 2858, "Error parsing NodeAction.accountActionSeq value")
XCTAssertEqual(result.globalActionSeq, 357585823156, "Error parsing NodeAction.globalActionSeq value")
XCTAssertTrue(result.irreversible, "Error parsing NodeAction.irreversible value")
}
func testNodeResponse() {
guard let url = Bundle.module.url(forResource: "NodeResponse", withExtension: "json"),
let data = try? Data(contentsOf: url),
let result = try? JSONDecoder().decode(NodeResponse.self, from: data)
else {
XCTFail("Error reading JSON file")
return
}
XCTAssertNotNil(result.actions, "Error parsing NodeResponse")
XCTAssertEqual(result.actions.count, 1, "Error parsing NodeResponse.actions")
}
}
@@ -0,0 +1,68 @@
//
// NodeServiceTests.swift
//
//
// Created by Nut.Tech on 16.01.2023.
//
import XCTest
@testable import WalletNetwork
import Mocker
final class NodeServiceTests: XCTestCase {
override func tearDown() {
Mocker.removeAll()
}
func testFetchNodeActions() async {
let accountName = "testmalinka3"
let offset = -100
let url = URL(string: "https://eos.greymass.com/v1/history/get_actions?account_name=\(accountName)&offset=\(offset)")!
let configuration = URLSessionConfiguration.af.default
configuration.protocolClasses = [MockingURLProtocol.self]
let env = NetworkEnvironmentImpl.createStubNodes(configuration: configuration, url: url)
let service = NodeService(environment: env)
Mock(url: url,
ignoreQuery: true,
dataType: .json,
statusCode: 200,
data: [ .get: DeviceServiceData.nodeActionsExample ]
).register()
do {
let state = try await service.fetchActions(account: accountName,
limit: offset)
guard let firstAction = state.first else {
XCTFail("Error parsing NodeActions")
return
}
XCTAssertEqual(state.count, 100, "Incorrect number of node actions")
XCTAssertEqual(firstAction.accountActionSeq, 2759, "Error parsing NodeAction.accountActionSeq")
XCTAssertEqual(firstAction.globalActionSeq, 357563493447, "Error parsing NodeAction.globalActionSeq")
XCTAssertTrue(firstAction.irreversible, "Error parsing NodeAction.irreversible")
XCTAssertNotNil(firstAction.actionTrace, "Error parsing NodeAction.actionTrace")
XCTAssertEqual(firstAction.actionTrace.blockTime, "2023-01-09T13:55:06.000", "Error parsing NodeAction.actionTrace.blockTime")
XCTAssertEqual(firstAction.actionTrace.blockNum, 288184258, "Error parsing NodeAction.actionTrace.blockNum")
XCTAssertEqual(firstAction.actionTrace.trxId, "a4dfd44c82cf0a3be1930bf6e4ec6ea51c1b331a4e77864a0d2cae4d06e8683d", "Error parsing NodeAction.actionTrace.trxId")
XCTAssertEqual(firstAction.actionTrace.receiver, "testmalinka1", "Error parsing NodeAction.actionTrace.receiver")
let act = firstAction.actionTrace.act
XCTAssertEqual(act.account, "eosio.token", "Error parsing NodeActionTrace.act.account")
XCTAssertEqual(act.name, "transfer", "Error parsing NodeActionTrace.act.name")
XCTAssertEqual(act.authorization.count, 1, "Error parsing NodeActionTrace.act.authorization")
XCTAssertNotNil(act.data, "Error parsing NodeActionTrace.act.data")
guard let authorization = act.authorization.first else {
XCTFail("Error parsing NodeAction.actionTrace.act.authorization")
return
}
XCTAssertEqual(authorization.permission, "owner", "Error parsing NodeActionTrace.act.authorization.permission")
XCTAssertEqual(authorization.actor, "testmalinka1", "Error parsing NodeActionTrace.act.authorization.actor")
} catch {
XCTFail("Catch exceprion \(error)")
}
}
}
@@ -0,0 +1,51 @@
{
"account_action_seq": 2858,
"action_trace": {
"account_ram_deltas": [],
"act": {
"account": "eosio.token",
"authorization": [
{
"actor": "testmalinka1",
"permission": "owner"
}
],
"data": {
"from": "testmalinka1",
"memo": "buyram:testmalinka1",
"quantity": "0.1000 EOS",
"to": "malinkawallt"
},
"hex_data": "100c9c2e1a99b1ca906334dcc0e9a291e80300000000000004454f53000000001362757972616d3a746573746d616c696e6b6131",
"name": "transfer"
},
"action_ordinal": 4,
"block_num": 288713481,
"block_time": "2023-01-12T15:27:01.500",
"closest_unnotified_ancestor_action_ordinal": 2,
"context_free": false,
"creator_action_ordinal": 2,
"elapsed": 2,
"producer_block_id": "11356b09099ac39c311d160b99824c40825a5b65f7ddc75fb1e4a5d4c57cde68",
"receipt": {
"abi_sequence": 4,
"act_digest": "0d8c0d9d769f6b68d2b3b2cc1dd2b219eb1ddd7d52c83d221abd74541f6f687b",
"auth_sequence": [
[
"testmalinka1",
2192
]
],
"code_sequence": 4,
"global_sequence": 357585823156,
"receiver": "malinkawallt",
"recv_sequence": 14905
},
"receiver": "malinkawallt",
"trx_id": "233cb97fcc9a6c8cc7943e021cd9705dd5ff7b82b1fa3a93afaf240f35f2c31c"
},
"block_num": 288713481,
"block_time": "2023-01-12T15:27:01.500",
"global_action_seq": 357585823156,
"irreversible": true
}
@@ -0,0 +1,44 @@
{
"account_ram_deltas": [],
"act": {
"account": "eosio.token",
"authorization": [
{
"actor": "testmalinka1",
"permission": "owner"
}
],
"data": {
"from": "testmalinka1",
"memo": "buyram:testmalinka1",
"quantity": "0.1000 EOS",
"to": "malinkawallt"
},
"hex_data": "100c9c2e1a99b1ca906334dcc0e9a291e80300000000000004454f53000000001362757972616d3a746573746d616c696e6b6131",
"name": "transfer"
},
"action_ordinal": 4,
"block_num": 288713481,
"block_time": "2023-01-12T15:27:01.500",
"closest_unnotified_ancestor_action_ordinal": 2,
"context_free": false,
"creator_action_ordinal": 2,
"elapsed": 2,
"producer_block_id": "11356b09099ac39c311d160b99824c40825a5b65f7ddc75fb1e4a5d4c57cde68",
"receipt": {
"abi_sequence": 4,
"act_digest": "0d8c0d9d769f6b68d2b3b2cc1dd2b219eb1ddd7d52c83d221abd74541f6f687b",
"auth_sequence": [
[
"testmalinka1",
2192
]
],
"code_sequence": 4,
"global_sequence": 357585823156,
"receiver": "malinkawallt",
"recv_sequence": 14905
},
"receiver": "malinkawallt",
"trx_id": "233cb97fcc9a6c8cc7943e021cd9705dd5ff7b82b1fa3a93afaf240f35f2c31c"
}
@@ -0,0 +1,57 @@
{
"actions": [
{
"account_action_seq": 2858,
"action_trace": {
"account_ram_deltas": [],
"act": {
"account": "eosio.token",
"authorization": [
{
"actor": "testmalinka1",
"permission": "owner"
}
],
"data": {
"from": "testmalinka1",
"memo": "buyram:testmalinka1",
"quantity": "0.1000 EOS",
"to": "malinkawallt"
},
"hex_data": "100c9c2e1a99b1ca906334dcc0e9a291e80300000000000004454f53000000001362757972616d3a746573746d616c696e6b6131",
"name": "transfer"
},
"action_ordinal": 4,
"block_num": 288713481,
"block_time": "2023-01-12T15:27:01.500",
"closest_unnotified_ancestor_action_ordinal": 2,
"context_free": false,
"creator_action_ordinal": 2,
"elapsed": 2,
"producer_block_id": "11356b09099ac39c311d160b99824c40825a5b65f7ddc75fb1e4a5d4c57cde68",
"receipt": {
"abi_sequence": 4,
"act_digest": "0d8c0d9d769f6b68d2b3b2cc1dd2b219eb1ddd7d52c83d221abd74541f6f687b",
"auth_sequence": [
[
"testmalinka1",
2192
]
],
"code_sequence": 4,
"global_sequence": 357585823156,
"receiver": "malinkawallt",
"recv_sequence": 14905
},
"receiver": "malinkawallt",
"trx_id": "233cb97fcc9a6c8cc7943e021cd9705dd5ff7b82b1fa3a93afaf240f35f2c31c"
},
"block_num": 288713481,
"block_time": "2023-01-12T15:27:01.500",
"global_action_seq": 357585823156,
"irreversible": true
}
],
"head_block_num": 288838483,
"last_irreversible_block": 288838158
}
@@ -54,14 +54,14 @@ extension Network.Service.Actions {
parameters["offset"] = -limit
parameters["pos"] = skip
let record = ApplicationEnvironment.shared().current
guard let service = try? AccountService(environment: record.networkEnvironment())
guard let service = try? NodeService(environment: record.networkEnvironment())
else {
completion([], nil)
return
}
Task {
do {
let nodeActions = try await service.fetchNodeActions(account: account, limit: limit, skip: skip)
let nodeActions = try await service.fetchActions(account: account, limit: limit, skip: skip)
completion(nodeActions, nil)
} catch {
completion([], error)