* feat(post-application): add schema and shared types for provider ingestion (#136) * test(orchestrator): ensure full localStorage shape in vitest setup * feat(post-application): add provider registry and dispatcher framework (#137) (#146) * Implement Gmail provider credential persistence (#147) * Add unified post-application provider action API (#148) * Implement Gmail ingestion sync with 95/60 relevance policy * Implement Gmail ingestion sync with 95/60 relevance policy (#149) * feat(post-application): add job mapping engine with llm rerank fallback * feat(post-application): add inbox review APIs with transactional approve/deny (#151) * feat(post-application): add tracking inbox UI with provider controls (#152) * oauth implementation * UI changes * see past runs in more detail * occurred at comes from email * state mismatch * better UI representation * comments * comments * comments * comments * documentation * explainer * set things manually * scrolling * any found email can be pending * searchable download * Email-to-Job Matching Decision Tree * email viewer list improvement * simplification initial commit * exclude discovered jobs * show only resady * dropdown * mermaid * syntax * targets is the same as logging that is done manually * event label * duplicate avoidance * clean up html * token saving * print * send idx not uuid * remove logging * formatting * better documentation * documentation * comments * process all * comments
59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
|
// allows you to do things like:
|
|
// expect(element).toHaveTextContent(/react/i)
|
|
// learn more: https://github.com/testing-library/jest-dom
|
|
import "@testing-library/jest-dom";
|
|
|
|
if (typeof globalThis.ResizeObserver === "undefined") {
|
|
class ResizeObserver {
|
|
observe() {}
|
|
unobserve() {}
|
|
disconnect() {}
|
|
}
|
|
|
|
globalThis.ResizeObserver = ResizeObserver;
|
|
}
|
|
|
|
const hasStorageShape = (value: unknown): value is Storage => {
|
|
if (!value || typeof value !== "object") return false;
|
|
const storage = value as Partial<Storage>;
|
|
return (
|
|
typeof storage.getItem === "function" &&
|
|
typeof storage.setItem === "function" &&
|
|
typeof storage.removeItem === "function" &&
|
|
typeof storage.clear === "function" &&
|
|
typeof storage.key === "function"
|
|
);
|
|
};
|
|
|
|
if (!hasStorageShape(globalThis.localStorage)) {
|
|
const store = new Map<string, string>();
|
|
const storage: Storage = {
|
|
get length() {
|
|
return store.size;
|
|
},
|
|
clear() {
|
|
store.clear();
|
|
},
|
|
getItem(key: string) {
|
|
const value = store.get(key);
|
|
return value ?? null;
|
|
},
|
|
key(index: number) {
|
|
return Array.from(store.keys())[index] ?? null;
|
|
},
|
|
removeItem(key: string) {
|
|
store.delete(key);
|
|
},
|
|
setItem(key: string, value: string) {
|
|
store.set(key, value);
|
|
},
|
|
};
|
|
|
|
Object.defineProperty(globalThis, "localStorage", {
|
|
configurable: true,
|
|
writable: true,
|
|
value: storage,
|
|
});
|
|
}
|