## Description This PR has the following changes - Modify the prefetch api cache strategy to handle multiple prefetch requests. - Convert the service worker files from js to ts - Code splitting of CE and EE for service worker utils to handle EE specific changes - Jest test cases for the updated logic Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/9511154598> > Commit: 785197e27873e71ed457f785a73d4ea57f379213 > Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=9511154598&attempt=1" target="_blank">Click here!</a> <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Enhanced API request handling with new utility functions and caching strategies for service worker operations. - Updated service worker configuration to TypeScript for improved type safety and maintainability. - Added type definitions for `node-fetch` to support new service worker functionalities. - **Refactor** - Consolidated `view` and `edit` endpoint URL construction in `ConsolidatedPageLoadApi` for better code maintainability. - **Chores** - Updated dependencies in `package.json` for better development experience and compatibility. - Added tests for new service worker utility functions to ensure reliability and correctness. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
625 lines
21 KiB
TypeScript
625 lines
21 KiB
TypeScript
import { APP_MODE } from "entities/App";
|
|
import type { TApplicationParams } from "./serviceWorkerUtils";
|
|
import {
|
|
matchBuilderPath,
|
|
matchViewerPath,
|
|
getSearchQuery,
|
|
getConsolidatedApiPrefetchRequest,
|
|
getApplicationParamsFromUrl,
|
|
getPrefetchRequests,
|
|
PrefetchApiService,
|
|
} from "./serviceWorkerUtils";
|
|
import { Mutex } from "async-mutex";
|
|
import { Request as NFRequest, Response as NFResponse } from "node-fetch";
|
|
|
|
(global as any).fetch = jest.fn() as jest.Mock;
|
|
(global as any).caches = {
|
|
open: jest.fn(),
|
|
delete: jest.fn(),
|
|
};
|
|
|
|
describe("serviceWorkerUtils", () => {
|
|
describe("matchBuilderPath", () => {
|
|
it("should match the standard builder path", () => {
|
|
const pathName = "/app/applicationSlug/pageSlug-123/edit";
|
|
const options = { end: false };
|
|
const result = matchBuilderPath(pathName, options);
|
|
|
|
expect(result).toBeTruthy();
|
|
if (result) {
|
|
expect(result.params).toHaveProperty("applicationSlug");
|
|
expect(result.params).toHaveProperty("pageSlug");
|
|
expect(result.params).toHaveProperty("pageId", "123");
|
|
} else {
|
|
fail("Expected result to be truthy");
|
|
}
|
|
});
|
|
|
|
it("should match the standard builder path for alphanumeric pageId", () => {
|
|
const pathName =
|
|
"/app/applicationSlug/pageSlug-6616733a6e70274710f21a07/edit";
|
|
const options = { end: false };
|
|
const result = matchBuilderPath(pathName, options);
|
|
|
|
expect(result).toBeTruthy();
|
|
if (result) {
|
|
expect(result.params).toHaveProperty("applicationSlug");
|
|
expect(result.params).toHaveProperty("pageSlug");
|
|
expect(result.params).toHaveProperty(
|
|
"pageId",
|
|
"6616733a6e70274710f21a07",
|
|
);
|
|
} else {
|
|
fail("Expected result to be truthy");
|
|
}
|
|
});
|
|
|
|
it("should match the custom builder path", () => {
|
|
const pathName = "/app/customSlug-custom-456/edit";
|
|
const options = { end: false };
|
|
const result = matchBuilderPath(pathName, options);
|
|
|
|
expect(result).toBeTruthy();
|
|
if (result) {
|
|
expect(result.params).toHaveProperty("customSlug");
|
|
expect(result.params).toHaveProperty("pageId", "456");
|
|
} else {
|
|
fail("Expected result to be truthy");
|
|
}
|
|
});
|
|
|
|
it("should match the deprecated builder path", () => {
|
|
const pathName = "/applications/appId123/pages/456/edit";
|
|
const options = { end: false };
|
|
const result = matchBuilderPath(pathName, options);
|
|
|
|
expect(result).toBeTruthy();
|
|
if (result) {
|
|
expect(result.params).toHaveProperty("applicationId", "appId123");
|
|
expect(result.params).toHaveProperty("pageId", "456");
|
|
} else {
|
|
fail("Expected result to be truthy");
|
|
}
|
|
});
|
|
|
|
it("should not match incorrect builder path", () => {
|
|
const pathName = "/app/applicationSlug/nonMatching-123";
|
|
const options = { end: false };
|
|
const result = matchBuilderPath(pathName, options);
|
|
|
|
expect(result).toBeFalsy();
|
|
});
|
|
|
|
it("should not match when no pageId is present", () => {
|
|
const pathName = "/app/applicationSlug/pageSlug-edit";
|
|
const options = { end: false };
|
|
const result = matchBuilderPath(pathName, options);
|
|
|
|
expect(result).toBeFalsy();
|
|
});
|
|
|
|
it("should match when the path is edit widgets", () => {
|
|
const pathName =
|
|
"/app/applicationSlug/pageSlug-123/edit/widgets/t36hb2zukr";
|
|
const options = { end: false };
|
|
const result = matchBuilderPath(pathName, options);
|
|
|
|
if (result) {
|
|
expect(result.params).toHaveProperty("applicationSlug");
|
|
expect(result.params).toHaveProperty("pageSlug");
|
|
expect(result.params).toHaveProperty("pageId", "123");
|
|
} else {
|
|
fail("Expected result to be truthy");
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("matchViewerPath", () => {
|
|
it("should match the standard viewer path", () => {
|
|
const pathName = "/app/applicationSlug/pageSlug-123";
|
|
const result = matchViewerPath(pathName);
|
|
|
|
expect(result).toBeTruthy();
|
|
if (result) {
|
|
expect(result.params).toHaveProperty("applicationSlug");
|
|
expect(result.params).toHaveProperty("pageSlug");
|
|
expect(result.params).toHaveProperty("pageId", "123");
|
|
} else {
|
|
fail("Expected result to be truthy");
|
|
}
|
|
});
|
|
|
|
it("should match the custom viewer path", () => {
|
|
const pathName = "/app/customSlug-custom-456";
|
|
const result = matchViewerPath(pathName);
|
|
|
|
expect(result).toBeTruthy();
|
|
if (result) {
|
|
expect(result.params).toHaveProperty("customSlug");
|
|
expect(result.params).toHaveProperty("pageId", "456");
|
|
} else {
|
|
fail("Expected result to be truthy");
|
|
}
|
|
});
|
|
|
|
it("should match the deprecated viewer path", () => {
|
|
const pathName = "/applications/appId123/pages/456";
|
|
const result = matchViewerPath(pathName);
|
|
|
|
expect(result).toBeTruthy();
|
|
if (result) {
|
|
expect(result.params).toHaveProperty("applicationId", "appId123");
|
|
expect(result.params).toHaveProperty("pageId", "456");
|
|
} else {
|
|
fail("Expected result to be truthy");
|
|
}
|
|
});
|
|
|
|
it("should not match when no pageId is present", () => {
|
|
const pathName = "/app/applicationSlug/pageSlug";
|
|
const result = matchViewerPath(pathName);
|
|
|
|
expect(result).toBeFalsy();
|
|
});
|
|
});
|
|
|
|
describe("getSearchQuery", () => {
|
|
it("should return the search query from the URL", () => {
|
|
const search = "?key=value";
|
|
const key = "key";
|
|
const result = getSearchQuery(search, key);
|
|
expect(result).toEqual("value");
|
|
});
|
|
|
|
it("should return an empty string if the key is not present in the URL", () => {
|
|
const search = "?key=value";
|
|
const key = "invalid";
|
|
const result = getSearchQuery(search, key);
|
|
expect(result).toEqual("");
|
|
});
|
|
|
|
it("should return an empty string if the search query is empty", () => {
|
|
const search = "";
|
|
const key = "key";
|
|
const result = getSearchQuery(search, key);
|
|
expect(result).toEqual("");
|
|
});
|
|
});
|
|
|
|
describe("getApplicationParamsFromUrl", () => {
|
|
it("should parse URL and return correct params for builder path", () => {
|
|
const url = new URL(
|
|
"https://app.appsmith.com/app/my-app/page-123/edit?branch=main",
|
|
);
|
|
const expectedParams: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "123",
|
|
applicationId: undefined,
|
|
branchName: "main",
|
|
appMode: APP_MODE.EDIT,
|
|
};
|
|
|
|
expect(getApplicationParamsFromUrl(url)).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should parse URL and return correct params for viewer path", () => {
|
|
const url = new URL(
|
|
"https://app.appsmith.com/app/my-app/page-123?branch=main",
|
|
);
|
|
const expectedParams: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "123",
|
|
applicationId: undefined,
|
|
branchName: "main",
|
|
appMode: APP_MODE.PUBLISHED,
|
|
};
|
|
|
|
expect(getApplicationParamsFromUrl(url)).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should return null if the path does not match any pattern", () => {
|
|
const url = new URL("https://app.appsmith.com/invalid/path?branch=main");
|
|
expect(getApplicationParamsFromUrl(url)).toBeNull();
|
|
});
|
|
|
|
it("should parse deprecated builder path and return correct params", () => {
|
|
const url = new URL(
|
|
"https://app.appsmith.com/applications/app-123/pages/page-123/edit?branch=main",
|
|
);
|
|
const expectedParams: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "page-123",
|
|
applicationId: "app-123",
|
|
branchName: "main",
|
|
appMode: APP_MODE.EDIT,
|
|
};
|
|
|
|
expect(getApplicationParamsFromUrl(url)).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should parse deprecated viewer path and return correct params", () => {
|
|
const url = new URL(
|
|
"https://app.appsmith.com/applications/app-123/pages/page-123?branch=main",
|
|
);
|
|
const expectedParams: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "page-123",
|
|
applicationId: "app-123",
|
|
branchName: "main",
|
|
appMode: APP_MODE.PUBLISHED,
|
|
};
|
|
|
|
expect(getApplicationParamsFromUrl(url)).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should parse custom builder path and return correct params", () => {
|
|
const url = new URL(
|
|
"https://app.appsmith.com/app/custom-app-123/edit?branch=main",
|
|
);
|
|
const expectedParams: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "123",
|
|
applicationId: undefined,
|
|
branchName: "main",
|
|
appMode: APP_MODE.EDIT,
|
|
};
|
|
|
|
expect(getApplicationParamsFromUrl(url)).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should parse custom viewer path and return correct params", () => {
|
|
const url = new URL(
|
|
"https://app.appsmith.com/app/custom-app-123?branch=main",
|
|
);
|
|
const expectedParams: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "123",
|
|
applicationId: undefined,
|
|
branchName: "main",
|
|
appMode: APP_MODE.PUBLISHED,
|
|
};
|
|
|
|
expect(getApplicationParamsFromUrl(url)).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should parse URL and return params with empty branch name if branch query param is not present", () => {
|
|
const url = new URL("https://app.appsmith.com/app/my-app/page-123/edit");
|
|
const expectedParams: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "123",
|
|
applicationId: undefined,
|
|
branchName: "",
|
|
appMode: APP_MODE.EDIT,
|
|
};
|
|
|
|
expect(getApplicationParamsFromUrl(url)).toEqual(expectedParams);
|
|
});
|
|
});
|
|
|
|
describe("getConsolidatedApiPrefetchRequest", () => {
|
|
beforeAll(() => {
|
|
(global as any).Request = NFRequest;
|
|
});
|
|
|
|
it("should return null if pageId is not provided", () => {
|
|
const params: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
branchName: "main",
|
|
appMode: APP_MODE.EDIT,
|
|
};
|
|
|
|
expect(getConsolidatedApiPrefetchRequest(params)).toBeNull();
|
|
});
|
|
|
|
it("should create request for EDIT mode with applicationId", () => {
|
|
const params: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "page123",
|
|
applicationId: "app123",
|
|
branchName: "main",
|
|
appMode: APP_MODE.EDIT,
|
|
};
|
|
|
|
const request = getConsolidatedApiPrefetchRequest(params);
|
|
expect(request).toBeInstanceOf(Request);
|
|
expect(request?.url).toBe(
|
|
`https://app.appsmith.com/api/v1/consolidated-api/edit?defaultPageId=page123&applicationId=app123`,
|
|
);
|
|
expect(request?.method).toBe("GET");
|
|
expect(request?.headers.get("Branchname")).toBe("main");
|
|
});
|
|
|
|
it("should create request for PUBLISHED mode with applicationId", () => {
|
|
const params: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "page123",
|
|
applicationId: "app123",
|
|
branchName: "main",
|
|
appMode: APP_MODE.PUBLISHED,
|
|
};
|
|
|
|
const request = getConsolidatedApiPrefetchRequest(params);
|
|
expect(request).toBeInstanceOf(Request);
|
|
expect(request?.url).toBe(
|
|
`https://app.appsmith.com/api/v1/consolidated-api/view?defaultPageId=page123&applicationId=app123`,
|
|
);
|
|
expect(request?.method).toBe("GET");
|
|
expect(request?.headers.get("Branchname")).toBe("main");
|
|
});
|
|
|
|
it("should create request for EDIT mode without applicationId", () => {
|
|
const params: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "page123",
|
|
branchName: "main",
|
|
appMode: APP_MODE.EDIT,
|
|
};
|
|
|
|
const request = getConsolidatedApiPrefetchRequest(params);
|
|
expect(request).toBeInstanceOf(Request);
|
|
expect(request?.url).toBe(
|
|
`https://app.appsmith.com/api/v1/consolidated-api/edit?defaultPageId=page123`,
|
|
);
|
|
expect(request?.method).toBe("GET");
|
|
expect(request?.headers.get("Branchname")).toBe("main");
|
|
});
|
|
|
|
it("should create request for PUBLISHED mode without applicationId", () => {
|
|
const params: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "page123",
|
|
branchName: "main",
|
|
appMode: APP_MODE.PUBLISHED,
|
|
};
|
|
|
|
const request = getConsolidatedApiPrefetchRequest(params);
|
|
expect(request).toBeInstanceOf(Request);
|
|
expect(request?.url).toBe(
|
|
`https://app.appsmith.com/api/v1/consolidated-api/view?defaultPageId=page123`,
|
|
);
|
|
expect(request?.method).toBe("GET");
|
|
expect(request?.headers.get("Branchname")).toBe("main");
|
|
});
|
|
|
|
it("should return null for an unknown app mode", () => {
|
|
const params: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
pageId: "page123",
|
|
branchName: "main",
|
|
appMode: "UNKNOWN" as APP_MODE,
|
|
};
|
|
|
|
expect(getConsolidatedApiPrefetchRequest(params)).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("getPrefetchRequests", () => {
|
|
it("should return prefetch requests with consolidated api request", () => {
|
|
const params: TApplicationParams = {
|
|
origin: "https://app.appsmith.com",
|
|
branchName: "main",
|
|
appMode: APP_MODE.EDIT,
|
|
pageId: "page123",
|
|
};
|
|
const requests = getPrefetchRequests(params);
|
|
expect(requests).toHaveLength(1);
|
|
const [consolidatedAPIRequest] = requests;
|
|
expect(consolidatedAPIRequest).toBeInstanceOf(Request);
|
|
expect(consolidatedAPIRequest?.url).toBe(
|
|
`https://app.appsmith.com/api/v1/consolidated-api/edit?defaultPageId=page123`,
|
|
);
|
|
expect(consolidatedAPIRequest?.method).toBe("GET");
|
|
expect(consolidatedAPIRequest?.headers.get("Branchname")).toBe("main");
|
|
});
|
|
});
|
|
|
|
describe("PrefetchApiService", () => {
|
|
let prefetchApiService: PrefetchApiService;
|
|
let mockCache: any;
|
|
|
|
beforeEach(() => {
|
|
prefetchApiService = new PrefetchApiService();
|
|
mockCache = {
|
|
put: jest.fn(),
|
|
match: jest.fn(),
|
|
delete: jest.fn(),
|
|
};
|
|
(global as any).caches.open.mockResolvedValue(mockCache);
|
|
(global as any).Request = NFRequest;
|
|
(global as any).Response = NFResponse;
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe("getRequestKey", () => {
|
|
it("should return the correct request key", () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
request.headers.append("branchname", "main");
|
|
const key = prefetchApiService.getRequestKey(request);
|
|
expect(key).toBe("GET:https://app.appsmith.com/:branchname:main");
|
|
});
|
|
});
|
|
|
|
describe("aqcuireFetchMutex", () => {
|
|
it("should acquire a new mutex if not present", async () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
const acquireSpy = jest.spyOn(Mutex.prototype, "acquire");
|
|
await prefetchApiService.aqcuireFetchMutex(request);
|
|
expect(acquireSpy).toHaveBeenCalled();
|
|
});
|
|
|
|
it("should reuse existing mutex if present", async () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
const mutex = new Mutex();
|
|
prefetchApiService.prefetchFetchMutexMap.set(
|
|
prefetchApiService.getRequestKey(request),
|
|
mutex,
|
|
);
|
|
const acquireSpy = jest.spyOn(mutex, "acquire");
|
|
await prefetchApiService.aqcuireFetchMutex(request);
|
|
expect(acquireSpy).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe("waitForUnlock", () => {
|
|
it("should wait for the mutex to unlock if it exists", async () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
const mutex = new Mutex();
|
|
prefetchApiService.prefetchFetchMutexMap.set(
|
|
prefetchApiService.getRequestKey(request),
|
|
mutex,
|
|
);
|
|
const waitForUnlockSpy = jest.spyOn(mutex, "waitForUnlock");
|
|
await prefetchApiService.waitForUnlock(request);
|
|
expect(waitForUnlockSpy).toHaveBeenCalled();
|
|
});
|
|
|
|
it("should do nothing if the mutex does not exist", async () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
await expect(
|
|
prefetchApiService.waitForUnlock(request),
|
|
).resolves.not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe("releaseFetchMutex", () => {
|
|
it("should release the mutex if it exists", () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
const mutex = new Mutex();
|
|
prefetchApiService.prefetchFetchMutexMap.set(
|
|
prefetchApiService.getRequestKey(request),
|
|
mutex,
|
|
);
|
|
const releaseSpy = jest.spyOn(mutex, "release");
|
|
prefetchApiService.releaseFetchMutex(request);
|
|
expect(releaseSpy).toHaveBeenCalled();
|
|
});
|
|
|
|
it("should do nothing if the mutex does not exist", () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
expect(() =>
|
|
prefetchApiService.releaseFetchMutex(request),
|
|
).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe("cacheApi", () => {
|
|
it("should acquire the mutex, fetch the request, cache the response, and release the mutex", async () => {
|
|
const request = new Request("https://app.appsmith.com/sdfsdf", {
|
|
method: "GET",
|
|
});
|
|
const response = new Response("Test response", {
|
|
status: 200,
|
|
statusText: "OK",
|
|
});
|
|
|
|
(global as any).fetch.mockResolvedValue(response);
|
|
|
|
const acquireSpy = jest.spyOn(Mutex.prototype, "acquire");
|
|
const releaseSpy = jest.spyOn(Mutex.prototype, "release");
|
|
|
|
await prefetchApiService.cacheApi(request);
|
|
|
|
expect(acquireSpy).toHaveBeenCalled();
|
|
expect((global as any).fetch).toHaveBeenCalledWith(request);
|
|
expect(mockCache.put).toHaveBeenCalledWith(
|
|
request,
|
|
expect.objectContaining({
|
|
status: 200,
|
|
statusText: "OK",
|
|
}),
|
|
);
|
|
expect(releaseSpy).toHaveBeenCalled();
|
|
});
|
|
|
|
it("should delete the cache and release the mutex if fetch fails", async () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
(global as any).fetch.mockRejectedValue(new Error("Fetch error"));
|
|
|
|
const acquireSpy = jest.spyOn(Mutex.prototype, "acquire");
|
|
const releaseSpy = jest.spyOn(Mutex.prototype, "release");
|
|
|
|
await prefetchApiService.cacheApi(request);
|
|
|
|
expect(acquireSpy).toHaveBeenCalled();
|
|
expect(mockCache.delete).toHaveBeenCalledWith(request);
|
|
expect(releaseSpy).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe("getCachedResponse", () => {
|
|
it("should wait for the mutex to unlock, get the cached response if valid, and delete it afterwards", async () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
const response = new Response("test response", {
|
|
headers: { date: new Date(Date.now() - 1000).toUTCString() },
|
|
});
|
|
mockCache.match.mockResolvedValue(response);
|
|
const mutex = new Mutex();
|
|
prefetchApiService.prefetchFetchMutexMap.set(
|
|
prefetchApiService.getRequestKey(request),
|
|
mutex,
|
|
);
|
|
const waitForUnlockSpy = jest.spyOn(Mutex.prototype, "waitForUnlock");
|
|
|
|
const cachedResponse =
|
|
await prefetchApiService.getCachedResponse(request);
|
|
|
|
expect(waitForUnlockSpy).toHaveBeenCalled();
|
|
expect(mockCache.match).toHaveBeenCalledWith(request);
|
|
expect(mockCache.delete).toHaveBeenCalledWith(request);
|
|
expect(cachedResponse).toBe(response);
|
|
});
|
|
|
|
it("should return null if the cache is invalid", async () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
const response = new Response("test response", {
|
|
headers: { date: new Date(Date.now() - 3 * 60 * 1000).toUTCString() },
|
|
});
|
|
mockCache.match.mockResolvedValue(response);
|
|
|
|
const cachedResponse =
|
|
await prefetchApiService.getCachedResponse(request);
|
|
|
|
expect(mockCache.match).toHaveBeenCalledWith(request);
|
|
expect(mockCache.delete).toHaveBeenCalledWith(request);
|
|
expect(cachedResponse).toBeNull();
|
|
});
|
|
|
|
it("should return null if there is no cached response", async () => {
|
|
const request = new Request("https://app.appsmith.com", {
|
|
method: "GET",
|
|
});
|
|
mockCache.match.mockResolvedValue(null);
|
|
|
|
const cachedResponse =
|
|
await prefetchApiService.getCachedResponse(request);
|
|
|
|
expect(mockCache.match).toHaveBeenCalledWith(request);
|
|
expect(cachedResponse).toBeNull();
|
|
});
|
|
});
|
|
});
|
|
});
|