UNPKG

@onflow/flow-js-testing

Version:

This package will expose a set of utility methods, to allow Cadence code testing with libraries like Jest

374 lines (331 loc) 9.82 kB
/* eslint-disable jest/expect-expect */ import {config} from "@onflow/fcl" import path from "path" import { emulator, init, sendTransaction, executeScript, getAccountAddress, shallResolve, shallThrow, shallPass, } from "../../src" import { createAccount, pubFlowKey, HashAlgorithm, SignatureAlgorithm, } from "../../src" import {permute} from "../util/permute" import {DEFAULT_TEST_TIMEOUT} from "../util/timeout.const" // We need to set timeout for a higher number, cause some transactions might take up some time jest.setTimeout(DEFAULT_TEST_TIMEOUT) describe("interactions - sendTransaction", () => { // Instantiate emulator and path to Cadence files beforeEach(async () => { const basePath = path.resolve(__dirname, "../cadence") await init(basePath) return emulator.start() }) // Stop emulator, so it could be restarted afterEach(async () => { return emulator.stop() }) test("sendTransaction - shall throw when no code and name provided", async () => { await shallThrow(async () => { return sendTransaction({}) }) }) test("sendTransaction - shall pass with name provided", async () => { await shallPass(async () => { const name = "log-signer-address" return sendTransaction({name}) }) }) test("sendTransaction - shall pass with name passed directly", async () => { await shallPass(async () => { return sendTransaction("log-signer-address") }) }) test("sendTransaction - shall pass with code provided", async () => { await shallPass(async () => { const code = ` transaction{ prepare(signer: &Account){ log(signer.address) } } ` return sendTransaction({code}) }) }) test("sendTransaction - shall capture logs", async () => { const [, , logs] = await shallPass(async () => { const code = ` transaction{ prepare(signer: &Account){ log("hello world") } } ` return sendTransaction({code}) }) expect(logs).toEqual(["hello world"]) }) test("sendTransaction - shall pass with signer address", async () => { const Alice = await getAccountAddress("Alice") const code = ` transaction{ prepare(signer: &Account){ assert(signer.address == ${Alice}, message: "Signer address must be equal to Alice's Address") } } ` const signers = [Alice] await shallPass(sendTransaction({code, signers})) }) test("sendTransaction - shall pass with signer object using default private key", async () => { const Alice = await getAccountAddress("Alice") const code = ` transaction{ prepare(signer: &Account){ assert(signer.address == ${Alice}, message: "Signer address must be equal to Alice's Address") } } ` const signers = [ { addr: Alice, keyId: 0, }, ] await shallPass(sendTransaction({code, signers})) }) test("sendTransaction - shall pass with signer object using custom private key", async () => { const Alice = await getAccountAddress("Alice") const code = ` transaction{ prepare(signer: &Account){ assert(signer.address == ${Alice}, message: "Signer address must be equal to Alice's Address") } } ` const signers = [ { addr: Alice, keyId: 0, privateKey: await config().get("PRIVATE_KEY"), }, ] await shallPass(sendTransaction({code, signers})) }) test.each( permute(Object.keys(HashAlgorithm), Object.keys(SignatureAlgorithm)) )( "sendTransaction - shall pass with custom signer - %s hash algorithm, %s signature algorithm", async (hashAlgorithm, signatureAlgorithm) => { const privateKey = "1234" const Adam = await createAccount({ name: "Adam", keys: [ await pubFlowKey({ privateKey, hashAlgorithm, signatureAlgorithm, weight: 1000, }), ], }) const code = ` transaction{ prepare(signer: &Account){ assert(signer.address == ${Adam}, message: "Signer address must be equal to Adam's Address") } } ` const signers = [ { addr: Adam, keyId: 0, privateKey, hashAlgorithm, signatureAlgorithm, }, ] await shallPass(sendTransaction({code, signers})) } ) test("sendTransaction - shall pass with custom signer - hashAlgorithm, signatureAlgorithm resolved via string - pubKey resolved via privKey", async () => { const hashAlgorithm = "ShA3_256" //varying caps to test case insensitivity const signatureAlgorithm = "eCdSA_P256" const privateKey = "1234" const Adam = await createAccount({ name: "Adam", keys: [ { privateKey, hashAlgorithm, signatureAlgorithm, weight: 1000, }, ], }) const code = ` transaction{ prepare(signer: &Account){ assert(signer.address == ${Adam}, message: "Signer address must be equal to Adam's Address") } } ` const signers = [ { addr: Adam, keyId: 0, privateKey, hashAlgorithm, signatureAlgorithm, }, ] await shallPass(sendTransaction({code, signers})) }) test("sendTransaction - argument mapper - basic", async () => { await shallPass(async () => { const code = ` transaction(a: Int){ prepare(signer: &Account){ log(signer.address) } } ` const args = ["42"] return sendTransaction({code, args}) }) }) test("sendTransaction - argument mapper - multiple", async () => { await shallPass(async () => { const code = ` transaction(a: Int, b: Int, name: String){ prepare(signer: &Account){ log(signer.address) } } ` const args = ["42", "1337", "Hello, Cadence"] return sendTransaction({code, args}) }) }) test("sendTransaction - argument mapper - automatic", async () => { await shallPass(async () => { const code = ` transaction(a: Int, b: Int, name: String){ prepare(signer: &Account){ log(signer.address) } } ` const args = ["42", "1337", "Hello, Cadence"] return sendTransaction({code, args}) }) }) test("sendTransaction - short notation, no signers", async () => { emulator.setLogging(true) await shallPass(async () => { return sendTransaction("log-signer-address") }) }) test("sendTransaction - short notation, Alice signed", async () => { emulator.setLogging(true) await shallPass(async () => { const Alice = await getAccountAddress("Alice") const signers = [Alice] return sendTransaction("log-signer-address", signers) }) }) test("sendTransaction - short notation, Alice signed, with args", async () => { emulator.setLogging(true) await shallPass(async () => { const args = ["Hello, from Cadence!"] const Alice = await getAccountAddress("Alice") const signers = [Alice] return sendTransaction("log-message", signers, args) }) }) }) describe("interactions - executeScript", () => { // Instantiate emulator and path to Cadence files beforeEach(async () => { const basePath = path.resolve(__dirname, "../cadence") await init(basePath) return emulator.start() }) // Stop emulator, so it could be restarted afterEach(async () => { return emulator.stop() }) test("executeScript - shall throw when no code and name provided", async () => { shallThrow(async () => { return executeScript({}) }) }) test("executeScript - shall pass with name provided", async () => { await shallResolve(async () => { const name = "log-message" return executeScript({name}) }) }) test("executeScript - shall pass with code provided", async () => { await shallResolve(async () => { const code = ` access(all) fun main(){ log("hello from cadence") } ` return executeScript({code}) }) }) test("executeScript - shall capture logs", async () => { const [, , logs] = await shallResolve(async () => { const code = ` access(all) fun main():Int{ log("hello from cadence") log("this second log has been captured!") return 42 } ` return executeScript({code}) }) expect(logs).toEqual([ "hello from cadence", "this second log has been captured!", ]) }) test("executeScript - shall pass with short notation", async () => { const [result, err] = await shallResolve(executeScript("log-message")) expect(err).toBe(null) expect(result).toBe("42") }) test("executeScript - shall pass with short notation and arguments", async () => { const message = "Hello, from Cadence!" const [result, err] = await shallResolve(() => { const args = [message] return executeScript("log-passed-message", args) }) expect(err).toBe(null) expect(result).toBe(message) }) test("executeScript - shall work properly for empty array as argument", async () => { const [result, err] = await shallResolve(async () => { const code = ` access(all) fun main(data: [String]): [String]{ log(data) return data } ` const args = [[]] return executeScript({code, args}) }) expect(err).toBe(null) expect(result.length).toBe(0) }) })