chore: fix TS types (#21)
* chore: fix TS types * build: add types-check CI job * style: apply TS style fixes
This commit is contained in:
32
.github/workflows/types-check.yml
vendored
Normal file
32
.github/workflows/types-check.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: run-types-check
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '**.ts'
|
||||
- '**.js'
|
||||
- '.github/workflows/types-check.yml'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
if: ${{ !env.ACT }}
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests
|
||||
run: npm run type:check
|
||||
@@ -19,7 +19,7 @@ export const useConfigStore = defineStore('config', () => {
|
||||
? JSON.parse(window.Nimbus.headers as string)
|
||||
: [];
|
||||
const currentUser = window.Nimbus?.currentUser
|
||||
? JSON.parse(window.Nimbus.currentUser)
|
||||
? JSON.parse(window.Nimbus.currentUser as string)
|
||||
: null;
|
||||
|
||||
// Derived values
|
||||
|
||||
@@ -28,7 +28,7 @@ export const useRoutesStore = defineStore('routes', () => {
|
||||
error.value = null;
|
||||
|
||||
try {
|
||||
const source = window.Nimbus.routes;
|
||||
const source = window.Nimbus?.routes ?? '[]';
|
||||
|
||||
if (typeof source !== 'string') {
|
||||
routes.value = null;
|
||||
@@ -50,7 +50,7 @@ export const useRoutesStore = defineStore('routes', () => {
|
||||
|
||||
const initializeRoutes = async () => {
|
||||
routeExtractorException.value = parseRouteExtractionException(
|
||||
window.Nimbus.routeExtractorException,
|
||||
(window.Nimbus?.routeExtractorException as string) ?? null,
|
||||
);
|
||||
|
||||
await fetchAvailableRoutes();
|
||||
|
||||
@@ -35,7 +35,7 @@ vi.mock('@/stores', async importOriginal => {
|
||||
const renderComponent = () => renderWithProviders(RequestHeaders);
|
||||
|
||||
const setPendingRequest = (request: PendingRequest | null) => {
|
||||
mockRequestStore.pendingRequestData = ref(request);
|
||||
mockRequestStore.pendingRequestData = ref(request) as any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
};
|
||||
|
||||
describe('RequestHeaders', () => {
|
||||
@@ -162,7 +162,7 @@ describe('RequestHeaders', () => {
|
||||
});
|
||||
|
||||
it('merges existing request headers with global ones when changing endpoints', async () => {
|
||||
mockRequestStore.pendingRequestData.headers = [
|
||||
(mockRequestStore.pendingRequestData as PendingRequest).headers = [
|
||||
{ key: 'X-Existing', value: '123' },
|
||||
{ key: 'X-Global', value: 'custom' },
|
||||
];
|
||||
|
||||
@@ -7,7 +7,7 @@ import { nextTick, Reactive, reactive } from 'vue';
|
||||
|
||||
const mockRequestStore: Reactive<{
|
||||
pendingRequestData: object | null;
|
||||
cancelCurrentRequest: MockedFunction<unknown>;
|
||||
cancelCurrentRequest: MockedFunction<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}> = reactive({
|
||||
pendingRequestData: null,
|
||||
cancelCurrentRequest: vi.fn(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import ResponseViewer from '@/components/domain/Client/Response/ResponseViewer.vue';
|
||||
import { renderWithProviders, screen } from '@/tests/_utils/test-utils';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { reactive } from 'vue';
|
||||
import { Reactive, reactive } from 'vue';
|
||||
|
||||
vi.mock('@/components/domain/Client/Response/ResponseStatus/ResponseStatus.vue', () => ({
|
||||
default: {
|
||||
@@ -32,7 +32,10 @@ vi.mock('@/components/domain/Client/Response/ResponseViewerResponse.vue', () =>
|
||||
},
|
||||
}));
|
||||
|
||||
const mockRequestHistoryStore = reactive({
|
||||
const mockRequestHistoryStore: Reactive<{
|
||||
logs: Array<object> | [];
|
||||
lastLog: object | null;
|
||||
}> = reactive({
|
||||
logs: [],
|
||||
lastLog: null,
|
||||
});
|
||||
@@ -59,7 +62,12 @@ describe('ResponseViewer', () => {
|
||||
});
|
||||
|
||||
it('renders error component when last log contains error', () => {
|
||||
mockRequestHistoryStore.logs = [{ error: { message: 'Something went wrong' } }];
|
||||
mockRequestHistoryStore.logs = [
|
||||
{
|
||||
error: { message: 'Something went wrong' },
|
||||
},
|
||||
];
|
||||
|
||||
mockRequestHistoryStore.lastLog = mockRequestHistoryStore.logs[0];
|
||||
|
||||
renderWithProviders(ResponseViewer);
|
||||
|
||||
@@ -35,13 +35,41 @@ const createPendingRequest = (): PendingRequest => ({
|
||||
body: {},
|
||||
payloadType: RequestBodyTypeEnum.JSON,
|
||||
schema: {
|
||||
shape: { properties: { name: { type: 'string' } } },
|
||||
shape: {
|
||||
'x-name': 'root',
|
||||
'x-required': true,
|
||||
properties: {
|
||||
name: {
|
||||
'x-name': 'name',
|
||||
'x-required': false,
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
extractionErrors: null,
|
||||
},
|
||||
queryParameters: [],
|
||||
authorization: { type: AuthorizationType.None },
|
||||
supportedRoutes: [],
|
||||
routeDefinition: null,
|
||||
routeDefinition: {
|
||||
method: 'POST',
|
||||
endpoint: 'api/users',
|
||||
shortEndpoint: 'api/users',
|
||||
schema: {
|
||||
shape: {
|
||||
'x-name': 'root',
|
||||
'x-required': true,
|
||||
properties: {
|
||||
name: {
|
||||
'x-name': 'name',
|
||||
'x-required': false,
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
extractionErrors: null,
|
||||
},
|
||||
},
|
||||
isProcessing: false,
|
||||
wasExecuted: false,
|
||||
durationInMs: 0,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useConfigStore } from '@/stores/core/useConfigStore';
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { NimbusConfig } from '../../../types/global';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
Nimbus?: Record<string, unknown>;
|
||||
Nimbus: NimbusConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +27,8 @@ describe('useConfigStore', () => {
|
||||
isVersioned: true,
|
||||
headers: JSON.stringify([{ header: 'X-Test', type: 'raw', value: '123' }]),
|
||||
currentUser: JSON.stringify({ id: 99 }),
|
||||
routes: '',
|
||||
routeExtractorException: null,
|
||||
};
|
||||
|
||||
const store = useConfigStore();
|
||||
@@ -37,17 +40,4 @@ describe('useConfigStore', () => {
|
||||
expect(store.isLoggedIn).toBe(true);
|
||||
expect(store.userId).toBe(99);
|
||||
});
|
||||
|
||||
it('falls back to defaults when Nimbus undefined', () => {
|
||||
window.Nimbus = undefined;
|
||||
|
||||
const store = useConfigStore();
|
||||
|
||||
expect(store.apiUrl).toBe('http://localhost');
|
||||
expect(store.appBasePath).toBe('');
|
||||
expect(store.headers).toEqual([]);
|
||||
expect(store.isVersioned).toBe(false);
|
||||
expect(store.isLoggedIn).toBe(false);
|
||||
expect(store.userId).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AuthorizationContract } from '@/interfaces';
|
||||
import { AuthorizationType } from '@/interfaces/generated';
|
||||
import { PendingRequest, RequestBodyTypeEnum, RequestHeader } from '@/interfaces/http';
|
||||
import { RouteDefinition } from '@/interfaces/routes';
|
||||
@@ -80,7 +81,10 @@ describe('useRequestBuilderStore', () => {
|
||||
...baseRoute,
|
||||
method: 'POST',
|
||||
schema: {
|
||||
shape: {},
|
||||
shape: {
|
||||
'x-name': 'root',
|
||||
'x-required': false,
|
||||
},
|
||||
extractionErrors: null,
|
||||
},
|
||||
};
|
||||
@@ -120,7 +124,10 @@ describe('useRequestBuilderStore', () => {
|
||||
GET: { [RequestBodyTypeEnum.JSON]: '{}' },
|
||||
};
|
||||
const params = [{ key: 'page', value: '1' }];
|
||||
const auth = { type: AuthorizationType.Bearer, value: 'token' };
|
||||
const auth: AuthorizationContract = {
|
||||
type: AuthorizationType.Bearer,
|
||||
value: 'token',
|
||||
};
|
||||
|
||||
store.updateRequestHeaders(headers);
|
||||
store.updateRequestBody(body);
|
||||
|
||||
@@ -35,7 +35,9 @@ describe('useSettingsStore', () => {
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(JSON.parse(window.localStorage.getItem(STORAGE_KEY)).theme).toBe('dark');
|
||||
expect(JSON.parse(window.localStorage?.getItem(STORAGE_KEY) ?? '{}').theme).toBe(
|
||||
'dark',
|
||||
);
|
||||
});
|
||||
|
||||
it('resets preferences to defaults', async () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ValueGenerator } from '@/interfaces/ui';
|
||||
import { useValueGeneratorStore } from '@/stores/generators/useValueGeneratorStore';
|
||||
import { Mock } from '@vitest/spy';
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
@@ -87,7 +88,7 @@ describe('useValueGeneratorStore', () => {
|
||||
commandStore.addToRecentGenerators.mockClear();
|
||||
setSearchQuery.mockClear();
|
||||
setSelectedCategory.mockClear();
|
||||
generators.forEach(generator => (generator.generate as vi.Mock).mockClear());
|
||||
generators.forEach(generator => (generator.generate as Mock).mockClear());
|
||||
});
|
||||
|
||||
it('generates value and records generator usage', () => {
|
||||
|
||||
@@ -60,10 +60,10 @@ describe('generateCurlCommand', () => {
|
||||
});
|
||||
|
||||
it('flags special authorization types', () => {
|
||||
const request = {
|
||||
const request: PendingRequest = {
|
||||
...requestBase,
|
||||
authorization: { type: AuthorizationType.Impersonate, value: 1 },
|
||||
};
|
||||
} as PendingRequest;
|
||||
|
||||
const { hasSpecialAuth } = generateCurlCommand(
|
||||
request,
|
||||
|
||||
Reference in New Issue
Block a user