Front end testing is important and is often part of User Acceptance testing.
Popular approaches uses Selenium along with a programming language - Java, Ruby, Python or C#
Update (2023)
There are now new options for web page automation that don't use selenium but do use a more modern approach to the framework.
They are Cypress and Playwright. They are referred to as 'javascript engine' testing frameworks, but don't be mislead by the name, these are web page html testing frameworks. Cypress is my favorite and comes with a modern ecosystem that makes going back to Selenium unlikely for me
The basic principle is that you create an instance of a Selenium object called 'WebDriver' that represents the instance of use of a specific browser, for example chromedriver for chrome.
You then write tests using this infrastructure. You refer to web page elements, you 'click' on links and buttons, you type text in input fields, you submit forms, etc. Basically if a user can do it, you can usually replicate that behaviour using selenium commands through the selected language and framework. In some cases is is done through a test framework tool, for example for Ruby on Rails (Application Framework), using RSpec (Test Framework) and Capybara (Selenium API)
One of hardest parts is certainly javascript and ajax testing.
Generally the approach here is:
Make sure selenium tests have good waiting strategies to allow for ajax and javascript
Write unit level tests in a javascript testing framework. This can either be a specific test framework used by the javascript framework being used or a more general one that can be used with various javascript frameworks. A good example of the latter is Jasmine. Jasmine tests will likely mock out the actual web page with a fragment specifically for testing. This is a big part of what makes them unit tests and not user acceptance tests.
Front end tests are the focus of my job. I actually find them a lot easier to write than model or controller tests! I do use practices like Page Objects to make sure the tests stay readable and maintainable.
As for 'automating at the controller level only' I think that might have been part of a bigger statement with more context. You should consider testing at model, controller and view levels for unit, integrated and user-acceptance testing using happy, sad and optional workflows.