In theory, a transaction is validated before it is sent, when a transaction is accepted into a node’s mempool, when it is selected for inclusion in a block, when the block is verified before being broadcast, and when it is in a block that is received by a node. However, there really is no need for doing this validation multiple times because the same validation is done every single time.
So instead many node software will validate the transaction only when it is received in the mempool and only keep valid transactions in the mempool. When a new block is received, the transactions that were in the mempool need to be removed from the mempool, and because it knows that those transactions were valid because they are in the mempool, it does not need to re-validate the transactions from the block. The only transactions that need to be validated in the block then are the new transactions which the node did not have in its mempool.
For miners, the transactions they select will be from the mempool which only contains valid transactions. Thus this removes the need to validate transactions before selection and after block creation.
Additionally, the node can cache validation results for invalid transactions so that if it sees such transactions in a block it can look up the result in the cache instead of re-validating the invalid transaction. They can do this for valid transactions too to skip some validation steps.