ftmocks-utils
v1.7.0
Published
Util functions for FtMocks
Readme
ftmocks-utils
Util functions for FtMocks — helpers for mocking network requests in Playwright and Jest tests, recording new mocks from real traffic, and driving the FtMocks event recorder/player.
npm install ftmocks-utilsUsage: initiatePlaywrightRoutes
initiatePlaywrightRoutes sets up Playwright network route mocks for your tests.
Example Test
import { test, expect } from "@playwright/test";
import { initiatePlaywrightRoutes } from "ftmocks-utils";
test("Sample test case", async ({ page }) => {
// Initiate Playwright routes with custom directories and patterns
await initiatePlaywrightRoutes(
page,
{
MOCK_DIR: "../ftmocks",
FALLBACK_DIR: "../public",
},
"Sample test case",
"**/*", // Pattern(s) to intercept; you can use a string or array of patterns
);
await page.goto("https://example-test.com/");
// Now your requests will be mocked as per your ftmocks setup
// Add your test steps and assertions here
});Parameters:
page: Playwright page object.ftmocksConifg: Object with configuration (see Configuration reference below). At minimum, provideMOCK_DIR(required).testName: (string) Name of this test, so ftmocks can find the right mock data.mockPath: (string or array) Glob pattern(s) for requests to intercept.excludeMockPath: (string, optional) Regex; matching URLs bypass mocking entirely viaroute.fallback().
Make sure your MOCK_DIR points to the directory where your FtMocks records are saved.
How requests are matched to mocks
For each intercepted request, initiatePlaywrightRoutes looks for a mock whose URL (path + sorted query string, minus any ignoreParams), method, and body match, in this order:
- An unserved mock in the current test's
_mock_list.json. - If none, the default mocks folder (
defaultMocks/). - If the test's
mode(set per-test intests.json) is not"strict", the closest-ranked mock by query-string/body similarity is used as a best-effort fallback.
A matched mock is marked served so the next identical request advances to the next matching mock instead of replaying the same one — this lets you record a sequence of responses (e.g. paginated or changing data) for the same endpoint. Served state is tracked in a _served.json file alongside the mocks and is reset at the start of each test run.
Two optional fields on a mock's JSON control ordering:
waitFor: (array of mock ids) This mock is only eligible once all listed mocks have already been served.waitForPrevious: (boolean) This mock is only eligible after any previously-served mock in the list.
Matching request headers (MATCH_HEADERS)
By default, only URL, method, and body are compared. To also require specific headers to match between the recorded mock and the incoming request, set MATCH_HEADERS in your ftmocksConifg (or per-test config) to a comma-separated list of header names:
await initiatePlaywrightRoutes(page, {
MOCK_DIR: "../ftmocks",
MATCH_HEADERS: "x-tenant-id,authorization",
}, "Sample test case");Header names are matched case-insensitively; values are compared as strings.
Suppressing missing-mock logs (.logIgnore)
When a request has no matching mock and the route falls back to the network (or a fallback file), ftmocks-utils logs a debug message such as missing mock data, falling back (Playwright) or missing mock data (Jest). Playwright also logs response is a file, serving file when a mock response is served from a file on disk. Some URLs are expected to be noisy (analytics, health checks, static bundles, etc.) and do not need those messages in the logs.
Add a .logIgnore file in your MOCK_DIR with one URL regex pattern per line. If an incoming URL matches any pattern, these debug logs are skipped for that request:
- missing mock data, falling back (Playwright) / missing mock data (Jest)
- response is a file, serving file (Playwright)
Static asset URLs (.js, .css, images, fonts, etc.) are already suppressed for the missing-mock messages and do not need to be listed.
Example (MOCK_DIR/.logIgnore):
# Analytics and telemetry
https://.*\.google-analytics\.com/.*
https://.*\.segment\.io/.*
# Expected unmocked API calls
/api/health
^wss?://.*/socket- Lines starting with
#and blank lines are ignored. - Each non-comment line is compiled as a JavaScript
RegExpand tested against the full request URL. - Invalid regex lines are skipped with a console warning.
See more API documentation at ftmocks.com or in the main FtMocks repository.
Usage: recordPlaywrightRoutes
recordPlaywrightRoutes allows you to record network requests and responses from a Playwright test session and save them as FtMocks mocks. This is useful for setting up new mocks or updating existing ones with actual traffic.
Example Usage
import { test } from "@playwright/test";
import { recordPlaywrightRoutes } from "ftmocks-utils";
test("Record API interactions", async ({ page }) => {
await recordPlaywrightRoutes(
page,
{
MOCK_DIR: "../ftmocks",
FALLBACK_DIR: "../public",
},
{
testName: "Recorded test",
mockPath: "**/*", // Intercept all requests by default
pattern: "^/api/.*", // Only record requests matching this regex pattern (e.g., API endpoints)
avoidDuplicatesInTheTest: true, // Skip duplicates within a single test recording
avoidDuplicatesWithDefaultMocks: true, // Skip duplicates with default mocks
},
);
await page.goto("https://your-app-under-test.com/");
// Interact with your page as needed; API requests will be recorded
});Parameters:
page: Playwright page object.ftmocksConifg: Object, must contain at minimumMOCK_DIR.FALLBACK_DIRis optional.EXCLUDED_HEADERS(comma-separated, defaultcookie,set-cookie,authorization,www-authenticate) strips those headers from the recorded request before saving.ignoreParams(array) is stored on each recorded mock so matching ignores those query params later.config: Object containing recording options:testName: (string) Name of the test, used for saving the mock data.mockPath: (string|array) Glob pattern(s) for requests to intercept.pattern: (string) Regex string; only requests matching this will be recorded.avoidDuplicatesInTheTest: (boolean) Skip duplicate entries during this run.avoidDuplicatesWithDefaultMocks: (boolean) Skip recording if identical default mocks are present.
Responses whose content is a file (images, fonts, other binary/static assets, detected by extension or content-type) are saved under _files/ and referenced from the mock JSON instead of being inlined.
After running the test, FtMocks-compatible mock files will be saved to the specified folder for easy reuse.
See more API documentation and advanced usage at ftmocks.com.
Usage: Jest integration
For Jest-based tests (e.g. React component tests), use initiateJestFetch to mock fetch and XMLHttpRequest from the same FtMocks mock data used by Playwright.
import { initiateJestFetch, initiateConsoleLogs } from "ftmocks-utils";
beforeEach(async () => {
await initiateJestFetch(jest, { MOCK_DIR: "../ftmocks" }, "Sample test case");
initiateConsoleLogs(jest, { MOCK_DIR: "../ftmocks" }, "Sample test case");
});initiateJestFetch(jest, ftmocksConifg, testName): Replacesglobal.fetchandglobal.XMLHttpRequestwith jest mocks backed by the same mock/default data and matching logic asinitiatePlaywrightRoutes. Unmatched requests resolve with a404and{ error: "Mock data not found" }.initiateConsoleLogs(jest, ftmocksConifg, testName): Redirectsconsole.log/debug/info/warn/errorto jest mocks that also append totest_<name>/_logs.json, so console output can be inspected/asserted on after the test.initiateJestEventSnaps(jest, ftmocksConifg, testName): Spies ondocument.addEventListenerfor the given event types (defaultclick, change, url, dblclick, contextmenu, configurable viaftmocksConifg.snapEvents) and saves an HTML snapshot (viasaveSnap) each time one fires.getByXPath(container, xpath): Returns the first DOM node matchingxpathwithincontainer(viadocument.evaluate), ornull. Used by generated React Testing Library and Angular tests to target recorded elements, e.g.fireEvent.click(getByXPath(dom.container, "//*[@id='submit']")).
Usage: Angular integration
For Angular unit tests (jest-preset-angular), ftmocksHttpInterceptor returns an Angular HttpInterceptorFn that serves HttpClient requests from the same FtMocks mock data. To keep ftmocks-utils free of any Angular dependency, you pass the Angular/RxJS primitives in:
import { HttpErrorResponse, HttpResponse, provideHttpClient, withInterceptors } from '@angular/common/http';
import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { of, throwError } from 'rxjs';
import { ftmocksHttpInterceptor } from 'ftmocks-utils';
TestBed.configureTestingModule({
imports: [AppComponent],
providers: [
provideHttpClient(
withInterceptors([
ftmocksHttpInterceptor({ MOCK_DIR: './testMockData' }, 'Sample test case', {
HttpResponse,
HttpErrorResponse,
of,
throwError,
}),
])
),
provideNoopAnimations(),
],
});ftmocksHttpInterceptor(ftmocksConifg, testName, { HttpResponse, HttpErrorResponse, of, throwError }): Matched2xxmocks resolve as anHttpResponse; matched non-2xxmocks and unmatched requests error with anHttpErrorResponse(mirroring realHttpClientbehavior), so the component's error path runs instead of receiving a bad body.
Other exported utilities
The functions below are primarily used internally by the FtMocks recorder/player (browser event recording, presentation/training playback modes, screenshot diffing, selector self-healing) rather than called directly from a typical test file. They're exported for advanced or programmatic use — see ftmocks.com for the full picture of how they fit into the FtMocks tool.
| Export | Purpose |
| --- | --- |
| injectEventRecordingScript(page, url, ftmocksConifg, testName, continueRecordEvents) | Injects a script into a Playwright page that records clicks, input, keypresses, and navigation into test_<name>/_events.json, generating resilient selectors for each target element. |
| runEvent({ page, event, ... }) | Replays a single recorded event (click, input, keypress, change, dblclick, contextmenu, hover, keydown, keyup, url) against a Playwright page. |
| runEventsForTest(page, ftmocksConifg, testName) | Replays all events in a test's _events.json in order. |
| runEventsInPresentationMode(page, ftmocksConifg, testName) | Replays events one at a time, advancing on each Shift keypress — useful for live demos. |
| runEventsInTrainingMode(page, ftmocksConifg, testName) | Walks a user through manually reproducing each recorded event in the browser, highlighting the expected target and confirming matches. |
| runEventsForScreenshots(page, ftmocksConifg, testName) | Replays events, capturing a screenshot before each and diffing it against the previously saved one (via pixelmatch), updating screenshotInfo on the event. |
| runEventsForHealingSelectors(page, ftmocksConifg, testName) | Replays events and re-resolves each event's selector(s) against the live page, updating stale selectors in place. |
| getMatchingMockData({ testMockData, defaultMockData, url, options, testConfig, testName, mode }) | The core matching function used by initiatePlaywrightRoutes/initiateJestFetch; returns the matched mock's response content, or null. |
| loadMockDataFromConfig(testConfig, testName?) | Reads and parses a test's _mock_list.json and each referenced mock_<id>.json, attaching served state. |
| getDefaultMockDataFromConfig(testConfig) | Same, but for the shared defaultMocks/ folder. |
| resetAllMockStats({ testMockData, testConfig, testName }) | Clears served state for a test before it runs. |
| resetServed(mockFolder) / markMockServed(mockFolder, mockId) / loadServedIds(mockFolder) / SERVED_FILE | Lower-level helpers for reading/writing the _served.json file that tracks which mocks have already been served. |
| compareMockToRequest(mock, req) / compareMockToFetchRequest(mock, fetchReq, testConfig) / isSameRequest(req1, req2) | Request-comparison primitives used by the matcher (Playwright request object vs. fetch-style { url, options } vs. raw request pair, respectively). |
| processURL(url, ignoreParams) | Normalizes a URL to pathname?sortedQueryString, optionally dropping specified query params, for stable comparison. |
| nameToFolder(name) | Converts a test name to its on-disk folder name (spaces → underscores). |
| getTestByName(ftmocksConifg, testName) | Looks up a test's entry (including its mode) from tests.json. |
| saveSnap(html, ftmocksConifg, testName) / deleteAllSnaps(ftmocksConifg, testName) | Save/clear HTML snapshots under test_<name>/_snaps. |
| deleteAllLogs(ftmocksConifg, testName) | Deletes a test's _logs.json. |
Configuration reference
These fields are read off the ftmocksConifg/testConfig object passed to the functions above:
| Field | Used by | Description |
| --- | --- | --- |
| MOCK_DIR | all | Root folder containing tests.json, defaultMocks/, and per-test test_<name>/ folders. Relative paths are resolved against process.cwd(). |
| FALLBACK_DIR | initiatePlaywrightRoutes | Folder to serve static files from when no mock matches (e.g. your built app). |
| FALLBACK_DIR_INDEX_FILE | initiatePlaywrightRoutes | Index file served for / when no mock matches (default index.html). |
| FALLBACK_DIR_INDEX_FILE_FOR_STATUS_404 | initiatePlaywrightRoutes | Index file served for the first unmatched request when it has no file extension (SPA-style 404 fallback; default index.html). |
| DISABLE_LOGS | initiatePlaywrightRoutes | Suppresses ftmocks-utils' own debug/info logging when truthy. |
| EXCLUDED_HEADERS | recordPlaywrightRoutes | Comma-separated header names stripped from recorded mocks (default cookie,set-cookie,authorization,www-authenticate). |
| MATCH_HEADERS | matching (initiatePlaywrightRoutes, initiateJestFetch) | Comma-separated header names that must match between mock and request; see above. |
| ignoreParams | matching, recordPlaywrightRoutes | Query param names to ignore both when recording and when matching requests to mocks. |
| snapEvents | initiateJestEventSnaps | Array of DOM event types to snapshot on (default click, change, url, dblclick, contextmenu). |
| recordScreenshots | injectEventRecordingScript | When truthy, saves a screenshot alongside each recorded event. |
| delay | event-running functions | Milliseconds to wait before each replayed event (default 1000). |
