@bbearai/react-native 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +139 -92
- package/dist/index.js +343 -171
- package/dist/index.mjs +346 -173
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -11361,6 +11361,239 @@ function shouldShowDeprecationWarning() {
|
|
|
11361
11361
|
if (shouldShowDeprecationWarning()) console.warn("\u26A0\uFE0F Node.js 18 and below are deprecated and will no longer be supported in future versions of @supabase/supabase-js. Please upgrade to Node.js 20 or later. For more information, visit: https://github.com/orgs/supabase/discussions/37217");
|
|
11362
11362
|
|
|
11363
11363
|
// ../core/dist/index.mjs
|
|
11364
|
+
var MAX_CONSOLE_LOGS = 50;
|
|
11365
|
+
var MAX_NETWORK_REQUESTS = 20;
|
|
11366
|
+
var MAX_NAVIGATION_HISTORY = 20;
|
|
11367
|
+
var MAX_RESPONSE_BODY_LENGTH = 500;
|
|
11368
|
+
var ContextCaptureManager = class {
|
|
11369
|
+
constructor() {
|
|
11370
|
+
this.consoleLogs = [];
|
|
11371
|
+
this.networkRequests = [];
|
|
11372
|
+
this.navigationHistory = [];
|
|
11373
|
+
this.originalConsole = {};
|
|
11374
|
+
this.isCapturing = false;
|
|
11375
|
+
}
|
|
11376
|
+
/**
|
|
11377
|
+
* Start capturing console logs, network requests, and navigation
|
|
11378
|
+
*/
|
|
11379
|
+
startCapture() {
|
|
11380
|
+
if (this.isCapturing) return;
|
|
11381
|
+
this.isCapturing = true;
|
|
11382
|
+
this.captureConsole();
|
|
11383
|
+
this.captureFetch();
|
|
11384
|
+
this.captureNavigation();
|
|
11385
|
+
}
|
|
11386
|
+
/**
|
|
11387
|
+
* Stop capturing and restore original functions
|
|
11388
|
+
*/
|
|
11389
|
+
stopCapture() {
|
|
11390
|
+
if (!this.isCapturing) return;
|
|
11391
|
+
this.isCapturing = false;
|
|
11392
|
+
if (this.originalConsole.log) console.log = this.originalConsole.log;
|
|
11393
|
+
if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
|
|
11394
|
+
if (this.originalConsole.error) console.error = this.originalConsole.error;
|
|
11395
|
+
if (this.originalConsole.info) console.info = this.originalConsole.info;
|
|
11396
|
+
if (this.originalFetch && typeof window !== "undefined") {
|
|
11397
|
+
window.fetch = this.originalFetch;
|
|
11398
|
+
}
|
|
11399
|
+
if (typeof window !== "undefined" && typeof history !== "undefined") {
|
|
11400
|
+
if (this.originalPushState) {
|
|
11401
|
+
history.pushState = this.originalPushState;
|
|
11402
|
+
}
|
|
11403
|
+
if (this.originalReplaceState) {
|
|
11404
|
+
history.replaceState = this.originalReplaceState;
|
|
11405
|
+
}
|
|
11406
|
+
if (this.popstateHandler) {
|
|
11407
|
+
window.removeEventListener("popstate", this.popstateHandler);
|
|
11408
|
+
}
|
|
11409
|
+
}
|
|
11410
|
+
}
|
|
11411
|
+
/**
|
|
11412
|
+
* Get captured context for a bug report
|
|
11413
|
+
*/
|
|
11414
|
+
getEnhancedContext() {
|
|
11415
|
+
return {
|
|
11416
|
+
consoleLogs: [...this.consoleLogs],
|
|
11417
|
+
networkRequests: [...this.networkRequests],
|
|
11418
|
+
navigationHistory: [...this.navigationHistory],
|
|
11419
|
+
performanceMetrics: this.getPerformanceMetrics(),
|
|
11420
|
+
environment: this.getEnvironmentInfo()
|
|
11421
|
+
};
|
|
11422
|
+
}
|
|
11423
|
+
/**
|
|
11424
|
+
* Get the auto-captured navigation history
|
|
11425
|
+
*/
|
|
11426
|
+
getNavigationHistory() {
|
|
11427
|
+
return [...this.navigationHistory];
|
|
11428
|
+
}
|
|
11429
|
+
/**
|
|
11430
|
+
* Get the current route (last entry in navigation history, or window.location)
|
|
11431
|
+
*/
|
|
11432
|
+
getCurrentRoute() {
|
|
11433
|
+
if (this.navigationHistory.length > 0) {
|
|
11434
|
+
return this.navigationHistory[this.navigationHistory.length - 1];
|
|
11435
|
+
}
|
|
11436
|
+
if (typeof window !== "undefined") {
|
|
11437
|
+
return window.location.pathname;
|
|
11438
|
+
}
|
|
11439
|
+
return "unknown";
|
|
11440
|
+
}
|
|
11441
|
+
/**
|
|
11442
|
+
* Manually track a navigation event (for React Native or custom routing)
|
|
11443
|
+
*/
|
|
11444
|
+
trackNavigation(route) {
|
|
11445
|
+
const last = this.navigationHistory[this.navigationHistory.length - 1];
|
|
11446
|
+
if (route === last) return;
|
|
11447
|
+
this.navigationHistory.push(route);
|
|
11448
|
+
if (this.navigationHistory.length > MAX_NAVIGATION_HISTORY) {
|
|
11449
|
+
this.navigationHistory.shift();
|
|
11450
|
+
}
|
|
11451
|
+
}
|
|
11452
|
+
/**
|
|
11453
|
+
* Clear captured data
|
|
11454
|
+
*/
|
|
11455
|
+
clear() {
|
|
11456
|
+
this.consoleLogs = [];
|
|
11457
|
+
this.networkRequests = [];
|
|
11458
|
+
this.navigationHistory = [];
|
|
11459
|
+
}
|
|
11460
|
+
/**
|
|
11461
|
+
* Add a log entry manually (for custom logging)
|
|
11462
|
+
*/
|
|
11463
|
+
addLog(level, message, args) {
|
|
11464
|
+
this.consoleLogs.push({
|
|
11465
|
+
level,
|
|
11466
|
+
message,
|
|
11467
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11468
|
+
args
|
|
11469
|
+
});
|
|
11470
|
+
if (this.consoleLogs.length > MAX_CONSOLE_LOGS) {
|
|
11471
|
+
this.consoleLogs = this.consoleLogs.slice(-MAX_CONSOLE_LOGS);
|
|
11472
|
+
}
|
|
11473
|
+
}
|
|
11474
|
+
/**
|
|
11475
|
+
* Add a network request manually
|
|
11476
|
+
*/
|
|
11477
|
+
addNetworkRequest(request) {
|
|
11478
|
+
this.networkRequests.push(request);
|
|
11479
|
+
if (this.networkRequests.length > MAX_NETWORK_REQUESTS) {
|
|
11480
|
+
this.networkRequests = this.networkRequests.slice(-MAX_NETWORK_REQUESTS);
|
|
11481
|
+
}
|
|
11482
|
+
}
|
|
11483
|
+
captureConsole() {
|
|
11484
|
+
if (typeof console === "undefined") return;
|
|
11485
|
+
const levels = ["log", "warn", "error", "info"];
|
|
11486
|
+
levels.forEach((level) => {
|
|
11487
|
+
this.originalConsole[level] = console[level];
|
|
11488
|
+
console[level] = (...args) => {
|
|
11489
|
+
this.originalConsole[level]?.apply(console, args);
|
|
11490
|
+
try {
|
|
11491
|
+
const message = args.map((arg) => {
|
|
11492
|
+
if (typeof arg === "string") return arg;
|
|
11493
|
+
try {
|
|
11494
|
+
return JSON.stringify(arg);
|
|
11495
|
+
} catch {
|
|
11496
|
+
return String(arg);
|
|
11497
|
+
}
|
|
11498
|
+
}).join(" ");
|
|
11499
|
+
this.addLog(level, message.slice(0, 500));
|
|
11500
|
+
} catch {
|
|
11501
|
+
}
|
|
11502
|
+
};
|
|
11503
|
+
});
|
|
11504
|
+
}
|
|
11505
|
+
captureFetch() {
|
|
11506
|
+
if (typeof window === "undefined" || typeof fetch === "undefined") return;
|
|
11507
|
+
this.originalFetch = window.fetch;
|
|
11508
|
+
const self2 = this;
|
|
11509
|
+
window.fetch = async function(input, init) {
|
|
11510
|
+
const startTime = Date.now();
|
|
11511
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
11512
|
+
const method = init?.method || "GET";
|
|
11513
|
+
try {
|
|
11514
|
+
const response = await self2.originalFetch.call(window, input, init);
|
|
11515
|
+
const requestEntry = {
|
|
11516
|
+
method,
|
|
11517
|
+
url: url.slice(0, 200),
|
|
11518
|
+
// Limit URL length
|
|
11519
|
+
status: response.status,
|
|
11520
|
+
duration: Date.now() - startTime,
|
|
11521
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
11522
|
+
};
|
|
11523
|
+
if (response.status >= 400) {
|
|
11524
|
+
try {
|
|
11525
|
+
const cloned = response.clone();
|
|
11526
|
+
const body = await cloned.text();
|
|
11527
|
+
if (body) {
|
|
11528
|
+
requestEntry.responseBody = body.slice(0, MAX_RESPONSE_BODY_LENGTH);
|
|
11529
|
+
}
|
|
11530
|
+
} catch {
|
|
11531
|
+
}
|
|
11532
|
+
}
|
|
11533
|
+
self2.addNetworkRequest(requestEntry);
|
|
11534
|
+
return response;
|
|
11535
|
+
} catch (error) {
|
|
11536
|
+
self2.addNetworkRequest({
|
|
11537
|
+
method,
|
|
11538
|
+
url: url.slice(0, 200),
|
|
11539
|
+
duration: Date.now() - startTime,
|
|
11540
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11541
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
11542
|
+
});
|
|
11543
|
+
throw error;
|
|
11544
|
+
}
|
|
11545
|
+
};
|
|
11546
|
+
}
|
|
11547
|
+
captureNavigation() {
|
|
11548
|
+
if (typeof window === "undefined" || typeof history === "undefined") return;
|
|
11549
|
+
this.trackNavigation(window.location.pathname);
|
|
11550
|
+
const self2 = this;
|
|
11551
|
+
this.originalPushState = history.pushState;
|
|
11552
|
+
history.pushState = function(...args) {
|
|
11553
|
+
self2.originalPushState.apply(history, args);
|
|
11554
|
+
self2.trackNavigation(window.location.pathname);
|
|
11555
|
+
};
|
|
11556
|
+
this.originalReplaceState = history.replaceState;
|
|
11557
|
+
history.replaceState = function(...args) {
|
|
11558
|
+
self2.originalReplaceState.apply(history, args);
|
|
11559
|
+
self2.trackNavigation(window.location.pathname);
|
|
11560
|
+
};
|
|
11561
|
+
this.popstateHandler = () => {
|
|
11562
|
+
self2.trackNavigation(window.location.pathname);
|
|
11563
|
+
};
|
|
11564
|
+
window.addEventListener("popstate", this.popstateHandler);
|
|
11565
|
+
}
|
|
11566
|
+
getPerformanceMetrics() {
|
|
11567
|
+
if (typeof window === "undefined" || typeof performance === "undefined") return void 0;
|
|
11568
|
+
const metrics = {};
|
|
11569
|
+
try {
|
|
11570
|
+
const navigation = performance.getEntriesByType("navigation")[0];
|
|
11571
|
+
if (navigation) {
|
|
11572
|
+
metrics.pageLoadTime = Math.round(navigation.loadEventEnd - navigation.startTime);
|
|
11573
|
+
}
|
|
11574
|
+
} catch {
|
|
11575
|
+
}
|
|
11576
|
+
try {
|
|
11577
|
+
const memory = performance.memory;
|
|
11578
|
+
if (memory) {
|
|
11579
|
+
metrics.memoryUsage = Math.round(memory.usedJSHeapSize / 1024 / 1024);
|
|
11580
|
+
}
|
|
11581
|
+
} catch {
|
|
11582
|
+
}
|
|
11583
|
+
return Object.keys(metrics).length > 0 ? metrics : void 0;
|
|
11584
|
+
}
|
|
11585
|
+
getEnvironmentInfo() {
|
|
11586
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") return void 0;
|
|
11587
|
+
return {
|
|
11588
|
+
language: navigator.language,
|
|
11589
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
11590
|
+
cookiesEnabled: navigator.cookieEnabled,
|
|
11591
|
+
localStorage: typeof localStorage !== "undefined",
|
|
11592
|
+
online: navigator.onLine
|
|
11593
|
+
};
|
|
11594
|
+
}
|
|
11595
|
+
};
|
|
11596
|
+
var contextCapture = new ContextCaptureManager();
|
|
11364
11597
|
var DEFAULT_SUPABASE_URL = "https://kyxgzjnqgvapvlnvqawz.supabase.co";
|
|
11365
11598
|
var getEnvVar = (key) => {
|
|
11366
11599
|
try {
|
|
@@ -11382,22 +11615,40 @@ var BugBearClient = class {
|
|
|
11382
11615
|
);
|
|
11383
11616
|
}
|
|
11384
11617
|
/**
|
|
11385
|
-
* Track navigation for context
|
|
11618
|
+
* Track navigation for context.
|
|
11619
|
+
* Also forwards to contextCapture for auto-tracked navigation.
|
|
11386
11620
|
*/
|
|
11387
11621
|
trackNavigation(route) {
|
|
11388
11622
|
this.navigationHistory.push(route);
|
|
11389
11623
|
if (this.navigationHistory.length > 10) {
|
|
11390
11624
|
this.navigationHistory.shift();
|
|
11391
11625
|
}
|
|
11626
|
+
contextCapture.trackNavigation(route);
|
|
11392
11627
|
}
|
|
11393
11628
|
/**
|
|
11394
|
-
* Get current navigation history
|
|
11629
|
+
* Get current navigation history.
|
|
11630
|
+
* Priority: config callback > manual tracking > auto-captured (pushState/popstate)
|
|
11395
11631
|
*/
|
|
11396
11632
|
getNavigationHistory() {
|
|
11397
11633
|
if (this.config.getNavigationHistory) {
|
|
11398
11634
|
return this.config.getNavigationHistory();
|
|
11399
11635
|
}
|
|
11400
|
-
|
|
11636
|
+
if (this.navigationHistory.length > 0) {
|
|
11637
|
+
return [...this.navigationHistory];
|
|
11638
|
+
}
|
|
11639
|
+
return contextCapture.getNavigationHistory();
|
|
11640
|
+
}
|
|
11641
|
+
/**
|
|
11642
|
+
* Get current app context.
|
|
11643
|
+
* Uses config.getAppContext() callback if provided, otherwise builds from available data.
|
|
11644
|
+
*/
|
|
11645
|
+
getAppContext() {
|
|
11646
|
+
if (this.config.getAppContext) {
|
|
11647
|
+
return this.config.getAppContext();
|
|
11648
|
+
}
|
|
11649
|
+
return {
|
|
11650
|
+
currentRoute: contextCapture.getCurrentRoute()
|
|
11651
|
+
};
|
|
11401
11652
|
}
|
|
11402
11653
|
/**
|
|
11403
11654
|
* Get current user info from host app or BugBear's own auth
|
|
@@ -11437,6 +11688,8 @@ var BugBearClient = class {
|
|
|
11437
11688
|
project_id: this.config.projectId,
|
|
11438
11689
|
reporter_id: userInfo.id,
|
|
11439
11690
|
// User ID from host app (required)
|
|
11691
|
+
reporter_name: testerInfo?.name || userInfo.name || null,
|
|
11692
|
+
reporter_email: userInfo.email || null,
|
|
11440
11693
|
tester_id: testerInfo?.id || null,
|
|
11441
11694
|
// Tester record ID (optional)
|
|
11442
11695
|
report_type: report.type,
|
|
@@ -11450,6 +11703,7 @@ var BugBearClient = class {
|
|
|
11450
11703
|
app_context: report.appContext,
|
|
11451
11704
|
device_info: report.deviceInfo || this.getDeviceInfo(),
|
|
11452
11705
|
navigation_history: this.getNavigationHistory(),
|
|
11706
|
+
enhanced_context: report.enhancedContext || contextCapture.getEnhancedContext(),
|
|
11453
11707
|
assignment_id: report.assignmentId,
|
|
11454
11708
|
test_case_id: report.testCaseId
|
|
11455
11709
|
};
|
|
@@ -11697,19 +11951,40 @@ var BugBearClient = class {
|
|
|
11697
11951
|
return { success: false, error: message };
|
|
11698
11952
|
}
|
|
11699
11953
|
}
|
|
11954
|
+
/**
|
|
11955
|
+
* Pass a test assignment — convenience wrapper around updateAssignmentStatus
|
|
11956
|
+
*/
|
|
11957
|
+
async passAssignment(assignmentId) {
|
|
11958
|
+
return this.updateAssignmentStatus(assignmentId, "passed");
|
|
11959
|
+
}
|
|
11960
|
+
/**
|
|
11961
|
+
* Fail a test assignment — convenience wrapper around updateAssignmentStatus
|
|
11962
|
+
*/
|
|
11963
|
+
async failAssignment(assignmentId) {
|
|
11964
|
+
return this.updateAssignmentStatus(assignmentId, "failed");
|
|
11965
|
+
}
|
|
11700
11966
|
/**
|
|
11701
11967
|
* Skip a test assignment with a required reason
|
|
11702
11968
|
* Marks the assignment as 'skipped' and records why it was skipped
|
|
11703
11969
|
*/
|
|
11704
11970
|
async skipAssignment(assignmentId, reason, notes) {
|
|
11971
|
+
let actualReason;
|
|
11972
|
+
let actualNotes;
|
|
11973
|
+
if (typeof reason === "object") {
|
|
11974
|
+
actualReason = reason.reason;
|
|
11975
|
+
actualNotes = reason.notes;
|
|
11976
|
+
} else {
|
|
11977
|
+
actualReason = reason;
|
|
11978
|
+
actualNotes = notes;
|
|
11979
|
+
}
|
|
11705
11980
|
try {
|
|
11706
11981
|
const updateData = {
|
|
11707
11982
|
status: "skipped",
|
|
11708
|
-
skip_reason:
|
|
11983
|
+
skip_reason: actualReason,
|
|
11709
11984
|
completed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
11710
11985
|
};
|
|
11711
|
-
if (
|
|
11712
|
-
updateData.notes =
|
|
11986
|
+
if (actualNotes) {
|
|
11987
|
+
updateData.notes = actualNotes;
|
|
11713
11988
|
}
|
|
11714
11989
|
const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
|
|
11715
11990
|
if (error) {
|
|
@@ -12683,163 +12958,6 @@ var BugBearClient = class {
|
|
|
12683
12958
|
function createBugBear(config) {
|
|
12684
12959
|
return new BugBearClient(config);
|
|
12685
12960
|
}
|
|
12686
|
-
var MAX_CONSOLE_LOGS = 50;
|
|
12687
|
-
var MAX_NETWORK_REQUESTS = 20;
|
|
12688
|
-
var ContextCaptureManager = class {
|
|
12689
|
-
constructor() {
|
|
12690
|
-
this.consoleLogs = [];
|
|
12691
|
-
this.networkRequests = [];
|
|
12692
|
-
this.originalConsole = {};
|
|
12693
|
-
this.isCapturing = false;
|
|
12694
|
-
}
|
|
12695
|
-
/**
|
|
12696
|
-
* Start capturing console logs and network requests
|
|
12697
|
-
*/
|
|
12698
|
-
startCapture() {
|
|
12699
|
-
if (this.isCapturing) return;
|
|
12700
|
-
this.isCapturing = true;
|
|
12701
|
-
this.captureConsole();
|
|
12702
|
-
this.captureFetch();
|
|
12703
|
-
}
|
|
12704
|
-
/**
|
|
12705
|
-
* Stop capturing and restore original functions
|
|
12706
|
-
*/
|
|
12707
|
-
stopCapture() {
|
|
12708
|
-
if (!this.isCapturing) return;
|
|
12709
|
-
this.isCapturing = false;
|
|
12710
|
-
if (this.originalConsole.log) console.log = this.originalConsole.log;
|
|
12711
|
-
if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
|
|
12712
|
-
if (this.originalConsole.error) console.error = this.originalConsole.error;
|
|
12713
|
-
if (this.originalConsole.info) console.info = this.originalConsole.info;
|
|
12714
|
-
if (this.originalFetch && typeof window !== "undefined") {
|
|
12715
|
-
window.fetch = this.originalFetch;
|
|
12716
|
-
}
|
|
12717
|
-
}
|
|
12718
|
-
/**
|
|
12719
|
-
* Get captured context for a bug report
|
|
12720
|
-
*/
|
|
12721
|
-
getEnhancedContext() {
|
|
12722
|
-
return {
|
|
12723
|
-
consoleLogs: [...this.consoleLogs],
|
|
12724
|
-
networkRequests: [...this.networkRequests],
|
|
12725
|
-
performanceMetrics: this.getPerformanceMetrics(),
|
|
12726
|
-
environment: this.getEnvironmentInfo()
|
|
12727
|
-
};
|
|
12728
|
-
}
|
|
12729
|
-
/**
|
|
12730
|
-
* Clear captured data
|
|
12731
|
-
*/
|
|
12732
|
-
clear() {
|
|
12733
|
-
this.consoleLogs = [];
|
|
12734
|
-
this.networkRequests = [];
|
|
12735
|
-
}
|
|
12736
|
-
/**
|
|
12737
|
-
* Add a log entry manually (for custom logging)
|
|
12738
|
-
*/
|
|
12739
|
-
addLog(level, message, args) {
|
|
12740
|
-
this.consoleLogs.push({
|
|
12741
|
-
level,
|
|
12742
|
-
message,
|
|
12743
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12744
|
-
args
|
|
12745
|
-
});
|
|
12746
|
-
if (this.consoleLogs.length > MAX_CONSOLE_LOGS) {
|
|
12747
|
-
this.consoleLogs = this.consoleLogs.slice(-MAX_CONSOLE_LOGS);
|
|
12748
|
-
}
|
|
12749
|
-
}
|
|
12750
|
-
/**
|
|
12751
|
-
* Add a network request manually
|
|
12752
|
-
*/
|
|
12753
|
-
addNetworkRequest(request) {
|
|
12754
|
-
this.networkRequests.push(request);
|
|
12755
|
-
if (this.networkRequests.length > MAX_NETWORK_REQUESTS) {
|
|
12756
|
-
this.networkRequests = this.networkRequests.slice(-MAX_NETWORK_REQUESTS);
|
|
12757
|
-
}
|
|
12758
|
-
}
|
|
12759
|
-
captureConsole() {
|
|
12760
|
-
if (typeof console === "undefined") return;
|
|
12761
|
-
const levels = ["log", "warn", "error", "info"];
|
|
12762
|
-
levels.forEach((level) => {
|
|
12763
|
-
this.originalConsole[level] = console[level];
|
|
12764
|
-
console[level] = (...args) => {
|
|
12765
|
-
this.originalConsole[level]?.apply(console, args);
|
|
12766
|
-
try {
|
|
12767
|
-
const message = args.map((arg) => {
|
|
12768
|
-
if (typeof arg === "string") return arg;
|
|
12769
|
-
try {
|
|
12770
|
-
return JSON.stringify(arg);
|
|
12771
|
-
} catch {
|
|
12772
|
-
return String(arg);
|
|
12773
|
-
}
|
|
12774
|
-
}).join(" ");
|
|
12775
|
-
this.addLog(level, message.slice(0, 500));
|
|
12776
|
-
} catch {
|
|
12777
|
-
}
|
|
12778
|
-
};
|
|
12779
|
-
});
|
|
12780
|
-
}
|
|
12781
|
-
captureFetch() {
|
|
12782
|
-
if (typeof window === "undefined" || typeof fetch === "undefined") return;
|
|
12783
|
-
this.originalFetch = window.fetch;
|
|
12784
|
-
const self2 = this;
|
|
12785
|
-
window.fetch = async function(input, init) {
|
|
12786
|
-
const startTime = Date.now();
|
|
12787
|
-
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
12788
|
-
const method = init?.method || "GET";
|
|
12789
|
-
try {
|
|
12790
|
-
const response = await self2.originalFetch.call(window, input, init);
|
|
12791
|
-
self2.addNetworkRequest({
|
|
12792
|
-
method,
|
|
12793
|
-
url: url.slice(0, 200),
|
|
12794
|
-
// Limit URL length
|
|
12795
|
-
status: response.status,
|
|
12796
|
-
duration: Date.now() - startTime,
|
|
12797
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
12798
|
-
});
|
|
12799
|
-
return response;
|
|
12800
|
-
} catch (error) {
|
|
12801
|
-
self2.addNetworkRequest({
|
|
12802
|
-
method,
|
|
12803
|
-
url: url.slice(0, 200),
|
|
12804
|
-
duration: Date.now() - startTime,
|
|
12805
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12806
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
12807
|
-
});
|
|
12808
|
-
throw error;
|
|
12809
|
-
}
|
|
12810
|
-
};
|
|
12811
|
-
}
|
|
12812
|
-
getPerformanceMetrics() {
|
|
12813
|
-
if (typeof window === "undefined" || typeof performance === "undefined") return void 0;
|
|
12814
|
-
const metrics = {};
|
|
12815
|
-
try {
|
|
12816
|
-
const navigation = performance.getEntriesByType("navigation")[0];
|
|
12817
|
-
if (navigation) {
|
|
12818
|
-
metrics.pageLoadTime = Math.round(navigation.loadEventEnd - navigation.startTime);
|
|
12819
|
-
}
|
|
12820
|
-
} catch {
|
|
12821
|
-
}
|
|
12822
|
-
try {
|
|
12823
|
-
const memory = performance.memory;
|
|
12824
|
-
if (memory) {
|
|
12825
|
-
metrics.memoryUsage = Math.round(memory.usedJSHeapSize / 1024 / 1024);
|
|
12826
|
-
}
|
|
12827
|
-
} catch {
|
|
12828
|
-
}
|
|
12829
|
-
return Object.keys(metrics).length > 0 ? metrics : void 0;
|
|
12830
|
-
}
|
|
12831
|
-
getEnvironmentInfo() {
|
|
12832
|
-
if (typeof window === "undefined" || typeof navigator === "undefined") return void 0;
|
|
12833
|
-
return {
|
|
12834
|
-
language: navigator.language,
|
|
12835
|
-
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
12836
|
-
cookiesEnabled: navigator.cookieEnabled,
|
|
12837
|
-
localStorage: typeof localStorage !== "undefined",
|
|
12838
|
-
online: navigator.onLine
|
|
12839
|
-
};
|
|
12840
|
-
}
|
|
12841
|
-
};
|
|
12842
|
-
var contextCapture = new ContextCaptureManager();
|
|
12843
12961
|
|
|
12844
12962
|
// src/BugBearProvider.tsx
|
|
12845
12963
|
import { Platform, Dimensions } from "react-native";
|
|
@@ -13040,6 +13158,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
|
|
|
13040
13158
|
useEffect(() => {
|
|
13041
13159
|
if (enabled && !hasInitialized.current) {
|
|
13042
13160
|
hasInitialized.current = true;
|
|
13161
|
+
contextCapture.startCapture();
|
|
13043
13162
|
const newClient = createBugBear(config);
|
|
13044
13163
|
setClient(newClient);
|
|
13045
13164
|
initializeBugBear(newClient);
|
|
@@ -13106,7 +13225,8 @@ import {
|
|
|
13106
13225
|
Platform as Platform4,
|
|
13107
13226
|
PanResponder,
|
|
13108
13227
|
Animated,
|
|
13109
|
-
ActivityIndicator as ActivityIndicator2
|
|
13228
|
+
ActivityIndicator as ActivityIndicator2,
|
|
13229
|
+
Keyboard as Keyboard2
|
|
13110
13230
|
} from "react-native";
|
|
13111
13231
|
|
|
13112
13232
|
// src/widget/logo.ts
|
|
@@ -13363,7 +13483,7 @@ function HomeScreen({ nav }) {
|
|
|
13363
13483
|
TouchableOpacity,
|
|
13364
13484
|
{
|
|
13365
13485
|
style: styles.actionCard,
|
|
13366
|
-
onPress: () => nav.push({ name: "
|
|
13486
|
+
onPress: () => nav.push({ name: "TEST_LIST" }),
|
|
13367
13487
|
activeOpacity: 0.7
|
|
13368
13488
|
},
|
|
13369
13489
|
/* @__PURE__ */ React2.createElement(Text, { style: styles.actionIcon }, "\u2705"),
|
|
@@ -13596,7 +13716,7 @@ var styles = StyleSheet2.create({
|
|
|
13596
13716
|
|
|
13597
13717
|
// src/widget/screens/TestDetailScreen.tsx
|
|
13598
13718
|
import React3, { useState as useState2, useEffect as useEffect3, useCallback as useCallback2 } from "react";
|
|
13599
|
-
import { View as View2, Text as Text2, TouchableOpacity as TouchableOpacity2, StyleSheet as StyleSheet3, Modal, TextInput } from "react-native";
|
|
13719
|
+
import { View as View2, Text as Text2, TouchableOpacity as TouchableOpacity2, StyleSheet as StyleSheet3, Modal, TextInput, Keyboard } from "react-native";
|
|
13600
13720
|
function TestDetailScreen({ testId, nav }) {
|
|
13601
13721
|
const { client, assignments, currentAssignment, refreshAssignments, getDeviceInfo, onNavigate } = useBugBear();
|
|
13602
13722
|
const displayedAssignment = testId ? assignments.find((a) => a.id === testId) || currentAssignment : currentAssignment;
|
|
@@ -13631,12 +13751,14 @@ function TestDetailScreen({ testId, nav }) {
|
|
|
13631
13751
|
const currentIndex = displayedAssignment ? assignments.indexOf(displayedAssignment) : -1;
|
|
13632
13752
|
const handlePass = useCallback2(async () => {
|
|
13633
13753
|
if (!client || !displayedAssignment) return;
|
|
13754
|
+
Keyboard.dismiss();
|
|
13634
13755
|
await client.passAssignment(displayedAssignment.id);
|
|
13635
13756
|
await refreshAssignments();
|
|
13636
13757
|
nav.replace({ name: "TEST_FEEDBACK", status: "passed", assignmentId: displayedAssignment.id });
|
|
13637
13758
|
}, [client, displayedAssignment, refreshAssignments, nav]);
|
|
13638
13759
|
const handleFail = useCallback2(async () => {
|
|
13639
13760
|
if (!client || !displayedAssignment) return;
|
|
13761
|
+
Keyboard.dismiss();
|
|
13640
13762
|
await client.failAssignment(displayedAssignment.id);
|
|
13641
13763
|
await refreshAssignments();
|
|
13642
13764
|
nav.replace({
|
|
@@ -13650,6 +13772,7 @@ function TestDetailScreen({ testId, nav }) {
|
|
|
13650
13772
|
}, [client, displayedAssignment, refreshAssignments, nav]);
|
|
13651
13773
|
const handleSkip = useCallback2(async () => {
|
|
13652
13774
|
if (!client || !displayedAssignment || !selectedSkipReason) return;
|
|
13775
|
+
Keyboard.dismiss();
|
|
13653
13776
|
setSkipping(true);
|
|
13654
13777
|
await client.skipAssignment(displayedAssignment.id, {
|
|
13655
13778
|
reason: selectedSkipReason,
|
|
@@ -13718,7 +13841,9 @@ function TestDetailScreen({ testId, nav }) {
|
|
|
13718
13841
|
{
|
|
13719
13842
|
style: styles2.navigateButton,
|
|
13720
13843
|
onPress: () => {
|
|
13844
|
+
Keyboard.dismiss();
|
|
13721
13845
|
onNavigate(testCase.targetRoute);
|
|
13846
|
+
nav.closeWidget?.();
|
|
13722
13847
|
}
|
|
13723
13848
|
},
|
|
13724
13849
|
/* @__PURE__ */ React3.createElement(Text2, { style: styles2.navigateText }, "\u{1F9ED} Go to test location")
|
|
@@ -14279,12 +14404,18 @@ function ReportScreen({ nav, prefill }) {
|
|
|
14279
14404
|
const [reportType, setReportType] = useState6(prefill?.type || "bug");
|
|
14280
14405
|
const [severity, setSeverity] = useState6("medium");
|
|
14281
14406
|
const [description, setDescription] = useState6("");
|
|
14407
|
+
const [affectedScreen, setAffectedScreen] = useState6("");
|
|
14282
14408
|
const [submitting, setSubmitting] = useState6(false);
|
|
14283
14409
|
const images = useImageAttachments(uploadImage, 5, "screenshots");
|
|
14284
14410
|
const isBugType = reportType === "bug" || reportType === "test_fail";
|
|
14285
14411
|
const handleSubmit = async () => {
|
|
14286
14412
|
if (!client || !description.trim()) return;
|
|
14287
14413
|
setSubmitting(true);
|
|
14414
|
+
const baseContext = client.getAppContext();
|
|
14415
|
+
const appContext = {
|
|
14416
|
+
...baseContext,
|
|
14417
|
+
currentRoute: affectedScreen.trim() || baseContext.currentRoute
|
|
14418
|
+
};
|
|
14288
14419
|
const screenshotUrls = images.getScreenshotUrls();
|
|
14289
14420
|
await client.submitReport({
|
|
14290
14421
|
type: reportType,
|
|
@@ -14292,7 +14423,7 @@ function ReportScreen({ nav, prefill }) {
|
|
|
14292
14423
|
severity: isBugType ? severity : void 0,
|
|
14293
14424
|
assignmentId: prefill?.assignmentId,
|
|
14294
14425
|
testCaseId: prefill?.testCaseId,
|
|
14295
|
-
appContext
|
|
14426
|
+
appContext,
|
|
14296
14427
|
deviceInfo: getDeviceInfo(),
|
|
14297
14428
|
screenshots: screenshotUrls.length > 0 ? screenshotUrls : void 0
|
|
14298
14429
|
});
|
|
@@ -14340,7 +14471,16 @@ function ReportScreen({ nav, prefill }) {
|
|
|
14340
14471
|
numberOfLines: 4,
|
|
14341
14472
|
textAlignVertical: "top"
|
|
14342
14473
|
}
|
|
14343
|
-
)), /* @__PURE__ */ React8.createElement(
|
|
14474
|
+
)), isBugType && /* @__PURE__ */ React8.createElement(View7, { style: styles7.section }, /* @__PURE__ */ React8.createElement(Text7, { style: shared.label }, "Which screen?"), /* @__PURE__ */ React8.createElement(
|
|
14475
|
+
TextInput3,
|
|
14476
|
+
{
|
|
14477
|
+
style: styles7.screenInput,
|
|
14478
|
+
value: affectedScreen,
|
|
14479
|
+
onChangeText: setAffectedScreen,
|
|
14480
|
+
placeholder: "e.g. Reservations, Settings...",
|
|
14481
|
+
placeholderTextColor: colors.textMuted
|
|
14482
|
+
}
|
|
14483
|
+
), /* @__PURE__ */ React8.createElement(Text7, { style: styles7.screenHint }, "Which screen or area was the bug on? (optional)")), /* @__PURE__ */ React8.createElement(
|
|
14344
14484
|
ImagePickerButtons,
|
|
14345
14485
|
{
|
|
14346
14486
|
images: images.images,
|
|
@@ -14371,7 +14511,9 @@ var styles7 = StyleSheet8.create({
|
|
|
14371
14511
|
severityRow: { flexDirection: "row", gap: 8 },
|
|
14372
14512
|
sevButton: { flex: 1, paddingVertical: 8, borderRadius: 8, alignItems: "center", borderWidth: 1, borderColor: colors.border, backgroundColor: colors.card },
|
|
14373
14513
|
sevText: { fontSize: 12, fontWeight: "500", color: colors.textSecondary, textTransform: "capitalize" },
|
|
14374
|
-
descInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12, fontSize: 14, color: colors.textPrimary, minHeight: 100 }
|
|
14514
|
+
descInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12, fontSize: 14, color: colors.textPrimary, minHeight: 100 },
|
|
14515
|
+
screenInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 12, paddingVertical: 8, fontSize: 13, color: colors.textPrimary },
|
|
14516
|
+
screenHint: { fontSize: 11, color: colors.textMuted, marginTop: 4 }
|
|
14375
14517
|
});
|
|
14376
14518
|
|
|
14377
14519
|
// src/widget/screens/ReportSuccessScreen.tsx
|
|
@@ -14842,10 +14984,29 @@ function BugBearButton({
|
|
|
14842
14984
|
}
|
|
14843
14985
|
};
|
|
14844
14986
|
const handleClose = () => {
|
|
14987
|
+
Keyboard2.dismiss();
|
|
14845
14988
|
setModalVisible(false);
|
|
14846
|
-
reset();
|
|
14847
14989
|
};
|
|
14848
|
-
const nav = {
|
|
14990
|
+
const nav = {
|
|
14991
|
+
push: (screen) => {
|
|
14992
|
+
Keyboard2.dismiss();
|
|
14993
|
+
push(screen);
|
|
14994
|
+
},
|
|
14995
|
+
pop: () => {
|
|
14996
|
+
Keyboard2.dismiss();
|
|
14997
|
+
pop();
|
|
14998
|
+
},
|
|
14999
|
+
replace: (screen) => {
|
|
15000
|
+
Keyboard2.dismiss();
|
|
15001
|
+
replace(screen);
|
|
15002
|
+
},
|
|
15003
|
+
reset: () => {
|
|
15004
|
+
Keyboard2.dismiss();
|
|
15005
|
+
reset();
|
|
15006
|
+
},
|
|
15007
|
+
canGoBack,
|
|
15008
|
+
closeWidget: handleClose
|
|
15009
|
+
};
|
|
14849
15010
|
const renderScreen = () => {
|
|
14850
15011
|
switch (currentScreen.name) {
|
|
14851
15012
|
case "HOME":
|
|
@@ -14902,7 +15063,7 @@ function BugBearButton({
|
|
|
14902
15063
|
behavior: Platform4.OS === "ios" ? "padding" : "height",
|
|
14903
15064
|
style: styles13.modalOverlay
|
|
14904
15065
|
},
|
|
14905
|
-
/* @__PURE__ */ React14.createElement(View13, { style: styles13.modalContainer }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.header }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerLeft }, canGoBack ? /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: pop, style: styles13.backButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.backText }, "\u2190 Back")) : /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerTitleRow }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerTitle }, "BugBear"), testerInfo && /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => push({ name: "PROFILE" }) }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerName }, testerInfo.name, " \u270E")))), getHeaderTitle() ? /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerScreenTitle, numberOfLines: 1 }, getHeaderTitle()) : null, /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: handleClose, style: styles13.closeButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.closeText }, "\u2715"))), /* @__PURE__ */ React14.createElement(
|
|
15066
|
+
/* @__PURE__ */ React14.createElement(View13, { style: styles13.modalContainer }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.header }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerLeft }, canGoBack ? /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerNavRow }, /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => nav.pop(), style: styles13.backButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.backText }, "\u2190 Back")), /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => nav.reset(), style: styles13.homeButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.homeText }, "\u{1F3E0}"))) : /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerTitleRow }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerTitle }, "BugBear"), testerInfo && /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => push({ name: "PROFILE" }) }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerName }, testerInfo.name, " \u270E")))), getHeaderTitle() ? /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerScreenTitle, numberOfLines: 1 }, getHeaderTitle()) : null, /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: handleClose, style: styles13.closeButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.closeText }, "\u2715"))), /* @__PURE__ */ React14.createElement(
|
|
14906
15067
|
ScrollView2,
|
|
14907
15068
|
{
|
|
14908
15069
|
style: styles13.content,
|
|
@@ -15003,15 +15164,27 @@ var styles13 = StyleSheet14.create({
|
|
|
15003
15164
|
flex: 1,
|
|
15004
15165
|
textAlign: "center"
|
|
15005
15166
|
},
|
|
15167
|
+
headerNavRow: {
|
|
15168
|
+
flexDirection: "row",
|
|
15169
|
+
alignItems: "center",
|
|
15170
|
+
gap: 8
|
|
15171
|
+
},
|
|
15006
15172
|
backButton: {
|
|
15007
15173
|
paddingVertical: 2,
|
|
15008
|
-
paddingRight:
|
|
15174
|
+
paddingRight: 4
|
|
15009
15175
|
},
|
|
15010
15176
|
backText: {
|
|
15011
15177
|
fontSize: 15,
|
|
15012
15178
|
color: colors.blue,
|
|
15013
15179
|
fontWeight: "500"
|
|
15014
15180
|
},
|
|
15181
|
+
homeButton: {
|
|
15182
|
+
paddingVertical: 2,
|
|
15183
|
+
paddingHorizontal: 6
|
|
15184
|
+
},
|
|
15185
|
+
homeText: {
|
|
15186
|
+
fontSize: 16
|
|
15187
|
+
},
|
|
15015
15188
|
closeButton: {
|
|
15016
15189
|
width: 32,
|
|
15017
15190
|
height: 32,
|