fix(response): reset response size on endpoint change (#9)
* fix(response): reset response size on endpoint change * test(request): move test to the right directory
This commit is contained in:
@@ -54,6 +54,15 @@ const status = computed(() => {
|
|||||||
return lastLog.value.response.status ?? STATUS.EMPTY;
|
return lastLog.value.response.status ?? STATUS.EMPTY;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const size = computed(() =>
|
||||||
|
prettyBytes(
|
||||||
|
pendingRequestData.value?.wasExecuted
|
||||||
|
? (lastLog.value?.response?.sizeInBytes ?? 0)
|
||||||
|
: 0, // <- When a new endpoint is initialized, we reset the size as well.
|
||||||
|
{ space: false },
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
const duration = computed(() => {
|
const duration = computed(() => {
|
||||||
return prettyMs(
|
return prettyMs(
|
||||||
// If there's a pending request that's processing, use its duration
|
// If there's a pending request that's processing, use its duration
|
||||||
@@ -67,10 +76,6 @@ const duration = computed(() => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const size = computed(() =>
|
|
||||||
prettyBytes(lastLog.value?.response?.sizeInBytes ?? 0, { space: false }),
|
|
||||||
);
|
|
||||||
|
|
||||||
const readableTime = computed(() => {
|
const readableTime = computed(() => {
|
||||||
if (lastLog.value?.response === undefined) {
|
if (lastLog.value?.response === undefined) {
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@@ -101,6 +101,9 @@ export interface PendingRequest {
|
|||||||
|
|
||||||
/** Request execution duration in milliseconds */
|
/** Request execution duration in milliseconds */
|
||||||
durationInMs?: number;
|
durationInMs?: number;
|
||||||
|
|
||||||
|
/** Whether the request was executed at least once */
|
||||||
|
wasExecuted?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Request {
|
export interface Request {
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ export const useRequestBuilderStore = defineStore('_requestBuilder', () => {
|
|||||||
supportedRoutes: availableRoutesForEndpoint,
|
supportedRoutes: availableRoutesForEndpoint,
|
||||||
routeDefinition: route,
|
routeDefinition: route,
|
||||||
isProcessing: false,
|
isProcessing: false,
|
||||||
|
wasExecuted: false,
|
||||||
durationInMs: 0,
|
durationInMs: 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export const useRequestExecutorStore = defineStore('_requestExecutor', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
requestData.isProcessing = false;
|
requestData.isProcessing = false;
|
||||||
|
requestData.wasExecuted = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
import ResponseStatus from '@/components/domain/Client/Response/ResponseStatus/ResponseStatus.vue';
|
||||||
|
import { STATUS } from '@/interfaces/http';
|
||||||
|
import { mountWithPlugins } from '@/tests/_utils/test-utils';
|
||||||
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
import { computed, reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
// Mock child to expose received props for assertions
|
||||||
|
vi.mock(
|
||||||
|
'@/components/domain/Client/Response/ResponseStatus/ResponseStatusCode.vue',
|
||||||
|
() => ({
|
||||||
|
default: {
|
||||||
|
name: 'ResponseStatusCode',
|
||||||
|
props: ['status', 'response'],
|
||||||
|
template:
|
||||||
|
'<div data-testid="status-code" :data-status="status">{{ status }}</div>',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mock stores used via '@/stores'
|
||||||
|
const mockRequestStore = reactive({
|
||||||
|
pendingRequestData: computed(() => mockPendingRequest.value),
|
||||||
|
cancelCurrentRequest: vi.fn(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const mockHistoryStore = reactive({
|
||||||
|
lastLog: ref<any>(null), // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
});
|
||||||
|
|
||||||
|
const mockPendingRequest = ref<any>(null); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
|
vi.mock('@/stores', () => ({
|
||||||
|
useRequestStore: () => mockRequestStore,
|
||||||
|
useRequestsHistoryStore: () => mockHistoryStore,
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('ResponseStatus', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockPendingRequest.value = null;
|
||||||
|
mockHistoryStore.lastLog = ref(null);
|
||||||
|
mockRequestStore.cancelCurrentRequest.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows PENDING status and cancel button while processing', () => {
|
||||||
|
mockPendingRequest.value = { isProcessing: true, durationInMs: 1234 };
|
||||||
|
const wrapper = mountWithPlugins(ResponseStatus);
|
||||||
|
|
||||||
|
const statusCode = wrapper.get('[data-testid="status-code"]');
|
||||||
|
expect(statusCode.attributes()['data-status']).toBe(String(STATUS.PENDING));
|
||||||
|
|
||||||
|
// Cancel button visible
|
||||||
|
const cancel = wrapper.find('button');
|
||||||
|
expect(cancel.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows EMPTY when no last response and not processing', () => {
|
||||||
|
mockPendingRequest.value = { isProcessing: false, durationInMs: 0 };
|
||||||
|
const wrapper = mountWithPlugins(ResponseStatus);
|
||||||
|
|
||||||
|
const statusCode = wrapper.get('[data-testid="status-code"]');
|
||||||
|
expect(statusCode.attributes()['data-status']).toBe(String(STATUS.EMPTY));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('derives status from last response when available', () => {
|
||||||
|
mockPendingRequest.value = {
|
||||||
|
isProcessing: false,
|
||||||
|
durationInMs: 0,
|
||||||
|
wasExecuted: true,
|
||||||
|
};
|
||||||
|
mockHistoryStore.lastLog = ref({ response: { status: 201, sizeInBytes: 1024 } });
|
||||||
|
const wrapper = mountWithPlugins(ResponseStatus);
|
||||||
|
|
||||||
|
const statusCode = wrapper.get('[data-testid="status-code"]');
|
||||||
|
expect(statusCode.attributes()['data-status']).toBe('201');
|
||||||
|
|
||||||
|
expect(wrapper.text()).toMatch(/1.02kB/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resets size to 0 when request not executed (new endpoint)', () => {
|
||||||
|
mockPendingRequest.value = {
|
||||||
|
isProcessing: false,
|
||||||
|
wasExecuted: false,
|
||||||
|
durationInMs: 0,
|
||||||
|
};
|
||||||
|
mockHistoryStore.lastLog = ref({ response: { sizeInBytes: 12345 } });
|
||||||
|
const wrapper = mountWithPlugins(ResponseStatus);
|
||||||
|
|
||||||
|
// Expects "0B" formatting from pretty-bytes with { space: false }
|
||||||
|
expect(wrapper.text()).toMatch(/0B/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses pending duration when processing, otherwise last log duration', () => {
|
||||||
|
// Processing case
|
||||||
|
mockPendingRequest.value = {
|
||||||
|
isProcessing: true,
|
||||||
|
durationInMs: 1500,
|
||||||
|
wasExecuted: false,
|
||||||
|
};
|
||||||
|
mockHistoryStore.lastLog = ref({ durationInMs: 9999 });
|
||||||
|
let wrapper = mountWithPlugins(ResponseStatus);
|
||||||
|
expect(wrapper.text()).toMatch(/1\.50s/);
|
||||||
|
|
||||||
|
// Completed case
|
||||||
|
mockPendingRequest.value = {
|
||||||
|
isProcessing: false,
|
||||||
|
durationInMs: 2500,
|
||||||
|
wasExecuted: true,
|
||||||
|
};
|
||||||
|
mockHistoryStore.lastLog = ref({
|
||||||
|
durationInMs: 3000,
|
||||||
|
response: { timestamp: 1700000000, status: STATUS.SUCCESS },
|
||||||
|
});
|
||||||
|
wrapper = mountWithPlugins(ResponseStatus);
|
||||||
|
expect(wrapper.text()).toMatch(/2\.50s/); // <- it prirotizes the one from the pending request.
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows readable time text when last response exists', () => {
|
||||||
|
mockPendingRequest.value = { isProcessing: false, durationInMs: 0 };
|
||||||
|
mockHistoryStore.lastLog = ref({
|
||||||
|
response: { timestamp: Math.floor(Date.now() / 1000) },
|
||||||
|
});
|
||||||
|
const wrapper = mountWithPlugins(ResponseStatus);
|
||||||
|
|
||||||
|
// The content is time-ago text; assert non-empty text region where it renders
|
||||||
|
const small = wrapper.find('small');
|
||||||
|
expect(small.exists()).toBe(true);
|
||||||
|
expect((small.text() ?? '').length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels request when cancel button clicked', async () => {
|
||||||
|
mockPendingRequest.value = { isProcessing: true, durationInMs: 0 };
|
||||||
|
const wrapper = mountWithPlugins(ResponseStatus);
|
||||||
|
|
||||||
|
const btn = wrapper.get('button');
|
||||||
|
await btn.trigger('click');
|
||||||
|
expect(mockRequestStore.cancelCurrentRequest).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user