# Error

{% embed url="<https://youtu.be/yY9lL4Jxkd8>" %}
Error
{% endembed %}

## Setup

Target contract:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract Error {
    error NotAuthorized();

    function throwError() external {
        require(false, "not authorized");
    }

    function throwCustomError() external {
        revert NotAuthorized();
    }
}
```

Test file:

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

import "forge-std/Test.sol";
import {Error} from "../src/Error.sol";

contract ErrorTest is Test {
    Error public err;

    function setUp() public {
        err = new Error();
    }

    function testFail() public {
        err.throwError();
    }

    function testRevert() public {
        vm.expectRevert();
        err.throwError();
    }

    function testRequireMessage() public {
        vm.expectRevert(bytes("not authorized"));
        err.throwError();
    }

    function testCustomError() public {
        vm.expectRevert(Error.NotAuthorized.selector);
        err.throwCustomError();
    }

    // Add label to assertions
    function testErrorLabel() public {
        assertEq(uint256(1), uint256(1), "test 1");
        assertEq(uint256(1), uint256(1), "test 2");
        assertEq(uint256(1), uint256(1), "test 3");
        assertEq(uint256(1), uint256(2), "test 4");
        assertEq(uint256(1), uint256(1), "test 5");
    }
}
```

## vm.expectRevert()

If we want a test case to simply revert, use `testFail` prefix in the function name:

```solidity
    function testFail() public {
        err.throwError();
    }
```

Another way of doing the same thing is to use `test` prefix in the function name and `vm.expectRevert()` before that operation:

```solidity
    function testRevert() public {
        vm.expectRevert();
        err.throwError();
    }
```

## Test require error message

If we want to test for a `require()` statement's error message, such as the following:

```solidity
    function throwError() external {
        require(false, "not authorized");
    }
```

use `vm.expectRevert(bytes(error_message))`:

```solidity
    function testRequireMessage() public {
        vm.expectRevert(bytes("not authorized"));
        err.throwError();
    }
```

## Custom error

If we want to test for custom error instead, such as the following:

```solidity
    function throwCustomError() external {
        revert NotAuthorized();
    }
```

use `vm.expectRevert(Error.custom_error_name.selector)`:

```solidity
    function testCustomError() public {
        vm.expectRevert(Error.NotAuthorized.selector);
        err.throwCustomError();
    }
```

## Label assertions

If we have a lot of assertions in a test case, Foundry won't tell us which ones succeed and which ones fail. For example:

```solidity
    function testErrorLabel() public {
        assertEq(uint256(1), uint256(1));
        assertEq(uint256(1), uint256(1));
        assertEq(uint256(1), uint256(1));
        assertEq(uint256(1), uint256(2));
        assertEq(uint256(1), uint256(1));
    }
```

The 4th assertion clearly would fail but Foundry won't tell us the failed one is the 4th assertion. In order to distinguish assertions, we can label them with different names:

```solidity
    // Add label to assertions
    function testErrorLabel() public {
        assertEq(uint256(1), uint256(1), "test 1");
        assertEq(uint256(1), uint256(1), "test 2");
        assertEq(uint256(1), uint256(1), "test 3");
        assertEq(uint256(1), uint256(2), "test 4");
        assertEq(uint256(1), uint256(1), "test 5");
    }
```
