PublicRole.behavior.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. const { shouldFail, constants, expectEvent } = require('openzeppelin-test-helpers');
  2. const { ZERO_ADDRESS } = constants;
  3. function capitalize (str) {
  4. return str.replace(/\b\w/g, l => l.toUpperCase());
  5. }
  6. function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], rolename, manager) {
  7. rolename = capitalize(rolename);
  8. describe('should behave like public role', function () {
  9. beforeEach('check preconditions', async function () {
  10. (await this.contract[`is${rolename}`](authorized)).should.equal(true);
  11. (await this.contract[`is${rolename}`](otherAuthorized)).should.equal(true);
  12. (await this.contract[`is${rolename}`](anyone)).should.equal(false);
  13. });
  14. if (manager === undefined) { // Managed roles are only assigned by the manager, and none are set at construction
  15. it('emits events during construction', async function () {
  16. await expectEvent.inConstruction(this.contract, `${rolename}Added`, {
  17. account: authorized,
  18. });
  19. });
  20. }
  21. it('reverts when querying roles for the null account', async function () {
  22. await shouldFail.reverting(this.contract[`is${rolename}`](ZERO_ADDRESS));
  23. });
  24. describe('access control', function () {
  25. context('from authorized account', function () {
  26. const from = authorized;
  27. it('allows access', async function () {
  28. await this.contract[`only${rolename}Mock`]({ from });
  29. });
  30. });
  31. context('from unauthorized account', function () {
  32. const from = anyone;
  33. it('reverts', async function () {
  34. await shouldFail.reverting(this.contract[`only${rolename}Mock`]({ from }));
  35. });
  36. });
  37. });
  38. describe('add', function () {
  39. const from = manager === undefined ? authorized : manager;
  40. context(`from ${manager ? 'the manager' : 'a role-haver'} account`, function () {
  41. it('adds role to a new account', async function () {
  42. await this.contract[`add${rolename}`](anyone, { from });
  43. (await this.contract[`is${rolename}`](anyone)).should.equal(true);
  44. });
  45. it(`emits a ${rolename}Added event`, async function () {
  46. const { logs } = await this.contract[`add${rolename}`](anyone, { from });
  47. expectEvent.inLogs(logs, `${rolename}Added`, { account: anyone });
  48. });
  49. it('reverts when adding role to an already assigned account', async function () {
  50. await shouldFail.reverting(this.contract[`add${rolename}`](authorized, { from }));
  51. });
  52. it('reverts when adding role to the null account', async function () {
  53. await shouldFail.reverting(this.contract[`add${rolename}`](ZERO_ADDRESS, { from }));
  54. });
  55. });
  56. });
  57. describe('remove', function () {
  58. // Non-managed roles have no restrictions on the mocked '_remove' function (exposed via 'remove').
  59. const from = manager || anyone;
  60. context(`from ${manager ? 'the manager' : 'any'} account`, function () {
  61. it('removes role from an already assigned account', async function () {
  62. await this.contract[`remove${rolename}`](authorized, { from });
  63. (await this.contract[`is${rolename}`](authorized)).should.equal(false);
  64. (await this.contract[`is${rolename}`](otherAuthorized)).should.equal(true);
  65. });
  66. it(`emits a ${rolename}Removed event`, async function () {
  67. const { logs } = await this.contract[`remove${rolename}`](authorized, { from });
  68. expectEvent.inLogs(logs, `${rolename}Removed`, { account: authorized });
  69. });
  70. it('reverts when removing from an unassigned account', async function () {
  71. await shouldFail.reverting(this.contract[`remove${rolename}`](anyone), { from });
  72. });
  73. it('reverts when removing role from the null account', async function () {
  74. await shouldFail.reverting(this.contract[`remove${rolename}`](ZERO_ADDRESS), { from });
  75. });
  76. });
  77. });
  78. describe('renouncing roles', function () {
  79. it('renounces an assigned role', async function () {
  80. await this.contract[`renounce${rolename}`]({ from: authorized });
  81. (await this.contract[`is${rolename}`](authorized)).should.equal(false);
  82. });
  83. it(`emits a ${rolename}Removed event`, async function () {
  84. const { logs } = await this.contract[`renounce${rolename}`]({ from: authorized });
  85. expectEvent.inLogs(logs, `${rolename}Removed`, { account: authorized });
  86. });
  87. it('reverts when renouncing unassigned role', async function () {
  88. await shouldFail.reverting(this.contract[`renounce${rolename}`]({ from: anyone }));
  89. });
  90. });
  91. });
  92. }
  93. module.exports = {
  94. shouldBehaveLikePublicRole,
  95. };