test
Some checks failed
test / Run tests (push) Failing after 6s
build / Build (push) Failing after 9s
Some checks failed
test / Run tests (push) Failing after 6s
build / Build (push) Failing after 9s
This commit is contained in:
3
packages/chrome-extension-mock/README.md
Normal file
3
packages/chrome-extension-mock/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# mock一个chrome扩展环境
|
||||
> 只针对自己的项目做了一些简单的封装,如果有需要可以自己修改
|
||||
|
32
packages/chrome-extension-mock/cookies.ts
Normal file
32
packages/chrome-extension-mock/cookies.ts
Normal file
@ -0,0 +1,32 @@
|
||||
export default class Cookies {
|
||||
getAllCookieStores(
|
||||
callback: (cookieStores: chrome.cookies.CookieStore[]) => void
|
||||
) {
|
||||
callback([
|
||||
{
|
||||
id: "0",
|
||||
tabIds: [1],
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
mockGetAll?: (
|
||||
details: chrome.cookies.GetAllDetails,
|
||||
callback: (cookies: chrome.cookies.Cookie[]) => void
|
||||
) => void | undefined;
|
||||
|
||||
getAll(
|
||||
details: chrome.cookies.GetAllDetails,
|
||||
callback: (cookies: chrome.cookies.Cookie[]) => void
|
||||
): void {
|
||||
this.mockGetAll?.(details, callback);
|
||||
}
|
||||
|
||||
set(details: chrome.cookies.SetDetails, callback?: () => void): void {
|
||||
callback?.();
|
||||
}
|
||||
|
||||
remove(details: chrome.cookies.Details, callback?: () => void): void {
|
||||
callback?.();
|
||||
}
|
||||
}
|
38
packages/chrome-extension-mock/declarativ_net_request.ts
Normal file
38
packages/chrome-extension-mock/declarativ_net_request.ts
Normal file
@ -0,0 +1,38 @@
|
||||
export default class DeclarativeNetRequest {
|
||||
HeaderOperation = {
|
||||
APPEND: "append",
|
||||
SET: "set",
|
||||
REMOVE: "remove",
|
||||
};
|
||||
|
||||
RuleActionType = {
|
||||
BLOCK: "block",
|
||||
REDIRECT: "redirect",
|
||||
ALLOW: "allow",
|
||||
UPGRADE_SCHEME: "upgradeScheme",
|
||||
MODIFY_HEADERS: "modifyHeaders",
|
||||
ALLOW_ALL_REQUESTS: "allowAllRequests",
|
||||
};
|
||||
|
||||
ResourceType = {
|
||||
MAIN_FRAME: "main_frame",
|
||||
SUB_FRAME: "sub_frame",
|
||||
STYLESHEET: "stylesheet",
|
||||
SCRIPT: "script",
|
||||
IMAGE: "image",
|
||||
FONT: "font",
|
||||
OBJECT: "object",
|
||||
XMLHTTPREQUEST: "xmlhttprequest",
|
||||
PING: "ping",
|
||||
CSP_REPORT: "csp_report",
|
||||
MEDIA: "media",
|
||||
WEBSOCKET: "websocket",
|
||||
OTHER: "other",
|
||||
};
|
||||
|
||||
updateSessionRules() {
|
||||
return new Promise<void>((resolve) => {
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
}
|
5
packages/chrome-extension-mock/downloads.ts
Normal file
5
packages/chrome-extension-mock/downloads.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export default class Downloads {
|
||||
download(_: any, callback: Function) {
|
||||
callback && callback();
|
||||
}
|
||||
}
|
9
packages/chrome-extension-mock/i18n.ts
Normal file
9
packages/chrome-extension-mock/i18n.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export default class I18n {
|
||||
getUILanguage() {
|
||||
return "zh-CN";
|
||||
}
|
||||
|
||||
getAcceptLanguages(callback: (lngs: string[]) => void) {
|
||||
callback(["zh-CN"]);
|
||||
}
|
||||
}
|
26
packages/chrome-extension-mock/index.ts
Normal file
26
packages/chrome-extension-mock/index.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import Cookies from "./cookies";
|
||||
import Downloads from "./downloads";
|
||||
import Notifications from "./notifications";
|
||||
import Runtime from "./runtime";
|
||||
import MockTab from "./tab";
|
||||
import WebRequest from "./web_reqeuest";
|
||||
import Storage from "./storage";
|
||||
import I18n from "./i18n";
|
||||
import DeclarativeNetRequest from "./declarativ_net_request";
|
||||
|
||||
const chromeMock = {
|
||||
tabs: new MockTab(),
|
||||
runtime: new Runtime(),
|
||||
webRequest: new WebRequest(),
|
||||
notifications: new Notifications(),
|
||||
downloads: new Downloads(),
|
||||
cookies: new Cookies(),
|
||||
storage: new Storage(),
|
||||
i18n: new I18n(),
|
||||
declarativeNetRequest: new DeclarativeNetRequest(),
|
||||
init() {},
|
||||
};
|
||||
// @ts-ignore
|
||||
global.chrome = chromeMock;
|
||||
|
||||
export default chromeMock;
|
64
packages/chrome-extension-mock/notifications.ts
Normal file
64
packages/chrome-extension-mock/notifications.ts
Normal file
@ -0,0 +1,64 @@
|
||||
export default class Notifications {
|
||||
notification: Map<string, boolean> = new Map();
|
||||
|
||||
onClosedHandler?: (id: string, byUser: boolean) => void;
|
||||
|
||||
onClosed = {
|
||||
addListener: (
|
||||
callback: (notificationId: string, byUser: boolean) => void
|
||||
) => {
|
||||
this.onClosedHandler = callback;
|
||||
},
|
||||
};
|
||||
|
||||
onButtonClickedHandler?: (id: string, index: number) => void;
|
||||
|
||||
onButtonClicked = {
|
||||
addListener: (
|
||||
callback: (notificationId: string, buttonIndex: number) => void
|
||||
) => {
|
||||
this.onButtonClickedHandler = callback;
|
||||
},
|
||||
};
|
||||
|
||||
mockClickButton(id: string, index: number) {
|
||||
this.onButtonClickedHandler?.(id, index);
|
||||
}
|
||||
|
||||
onClickedHandler?: (id: string) => void;
|
||||
|
||||
onClicked = {
|
||||
addListener: (callback: (notificationId: string) => void) => {
|
||||
this.onClickedHandler = callback;
|
||||
},
|
||||
};
|
||||
|
||||
create(
|
||||
options: chrome.notifications.NotificationOptions,
|
||||
callback?: (id: string) => void
|
||||
) {
|
||||
const id = Math.random().toString();
|
||||
this.notification.set(id, true);
|
||||
if (callback) {
|
||||
callback(id);
|
||||
}
|
||||
}
|
||||
|
||||
clear(id: string) {
|
||||
if (!this.notification.has(id)) {
|
||||
throw new Error("notification not found");
|
||||
}
|
||||
this.notification.delete(id);
|
||||
}
|
||||
|
||||
update(id: string) {
|
||||
if (!this.notification.has(id)) {
|
||||
throw new Error("notification not found");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
mockClick(id: string) {
|
||||
this.onClickedHandler?.(id);
|
||||
}
|
||||
}
|
62
packages/chrome-extension-mock/runtime.ts
Normal file
62
packages/chrome-extension-mock/runtime.ts
Normal file
@ -0,0 +1,62 @@
|
||||
type Port = chrome.runtime.Port & {
|
||||
setTargetPort: (port: chrome.runtime.Port) => void;
|
||||
messageListener: Array<(message: any) => void>;
|
||||
};
|
||||
|
||||
export default class Runtime {
|
||||
connectListener: Array<(port: chrome.runtime.Port) => void> = [];
|
||||
|
||||
onConnect = {
|
||||
addListener: (callback: (port: chrome.runtime.Port) => void) => {
|
||||
this.connectListener.push(callback);
|
||||
},
|
||||
};
|
||||
|
||||
Port(connectInfo?: chrome.runtime.ConnectInfo) {
|
||||
const messageListener: Array<(message: any) => void> = [];
|
||||
let targetPort: Port;
|
||||
return {
|
||||
setTargetPort(port: Port) {
|
||||
targetPort = port;
|
||||
},
|
||||
messageListener,
|
||||
name: connectInfo?.name || "",
|
||||
sender: {
|
||||
tab: {
|
||||
id: 1,
|
||||
} as unknown as chrome.tabs.Tab,
|
||||
url: window.location.href,
|
||||
},
|
||||
postMessage(message: any) {
|
||||
messageListener.forEach((callback) => {
|
||||
callback(message);
|
||||
});
|
||||
},
|
||||
onMessage: {
|
||||
addListener(callback: (message: any) => void) {
|
||||
targetPort.messageListener.push(callback);
|
||||
},
|
||||
} as unknown as chrome.events.Event<(message: any) => void>,
|
||||
onDisconnect: {
|
||||
addListener() {
|
||||
// do nothing
|
||||
},
|
||||
} as unknown as chrome.events.Event<() => void>,
|
||||
} as unknown as Port;
|
||||
}
|
||||
|
||||
connect(connectInfo?: chrome.runtime.ConnectInfo) {
|
||||
const port = this.Port(connectInfo);
|
||||
const targetPort = this.Port(connectInfo);
|
||||
targetPort.setTargetPort(port);
|
||||
port.setTargetPort(targetPort);
|
||||
this.connectListener.forEach((callback) => {
|
||||
callback(targetPort);
|
||||
});
|
||||
return port;
|
||||
}
|
||||
|
||||
getURL(path: string) {
|
||||
return `${window.location.href}${path}`;
|
||||
}
|
||||
}
|
33
packages/chrome-extension-mock/storage.ts
Normal file
33
packages/chrome-extension-mock/storage.ts
Normal file
@ -0,0 +1,33 @@
|
||||
export default class Storage {
|
||||
sync = new CrhomeStorage();
|
||||
local = new CrhomeStorage();
|
||||
session = new CrhomeStorage();
|
||||
}
|
||||
|
||||
export class CrhomeStorage {
|
||||
data: any = {};
|
||||
|
||||
get(key: string, callback: (data: any) => void) {
|
||||
if (key === null) {
|
||||
callback(this.data);
|
||||
return;
|
||||
}
|
||||
callback({ [key]: this.data[key] });
|
||||
}
|
||||
|
||||
set(data: any, callback: () => void) {
|
||||
this.data = Object.assign(this.data, data);
|
||||
callback();
|
||||
}
|
||||
|
||||
remove(keys: string | string[], callback: () => void) {
|
||||
if (typeof keys === "string") {
|
||||
delete this.data[keys];
|
||||
} else {
|
||||
keys.forEach((key) => {
|
||||
delete this.data[key];
|
||||
});
|
||||
}
|
||||
callback();
|
||||
}
|
||||
}
|
28
packages/chrome-extension-mock/tab.ts
Normal file
28
packages/chrome-extension-mock/tab.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import EventEmitter from "eventemitter3";
|
||||
|
||||
export default class MockTab {
|
||||
hook = new EventEmitter();
|
||||
|
||||
query() {
|
||||
return new Promise((resolve) => {
|
||||
resolve([]);
|
||||
});
|
||||
}
|
||||
|
||||
create(createProperties: chrome.tabs.CreateProperties, callback?: (tab: chrome.tabs.Tab) => void) {
|
||||
this.hook.emit("create", createProperties);
|
||||
callback?.({
|
||||
id: 1,
|
||||
} as chrome.tabs.Tab);
|
||||
}
|
||||
|
||||
remove(tabId: number) {
|
||||
this.hook.emit("remove", tabId);
|
||||
}
|
||||
|
||||
onRemoved = {
|
||||
addListener: (callback: any) => {
|
||||
this.hook.addListener("remove", callback);
|
||||
},
|
||||
};
|
||||
}
|
59
packages/chrome-extension-mock/web_reqeuest.ts
Normal file
59
packages/chrome-extension-mock/web_reqeuest.ts
Normal file
@ -0,0 +1,59 @@
|
||||
export default class WebRequest {
|
||||
sendHeader?: (
|
||||
details: chrome.webRequest.WebRequestHeadersDetails
|
||||
) => chrome.webRequest.BlockingResponse | void;
|
||||
|
||||
mockXhr(xhr: any): any {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
const _this = this;
|
||||
// eslint-disable-next-line func-names
|
||||
return function () {
|
||||
// eslint-disable-next-line new-cap
|
||||
const ret = new xhr();
|
||||
const header: chrome.webRequest.HttpHeader[] = [];
|
||||
ret.setRequestHeader = (k: string, v: string) => {
|
||||
header.push({
|
||||
name: k,
|
||||
value: v,
|
||||
});
|
||||
};
|
||||
const oldSend = ret.send.bind(ret);
|
||||
ret.send = (data: any) => {
|
||||
header.push({
|
||||
name: "cookie",
|
||||
value: "website=example.com",
|
||||
});
|
||||
const resp = _this.sendHeader?.({
|
||||
method: ret.method,
|
||||
url: ret.url,
|
||||
requestHeaders: header,
|
||||
initiator: chrome.runtime.getURL(""),
|
||||
} as chrome.webRequest.WebRequestHeadersDetails) as chrome.webRequest.BlockingResponse;
|
||||
resp.requestHeaders?.forEach((h) => {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
ret._authorRequestHeaders!.addHeader(h.name, h.value);
|
||||
});
|
||||
oldSend(data);
|
||||
};
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
onBeforeSendHeaders = {
|
||||
addListener: (callback: any) => {
|
||||
this.sendHeader = callback;
|
||||
},
|
||||
};
|
||||
|
||||
onHeadersReceived = {
|
||||
addListener: () => {
|
||||
// TODO
|
||||
},
|
||||
};
|
||||
|
||||
onCompleted = {
|
||||
addListener: () => {
|
||||
// TODO
|
||||
},
|
||||
};
|
||||
}
|
61
packages/message/mock_message.ts
Normal file
61
packages/message/mock_message.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import EventEmitter from "eventemitter3";
|
||||
import { Message, MessageConnect, MessageSend } from "./server";
|
||||
|
||||
export class MockMessageConnect implements MessageConnect {
|
||||
constructor(protected EE: EventEmitter) {}
|
||||
|
||||
onMessage(callback: (data: any) => void): void {
|
||||
this.EE.on("message", (data: any) => {
|
||||
callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
sendMessage(data: any): void {
|
||||
this.EE.emit("message", data);
|
||||
}
|
||||
|
||||
disconnect(): void {
|
||||
this.EE.emit("disconnect");
|
||||
}
|
||||
|
||||
onDisconnect(callback: () => void): void {
|
||||
this.EE.on("disconnect", callback);
|
||||
}
|
||||
}
|
||||
|
||||
export class MockMessageSend implements MessageSend {
|
||||
constructor(
|
||||
protected EE: EventEmitter,
|
||||
) {}
|
||||
|
||||
connect(data: any): Promise<MessageConnect> {
|
||||
return new Promise((resolve) => {
|
||||
const EE = new EventEmitter();
|
||||
const con = new MockMessageConnect(EE);
|
||||
this.EE.emit("connect", data, con);
|
||||
resolve(con);
|
||||
});
|
||||
}
|
||||
|
||||
sendMessage(data: any): Promise<any> {
|
||||
return new Promise((resolve) => {
|
||||
this.EE.emit("message", data, (resp: any) => {
|
||||
resolve(resp);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class MockMessage extends MockMessageSend implements Message {
|
||||
onConnect(callback: (data: any, con: MessageConnect) => void): void {
|
||||
this.EE.on("connect", (data: any, con: MessageConnect) => {
|
||||
callback(data, con);
|
||||
});
|
||||
}
|
||||
|
||||
onMessage(callback: (data: any, sendResponse: (data: any) => void) => void): void {
|
||||
this.EE.on("message", (data: any, sendResponse: (data: any) => void) => {
|
||||
callback(data, sendResponse);
|
||||
});
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user