Temporal
Course Description
Perfect for lead UI developers managing large apps, migrating codebases, or starting scalable projects while maintaining code quality. Learn unit testing with Vitest, continuous integration via GitHub Actions, component and accessibility testing with Axe, mocking techniques, and code standard enforcement using ESLint and Husky & Lint-Staged. Guide your team toward coding scalability!
This course and others like it are available as part of our Frontend Masters video subscription.
Preview
CloseWhat They're Saying
Steve's Enterprise UI Development course on Frontend Masters covers maintaining large codebases while maintaining code quality.
It's an amazing course I will recommend for anyone managing medium to large frontend codebase!

Mubarak Alhazan
React Frontend Engineer
I just completed "Enterprise UI Development: Testing & Code Quality" by Steve Kinney on Frontend Masters! It was great to learn more about Playwright and the philosophies to follow when inheriting a codebase.

Jorge Mendoza
JorgeMIIDev
Course Details
Published: May 26, 2023
Learning Paths
Topics
Learn Straight from the Experts Who Shape the Modern Web
Your Path to Senior Developer and Beyond
- 200+ In-depth courses
- 18 Learning Paths
- Industry Leading Experts
- Live Interactive Workshops
Table of Contents
Introduction
Section Duration: 32 minutes
- Steve Kinney explains the pitfalls of large codebases and why infrastructure is needed to manage a large codebase supported by a team of contributors.
- Steve discusses the core questions around enterprise UI development. How do you create maintainable code? What does it mean to be maintainable? Components of a well-architected UI application are also discussed in this lesson.
- Steve explains the tooling used throughout the course. Most of the code examples use React and TypeScript. Testing Library, Vitest, and Playwright will also be used in the course.
The Basics of Unit Testing
Section Duration: 1 hour, 24 minutes
- Steve explains the spectrum of tests used throughout an application. These include unit tests, component tests, end-to-end tests, and integration tests.
- Steve introduces Vitest and provides a basic unit test example and a description of the Vitest syntax. Instructions for running tests in the course repository are provided. A question about using Happy DOM vs. JS DOM is also covered in this lesson.
- Steve demonstrates the reporting options available with Vitest. The --reporter flag customizes the level of reporting. The --ui flag opens a user interface that displays tests and their results.
- Students are instructed to complete the test implementations in the exercise.tests.ts file. Use `npm test` to run the tests.
- Steve live codes some of the solutions to the Unit Testing exercise. The remaining solutions can be found in the `exercise.solution.test.ts` file.
- Steve demonstrates techniques for handling async behavior in unit tests. Asymmetric tests are also shown and are helpful when a value is generated each time, and the test only needs to know if it exists or is a proper type.
- Students are instructed to implement tests to ensure the randomly generated UUIDs exist and are well formed. Default packed status and removal behavior should also be tested.
- Steve live codes the solution to the Asymmetric Matching exercise. The full solution can be found in the `items-slice.solution.test.ts` file.
Building a CI Pipeline with Github Actions
Section Duration: 1 hour, 14 minutes
- Steve introduces GitHub actions and outlines a few use cases, like automatically running tests when commits are pushed to the repo. Actions reside in a YAML file inside a workflows folder.
- Steve demonstrates the user interface for GitHub actions. When a PR is opened, the status of the action will change from pending to in-progress. Details about each step can be viewed along with any console output.
- Steve challenges students to add a build step to the GitHub action. Branch protection rules are also explained, and the configuration settings are explored.
- Steve demonstrates how to run multiple jobs in parallel by creating a separate jobs object in the actions YAML file. If jobs depend on each other, the "needs" property can be used to specify the dependency's name.
- Steve explains that GitHub actions can store action dependencies with caching or artifacts. Caches are pinned to a specific version and have a unique ID to access them from other jobs, and they can be hashed using the package.lock file to ensure uniqueness. The GitHub UI will indicate when a cache is accessed and provides a way to remove caches manually.
- Steve demonstrates a shortcut for caching npm packages. Conditionals can also be used in job steps to determine if a cache is available. Running GitHub actions locally is also discussed in this lesson.
Component Testing
Section Duration: 1 hour, 59 minutes
- Steve introduces component testing and describes the value they add to a developer's workflow. These tests ensure application updates do not break UI implementation and test user interactions without requiring browser-based integration testing.
- Steve shares a brief overview of the component testing configuration used in the course repo. The testing suite jsdom can be configured for specific files or folders using globs in the vitest.config.ts file. Differences between jsdom and happy-dom are also discussed in this lesson.
- Steve configures a component test environment to use happy-dom and runs an initial test to demonstrate the DOM integration by logging results in the console.
- Steve explores the screen and fireEvent methods from Testing Library. The screen method provides APIs for querying the DOM and selecting elements based on different conditions. The fireEvent method dispatches common DOM events like click or change.
- Steve introduces the user-event package from Testing Library, which provides more accurate user event behavior. Duplicating the user setup and rendering in each test can become redundant, so an abstracted render method is created in the utilities file, and the test is refactored.
- Students are instructed to implement component tests to validate the correct initial count is displayed and that the count is reset when the reset button is clicked.
- Students are instructed to add component tests to the Packing List application. Tests include verifying there is an input field for adding new items, verifying the "Add New Items" button is disabled or enabled at the correct time, and verifying new items are added to the page.
- Steve codes part of the solution to the Testing Project exercise. The tests written verify there is an input field for adding new items.
- Steve continues coding the solution to the Testing Project exercise. The tests written verify the "Add New Item" button is disabled when no input is present and is enabled when text is entered into the input.
- Steve continues coding the solution to the Testing Project exercise. The tests written verify items are added to the "Unpacked Items List" when the "Add New Item" button is clicked. Testing the removal of an item is also included in this lesson.
- Steve discusses ways to isolate tests so their implementation does not affect other tests in the application. A question about handling async behavior or situations where animations must complete before a test can continue is also discussed in this lesson.
- Steve refactors the Packing List application to demonstrate further how to scope the resources required to run tests. This creates more modular tests and increases a test's encapsulation.
Accessibility Testing & Code Coverage
Section Duration: 49 minutes
- Steve discusses the importance of automating accessibility tests and introduces the Axe testing library. Accessibility violations will cause tests to fail and a descriptive list of ways to solve the violation is presented in the console.
- Steve introduces code coverage and runs a coverage report which displays the percentage of tested code in every source file in the application
- Steve walks through the coverage configuration options in the vitest.config.ts file. Thresholds and included/excluded file paths can be configured along with the reporter which allows the reports to be imported into other systems.
- Steve adds a step to the GitHub action to run a code coverage report.
- Steve walks through the GitHub UI for the action-generated coverage report. The output resides as an artifact and can be downloaded as a ZIP file in the summary section.
Mocking & Spying
Section Duration: 48 minutes
- Steve demonstrates how mocks allow developers to test code they don't control without requiring the necessary functions or APIs to be called. This is useful when the external function or API isn't available or would result in increased fees for usage. Mocks can be passed a custom implementation so mocked return values can be used later in the test.
- Steve explains that spies are similar to mocks except they watch a single method of an object. An alias can be used to call the underlying method. The method can also be added to tests to ensure it's called correctly.
- Steve shares a use case for mocking and creating custom implementations for third-party libraries. Questions about mocking server-side APIs are also discussed in this lesson.
- Steve uses the useFakeTimers and setSystemTime methods to mock the system time for a test. These methods freeze the system time and allow it to be set to any date-based value to make testing easier and more predictable.
- Steve introduces the Mock Service Worker library, which allows developers to mock API requests by intercepting requests on the network level with a service worker. The mock definitions can be seamlessly reused for testing, development, and debugging.
Integration Testing with Playwright
Section Duration: 54 minutes
- Steve introduces Playwright which enables end-to-end testing in web applications.
- Steve clones a new repo and installs Playwright. The Playwright tests will run in multiple browser environments and provide test summary reports for each. The Playwright VSCode extension is also introduced in this lesson.
- Steve briefly overviews the Playwright configuration options in the playwright.config.ts file.
- Steve writes a basic Playwright test that navigates to a URL, types text in an input field, and clicks on one of the results. End-to-end tests like this add confidence in UI behavior and can often eliminate the need for multiple component or unit tests.
- Steve demonstrates Playwright's ability to record user interactions in the browser and generate the Playwright test code. This can be done with the VSCode plugin or by launching the Playwright recording UI from the command line.
- Steve generates screenshots with Playwright. Screenshots can produce failing tests if the visual difference exceeds a threshold. They are helpful when refactoring a large code base because they ensure the UI remains the same.
- Steve records API requests with Playwright. The requests are saved to an HTTP archive (HAR) file. The HAR file can be used to mock future responses to network requests.
Enforcing Standards
Section Duration: 33 minutes
- Steve creates custom ESLint rules with AST Explorer. The custom rules can be added to a project to help developers adhere to custom coding standards.
- Steve introduces Husky, which is a command-line tool for generating pre-commit scripts. These scripts can catch linting or other code issues when code is committed versus waiting for a GitHub action to run.
- Steve answers questions about getting team buy-in for more comprehensive testing, component testing, building API transition layers.
Wrapping Up
Section Duration: 9 minutes
- Steve wraps up the course by sharing some of the design patterns that result in cleaner, more testable code.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops