Don't use msg.sender
for view functions,
await nftContract.getTokenUnlockableContent(0)
Sets msg.sender to 0 by default. You can specify a from
parameter if you want when calling a view functions (which remix does, thats why it works there) but the best option is always to have an address parameter in your function and not rely on msg.sender
EDIT : I also noticed you're making a check for msg.sender == ownerOf(tokenId);
if you're using that hoping that it would prevent non-token-owners from calling thé function, it doesnt work. And if you want data to remain private, don't store it in a smart contract in the first place.