[PM-10788] Handle `chrome.runtime.lastError` (#10479)
* Handle `chrome.runtime.lastError` * Add Tests
This commit is contained in:
parent
7387a1115a
commit
334601e74f
|
@ -74,8 +74,12 @@ export default abstract class AbstractChromeStorageService
|
||||||
}
|
}
|
||||||
|
|
||||||
async get<T>(key: string): Promise<T> {
|
async get<T>(key: string): Promise<T> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.chromeStorageApi.get(key, (obj: any) => {
|
this.chromeStorageApi.get(key, (obj) => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
return reject(chrome.runtime.lastError);
|
||||||
|
}
|
||||||
|
|
||||||
if (obj != null && obj[key] != null) {
|
if (obj != null && obj[key] != null) {
|
||||||
resolve(this.processGetObject(obj[key]));
|
resolve(this.processGetObject(obj[key]));
|
||||||
return;
|
return;
|
||||||
|
@ -98,16 +102,24 @@ export default abstract class AbstractChromeStorageService
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyedObj = { [key]: obj };
|
const keyedObj = { [key]: obj };
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
this.chromeStorageApi.set(keyedObj, () => {
|
this.chromeStorageApi.set(keyedObj, () => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
return reject(chrome.runtime.lastError);
|
||||||
|
}
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async remove(key: string): Promise<void> {
|
async remove(key: string): Promise<void> {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
this.chromeStorageApi.remove(key, () => {
|
this.chromeStorageApi.remove(key, () => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
return reject(chrome.runtime.lastError);
|
||||||
|
}
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -51,6 +51,10 @@ describe("ChromeStorageApiService", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
chrome.runtime.lastError = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
it("uses `objToStore` to prepare a value for set", async () => {
|
it("uses `objToStore` to prepare a value for set", async () => {
|
||||||
const key = "key";
|
const key = "key";
|
||||||
const value = { key: "value" };
|
const value = { key: "value" };
|
||||||
|
@ -73,6 +77,15 @@ describe("ChromeStorageApiService", () => {
|
||||||
await service.save(key, null);
|
await service.save(key, null);
|
||||||
expect(removeMock).toHaveBeenCalledWith(key, expect.any(Function));
|
expect(removeMock).toHaveBeenCalledWith(key, expect.any(Function));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("translates chrome.runtime.lastError to promise rejection", async () => {
|
||||||
|
setMock.mockImplementation((data, callback) => {
|
||||||
|
chrome.runtime.lastError = new Error("Test Error");
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(async () => await service.save("test", {})).rejects.toThrow("Test Error");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("get", () => {
|
describe("get", () => {
|
||||||
|
@ -87,6 +100,10 @@ describe("ChromeStorageApiService", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
chrome.runtime.lastError = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
it("returns a stored value when it is serialized", async () => {
|
it("returns a stored value when it is serialized", async () => {
|
||||||
const value = { key: "value" };
|
const value = { key: "value" };
|
||||||
store[key] = objToStore(value);
|
store[key] = objToStore(value);
|
||||||
|
@ -112,5 +129,15 @@ describe("ChromeStorageApiService", () => {
|
||||||
const result = await service.get(key);
|
const result = await service.get(key);
|
||||||
expect(result).toBeNull();
|
expect(result).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("translates chrome.runtime.lastError to promise rejection", async () => {
|
||||||
|
getMock.mockImplementation((key, callback) => {
|
||||||
|
chrome.runtime.lastError = new Error("Test Error");
|
||||||
|
callback();
|
||||||
|
chrome.runtime.lastError = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(async () => await service.get("test")).rejects.toThrow("Test Error");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -62,6 +62,7 @@ describe("BrowserLocalStorageService", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
chrome.runtime.lastError = undefined;
|
||||||
jest.resetAllMocks();
|
jest.resetAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -121,6 +122,24 @@ describe("BrowserLocalStorageService", () => {
|
||||||
|
|
||||||
expect(clearMock).toHaveBeenCalledTimes(1);
|
expect(clearMock).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("throws if get has chrome.runtime.lastError", async () => {
|
||||||
|
getMock.mockImplementation((key, callback) => {
|
||||||
|
chrome.runtime.lastError = new Error("Get Test Error");
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(async () => await service.reseed()).rejects.toThrow("Get Test Error");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws if save has chrome.runtime.lastError", async () => {
|
||||||
|
saveMock.mockImplementation((obj, callback) => {
|
||||||
|
chrome.runtime.lastError = new Error("Save Test Error");
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(async () => await service.reseed()).rejects.toThrow("Save Test Error");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe.each(["get", "has", "save", "remove"] as const)("%s", (method) => {
|
describe.each(["get", "has", "save", "remove"] as const)("%s", (method) => {
|
||||||
|
|
|
@ -81,8 +81,11 @@ export default class BrowserLocalStorageService extends AbstractChromeStorageSer
|
||||||
* Clears local storage
|
* Clears local storage
|
||||||
*/
|
*/
|
||||||
private async clear() {
|
private async clear() {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
this.chromeStorageApi.clear(() => {
|
this.chromeStorageApi.clear(() => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
return reject(chrome.runtime.lastError);
|
||||||
|
}
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -95,8 +98,12 @@ export default class BrowserLocalStorageService extends AbstractChromeStorageSer
|
||||||
* @returns Promise resolving to keyed object of all stored data
|
* @returns Promise resolving to keyed object of all stored data
|
||||||
*/
|
*/
|
||||||
private async getAll(): Promise<Record<string, unknown>> {
|
private async getAll(): Promise<Record<string, unknown>> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.chromeStorageApi.get(null, (allStorage) => {
|
this.chromeStorageApi.get(null, (allStorage) => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
return reject(chrome.runtime.lastError);
|
||||||
|
}
|
||||||
|
|
||||||
const resolved = Object.entries(allStorage).reduce(
|
const resolved = Object.entries(allStorage).reduce(
|
||||||
(agg, [key, value]) => {
|
(agg, [key, value]) => {
|
||||||
agg[key] = this.processGetObject(value);
|
agg[key] = this.processGetObject(value);
|
||||||
|
@ -110,7 +117,7 @@ export default class BrowserLocalStorageService extends AbstractChromeStorageSer
|
||||||
}
|
}
|
||||||
|
|
||||||
private async saveAll(data: Record<string, unknown>): Promise<void> {
|
private async saveAll(data: Record<string, unknown>): Promise<void> {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
const keyedData = Object.entries(data).reduce(
|
const keyedData = Object.entries(data).reduce(
|
||||||
(agg, [key, value]) => {
|
(agg, [key, value]) => {
|
||||||
agg[key] = objToStore(value);
|
agg[key] = objToStore(value);
|
||||||
|
@ -119,6 +126,10 @@ export default class BrowserLocalStorageService extends AbstractChromeStorageSer
|
||||||
{} as Record<string, SerializedValue>,
|
{} as Record<string, SerializedValue>,
|
||||||
);
|
);
|
||||||
this.chromeStorageApi.set(keyedData, () => {
|
this.chromeStorageApi.set(keyedData, () => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
return reject(chrome.runtime.lastError);
|
||||||
|
}
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue