E2E - Web3 interaction & more tests (#202)
* account switching & setting gas for e2e web3 * e2e web3 interaction + new specs * refund after payout spec * use send instead of sendAsync + update ganache script cmd * sign intercept + deterministic accounts * add authentication to creation tests * adjust cy.request call * refactor + WIP fiddle with xhr * xhook to modify incoming api requests
This commit is contained in:
parent
d367e6e474
commit
968974d8d7
|
@ -1 +1,3 @@
|
|||
{}
|
||||
{
|
||||
"baseUrl": "http://localhost:3000"
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,14 @@
|
|||
/// <reference types="cypress"/>
|
||||
import {
|
||||
loadWeb3,
|
||||
increaseTime,
|
||||
syncTimeWithEvm,
|
||||
randomString
|
||||
} from "../helpers";
|
||||
import { createDemoProposal, authenticateUser } from "../parts";
|
||||
|
||||
describe("authenticate", () => {
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
});
|
|
@ -3,13 +3,13 @@ import { loadWeb3, randomString, randomHex } from "../helpers";
|
|||
|
||||
describe("browse", () => {
|
||||
it("should load and be able to browse pages", () => {
|
||||
cy.visit("http://localhost:3000", { onBeforeLoad: loadWeb3 });
|
||||
cy.visit("http://localhost:3000", { onBeforeLoad: loadWeb3(0) });
|
||||
cy.title().should("include", "Grant.io - Home");
|
||||
|
||||
// test hero create link
|
||||
cy.get('.Home-hero-buttons a[href="/create"]')
|
||||
// {force: true} here overcomes a strange issue where the button moves up under the header
|
||||
// this is likely a cypress-related problem
|
||||
// this is likely a cypress scroll related problem
|
||||
.click({ force: true });
|
||||
cy.title().should("include", "Grant.io - Create a Proposal");
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/// <reference types="cypress"/>
|
||||
import {
|
||||
loadWeb3,
|
||||
increaseTime,
|
||||
syncTimeWithEvm,
|
||||
randomString
|
||||
} from "../helpers";
|
||||
import { createDemoProposal, authenticateUser } from "../parts";
|
||||
|
||||
describe("proposal", () => {
|
||||
const id = randomString();
|
||||
const title = `[${id}] e2e create cancel`;
|
||||
const amount = "1";
|
||||
|
||||
afterEach(function() {
|
||||
if (this.currentTest.state === "failed") {
|
||||
(Cypress as any).runner.stop();
|
||||
}
|
||||
});
|
||||
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
|
||||
it("creates demo proposal", () => {
|
||||
createDemoProposal(cy, title, amount);
|
||||
});
|
||||
|
||||
it("cancels the proposal", () => {
|
||||
cy.contains(".Proposal-top-main-menu > .ant-btn", "Actions").click();
|
||||
cy.contains(".ant-dropdown-menu-item", "Cancel proposal").click();
|
||||
cy.contains(".ant-modal-footer > div button", "Confirm").click();
|
||||
cy.contains("body", "Proposal didn’t get funded", { timeout: 20000 });
|
||||
cy.get(".ant-modal-wrap").should("not.be.visible");
|
||||
cy.contains(".Proposal-top-main-menu > .ant-btn", "Actions").click();
|
||||
cy.contains(".ant-dropdown-menu-item", "Cancel proposal").should(
|
||||
"have.attr",
|
||||
"aria-disabled",
|
||||
"true"
|
||||
);
|
||||
});
|
||||
|
||||
it("should appear unfunded to outsiders (account 9)", () => {
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(9) }));
|
||||
cy.contains("body", "Proposal didn’t get funded", { timeout: 20000 });
|
||||
});
|
||||
});
|
|
@ -0,0 +1,173 @@
|
|||
/// <reference types="cypress"/>
|
||||
import { loadWeb3, randomString, randomHex, syncTimeWithEvm } from "../helpers";
|
||||
import { authenticateUser } from "../parts";
|
||||
|
||||
describe("create.flow", () => {
|
||||
const time = new Date().toLocaleString();
|
||||
const id = randomString();
|
||||
const randomEthHex = randomHex(32);
|
||||
const nextYear = new Date().getUTCFullYear() + 1;
|
||||
const proposal = {
|
||||
title: `[${id}] e2e create flow`,
|
||||
brief: "e2e brief",
|
||||
category: "Community", // .anticon-team
|
||||
targetAmount: 5,
|
||||
body: `#### e2e Proposal ${id} {enter} **created** ${time} `,
|
||||
team: [
|
||||
{
|
||||
name: "Alisha Endtoend",
|
||||
title: "QA Robot0",
|
||||
ethAddress: `0x0000${randomEthHex}0000`,
|
||||
emailAddress: `qa.alisha.${id}@grant.io`
|
||||
},
|
||||
{
|
||||
name: "Billy Endtoend",
|
||||
title: "QA Robot1",
|
||||
ethAddress: `0x1111${randomEthHex}1111`,
|
||||
emailAddress: `qa.billy.${id}@grant.io`
|
||||
}
|
||||
],
|
||||
milestones: [
|
||||
{
|
||||
title: `e2e Milestone ${id} 0`,
|
||||
body: `e2e Milestone ${id} {enter} body 0`,
|
||||
date: {
|
||||
y: nextYear,
|
||||
m: "Jan",
|
||||
expect: "January " + nextYear
|
||||
}
|
||||
},
|
||||
{
|
||||
title: `e2e Milestone ${id} 1`,
|
||||
body: `e2e Milestone ${id} {enter} body 1`,
|
||||
date: {
|
||||
y: nextYear,
|
||||
m: "Feb",
|
||||
expect: "February " + nextYear
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
afterEach(function() {
|
||||
if (this.currentTest.state === "failed") {
|
||||
(Cypress as any).runner.stop();
|
||||
}
|
||||
});
|
||||
|
||||
context("create flow wizard", () => {
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
|
||||
it("create flow step 1", () => {
|
||||
cy.get('[href="/create"]').click();
|
||||
syncTimeWithEvm(cy);
|
||||
cy.get('.CreateFlow input[name="title"]').type(proposal.title);
|
||||
cy.get('.CreateFlow textarea[name="brief"]').type(proposal.brief);
|
||||
cy.contains("Select a category").click();
|
||||
cy.get(".ant-select-dropdown li .anticon-team").click();
|
||||
cy.get('.CreateFlow input[name="amountToRaise"]').type(
|
||||
"" + proposal.targetAmount
|
||||
);
|
||||
cy.wait(1000);
|
||||
cy.contains(".CreateFlow-footer-button", "Continue").click();
|
||||
});
|
||||
|
||||
it("create flow step 2", () => {
|
||||
cy.get("button.TeamForm-add").click();
|
||||
cy.get('.TeamMember-info input[name="name"]').type(proposal.team[1].name);
|
||||
cy.get('.TeamMember-info input[name="title"]').type(
|
||||
proposal.team[1].title
|
||||
);
|
||||
cy.get('.TeamMember-info input[name="ethAddress"]').type(
|
||||
proposal.team[1].ethAddress
|
||||
);
|
||||
cy.get('.TeamMember-info input[name="emailAddress"]').type(
|
||||
proposal.team[1].emailAddress
|
||||
);
|
||||
cy.get("button")
|
||||
.contains("Save changes")
|
||||
.click({ force: true });
|
||||
cy.wait(1000);
|
||||
cy.contains(".CreateFlow-footer-button", "Continue").click();
|
||||
});
|
||||
|
||||
it("create flow step 3", () => {
|
||||
cy.get(".DraftEditor-editorContainer > div").type(proposal.body);
|
||||
cy.get(".mde-tabs > :nth-child(2)").click();
|
||||
cy.wait(1000);
|
||||
cy.contains(".CreateFlow-footer-button", "Continue").click();
|
||||
});
|
||||
|
||||
it("create flow step 4", () => {
|
||||
cy.get('input[name="title"]').type(proposal.milestones[0].title);
|
||||
cy.get('textarea[name="body"]').type(proposal.milestones[0].body);
|
||||
cy.get('input[placeholder="Expected completion date"]').click();
|
||||
cy.get(".ant-calendar-month-panel-next-year-btn").click();
|
||||
cy.get(".ant-calendar-month-panel-month")
|
||||
.contains(proposal.milestones[0].date.m)
|
||||
.click();
|
||||
cy.get(".ant-calendar-picker-input").should(
|
||||
"have.value",
|
||||
proposal.milestones[0].date.expect
|
||||
);
|
||||
cy.get("button")
|
||||
.contains("Add another milestone")
|
||||
.click({ force: true });
|
||||
cy.get('input[name="title"]')
|
||||
.eq(1)
|
||||
.type(proposal.milestones[1].title);
|
||||
cy.get('textarea[name="body"]')
|
||||
.eq(1)
|
||||
.type(proposal.milestones[1].body);
|
||||
cy.get('input[placeholder="Expected completion date"]')
|
||||
.eq(1)
|
||||
.click();
|
||||
cy.get(".ant-calendar-month-panel-next-year-btn").click();
|
||||
cy.get(".ant-calendar-month-panel-month")
|
||||
.contains(proposal.milestones[1].date.m)
|
||||
.click();
|
||||
cy.get(".ant-calendar-picker-input")
|
||||
.eq(1)
|
||||
.should("have.value", proposal.milestones[1].date.expect);
|
||||
cy.wait(1000);
|
||||
cy.contains(".CreateFlow-footer-button", "Continue").click();
|
||||
});
|
||||
|
||||
it("create flow step 5", () => {
|
||||
cy.window()
|
||||
.then(w => (w as any).web3.eth.getAccounts())
|
||||
.then(accts => {
|
||||
cy.get('input[name="payOutAddress"]').type(accts[0]);
|
||||
cy.get("button")
|
||||
.contains("Add another trustee")
|
||||
.click({ force: true });
|
||||
cy.get(
|
||||
'input[placeholder="0x8B0B72F8bDE212991135668922fD5acE557DE6aB"]'
|
||||
)
|
||||
.eq(1)
|
||||
.type(accts[1]);
|
||||
cy.get('input[name="deadline"][value="2592000"]').click({
|
||||
force: true
|
||||
});
|
||||
cy.get('input[name="milestoneDeadline"][value="259200"]').click({
|
||||
force: true
|
||||
});
|
||||
});
|
||||
cy.wait(1000);
|
||||
cy.contains(".CreateFlow-footer-button", "Continue").click();
|
||||
});
|
||||
|
||||
it("publishes the proposal", () => {
|
||||
cy.get("button")
|
||||
.contains("Publish")
|
||||
.click();
|
||||
cy.get(".CreateFinal-loader-text").contains("Deploying contract...");
|
||||
cy.get(".CreateFinal-message-text a", { timeout: 20000 })
|
||||
.contains("Click here")
|
||||
.click();
|
||||
cy.get(".Proposal-top-main-title").contains(proposal.title);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,61 @@
|
|||
/// <reference types="cypress"/>
|
||||
import {
|
||||
loadWeb3,
|
||||
increaseTime,
|
||||
syncTimeWithEvm,
|
||||
randomString
|
||||
} from "../helpers";
|
||||
import { createDemoProposal, authenticateUser } from "../parts";
|
||||
|
||||
describe("create.fund.cancel", () => {
|
||||
const id = randomString();
|
||||
const title = `[${id}] e2e create fund cancel`;
|
||||
const amount = "1";
|
||||
|
||||
afterEach(function() {
|
||||
if (this.currentTest.state === "failed") {
|
||||
(Cypress as any).runner.stop();
|
||||
}
|
||||
});
|
||||
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
|
||||
it("create demo proposal", () => {
|
||||
createDemoProposal(cy, title, amount);
|
||||
});
|
||||
|
||||
it("funds the proposal with account 5", () => {
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(5) }));
|
||||
cy.get(".ant-input", { timeout: 20000 }).type(amount);
|
||||
cy.get(".ant-form > .ant-btn").click();
|
||||
cy.get(".ProposalCampaignBlock-fundingOver", { timeout: 20000 }).contains(
|
||||
"Proposal has been funded"
|
||||
);
|
||||
});
|
||||
|
||||
it("cancels the proposal (refund contributors)", () => {
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.contains(".Proposal-top-main-menu > .ant-btn", "Actions").click();
|
||||
cy.contains(".ant-dropdown-menu-item", "Refund contributors").click();
|
||||
cy.contains(".ant-modal-footer > div button", "Confirm").click();
|
||||
cy.get(".ant-modal-wrap", { timeout: 20000 }).should("not.be.visible");
|
||||
cy.contains(".Proposal-top-main-menu > .ant-btn", "Actions").click();
|
||||
cy.contains(".ant-dropdown-menu-item", "Refund contributors").should(
|
||||
"have.attr",
|
||||
"aria-disabled",
|
||||
"true"
|
||||
);
|
||||
});
|
||||
|
||||
it("refunds the contributor (account 5)", () => {
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(5) }));
|
||||
cy.contains(".ant-tabs-nav > :nth-child(1) > :nth-child(4)", "Refund", {
|
||||
timeout: 20000
|
||||
}).click();
|
||||
// force disables cypress' auto scrolling which messes up UI in this case
|
||||
cy.contains(".ant-btn", "Get your refund").click({ force: true });
|
||||
cy.contains("body", "Your refund has been processed", { timeout: 20000 });
|
||||
});
|
||||
});
|
|
@ -0,0 +1,126 @@
|
|||
/// <reference types="cypress"/>
|
||||
import {
|
||||
loadWeb3,
|
||||
randomString,
|
||||
syncTimeWithEvm,
|
||||
increaseTime
|
||||
} from "../helpers";
|
||||
import { createDemoProposal, fundProposal, authenticateUser } from "../parts";
|
||||
|
||||
describe("create.fund.complete.minority-no-votes", () => {
|
||||
const id = randomString();
|
||||
const title = `[${id}] e2e minority no-votes complete`;
|
||||
const amount = "1";
|
||||
|
||||
afterEach(function() {
|
||||
if (this.currentTest.state === "failed") {
|
||||
//(Cypress as any).runner.stop();
|
||||
this.skip();
|
||||
}
|
||||
});
|
||||
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
|
||||
it("creates demo proposal", () => {
|
||||
createDemoProposal(cy, title, amount);
|
||||
});
|
||||
|
||||
it("funds the proposal from accounts 5, 6 & 7", () => {
|
||||
fundProposal(cy, 5, 0.1);
|
||||
fundProposal(cy, 6, 0.2);
|
||||
fundProposal(cy, 7, 0.7);
|
||||
cy.get(".ProposalCampaignBlock-fundingOver", { timeout: 20000 }).contains(
|
||||
"Proposal has been funded"
|
||||
);
|
||||
});
|
||||
|
||||
it("receives initial payout", () => {
|
||||
// MILESTONE 1
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.get(".MilestoneAction-top > div > .ant-btn", { timeout: 20000 }).click();
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive initial payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
});
|
||||
|
||||
it("requests milestone 2 payout", () => {
|
||||
// MILESTONE 2
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
cy.contains(".MilestoneAction-progress-text", "voted against payout", {
|
||||
timeout: 20000
|
||||
});
|
||||
});
|
||||
|
||||
it("minority funder (acct 5) votes no", () => {
|
||||
// VOTE NO
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(5) }));
|
||||
cy.contains(".ant-btn", "Vote against payout", { timeout: 20000 })
|
||||
.click()
|
||||
.should("have.class", "ant-btn-loading");
|
||||
cy.contains(".ant-btn", "Revert vote against payout", { timeout: 20000 });
|
||||
});
|
||||
|
||||
it("expires milestone 2 voting period & receives payout", () => {
|
||||
// EXPIRE
|
||||
increaseTime(cy, 70000);
|
||||
// RECEIVE PAYOUT
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
});
|
||||
|
||||
it("requests milestone 3 payout", () => {
|
||||
// MILESTONE 3
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
cy.contains(".MilestoneAction-progress-text", "voted against payout", {
|
||||
timeout: 20000
|
||||
});
|
||||
});
|
||||
|
||||
it("minority funder (acct 5) votes no", () => {
|
||||
// VOTE NO
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(5) }));
|
||||
cy.contains(".ant-btn", "Vote against payout", { timeout: 20000 })
|
||||
.click()
|
||||
.should("have.class", "ant-btn-loading");
|
||||
cy.contains(".ant-btn", "Revert vote against payout", { timeout: 20000 });
|
||||
});
|
||||
|
||||
it("expires milestone 3 voting period & receives payout", () => {
|
||||
// EXPIRE
|
||||
increaseTime(cy, 70000);
|
||||
// RECEIVE PAYOUT
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
});
|
||||
|
||||
it("should not have receive button", () => {
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).should("not.exist");
|
||||
});
|
||||
});
|
|
@ -0,0 +1,103 @@
|
|||
/// <reference types="cypress"/>
|
||||
import {
|
||||
loadWeb3,
|
||||
increaseTime,
|
||||
syncTimeWithEvm,
|
||||
randomString
|
||||
} from "../helpers";
|
||||
import { createDemoProposal, authenticateUser } from "../parts";
|
||||
|
||||
describe("create.fund.complete", () => {
|
||||
const id = randomString();
|
||||
const title = `[${id}] e2e create fund complete`;
|
||||
const amount = "1";
|
||||
|
||||
afterEach(function() {
|
||||
if (this.currentTest.state === "failed") {
|
||||
//(Cypress as any).runner.stop();
|
||||
this.skip();
|
||||
}
|
||||
});
|
||||
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
|
||||
it("create demo proposal", () => {
|
||||
createDemoProposal(cy, title, amount);
|
||||
});
|
||||
|
||||
it("funds the proposal with account 5", () => {
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(5) }));
|
||||
cy.get(".ant-input", { timeout: 20000 }).type(amount);
|
||||
cy.get(".ant-form > .ant-btn").click();
|
||||
cy.get(".ProposalCampaignBlock-fundingOver", { timeout: 20000 }).contains(
|
||||
"Proposal has been funded"
|
||||
);
|
||||
});
|
||||
|
||||
it("receives initial payout", () => {
|
||||
// MILESTONE 1
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request initial payout",
|
||||
{ timeout: 20000 }
|
||||
)
|
||||
.as("RequestPayout")
|
||||
.click();
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive initial payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
});
|
||||
|
||||
it("requests and receives milestone 2 payout", () => {
|
||||
// MILESTONE 2
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
cy.contains(".MilestoneAction-progress-text", "voted against payout", {
|
||||
timeout: 20000
|
||||
});
|
||||
// EXPIRE
|
||||
increaseTime(cy, 70000);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
});
|
||||
|
||||
it("requests and receives milestone 3 payout", () => {
|
||||
// MILESTONE 3
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
cy.contains(".MilestoneAction-progress-text", "voted against payout", {
|
||||
timeout: 20000
|
||||
});
|
||||
// EXPIRE
|
||||
increaseTime(cy, 70000);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
});
|
||||
|
||||
it("should not have receive button", () => {
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).should("not.exist");
|
||||
});
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
/// <reference types="cypress"/>
|
||||
import { loadWeb3, randomString, syncTimeWithEvm } from "../helpers";
|
||||
import { createDemoProposal, fundProposal, authenticateUser } from "../parts";
|
||||
|
||||
describe("create.fund.ms2.majority-no-vote", () => {
|
||||
const id = randomString();
|
||||
const title = `[${id}] e2e ms2 majority no-vote`;
|
||||
const amount = "1";
|
||||
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
|
||||
it("creates demo proposal", () => {
|
||||
createDemoProposal(cy, title, amount);
|
||||
});
|
||||
|
||||
it("fund the proposal with 5th account", () => {
|
||||
fundProposal(cy, 5, 1);
|
||||
cy.get(".ProposalCampaignBlock-fundingOver", { timeout: 20000 }).contains(
|
||||
"Proposal has been funded"
|
||||
);
|
||||
});
|
||||
|
||||
it("receives initial payout for milestone 1", () => {
|
||||
// MILESTONE 1
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.get(".MilestoneAction-top > div > .ant-btn", { timeout: 20000 }).click();
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive initial payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
);
|
||||
});
|
||||
|
||||
it("requests milestone 2 payout", () => {
|
||||
// MILESTONE 2
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
cy.contains(".MilestoneAction-progress-text", "voted against payout", {
|
||||
timeout: 20000
|
||||
});
|
||||
});
|
||||
|
||||
it("vote against milestone 2 payout as account 5", () => {
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(5) }));
|
||||
cy.contains(".ant-btn", "Vote against payout", { timeout: 20000 }).click();
|
||||
cy.contains(".ant-btn", "Revert vote against payout", { timeout: 20000 });
|
||||
});
|
||||
});
|
|
@ -0,0 +1,87 @@
|
|||
/// <reference types="cypress"/>
|
||||
import {
|
||||
loadWeb3,
|
||||
randomString,
|
||||
syncTimeWithEvm,
|
||||
increaseTime
|
||||
} from "../helpers";
|
||||
import { createDemoProposal, fundProposal, authenticateUser } from "../parts";
|
||||
|
||||
describe("create.fund.ms2.no-vote.re-vote", () => {
|
||||
const id = randomString();
|
||||
const title = `[${id}] e2e ms2 no-vote expire re-vote`;
|
||||
const amount = "1";
|
||||
|
||||
afterEach(function() {
|
||||
if (this.currentTest.state === "failed") {
|
||||
//(Cypress as any).runner.stop();
|
||||
this.skip();
|
||||
}
|
||||
});
|
||||
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
|
||||
it("creates demo proposal", () => {
|
||||
createDemoProposal(cy, title, amount);
|
||||
});
|
||||
|
||||
it("fund the proposal with 5th account", () => {
|
||||
fundProposal(cy, 5, 1);
|
||||
cy.get(".ProposalCampaignBlock-fundingOver", { timeout: 20000 }).contains(
|
||||
"Proposal has been funded"
|
||||
);
|
||||
});
|
||||
|
||||
it("receives initial payout for milestone 1", () => {
|
||||
// MILESTONE 1
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.get(".MilestoneAction-top > div > .ant-btn", { timeout: 20000 }).click();
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive initial payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
});
|
||||
|
||||
it("request milestone 2 payout", () => {
|
||||
// MILESTONE 2
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
cy.contains(".MilestoneAction-progress-text", "voted against payout", {
|
||||
timeout: 20000
|
||||
});
|
||||
});
|
||||
|
||||
it("vote against milestone 2 payout as 5th account", () => {
|
||||
// reload page with 5th account
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(5) }));
|
||||
cy.contains(".ant-btn", "Vote against payout", { timeout: 20000 })
|
||||
.click()
|
||||
.should("have.class", "ant-btn-loading");
|
||||
cy.contains(".ant-btn", "Revert vote against payout", { timeout: 20000 });
|
||||
});
|
||||
|
||||
it("milestone 2 vote expires and payout is requested again", () => {
|
||||
// EXPIRE
|
||||
increaseTime(cy, 70000);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.contains("Payout was voted against");
|
||||
// RE-REQUEST PAYOUT
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
// TODO: fix this bug (the following fails)
|
||||
cy.contains(".MilestoneAction-progress-text", "voted against payout", {
|
||||
timeout: 20000
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,69 @@
|
|||
/// <reference types="cypress"/>
|
||||
import {
|
||||
loadWeb3,
|
||||
randomString,
|
||||
syncTimeWithEvm,
|
||||
increaseTime
|
||||
} from "../helpers";
|
||||
import { createDemoProposal, fundProposal, authenticateUser } from "../parts";
|
||||
|
||||
describe("create.fund.ms2.refund-after-payout", () => {
|
||||
const id = randomString();
|
||||
const title = `[${id}] e2e ms2 refund after payout`;
|
||||
const amount = "1";
|
||||
|
||||
afterEach(function() {
|
||||
if (this.currentTest.state === "failed") {
|
||||
//(Cypress as any).runner.stop();
|
||||
this.skip();
|
||||
}
|
||||
});
|
||||
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
|
||||
it("creates demo proposal", () => {
|
||||
createDemoProposal(cy, title, amount);
|
||||
});
|
||||
|
||||
it("fund the proposal with account 5", () => {
|
||||
fundProposal(cy, 5, 1);
|
||||
cy.get(".ProposalCampaignBlock-fundingOver", { timeout: 20000 }).contains(
|
||||
"Proposal has been funded"
|
||||
);
|
||||
});
|
||||
|
||||
it("receives initial payout for milestone 1", () => {
|
||||
// MILESTONE 1
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.get(".MilestoneAction-top > div > .ant-btn", { timeout: 20000 }).click();
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive initial payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
);
|
||||
});
|
||||
|
||||
it("majority refund vote and get refund (account 5)", () => {
|
||||
// REFUND
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(5) }));
|
||||
cy.contains(".ant-tabs-nav > :nth-child(1) > :nth-child(4)", "Refund", {
|
||||
timeout: 20000
|
||||
}).click();
|
||||
// INCREASE TIME
|
||||
increaseTime(cy, 70000);
|
||||
// force disables cypress' auto scrolling which messes up UI in this case
|
||||
cy.contains(".ant-btn", "Vote for refund").click({ force: true });
|
||||
cy.contains(".ant-btn", "Get your refund", { timeout: 20000 }).click({
|
||||
force: true
|
||||
});
|
||||
cy.contains("body", "Your refund has been processed", { timeout: 20000 });
|
||||
});
|
||||
});
|
|
@ -0,0 +1,93 @@
|
|||
/// <reference types="cypress"/>
|
||||
import {
|
||||
loadWeb3,
|
||||
randomString,
|
||||
syncTimeWithEvm,
|
||||
increaseTime
|
||||
} from "../helpers";
|
||||
import { createDemoProposal, fundProposal, authenticateUser } from "../parts";
|
||||
|
||||
describe("create.fund.ms2.revert-no-vote", () => {
|
||||
const id = randomString();
|
||||
const title = `[${id}] e2e ms2 revert no-vote`;
|
||||
const amount = "1";
|
||||
|
||||
afterEach(function() {
|
||||
if (this.currentTest.state === "failed") {
|
||||
//(Cypress as any).runner.stop();
|
||||
this.skip();
|
||||
}
|
||||
});
|
||||
|
||||
it("authenticates and creates if necessary", () => {
|
||||
authenticateUser(cy, 0);
|
||||
});
|
||||
|
||||
it("creates demo proposal", () => {
|
||||
createDemoProposal(cy, title, amount);
|
||||
});
|
||||
|
||||
it("funds the proposal with 5th account", () => {
|
||||
fundProposal(cy, 5, 1);
|
||||
cy.get(".ProposalCampaignBlock-fundingOver", { timeout: 20000 }).contains(
|
||||
"Proposal has been funded"
|
||||
);
|
||||
});
|
||||
|
||||
it("receives initial payout for milestone 1", () => {
|
||||
// MILESTONE 1
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.get(".MilestoneAction-top > div > .ant-btn", { timeout: 20000 }).click();
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive initial payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
});
|
||||
|
||||
it("requests milestone 2 payout", () => {
|
||||
// MILESTONE 2
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
).click();
|
||||
cy.contains(".MilestoneAction-progress-text", "voted against payout", {
|
||||
timeout: 20000
|
||||
});
|
||||
});
|
||||
|
||||
it("votes against milestone 2 payout as account 5 and then reverts the vote", () => {
|
||||
// NO VOTE... REVERT
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(5) }));
|
||||
cy.contains(".ant-btn", "Vote against payout", { timeout: 20000 })
|
||||
.click()
|
||||
.should("have.class", "ant-btn-loading");
|
||||
cy.contains(".ant-btn", "Revert vote against payout", { timeout: 20000 })
|
||||
.click()
|
||||
.should("have.class", "ant-btn-loading");
|
||||
cy.contains(".ant-btn", "Vote against payout", { timeout: 20000 });
|
||||
});
|
||||
|
||||
it("milestone 2 vote expires and payout is received", () => {
|
||||
// EXPIRE
|
||||
increaseTime(cy, 70000);
|
||||
// PAYOUT
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(0) }));
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Receive milestone payout"
|
||||
).click();
|
||||
});
|
||||
|
||||
it("milestone 3 becomes active", () => {
|
||||
// MILESTONE 3
|
||||
cy.contains(
|
||||
".MilestoneAction-top > div > .ant-btn",
|
||||
"Request milestone payout",
|
||||
{ timeout: 20000 }
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,192 +0,0 @@
|
|||
/// <reference types="cypress"/>
|
||||
import { loadWeb3, randomString, randomHex } from "../helpers";
|
||||
|
||||
describe("create proposal", () => {
|
||||
it("should load and be able to browse pages", () => {
|
||||
cy.visit("http://localhost:3000/create", { onBeforeLoad: loadWeb3 });
|
||||
|
||||
// populate ethAccounts
|
||||
cy.wait(1000);
|
||||
cy.window()
|
||||
.then(w => (w as any).web3.eth.getAccounts())
|
||||
.as("EthAccounts");
|
||||
|
||||
// demo proposal
|
||||
// cy.get("button.CreateFlow-footer-example").click();
|
||||
|
||||
const time = new Date().toLocaleString();
|
||||
const id = randomString();
|
||||
const randomEthHex = randomHex(32);
|
||||
const nextYear = new Date().getUTCFullYear() + 1;
|
||||
const proposal = {
|
||||
title: "e2e - smoke - create " + time,
|
||||
brief: "e2e brief",
|
||||
category: "Community", // .anticon-team
|
||||
targetAmount: 5,
|
||||
body: `#### e2e Proposal ${id} {enter} **created** ${time} `,
|
||||
team: [
|
||||
{
|
||||
name: "Alisha Endtoend",
|
||||
title: "QA Robot0",
|
||||
ethAddress: `0x0000${randomEthHex}0000`,
|
||||
emailAddress: `qa.alisha.${id}@grant.io`
|
||||
},
|
||||
{
|
||||
name: "Billy Endtoend",
|
||||
title: "QA Robot1",
|
||||
ethAddress: `0x1111${randomEthHex}1111`,
|
||||
emailAddress: `qa.billy.${id}@grant.io`
|
||||
}
|
||||
],
|
||||
milestones: [
|
||||
{
|
||||
title: `e2e Milestone ${id} 0`,
|
||||
body: `e2e Milestone ${id} {enter} body 0`,
|
||||
date: {
|
||||
y: nextYear,
|
||||
m: "Jan",
|
||||
expect: "January " + nextYear
|
||||
}
|
||||
},
|
||||
{
|
||||
title: `e2e Milestone ${id} 1`,
|
||||
body: `e2e Milestone ${id} {enter} body 1`,
|
||||
date: {
|
||||
y: nextYear,
|
||||
m: "Feb",
|
||||
expect: "February " + nextYear
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// step 1
|
||||
cy.get('.CreateFlow input[name="title"]', { timeout: 20000 }).type(
|
||||
proposal.title
|
||||
);
|
||||
cy.get('.CreateFlow textarea[name="brief"]').type(proposal.brief);
|
||||
cy.contains("Select a category").click();
|
||||
cy.get(".ant-select-dropdown li .anticon-team").click();
|
||||
cy.get('.CreateFlow input[name="amountToRaise"]').type(
|
||||
"" + proposal.targetAmount
|
||||
);
|
||||
cy.get(".CreateFlow-footer-button")
|
||||
.contains("Continue")
|
||||
.as("Continue")
|
||||
.click();
|
||||
|
||||
// step 2
|
||||
cy.get('.TeamMember-info input[name="name"]').type(proposal.team[0].name);
|
||||
cy.get('.TeamMember-info input[name="title"]').type(proposal.team[0].title);
|
||||
cy.get("@EthAccounts").then(accts => {
|
||||
cy.get('.TeamMember-info input[name="ethAddress"]').type(
|
||||
accts[0].toString()
|
||||
);
|
||||
});
|
||||
cy.get('.TeamMember-info input[name="emailAddress"]').type(
|
||||
proposal.team[0].emailAddress
|
||||
);
|
||||
cy.get("button")
|
||||
.contains("Save changes")
|
||||
.click({ force: true });
|
||||
|
||||
cy.get("button.TeamForm-add").click();
|
||||
cy.get('.TeamMember-info input[name="name"]').type(proposal.team[1].name);
|
||||
cy.get('.TeamMember-info input[name="title"]').type(proposal.team[1].title);
|
||||
cy.get("@EthAccounts").then(accts => {
|
||||
cy.get('.TeamMember-info input[name="ethAddress"]').type(
|
||||
accts[1].toString()
|
||||
);
|
||||
});
|
||||
cy.get('.TeamMember-info input[name="emailAddress"]').type(
|
||||
proposal.team[1].emailAddress
|
||||
);
|
||||
cy.get("button")
|
||||
.contains("Save changes")
|
||||
.click({ force: true });
|
||||
|
||||
cy.wait(1000);
|
||||
cy.get("@Continue").click();
|
||||
|
||||
// step 3
|
||||
cy.get(".DraftEditor-editorContainer > div").type(proposal.body);
|
||||
cy.get(".mde-tabs > :nth-child(2)").click();
|
||||
|
||||
cy.wait(1000);
|
||||
cy.get("@Continue").click();
|
||||
|
||||
// step 4
|
||||
cy.get('input[name="title"]').type(proposal.milestones[0].title);
|
||||
cy.get('textarea[name="body"]').type(proposal.milestones[0].body);
|
||||
cy.get('input[placeholder="Expected completion date"]').click();
|
||||
cy.get(".ant-calendar-month-panel-next-year-btn").click();
|
||||
cy.get(".ant-calendar-month-panel-month")
|
||||
.contains(proposal.milestones[0].date.m)
|
||||
.click();
|
||||
cy.get(".ant-calendar-picker-input").should(
|
||||
"have.value",
|
||||
proposal.milestones[0].date.expect
|
||||
);
|
||||
|
||||
cy.get("button")
|
||||
.contains("Add another milestone")
|
||||
.click({ force: true });
|
||||
|
||||
cy.get('input[name="title"]')
|
||||
.eq(1)
|
||||
.type(proposal.milestones[1].title);
|
||||
cy.get('textarea[name="body"]')
|
||||
.eq(1)
|
||||
.type(proposal.milestones[1].body);
|
||||
cy.get('input[placeholder="Expected completion date"]')
|
||||
.eq(1)
|
||||
.click();
|
||||
cy.get(".ant-calendar-month-panel-next-year-btn").click();
|
||||
cy.get(".ant-calendar-month-panel-month")
|
||||
.contains(proposal.milestones[1].date.m)
|
||||
.click();
|
||||
cy.get(".ant-calendar-picker-input")
|
||||
.eq(1)
|
||||
.should("have.value", proposal.milestones[1].date.expect);
|
||||
|
||||
cy.wait(1000);
|
||||
cy.get("@Continue").click();
|
||||
|
||||
// step 5
|
||||
cy.window()
|
||||
.then(w => (w as any).web3.eth.getAccounts())
|
||||
.then(accts => {
|
||||
cy.get('input[name="payOutAddress"]').type(accts[0]);
|
||||
cy.get("button")
|
||||
.contains("Add another trustee")
|
||||
.click({ force: true });
|
||||
cy.get(
|
||||
'input[placeholder="0x8B0B72F8bDE212991135668922fD5acE557DE6aB"]'
|
||||
)
|
||||
.eq(1)
|
||||
.type(accts[1]);
|
||||
cy.get('input[name="deadline"][value="2592000"]').click({
|
||||
force: true
|
||||
});
|
||||
cy.get('input[name="milestoneDeadline"][value="259200"]').click({
|
||||
force: true
|
||||
});
|
||||
});
|
||||
|
||||
cy.wait(1000);
|
||||
cy.get("@Continue").click();
|
||||
|
||||
// final
|
||||
cy.get("button")
|
||||
.contains("Publish")
|
||||
.click();
|
||||
cy.get(".CreateFinal-loader-text").contains("Deploying contract...");
|
||||
|
||||
cy.get(".CreateFinal-message-text a", { timeout: 20000 })
|
||||
.contains("Click here")
|
||||
.click();
|
||||
|
||||
// done
|
||||
cy.get(".Proposal-top-main-title").contains(proposal.title);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
/// <reference types="cypress"/>
|
||||
import {
|
||||
loadWeb3,
|
||||
increaseTime,
|
||||
randomString,
|
||||
syncTimeWithEvm
|
||||
} from "../helpers";
|
||||
|
||||
// describe("sandbox", () => {
|
||||
// it("how to increase time", () => {
|
||||
// cy.visit("http://localhost:3000", { onBeforeLoad: loadWeb3(0) });
|
||||
// // increase time on browser and ganache
|
||||
// increaseTime(cy, 60000);
|
||||
// });
|
||||
// });
|
|
@ -0,0 +1,107 @@
|
|||
/// <reference types="cypress"/>
|
||||
import { syncTimeWithEvm, loadWeb3, testAccounts } from "./helpers";
|
||||
|
||||
export const authenticateUser = (
|
||||
cy: Cypress.Chainable,
|
||||
accountIndex: number
|
||||
) => {
|
||||
const name = `Qual Itty ${accountIndex}`;
|
||||
const ethAccount = testAccounts[accountIndex][0];
|
||||
const title = `QA Robot ${accountIndex}`;
|
||||
const email = `qa.robot.${accountIndex}@grant.io`;
|
||||
cy.visit("http://localhost:3000", { onBeforeLoad: loadWeb3(accountIndex) });
|
||||
syncTimeWithEvm(cy);
|
||||
cy.get(".AuthButton").click();
|
||||
cy.request({
|
||||
url: `http://localhost:5000/api/v1/users/${ethAccount}`,
|
||||
method: "GET",
|
||||
failOnStatusCode: false
|
||||
})
|
||||
.its("status")
|
||||
.then(status => {
|
||||
if (status === 200) {
|
||||
cy.contains("button", "Prove identity").click();
|
||||
} else {
|
||||
cy.get("input[name='name']").type(name);
|
||||
cy.get("input[name='title']").type(title);
|
||||
cy.get("input[name='email']").type(email);
|
||||
cy.contains("button", "Claim Identity").click();
|
||||
}
|
||||
cy.contains(".ProfileUser", email);
|
||||
});
|
||||
};
|
||||
|
||||
export const createDemoProposal = (
|
||||
cy: Cypress.Chainable,
|
||||
title: string,
|
||||
amount: string
|
||||
) => {
|
||||
cy.get('[href="/create"]').click();
|
||||
|
||||
// expects to be @ /create
|
||||
cy.url().should("contain", "/create");
|
||||
|
||||
cy.log("CREATE DEMO PROPOSAL", title, amount);
|
||||
|
||||
// demo proposal
|
||||
cy.get("button.CreateFlow-footer-example").click();
|
||||
|
||||
// change name
|
||||
cy.get(".ant-steps > :nth-child(1)").click();
|
||||
cy.get('.CreateFlow input[name="title"]', { timeout: 20000 })
|
||||
.clear()
|
||||
.type(title)
|
||||
.blur();
|
||||
cy.get('.CreateFlow input[name="amountToRaise"]')
|
||||
.clear()
|
||||
.type(amount)
|
||||
.blur();
|
||||
cy.wait(1000);
|
||||
|
||||
// remove extra trustees
|
||||
cy.get(".ant-steps > :nth-child(5)").click();
|
||||
cy.get(
|
||||
":nth-child(11) > .ant-form-item-control-wrapper div > button"
|
||||
).click();
|
||||
cy.get(
|
||||
":nth-child(10) > .ant-form-item-control-wrapper div > button"
|
||||
).click();
|
||||
cy.get(":nth-child(9) > .ant-form-item-control-wrapper div > button").click();
|
||||
cy.get(":nth-child(8) > .ant-form-item-control-wrapper div > button").click();
|
||||
cy.get(":nth-child(7) > .ant-form-item-control-wrapper div > button").click();
|
||||
cy.wait(1000);
|
||||
cy.get(".CreateFlow-footer-button")
|
||||
.contains("Continue")
|
||||
.click();
|
||||
|
||||
// final
|
||||
cy.get("button")
|
||||
.contains("Publish")
|
||||
.click();
|
||||
cy.get(".CreateFinal-loader-text").contains("Deploying contract...");
|
||||
cy.get(".CreateFinal-message-text a", { timeout: 30000 })
|
||||
.contains("Click here")
|
||||
.click();
|
||||
|
||||
// created
|
||||
cy.get(".Proposal-top-main-title").contains(title);
|
||||
};
|
||||
|
||||
export const fundProposal = (
|
||||
cy: Cypress.Chainable,
|
||||
accountIndex: number,
|
||||
amount: number
|
||||
) => {
|
||||
// expects to be @ /proposals/<proposal>
|
||||
cy.url().should("contain", "/proposals/");
|
||||
|
||||
// reload page with accountIndex account
|
||||
syncTimeWithEvm(cy);
|
||||
cy.url().then(url => cy.visit(url, { onBeforeLoad: loadWeb3(accountIndex) }));
|
||||
|
||||
// fund proposal
|
||||
cy.get(".ant-input", { timeout: 20000 }).type(amount + "");
|
||||
cy.contains(".ant-form > .ant-btn", "Fund this project", { timeout: 20000 })
|
||||
.click()
|
||||
.should("not.have.attr", "loading");
|
||||
};
|
|
@ -2,3 +2,7 @@ declare module "*.json" {
|
|||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module "eth-sig-util" {
|
||||
export function signTypedData(k: any, d: any): string;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"@cypress/webpack-preprocessor": "^2.0.1",
|
||||
"@types/web3": "^1.0.3",
|
||||
"cypress": "^3.1.0",
|
||||
"eth-sig-util": "^2.1.0",
|
||||
"ts-loader": "^5.0.0",
|
||||
"typescript": "^3.0.3",
|
||||
"web3": "^1.0.0-beta.36",
|
||||
|
|
115
e2e/yarn.lock
115
e2e/yarn.lock
|
@ -1011,6 +1011,16 @@ binary-extensions@^1.0.0:
|
|||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
|
||||
|
||||
bindings@^1.2.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7"
|
||||
|
||||
bip66@^1.1.3:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22"
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
bl@^1.0.0:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
|
||||
|
@ -1040,7 +1050,7 @@ bn.js@4.11.6:
|
|||
version "4.11.6"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
|
||||
|
||||
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.6, bn.js@^4.4.0:
|
||||
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0:
|
||||
version "4.11.8"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
|
||||
|
||||
|
@ -1100,7 +1110,7 @@ brorand@^1.0.1:
|
|||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
||||
|
||||
browserify-aes@^1.0.0, browserify-aes@^1.0.4:
|
||||
browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
|
||||
dependencies:
|
||||
|
@ -1213,7 +1223,7 @@ buffer@^4.3.0:
|
|||
ieee754 "^1.1.4"
|
||||
isarray "^1.0.0"
|
||||
|
||||
buffer@^5.0.5:
|
||||
buffer@^5.0.5, buffer@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6"
|
||||
dependencies:
|
||||
|
@ -1779,6 +1789,14 @@ domain-browser@^1.1.1:
|
|||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
|
||||
|
||||
drbg.js@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b"
|
||||
dependencies:
|
||||
browserify-aes "^1.0.6"
|
||||
create-hash "^1.1.2"
|
||||
create-hmac "^1.1.4"
|
||||
|
||||
duplexer3@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
|
||||
|
@ -1820,7 +1838,7 @@ elliptic@6.3.3:
|
|||
hash.js "^1.0.0"
|
||||
inherits "^2.0.1"
|
||||
|
||||
elliptic@^6.0.0, elliptic@^6.4.0:
|
||||
elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0:
|
||||
version "6.4.1"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a"
|
||||
dependencies:
|
||||
|
@ -1920,6 +1938,46 @@ eth-lib@0.2.7:
|
|||
elliptic "^6.4.0"
|
||||
xhr-request-promise "^0.1.2"
|
||||
|
||||
eth-sig-util@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.1.0.tgz#33e60e5486897a2ddeb4bf5a0993b2c6d5cc9e19"
|
||||
dependencies:
|
||||
buffer "^5.2.1"
|
||||
elliptic "^6.4.0"
|
||||
ethereumjs-abi "0.6.5"
|
||||
ethereumjs-util "^5.1.1"
|
||||
tweetnacl "^1.0.0"
|
||||
tweetnacl-util "^0.15.0"
|
||||
|
||||
ethereumjs-abi@0.6.5:
|
||||
version "0.6.5"
|
||||
resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241"
|
||||
dependencies:
|
||||
bn.js "^4.10.0"
|
||||
ethereumjs-util "^4.3.0"
|
||||
|
||||
ethereumjs-util@^4.3.0:
|
||||
version "4.5.0"
|
||||
resolved "http://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
|
||||
dependencies:
|
||||
bn.js "^4.8.0"
|
||||
create-hash "^1.1.2"
|
||||
keccakjs "^0.2.0"
|
||||
rlp "^2.0.0"
|
||||
secp256k1 "^3.0.1"
|
||||
|
||||
ethereumjs-util@^5.1.1:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642"
|
||||
dependencies:
|
||||
bn.js "^4.11.0"
|
||||
create-hash "^1.1.2"
|
||||
ethjs-util "^0.1.3"
|
||||
keccak "^1.0.2"
|
||||
rlp "^2.0.0"
|
||||
safe-buffer "^5.1.1"
|
||||
secp256k1 "^3.0.1"
|
||||
|
||||
ethers@4.0.0-beta.1:
|
||||
version "4.0.0-beta.1"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.1.tgz#0648268b83e0e91a961b1af971c662cdf8cbab6d"
|
||||
|
@ -1942,6 +2000,13 @@ ethjs-unit@0.1.6:
|
|||
bn.js "4.11.6"
|
||||
number-to-bn "1.7.0"
|
||||
|
||||
ethjs-util@^0.1.3:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536"
|
||||
dependencies:
|
||||
is-hex-prefixed "1.0.0"
|
||||
strip-hex-prefix "1.0.0"
|
||||
|
||||
eventemitter3@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0"
|
||||
|
@ -2872,7 +2937,16 @@ jsprim@^1.2.2:
|
|||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
keccakjs@^0.2.1:
|
||||
keccak@^1.0.2:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80"
|
||||
dependencies:
|
||||
bindings "^1.2.1"
|
||||
inherits "^2.0.3"
|
||||
nan "^2.2.1"
|
||||
safe-buffer "^5.1.0"
|
||||
|
||||
keccakjs@^0.2.0, keccakjs@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d"
|
||||
dependencies:
|
||||
|
@ -3238,6 +3312,10 @@ nan@^2.0.8, nan@^2.3.3, nan@^2.9.2:
|
|||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099"
|
||||
|
||||
nan@^2.2.1:
|
||||
version "2.11.1"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766"
|
||||
|
||||
nano-json-stream-parser@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f"
|
||||
|
@ -3926,6 +4004,12 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
|
|||
hash-base "^3.0.0"
|
||||
inherits "^2.0.1"
|
||||
|
||||
rlp@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9"
|
||||
dependencies:
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
run-queue@^1.0.0, run-queue@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
|
||||
|
@ -3990,6 +4074,19 @@ scryptsy@^1.2.1:
|
|||
dependencies:
|
||||
pbkdf2 "^3.0.3"
|
||||
|
||||
secp256k1@^3.0.1:
|
||||
version "3.5.2"
|
||||
resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.2.tgz#f95f952057310722184fe9c914e6b71281f2f2ae"
|
||||
dependencies:
|
||||
bindings "^1.2.1"
|
||||
bip66 "^1.1.3"
|
||||
bn.js "^4.11.3"
|
||||
create-hash "^1.1.2"
|
||||
drbg.js "^1.0.1"
|
||||
elliptic "^6.2.3"
|
||||
nan "^2.2.1"
|
||||
safe-buffer "^5.1.0"
|
||||
|
||||
seek-bzip@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc"
|
||||
|
@ -4526,10 +4623,18 @@ tunnel-agent@^0.6.0:
|
|||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
tweetnacl-util@^0.15.0:
|
||||
version "0.15.0"
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.0.tgz#4576c1cee5e2d63d207fee52f1ba02819480bc75"
|
||||
|
||||
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
version "0.14.5"
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||
|
||||
tweetnacl@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.0.tgz#713d8b818da42068740bf68386d0479e66fc8a7b"
|
||||
|
||||
type-is@~1.6.15, type-is@~1.6.16:
|
||||
version "1.6.16"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
|
||||
|
|
|
@ -16,7 +16,13 @@ const getContractInstance = async (
|
|||
deployedAddress = deployedAddress || contractDefinition.networks[networkId].address;
|
||||
|
||||
// create the instance
|
||||
return new web3.eth.Contract(contractDefinition.abi, deployedAddress);
|
||||
const contract = new web3.eth.Contract(contractDefinition.abi, deployedAddress);
|
||||
|
||||
// use gas from e2e injected window.web3.provider
|
||||
if ((web3.currentProvider as any)._e2eContractGas) {
|
||||
contract.options.gas = (web3.currentProvider as any)._e2eContractGas;
|
||||
}
|
||||
return contract;
|
||||
};
|
||||
|
||||
export default getContractInstance;
|
||||
|
|
|
@ -508,7 +508,7 @@ export function signData(data: object, dataTypes: object, primaryType: string) {
|
|||
primaryType,
|
||||
};
|
||||
|
||||
(web3.currentProvider as any).sendAsync(
|
||||
(web3.currentProvider as any).send(
|
||||
{
|
||||
method: 'eth_signTypedData_v3',
|
||||
params: [accounts[0], JSON.stringify(rawTypedData)],
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"heroku-postbuild": "yarn build",
|
||||
"tsc": "tsc",
|
||||
"link-contracts": "cd client/lib && ln -s ../../build/contracts contracts",
|
||||
"ganache": "ganache-cli -b 5",
|
||||
"ganache": "ganache-cli -b 5 -s testGrantIo -e 1000",
|
||||
"truffle": "truffle exec ./bin/init-truffle.js && cd client/lib/contracts && truffle console",
|
||||
"storybook": "start-storybook -p 9001 -c .storybook"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue