Add double-Alt shortcut to expand and display RequestQueueProgress:
- Update visibility logic with a double-Alt keypress detection. - Introduce `isShortcutActivated` and `lastAltKeyPressedAtMs` for shortcut tracking. - Adjust template rendering to depend on the shortcut activation state. - Add unit tests to validate double-Alt behavior and its impact on visibility and expansion.
This commit is contained in:
@@ -16,12 +16,15 @@ const METHOD_ICON_CLASS = Object.freeze({
|
||||
DELETE: "fa-trash",
|
||||
DEFAULT: "fa-exchange-alt",
|
||||
});
|
||||
const FN_DOUBLE_PRESS_WINDOW_MS = 450;
|
||||
|
||||
const isVisible = ref(false);
|
||||
const isExpanded = ref(REQUEST_QUEUE_CONFIG.inspector.expandedByDefault);
|
||||
const isShortcutActivated = ref(false);
|
||||
const nowMs = ref(Date.now());
|
||||
const pingLatencyMs = ref(null);
|
||||
const pingIsUnavailable = ref(false);
|
||||
const lastFnKeyPressedAtMs = ref(0);
|
||||
|
||||
let hideTimer = null;
|
||||
let tickerTimer = null;
|
||||
@@ -40,6 +43,7 @@ const shouldRenderForBatch = computed(() =>
|
||||
const activeRequests = computed(() => requestQueueState.activeRequests || []);
|
||||
const recentRequests = computed(() => requestQueueState.recentRequests || []);
|
||||
const errorRequests = computed(() => requestQueueState.errorRequests || []);
|
||||
const shouldRenderComponent = computed(() => isShortcutActivated.value === true);
|
||||
const appEnvironmentLabel = computed(() => {
|
||||
const isDev = import.meta.env.VITE_IS_DEV;
|
||||
return isDev ? "Development" : "Production";
|
||||
@@ -182,6 +186,24 @@ const toggleExpanded = () => {
|
||||
isExpanded.value = !isExpanded.value;
|
||||
};
|
||||
|
||||
const handleWindowKeydown = (event) => {
|
||||
if (event?.key !== "Fn" || event?.repeat === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pressedAt = Date.now();
|
||||
if (
|
||||
Number(lastFnKeyPressedAtMs.value) > 0
|
||||
&& (pressedAt - Number(lastFnKeyPressedAtMs.value)) <= FN_DOUBLE_PRESS_WINDOW_MS
|
||||
) {
|
||||
isShortcutActivated.value = true;
|
||||
isExpanded.value = true;
|
||||
isVisible.value = true;
|
||||
}
|
||||
|
||||
lastFnKeyPressedAtMs.value = pressedAt;
|
||||
};
|
||||
|
||||
const handleClearErrors = () => {
|
||||
clearErrorRequests();
|
||||
};
|
||||
@@ -216,6 +238,8 @@ watch([hasOutstandingRequests, shouldRenderForBatch, hasStoredInspectorItems], (
|
||||
}, { immediate: true });
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("keydown", handleWindowKeydown);
|
||||
|
||||
tickerTimer = setInterval(() => {
|
||||
nowMs.value = Date.now();
|
||||
}, REQUEST_QUEUE_CONFIG.inspector.timerRefreshMs);
|
||||
@@ -228,6 +252,7 @@ onMounted(() => {
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
clearHideTimer();
|
||||
window.removeEventListener("keydown", handleWindowKeydown);
|
||||
|
||||
if (tickerTimer !== null) {
|
||||
clearInterval(tickerTimer);
|
||||
@@ -243,7 +268,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
<template>
|
||||
<transition name="queue-progress-fade">
|
||||
<div v-if="isVisible" class="request-queue-progress-shell" data-testid="request-queue-progress">
|
||||
<div v-if="shouldRenderComponent" class="request-queue-progress-shell" data-testid="request-queue-progress">
|
||||
<div v-if="isExpanded" class="request-queue-progress__expanded-layout">
|
||||
<aside class="request-queue-progress__side request-queue-progress__side--errors" data-testid="request-queue-errors-box">
|
||||
<div class="request-queue-progress__side-header">
|
||||
|
||||
@@ -32,6 +32,12 @@ const createDeferred = () => {
|
||||
return { promise, resolve, reject };
|
||||
};
|
||||
|
||||
const triggerAltDoublePress = async () => {
|
||||
window.dispatchEvent(new KeyboardEvent("keydown", { key: "Alt" }));
|
||||
window.dispatchEvent(new KeyboardEvent("keydown", { key: "Alt" }));
|
||||
await flushMicrotasks();
|
||||
};
|
||||
|
||||
describe("RequestQueueProgress", () => {
|
||||
const resetSessionUserState = () => {
|
||||
SessionUser.isSubuser.value = false;
|
||||
@@ -66,7 +72,7 @@ describe("RequestQueueProgress", () => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("shows request queue progress and hides shortly after completion", async () => {
|
||||
it("is hidden by default and becomes visible + expanded on double-alt", async () => {
|
||||
const wrapper = mount(RequestQueueProgress);
|
||||
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(false);
|
||||
@@ -78,8 +84,11 @@ describe("RequestQueueProgress", () => {
|
||||
const requestTwo = enqueueRequest(() => second.promise);
|
||||
|
||||
await flushMicrotasks();
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(false);
|
||||
|
||||
await triggerAltDoublePress();
|
||||
expect(wrapper.get("[data-testid='request-queue-progress']").text()).toContain("1 active, 1 queued");
|
||||
expect(wrapper.find("[data-testid='request-queue-progress-details']").exists()).toBe(true);
|
||||
|
||||
first.resolve({ status: 200 });
|
||||
await flushManyMicrotasks();
|
||||
@@ -95,10 +104,10 @@ describe("RequestQueueProgress", () => {
|
||||
vi.advanceTimersByTime(2600);
|
||||
await flushMicrotasks();
|
||||
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(false);
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(true);
|
||||
});
|
||||
|
||||
it("does not show progress below configured minimum batch size", async () => {
|
||||
it("stays hidden until double-alt even for small batches", async () => {
|
||||
const wrapper = mount(RequestQueueProgress);
|
||||
const onlyRequest = createDeferred();
|
||||
|
||||
@@ -106,12 +115,12 @@ describe("RequestQueueProgress", () => {
|
||||
await flushManyMicrotasks();
|
||||
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(false);
|
||||
await triggerAltDoublePress();
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(true);
|
||||
|
||||
onlyRequest.resolve({ status: 200 });
|
||||
await request;
|
||||
await flushManyMicrotasks();
|
||||
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(false);
|
||||
});
|
||||
|
||||
it("expands upward with active endpoint details, method icon and timer", async () => {
|
||||
@@ -123,8 +132,7 @@ describe("RequestQueueProgress", () => {
|
||||
const requestTwo = enqueueRequest(() => second.promise, { method: "GET", url: "/order/items" });
|
||||
|
||||
await flushManyMicrotasks();
|
||||
|
||||
await wrapper.get("[data-testid='request-queue-progress-toggle']").trigger("click");
|
||||
await triggerAltDoublePress();
|
||||
await flushManyMicrotasks();
|
||||
|
||||
expect(wrapper.find("[data-testid='request-queue-errors-box']").exists()).toBe(true);
|
||||
@@ -171,7 +179,7 @@ describe("RequestQueueProgress", () => {
|
||||
const requestTwo = enqueueRequest(() => second.promise, { method: "GET", url: "/subuser-check-2" });
|
||||
await flushManyMicrotasks();
|
||||
|
||||
await wrapper.get("[data-testid='request-queue-progress-toggle']").trigger("click");
|
||||
await triggerAltDoublePress();
|
||||
await flushManyMicrotasks();
|
||||
|
||||
const userBox = wrapper.get("[data-testid='request-queue-user-box']");
|
||||
@@ -245,7 +253,7 @@ describe("RequestQueueProgress", () => {
|
||||
expect(requestQueueState.missingPermissions.length).toBe(1);
|
||||
expect(requestQueueState.missingPermissions[0].permission).toBe("department_notification_sms_get");
|
||||
|
||||
await wrapper.get("[data-testid='request-queue-progress-toggle']").trigger("click");
|
||||
await triggerAltDoublePress();
|
||||
await flushManyMicrotasks();
|
||||
|
||||
const errorsBox = wrapper.get("[data-testid='request-queue-errors-box']");
|
||||
@@ -293,13 +301,14 @@ describe("RequestQueueProgress", () => {
|
||||
await failed;
|
||||
await flushManyMicrotasks();
|
||||
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(false);
|
||||
await triggerAltDoublePress();
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(true);
|
||||
|
||||
vi.advanceTimersByTime(30_000);
|
||||
await flushManyMicrotasks();
|
||||
|
||||
expect(wrapper.find("[data-testid='request-queue-progress']").exists()).toBe(true);
|
||||
await wrapper.get("[data-testid='request-queue-progress-toggle']").trigger("click");
|
||||
await flushManyMicrotasks();
|
||||
|
||||
const errorsBox = wrapper.get("[data-testid='request-queue-errors-box']");
|
||||
|
||||
Reference in New Issue
Block a user