How to write a successful test.js file for my ERC721 contract's proxy

Here is my smart contract below..

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;


import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";


contract ERC721 is Initializable, ERC721URIStorageUpgradeable, PausableUpgradeable, AccessControlUpgradeable {
  
  bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
  bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
  bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
  bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
  // May also need to import "ERC721Upgradeable.sol",
  // and declare it within the parameters of the initialize function.

  
  // Base URI
  string private _baseUri;
  address _forwarder;
  
  mapping(uint256 => string) private _digests;
  mapping(uint256 => string) private _infoRoots;
  
  // Addresses under operator control
  mapping(address => bool) private _operatorEnabled;

/// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }
  
 
function initialize() initializer public {
    __ERC721_init("", "");
    __ERC721URIStorage_init();
    __Pausable_init();
    __AccessControl_init();
    _baseUri = "";
    _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    _setupRole(PAUSER_ROLE, msg.sender);
    _setupRole(MINTER_ROLE, msg.sender);
    _setupRole(BURNER_ROLE, msg.sender);
    _setupRole(OPERATOR_ROLE, msg.sender);
  }

  
  function pause() external onlyRole(PAUSER_ROLE) {
    _pause();
  }

  function unpause() external onlyRole(PAUSER_ROLE) {
    _unpause();
  }

  /**
   * @dev See {ERC20-_beforeTokenTransfer}.
   * Taken from ERC20Pausable
   *
   * Requirements:
   *
   * - the contract must not be paused.
   */
  function _beforeTokenTransfer(address from, address to, uint256 amount, uint256 batchSize) internal virtual override  {
    super._beforeTokenTransfer(from, to, amount, batchSize);
    require(!paused(), "ERC721Pausable: token transfer while paused");
  }
  
  function mint(address to, uint256 tokenId, string memory tokenUri, string memory _digest) public onlyRole(MINTER_ROLE) {
    _mint(to, tokenId);
    _setTokenURI(tokenId, tokenUri);
    _digests[tokenId] = _digest;
  }

  function burn(uint256 tokenId) public onlyRole(BURNER_ROLE) {
    _burn(tokenId);
  }
  
  function setBaseURI(string memory uri) external onlyRole(OPERATOR_ROLE) {
    _baseUri = uri;
  }

  /**
   * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
   * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
   * by default, can be overriden in child contracts.
   */
  function _baseURI() internal view virtual override returns (string memory) {
    return _baseUri;
  }

  function infoRoot(uint256 tokenId) external view virtual returns (string memory) {
    require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");

    string memory _infoRoot = _infoRoots[tokenId];

    // If there is no infoRoot set, return an empty string.
    if (bytes(_infoRoot).length == 0) {
      return "";
    }

    return _infoRoot;
  }

  function setInfoRoot(uint256 tokenId, string memory _infoRoot) external onlyRole(OPERATOR_ROLE) whenNotPaused() {
    require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
    _infoRoots[tokenId] = _infoRoot;
  }
  
  function digest(uint256 tokenId) external view virtual returns (string memory) {
    require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");

    string memory _digest = _digests[tokenId];

    // If there is no digest set, return an empty string.
    if (bytes(_digest).length == 0) {
      return "";
    }

    return _digest;
  }
  
  function setdigest(uint256 tokenId, string memory _digest) external onlyRole(OPERATOR_ROLE) whenNotPaused() {
    require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
    _digests[tokenId] = _digest;
  }

  // Operator initiatiated token transfer
  function operatorTransfer(address recipient, uint256 tokenId) external onlyRole(OPERATOR_ROLE) whenNotPaused() returns (bool) {
    address owner = ownerOf(tokenId);
    require(isOperatorControlled(owner), "ERC721: sender not under operator control");
    // Reset appoval
    _approve(msg.sender, tokenId);
    transferFrom(owner, recipient, tokenId);
    return true;
  }
  
  // Address owner can enable their address for operator control
  // Default state is operator disabled
  function enableOperatorControl() external whenNotPaused() returns (bool) {
    require(msgSender() != address(0), "ERC20: owner is a zero address");
    require(!isOperatorControlled(msgSender()), "ERC20: owner already under operator control");
    _operatorEnabled[msgSender()] = true;
    return true;
  }
  
  // Operator role can remove operator control from an address
  function disableOperatorControl(address owner) external onlyRole(OPERATOR_ROLE) whenNotPaused() returns (bool) {
    require(owner != address(0), "ERC721: owner is a zero address");
    require(isOperatorControlled(owner), "ERC721: owner not under operator control");
    _operatorEnabled[owner] = false;
    return true;
  }
  
  function isOperatorControlled(address owner) public view returns (bool) {
    require(owner != address(0), "ERC721: owner is a zero address");
    return _operatorEnabled[owner];
  }

  function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Upgradeable, AccessControlUpgradeable) returns (bool) {
      return super.supportsInterface(interfaceId);
  }

  function msgSender() internal view returns(address sender) {
    if(msg.sender == _forwarder) {
      bytes memory array = msg.data;
      uint256 index = msg.data.length;
      assembly {
          // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
          sender := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
      }
    } else {
        sender = msg.sender;
    }
    return sender;
  }

  function setForwarder(address forwarder) external onlyRole(OPERATOR_ROLE) returns (bool) {
    _forwarder = forwarder;
    return true;
  }
  
  function getForwarder() external view returns (address) {
    return _forwarder;
  }
}

I want to write a test that will interact with the proxy that i have written in migration files ( see below ). This compiles successfully.

const ERC721 = artifacts.require("ERC721");
const { deployProxy } = require('@openzeppelin/truffle-upgrades');

module.exports = async function (deployer) {
  await deployProxy(ERC721, { deployer, initializer: 'initialize'} );
};

However, i have so far written the below test file, but it fails the test and returns the error message:

"1) Contract: ERC721 (proxy)
"before each" hook for "retrieve returns a value previously initialized":
ReferenceError: ERC721 is not defined"

// test/Box.proxy.test.js
// Load dependencies
const { expect } = require('chai');
const { deployProxy } = require('@openzeppelin/truffle-upgrades');
 
// Load compiled artifacts
const Box = artifacts.require('ERC721');
 
// Start test block
contract('ERC721 (proxy)', function () {
  beforeEach(async function () {
    // Deploy a new Box contract for each test
    this.erc721 = await deployProxy(ERC721, {initializer: 'initialize'});
  });
 
  // Test case
  it('retrieve returns a value previously initialized', async function () {
    // Test if the returned value is the same one
    // Note that we need to use strings to compare the 256 bit integers
    expect((await this.erc721.retrieve()).toString()).to.equal('');
  });
});

What am I doing incorrectly?

Thanks in advance

Your code has an error:

const Box = artifacts.require('ERC721');

Should be

const ERC721 = artifacts.require('ERC721');

Thanks for pointing that out!