-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple collections per seller #592
Conversation
bc45b66
to
ddc26fe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really good.
Just some thoughts
test/protocol/ExchangeHandlerTest.js
Outdated
it("should work on an additional collection", async function () { | ||
const externalId = `Brand1`; | ||
const contractURI = `https://brand1.com`; | ||
|
||
// Create a new collection | ||
await accountHandler.connect(assistant).createNewCollection(externalId, contractURI); | ||
|
||
offer.collectionIndex = 1; | ||
offer.id = await offerHandler.getNextOfferId(); | ||
exchange.id = await exchangeHandler.getNextExchangeId(); | ||
const tokenId = deriveTokenId(offer.id, exchange.id); | ||
|
||
// Create the offer | ||
await offerHandler | ||
.connect(assistant) | ||
.createOffer(offer, offerDates, offerDurations, disputeResolverId, agentId); | ||
|
||
// Commit to offer, creating a new exchange | ||
await exchangeHandler.connect(buyer).commitToOffer(buyer.address, offer.id, { value: price }); | ||
|
||
// expected address of the first additional collection | ||
const additionalCollectionAddress = calculateContractAddress(accountHandler.address, "2"); | ||
const additionalCollection = await ethers.getContractAt("BosonVoucher", additionalCollectionAddress); | ||
|
||
// Revoke the voucher, expecting event | ||
await expect(exchangeHandler.connect(assistant).revokeVoucher(exchange.id)) | ||
.to.emit(additionalCollection, "Transfer") | ||
.withArgs(buyer.address, ethers.constants.AddressZero, tokenId); | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose it would be more logical if we organized test contexts based on previous steps required instead of always grouping them by function. This way, we could avoid repeating a lot of pre-test setups. Sometimes I also feel that our test organization leads to test duplication. For example, if we want to test a code block in commitToOfferInternal
, we end up repeating the same test at least three times because we have three functions that call commitToOfferInternal
(commitToOffer, commitToPreMintedOffer, and more recently commitToConditionalOffer).
I'm not saying that you should do this in this PR, just wanted to bring this topic up for future discussions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that some test files are a bit out of hand, and would benefit from some refactoring.
But I'm not sure that the different grouping actually generally solves the duplication, it just turns the code around (it requires that some other part is duplicated).
For example, consider these two organizations:
opt 1:
context A
setup A
... other tests with setup A ...
test D with an additional setup D
context B
setup B
... other tests with setup B ...
test D with an additional setup D
opt 2:
context D
setup D
test D with an additional setup A
test D with an additional setup B
context XY
setup XY
...
test X with setup A
test Y with setup B
In both cases the test D
is the test that is a "duplicate", except that tested functions A and B are different (let's say commitToOffer
, commitToPreMintedOffer
). Test D requires a setup that is a combination of setups for A and D or B and D.
Opt 1 is similar to what we have now, so the top context is based on the function and we later duplicated the code for test D.
Now if we turn this around and group it by test D, we still need two tests, where one includes A specific setup and the other has B specific setup. We sure can do that. But there will still exist other contexts that will require either setup A or setup B. So instead of setup D being duplicated across contexts, now contexts A and B will be duplicated.
And in some cases, opt 2 is indeed better (for example, if setup D is long compared to setup A/B). So if we just wanted to optimize the tests we could regroup them. And that would lead to scenario-based contexts. We had that in v1 and I can tell you it was a nightmare to maintain. When some feature was added/removed it was sometimes even hard to accurately pinpoint into which scenario(s) we should add it.
Also, I think it makes sense to stick to the same option across all tests. And if I'm choosing between what have now and setup-based contexts, I'm sticking with the function based.
But I agree a lot of parts could be refactored to reuse the same code. Because now, if we make a change that affects a "duplicate" test, we need to go and find all affected instances. Ideally, the duplicated part would be a sort of util function (can be on a file level if other tests don't need it) and the test would simply invoke that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Utility functions make sense to me. We can start migrating to functions when we need to add or refactor a test. A separate file would be better IMO, as we could reuse it in different facets, such as ExchangeHandlerTest and OrchestrationHandlerTest. I believe this would help make the codebase more legible, as our test files are currently too large.
f991c72
to
a7662ad
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me !
*/ | ||
function getSellersCollections( | ||
uint256 _sellerId | ||
) external view returns (address defaultVoucherAddress, BosonTypes.Collection[] memory additionalCollections); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we worry about the Collection[] being too big ? Do we need something like a getCollection(CollectionID)
or something ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even if this is a good idea, i wouldn't block on it ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think is a good idea, nice catch.
I create an issue so this doesn't get loss
#709
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
*/ | ||
function getSellersCollections( | ||
uint256 _sellerId | ||
) external view returns (address defaultVoucherAddress, BosonTypes.Collection[] memory additionalCollections); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think is a good idea, nice catch.
I create an issue so this doesn't get loss
#709
@anajuliabit thanks for creating the issue. |
PR implements #590.
contracts/domain/BosonTypes.sol
:Collection
which contains collection address and its external idcollectionIndex
is added toOffer
structcontracts/interfaces/handlers/IBosonAccountHandler.sol
andcontracts/protocol/facets/SellerHandlerFacet.sol
two methods are added:createNewCollection
that creates an additional collection for the sellergetSellersCollections
which returns default boson voucher address and list of additional collectionscontracts/protocol/facets/ExchangeHandlerFacet.sol
,initializeVoucher
is changed to accept_collectionIndex
and add it as part of the name and symbol. Might still be changed: Multiple collections per seller BPIPs#15 (comment)CollectionCreated
which is emitted when a new collection is createdCollection
andOffer