I’ve done both. I like test code living in parallel with the application code. We already had this paradigm for unit and integration tests. Extending it to functional/end-to-end tests seems like a no-brainer in hindsight.
The biggest advantage here is that tests should align with the current code implementation. There’s no cross referencing between two repos to figure out what version of the tests need to be run against a particular version of the code. This in turn simplified our CI pipeline - only one repo to keep track of, check out, build, and run tests against.
Another benefit is that by pushing the code closer to code developers work with, it encourages them to take some ownership of the functional tests. We don’t gate on end-to-end tests since we’re not mature enough to have requirements/contracts specced out to the point where they can be updated at the same time as the features are built/updated/etc, but seeing the functional tests fail encourages folks to do that.