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; } }
関数とその機能を覚えていけば、行けそうな気がして来た