Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
134 lines
4.6 KiB
JavaScript
134 lines
4.6 KiB
JavaScript
// src/common.ts
|
|
import { wrapGlobalTestMethod } from "@wdio/utils";
|
|
|
|
// src/constants.ts
|
|
var INTERFACES = {
|
|
bdd: ["it", "specify", "before", "beforeEach", "after", "afterEach"],
|
|
tdd: ["test", "suiteSetup", "setup", "suiteTeardown", "teardown"],
|
|
qunit: ["test", "before", "beforeEach", "after", "afterEach"]
|
|
};
|
|
var TEST_INTERFACES = {
|
|
bdd: ["it", "specify"],
|
|
tdd: ["test"],
|
|
qunit: ["test"]
|
|
};
|
|
var MOCHA_TIMEOUT_MESSAGE = 'For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.';
|
|
|
|
// src/common.ts
|
|
var MOCHA_UI_TYPE_EXTRACTOR = /^(?:.*-)?([^-.]+)(?:.js)?$/;
|
|
var DEFAULT_INTERFACE_TYPE = "bdd";
|
|
function formatMessage(params) {
|
|
const message = {
|
|
type: params.type
|
|
};
|
|
const payload = params.payload;
|
|
const mochaAllHooksIfPresent = payload?.title?.match(/^"(before|after)( all| each)?" hook/);
|
|
if (params.err) {
|
|
const isSkipError = /^(sync|async) skip; aborting execution$/.test(params.err.message || "");
|
|
const isHookSkip = isSkipError && mochaAllHooksIfPresent;
|
|
if (isHookSkip) {
|
|
message.type = "hook:end";
|
|
} else {
|
|
if (params.err && params.err.message && params.err.message.includes(MOCHA_TIMEOUT_MESSAGE)) {
|
|
const testName = (payload?.parent?.title ? `${payload.parent.title} ${payload.title}` : payload?.title) || "unknown test";
|
|
const replacement = `The execution in the test "${testName}" took too long. Try to reduce the run time or increase your timeout for test specs (https://webdriver.io/docs/timeouts).`;
|
|
params.err.message = params.err.message.replace(MOCHA_TIMEOUT_MESSAGE, replacement);
|
|
params.err.stack = params.err.stack.replace(MOCHA_TIMEOUT_MESSAGE, replacement);
|
|
}
|
|
message.error = {
|
|
name: params.err.name,
|
|
message: params.err.message,
|
|
stack: params.err.stack,
|
|
type: params.err.type || params.err.name,
|
|
expected: params.err.expected,
|
|
actual: params.err.actual
|
|
};
|
|
if (mochaAllHooksIfPresent) {
|
|
message.type = "hook:end";
|
|
}
|
|
}
|
|
}
|
|
if (payload) {
|
|
message.title = payload.title;
|
|
message.parent = payload.parent ? payload.parent.title : void 0;
|
|
let fullTitle = message.title;
|
|
if (payload.parent) {
|
|
let parent = payload.parent;
|
|
while (parent && parent.title) {
|
|
fullTitle = parent.title + "." + fullTitle;
|
|
parent = parent.parent;
|
|
}
|
|
}
|
|
message.fullTitle = fullTitle;
|
|
message.pending = payload.pending || false;
|
|
message.file = payload.file;
|
|
message.duration = payload.duration;
|
|
message.body = payload.body;
|
|
if (payload.ctx && payload.ctx.currentTest) {
|
|
message.currentTest = payload.ctx.currentTest.title;
|
|
}
|
|
if (params.type.match(/Test/)) {
|
|
message.passed = payload.state === "passed";
|
|
}
|
|
if (payload.parent?.title && mochaAllHooksIfPresent) {
|
|
const hookName = mochaAllHooksIfPresent[0];
|
|
message.title = `${hookName} for ${payload.parent.title}`;
|
|
}
|
|
if (payload.context) {
|
|
message.context = payload.context;
|
|
}
|
|
}
|
|
return message;
|
|
}
|
|
function requireExternalModules(mods, loader = loadModule) {
|
|
return mods.map((mod) => {
|
|
if (!mod) {
|
|
return Promise.resolve();
|
|
}
|
|
mod = mod.includes(":") ? mod.substring(mod.lastIndexOf(":") + 1) : mod;
|
|
if (mod.startsWith("./") && globalThis.process) {
|
|
mod = `${globalThis.process.cwd()}/${mod.slice(2)}`;
|
|
}
|
|
return loader(mod);
|
|
});
|
|
}
|
|
function setupEnv(cid, options, beforeTest, beforeHook, afterTest, afterHook) {
|
|
const match = MOCHA_UI_TYPE_EXTRACTOR.exec(options.ui);
|
|
const type = match && INTERFACES[match[1]] && match[1] || DEFAULT_INTERFACE_TYPE;
|
|
const hookArgsFn = (context) => {
|
|
return [{ ...context.test, parent: context.test?.parent?.title }, context];
|
|
};
|
|
INTERFACES[type].forEach((fnName) => {
|
|
const isTest = TEST_INTERFACES[type].flatMap((testCommand) => [testCommand, testCommand + ".only"]).includes(fnName);
|
|
wrapGlobalTestMethod(
|
|
isTest,
|
|
isTest ? beforeTest : beforeHook,
|
|
// @ts-ignore
|
|
hookArgsFn,
|
|
isTest ? afterTest : afterHook,
|
|
hookArgsFn,
|
|
fnName,
|
|
cid
|
|
);
|
|
});
|
|
const { compilers = [] } = options;
|
|
return requireExternalModules([...compilers]);
|
|
}
|
|
async function loadModule(name) {
|
|
try {
|
|
return await import(
|
|
/* @vite-ignore */
|
|
name
|
|
);
|
|
} catch {
|
|
throw new Error(`Module ${name} can't get loaded. Are you sure you have installed it?
|
|
Note: if you've installed WebdriverIO globally you need to install these external modules globally too!`);
|
|
}
|
|
}
|
|
export {
|
|
formatMessage,
|
|
loadModule,
|
|
requireExternalModules,
|
|
setupEnv
|
|
};
|