fundraiser_factory_test.js
const FundraiserFactoryContract = artifacts.require("FundraiserFactory");
const FundraiserContract = artifacts.require("Fundraiser");
contract("FundraiserFactory: deployment", ()=> {
it("has been deployed", async() => {
const fundraiserFactory = FundraiserFactoryContract.deployed();
assert(fundraiserFactory, "fundraiser factory was not deployed");
})
});
contract("FundraiserFactory: createFundraiser", (accounts) => {
let fundraiserFactory;
const name = "Beneficiary Name";
const url = "beneficiaryname.org";
const imageURL = "https://placekitten.com/600/350"
const description = "Beneficiary Description"
const beneficiary = accounts[1];
it("increments the fundraisersCount", async() => {
fundraiserFactory = await FundraiserFactoryContract.deployed();
const currentFundraisersCount = fundraiserFactory.fundraisersCount();
await fundraiserFactory.createFundraiser(
name,
url,
imageURL,
description,
beneficiary
);
const newFundraisersCount = await fundraiserFactory.fundraisersCount();
// assert.equal(
// newFundraisersCount - currentFundraisersCount,
// 1,
// "should increment by 1"
// );
});
it("emits the FundraiserCreated event", async() => {
fundraiserFactory = await FundraiserFactoryContract.deployed();
const tx = await fundraiserFactory.createFundraiser(
name,
url,
imageURL,
description,
beneficiary
);
const expectedEvent = "FundraiserCreated";
const actualEvent = tx.logs[0].event;
assert.equal(actualEvent, expectedEvent, "event should match");
})
});
contract("FundraiserFactory: fundraisers", (accounts) => {
async function createFundraiserFactory(fundraiserCount, accounts){
const factory = await FundraiserFactoryContract.new();
await addFundraisers(factory, fundraiserCount, accounts);
return factory;
}
async function addFundraisers(factory, count, accounts){
const name = "Beneficiary";
const lowerCaseName = name.toLowerCase();
const beneficiary = accounts[1];
for (let i = 0; i < count; i++){
await factory.createFundraiser(
`${name} ${i}`,
`${lowerCaseName}${i}.com`,
`${lowerCaseName}${i}.png`,
`Description for ${name} ${i}`,
beneficiary
);
}
}
describe("when fundraisers collection is empty", () => {
it("returns an empty collection", async() => {
const factory = await createFundraiserFactory(0, accounts);
const fundraisers = await factory.fundraisers(10, 0);
assert.equal(
fundraisers.length,
0,
"collection should be empty"
);
});
});
describe("varying limits", async() => {
let factory;
beforeEach(async() => {
factory = await createFundraiserFactory(30, accounts);
});
it("returns 10 results when limit requested is 10", async()=> {
const fundraisers = await factory.fundraisers(10, 0);
assert.equal(
fundraisers.length,
10,
"results size should be 10"
);
});
xit("returns 20 results when limit requested is 20", async() => {
const fundraisers = await factory.fundraisers(20, 0);
assert.equal(
fundraisers.length,
20,
"results size should be 20"
);
});
xit("returns 20 results when limit requested is 30", async() => {
const fundraisers = await factory.fundraisers(30, 0);
assert.equal(
fundraisers.length,
20,
"results size should be 20"
);
});
});
describe("varying offset", () => {
let factory;
beforeEach(async() => {
factory = await createFundraiserFactory(10, accounts);
});
it("contains the fundraiser with the appropriate offset", async() => {
const fundraisers = await factory.fundraisers(1, 0);
const fundraiser = await FundraiserContract.at(fundraisers[0]);
const name = await fundraiser.name();
assert.ok(await name.includes(0), `${name} did not include the offset`);
});
it("contains the fundraiser with the appropriate offset", async() => {
const fundraisers = await factory.fundraisers(1, 7);
const fundraiser = await FundraiserContract.at(fundraisers[0]);
const name = await fundraiser.name();
assert.ok(await name.includes(7), `${name} did not include the offset`);
})
});
describe("boundary conditions", ()=> {
let factory;
beforeEach(async() => {
factory = await createFundraiserFactory(10, accounts);
});
it("raises out of bounds error", async () => {
try {
await factory.fundraisers(1, 11);
assert.fail("error was not raised")
} catch(err) {
const expected = "offset out of bounds";
assert.ok(err.message.includes(expected), `${err.message}`);
}
});
it("adjusts return size to prevent out of bounds error", async() => {
try {
const fundraisers = await factory.fundraisers(10, 5);
assert.equal(
fundraisers.length,
5,
"collection adjusted"
);
} catch(err) {
assert.fail("limit and offset exceeded bounds");
}
})
})
})
contracts
pragma solidity >0.4.23 <=0.8.0;
import "./Fundraiser.sol";
contract FundraiserFactory {
uint256 constant maxLimit = 20;
Fundraiser[] private _fundraisers;
event FundraiserCreated(Fundraiser indexed fundraiser, address indexed owner);
function createFundraiser(
string memory name,
string memory url,
string memory imageURL,
string memory description,
address payable beneficiary
)
public {
Fundraiser fundraiser = new Fundraiser(
name,
url,
imageURL,
description,
beneficiary,
msg.sender
);
_fundraisers.push(fundraiser);
emit FundraiserCreated(fundraiser, fundraiser.owner());
}
function fundraisersCount() public view returns(uint256) {
return _fundraisers.length;
}
function fundraisers(uint256 limit, uint256 offset) public view returns(Fundraiser[] memory coll){
require(offset <= fundraisersCount(), "offset out of bounds");
uint256 size = fundraisersCount() - offset;
size = size < limit ? size : limit;
size = size < maxLimit ? size : maxLimit;
coll = new Fundraiser[](size);
for(uint256 i = 0; i < size; i++){
coll[i] = _fundraisers[offset + i];
}
return coll;
}
}
関数とその機能を覚えていけば、行けそうな気がして来た