feat: enforce frontend code coverage

This commit is contained in:
Julian Sommer
2026-03-11 10:25:04 +10:00
parent e26cd7fd82
commit 40e09f0886
8 changed files with 591 additions and 4 deletions
+2 -2
View File
@@ -42,8 +42,8 @@ jobs:
- name: Run Biome Check
run: pnpm check
- name: Run Tests
run: pnpm test
- name: Run Tests with Coverage
run: pnpm test:coverage
- name: Build Frontend
run: pnpm build
+1
View File
@@ -2,3 +2,4 @@ node_modules
.tanstack
*.tsbuildinfo
.pnpm-store
coverage
File diff suppressed because one or more lines are too long
@@ -9,6 +9,7 @@
"check": "biome check",
"fix": "biome check --fix",
"test": "vitest run",
"test:coverage": "vitest run --coverage",
"test:watch": "vitest"
},
"dependencies": {
@@ -45,6 +46,7 @@
"@typescript/native-preview": "7.0.0-dev.20260307.1",
"@vitejs/plugin-basic-ssl": "^2.1.4",
"@vitejs/plugin-react": "^5.1.4",
"@vitest/coverage-v8": "^4.0.18",
"babel-plugin-react-compiler": "^1.0.0",
"jsdom": "^28.1.0",
"typescript": "^5.9.3",
+114
View File
@@ -102,6 +102,9 @@ importers:
'@vitejs/plugin-react':
specifier: ^5.1.4
version: 5.1.4(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0))
'@vitest/coverage-v8':
specifier: ^4.0.18
version: 4.0.18(vitest@4.0.18(@types/node@24.12.0)(jiti@2.6.1)(jsdom@28.1.0)(lightningcss@1.31.1)(tsx@4.21.0))
babel-plugin-react-compiler:
specifier: ^1.0.0
version: 1.0.0
@@ -440,6 +443,10 @@ packages:
'@types/react':
optional: true
'@bcoe/v8-coverage@1.0.2':
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
engines: {node: '>=18'}
'@biomejs/biome@2.4.6':
resolution: {integrity: sha512-QnHe81PMslpy3mnpL8DnO2M4S4ZnYPkjlGCLWBZT/3R9M6b5daArWMMtEfP52/n174RKnwRIf3oT8+wc9ihSfQ==}
engines: {node: '>=14.21.3'}
@@ -1382,6 +1389,15 @@ packages:
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
'@vitest/coverage-v8@4.0.18':
resolution: {integrity: sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==}
peerDependencies:
'@vitest/browser': 4.0.18
vitest: 4.0.18
peerDependenciesMeta:
'@vitest/browser':
optional: true
'@vitest/expect@4.0.18':
resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==}
@@ -1451,6 +1467,9 @@ packages:
resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
engines: {node: '>=4'}
ast-v8-to-istanbul@0.3.12:
resolution: {integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==}
babel-dead-code-elimination@1.0.12:
resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==}
@@ -1660,10 +1679,17 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
html-encoding-sniffer@6.0.0:
resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
http-proxy-agent@7.0.2:
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
engines: {node: '>= 14'}
@@ -1705,10 +1731,25 @@ packages:
resolution: {integrity: sha512-waFfC72ZNfwLLuJ2iLaoVaqcNo+CAaLR7xCpAn0Y5WfGzkNHv7ZN39Vbi1y+kb+Zs46XHOX3tZNExroFUPX+Kg==}
engines: {node: '>=18'}
istanbul-lib-coverage@3.2.2:
resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
engines: {node: '>=8'}
istanbul-lib-report@3.0.1:
resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
engines: {node: '>=10'}
istanbul-reports@3.2.0:
resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==}
engines: {node: '>=8'}
jiti@2.6.1:
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true
js-tokens@10.0.0:
resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==}
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -1827,6 +1868,13 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
magicast@0.5.2:
resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==}
make-dir@4.0.0:
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
engines: {node: '>=10'}
mdn-data@2.27.1:
resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==}
@@ -1970,6 +2018,11 @@ packages:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
semver@7.7.4:
resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==}
engines: {node: '>=10'}
hasBin: true
seroval-plugins@1.5.0:
resolution: {integrity: sha512-EAHqADIQondwRZIdeW2I636zgsODzoBDwb3PT/+7TLDWyw1Dy/Xv7iGUIEXXav7usHDE9HVhOU61irI3EnyyHA==}
engines: {node: '>=10'}
@@ -2017,6 +2070,10 @@ packages:
strnum@2.2.0:
resolution: {integrity: sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==}
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
symbol-tree@3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
@@ -2969,6 +3026,8 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.14
'@bcoe/v8-coverage@1.0.2': {}
'@biomejs/biome@2.4.6':
optionalDependencies:
'@biomejs/cli-darwin-arm64': 2.4.6
@@ -3865,6 +3924,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@vitest/coverage-v8@4.0.18(vitest@4.0.18(@types/node@24.12.0)(jiti@2.6.1)(jsdom@28.1.0)(lightningcss@1.31.1)(tsx@4.21.0))':
dependencies:
'@bcoe/v8-coverage': 1.0.2
'@vitest/utils': 4.0.18
ast-v8-to-istanbul: 0.3.12
istanbul-lib-coverage: 3.2.2
istanbul-lib-report: 3.0.1
istanbul-reports: 3.2.0
magicast: 0.5.2
obug: 2.1.1
std-env: 3.10.0
tinyrainbow: 3.0.3
vitest: 4.0.18(@types/node@24.12.0)(jiti@2.6.1)(jsdom@28.1.0)(lightningcss@1.31.1)(tsx@4.21.0)
'@vitest/expect@4.0.18':
dependencies:
'@standard-schema/spec': 1.1.0
@@ -3931,6 +4004,12 @@ snapshots:
dependencies:
tslib: 2.8.1
ast-v8-to-istanbul@0.3.12:
dependencies:
'@jridgewell/trace-mapping': 0.3.31
estree-walker: 3.0.3
js-tokens: 10.0.0
babel-dead-code-elimination@1.0.12:
dependencies:
'@babel/core': 7.29.0
@@ -4138,12 +4217,16 @@ snapshots:
graceful-fs@4.2.11: {}
has-flag@4.0.0: {}
html-encoding-sniffer@6.0.0:
dependencies:
'@exodus/bytes': 1.15.0
transitivePeerDependencies:
- '@noble/hashes'
html-escaper@2.0.2: {}
http-proxy-agent@7.0.2:
dependencies:
agent-base: 7.1.4
@@ -4180,8 +4263,23 @@ snapshots:
isbot@5.1.35: {}
istanbul-lib-coverage@3.2.2: {}
istanbul-lib-report@3.0.1:
dependencies:
istanbul-lib-coverage: 3.2.2
make-dir: 4.0.0
supports-color: 7.2.0
istanbul-reports@3.2.0:
dependencies:
html-escaper: 2.0.2
istanbul-lib-report: 3.0.1
jiti@2.6.1: {}
js-tokens@10.0.0: {}
js-tokens@4.0.0: {}
jsdom@28.1.0:
@@ -4282,6 +4380,16 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
magicast@0.5.2:
dependencies:
'@babel/parser': 7.29.0
'@babel/types': 7.29.0
source-map-js: 1.2.1
make-dir@4.0.0:
dependencies:
semver: 7.7.4
mdn-data@2.27.1: {}
min-indent@1.0.1: {}
@@ -4426,6 +4534,8 @@ snapshots:
semver@6.3.1: {}
semver@7.7.4: {}
seroval-plugins@1.5.0(seroval@1.5.0):
dependencies:
seroval: 1.5.0
@@ -4461,6 +4571,10 @@ snapshots:
strnum@2.2.0: {}
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
symbol-tree@3.2.4: {}
tabbable@6.4.0: {}
@@ -10,9 +10,26 @@ vi.mock("@/lib/awsClient", () => ({
}))
import {
useAttachVolume,
useCopySnapshot,
useCreateImage,
useCreateInstance,
useCreateKeyPair,
useCreateSnapshot,
useCreateSubnet,
useCreateVolume,
useCreateVpc,
useDeleteKeyPair,
useDeleteSnapshot,
useDeleteSubnet,
useDeleteVolume,
useDeleteVpc,
useDetachVolume,
useGetConsoleOutput,
useImportKeyPair,
useModifyInstanceAttribute,
useModifyVolume,
useRebootInstance,
useStartInstance,
useStopInstance,
useTerminateInstance,
@@ -187,6 +204,247 @@ describe("useImportKeyPair", () => {
})
})
describe("useRebootInstance", () => {
it("sends RebootInstancesCommand with the instance ID", async () => {
createQueryClient()
const { result } = renderHook(() => useRebootInstance(), { wrapper })
result.current.mutate("i-abc123")
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
InstanceIds: ["i-abc123"],
})
})
})
describe("useCreateKeyPair", () => {
it("sends CreateKeyPairCommand with key name and rsa type", async () => {
createQueryClient()
const { result } = renderHook(() => useCreateKeyPair(), { wrapper })
result.current.mutate({ keyName: "my-key" })
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
KeyName: "my-key",
KeyType: "rsa",
})
})
})
describe("useDeleteKeyPair", () => {
it("sends DeleteKeyPairCommand with key pair ID", async () => {
createQueryClient()
const { result } = renderHook(() => useDeleteKeyPair(), { wrapper })
result.current.mutate("kp-abc123")
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
KeyPairId: "kp-abc123",
})
})
})
describe("useCreateVolume", () => {
it("sends CreateVolumeCommand with size and availability zone", async () => {
createQueryClient()
const { result } = renderHook(() => useCreateVolume(), { wrapper })
result.current.mutate({ size: 100, availabilityZone: "us-east-1a" })
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
Size: 100,
AvailabilityZone: "us-east-1a",
VolumeType: "gp3",
})
})
})
describe("useModifyVolume", () => {
it("sends ModifyVolumeCommand with volume ID and new size", async () => {
createQueryClient()
const { result } = renderHook(() => useModifyVolume(), { wrapper })
result.current.mutate({ volumeId: "vol-123", size: 200 })
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
VolumeId: "vol-123",
Size: 200,
})
})
})
describe("useDeleteVolume", () => {
it("sends DeleteVolumeCommand with volume ID", async () => {
createQueryClient()
const { result } = renderHook(() => useDeleteVolume(), { wrapper })
result.current.mutate("vol-123")
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
VolumeId: "vol-123",
})
})
})
describe("useCreateSnapshot", () => {
it("sends CreateSnapshotCommand with volume ID and description", async () => {
createQueryClient()
const { result } = renderHook(() => useCreateSnapshot(), { wrapper })
result.current.mutate({ volumeId: "vol-123", description: "backup" })
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
VolumeId: "vol-123",
Description: "backup",
})
})
it("omits Description when empty", async () => {
createQueryClient()
const { result } = renderHook(() => useCreateSnapshot(), { wrapper })
result.current.mutate({ volumeId: "vol-123", description: "" })
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input.Description).toBeUndefined()
})
})
describe("useDeleteSnapshot", () => {
it("sends DeleteSnapshotCommand with snapshot ID", async () => {
createQueryClient()
const { result } = renderHook(() => useDeleteSnapshot(), { wrapper })
result.current.mutate("snap-123")
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
SnapshotId: "snap-123",
})
})
})
describe("useCopySnapshot", () => {
it("sends CopySnapshotCommand with source details", async () => {
createQueryClient()
const { result } = renderHook(() => useCopySnapshot(), { wrapper })
result.current.mutate({
sourceSnapshotId: "snap-123",
sourceRegion: "us-east-1",
description: "copy",
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
SourceSnapshotId: "snap-123",
SourceRegion: "us-east-1",
Description: "copy",
})
})
})
describe("useAttachVolume", () => {
it("sends AttachVolumeCommand with volume, instance, and device", async () => {
createQueryClient()
const { result } = renderHook(() => useAttachVolume(), { wrapper })
result.current.mutate({
volumeId: "vol-123",
instanceId: "i-abc",
device: "/dev/sdf",
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
VolumeId: "vol-123",
InstanceId: "i-abc",
Device: "/dev/sdf",
})
})
})
describe("useDetachVolume", () => {
it("sends DetachVolumeCommand with volume, instance, and force", async () => {
createQueryClient()
const { result } = renderHook(() => useDetachVolume(), { wrapper })
result.current.mutate({
volumeId: "vol-123",
instanceId: "i-abc",
force: true,
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
VolumeId: "vol-123",
InstanceId: "i-abc",
Force: true,
})
})
})
describe("useModifyInstanceAttribute", () => {
it("sends ModifyInstanceAttributeCommand with instance type", async () => {
createQueryClient()
const { result } = renderHook(() => useModifyInstanceAttribute(), {
wrapper,
})
result.current.mutate({
instanceId: "i-abc",
instanceType: "t3.large",
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
InstanceId: "i-abc",
InstanceType: { Value: "t3.large" },
})
})
})
describe("useGetConsoleOutput", () => {
it("sends GetConsoleOutputCommand with instance ID", async () => {
createQueryClient()
const { result } = renderHook(() => useGetConsoleOutput(), { wrapper })
result.current.mutate("i-abc123")
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
InstanceId: "i-abc123",
})
})
})
describe("useCreateImage", () => {
it("sends CreateImageCommand with instance ID and name", async () => {
createQueryClient()
const { result } = renderHook(() => useCreateImage(), { wrapper })
result.current.mutate({
instanceId: "i-abc",
name: "my-image",
description: "test image",
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
InstanceId: "i-abc",
Name: "my-image",
Description: "test image",
})
})
})
describe("useCreateVpc", () => {
it("includes TagSpecifications when name is provided", async () => {
createQueryClient()
@@ -216,3 +474,51 @@ describe("useCreateVpc", () => {
expect(mockSend.mock.calls[0]?.[0].input.TagSpecifications).toBeUndefined()
})
})
describe("useDeleteVpc", () => {
it("sends DeleteVpcCommand with VPC ID", async () => {
createQueryClient()
const { result } = renderHook(() => useDeleteVpc(), { wrapper })
result.current.mutate("vpc-123")
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
VpcId: "vpc-123",
})
})
})
describe("useCreateSubnet", () => {
it("sends CreateSubnetCommand with VPC ID and CIDR block", async () => {
createQueryClient()
const { result } = renderHook(() => useCreateSubnet(), { wrapper })
result.current.mutate({
vpcId: "vpc-123",
cidrBlock: "10.0.1.0/24",
availabilityZone: "us-east-1a",
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
VpcId: "vpc-123",
CidrBlock: "10.0.1.0/24",
AvailabilityZone: "us-east-1a",
})
})
})
describe("useDeleteSubnet", () => {
it("sends DeleteSubnetCommand with subnet ID", async () => {
createQueryClient()
const { result } = renderHook(() => useDeleteSubnet(), { wrapper })
result.current.mutate("subnet-123")
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
SubnetId: "subnet-123",
})
})
})
@@ -1,4 +1,4 @@
import { describe, expect, it, vi } from "vitest"
import { afterEach, describe, expect, it, vi } from "vitest"
const mockSend = vi.fn().mockResolvedValue({})
@@ -147,6 +147,10 @@ describe("staleTime and refetchInterval", () => {
})
describe("queryFn", () => {
afterEach(() => {
mockSend.mockClear()
})
it("ec2ImageQueryOptions returns empty result for undefined imageId", async () => {
const options = ec2ImageQueryOptions(undefined)
const queryFn = options.queryFn as (ctx: never) => Promise<unknown>
@@ -154,4 +158,159 @@ describe("queryFn", () => {
expect(result).toEqual({ Images: [], $metadata: {} })
expect(mockSend).not.toHaveBeenCalled()
})
it("ec2ImageQueryOptions sends DescribeImagesCommand for valid imageId", async () => {
const queryFn = ec2ImageQueryOptions("ami-123").queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
ImageIds: ["ami-123"],
})
})
it("ec2InstancesQueryOptions sends DescribeInstancesCommand", async () => {
const queryFn = ec2InstancesQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
expect(mockSend.mock.calls[0]?.[0].input).toEqual({})
})
it("ec2InstanceQueryOptions sends DescribeInstancesCommand with ID", async () => {
const queryFn = ec2InstanceQueryOptions("i-123").queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
InstanceIds: ["i-123"],
})
})
it("ec2KeyPairsQueryOptions sends DescribeKeyPairsCommand", async () => {
const queryFn = ec2KeyPairsQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
expect(mockSend.mock.calls[0]?.[0].input).toEqual({})
})
it("ec2KeyPairQueryOptions sends DescribeKeyPairsCommand with ID", async () => {
const queryFn = ec2KeyPairQueryOptions("kp-abc").queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
KeyPairIds: ["kp-abc"],
})
})
it("ec2VolumesQueryOptions sends DescribeVolumesCommand", async () => {
const queryFn = ec2VolumesQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
})
it("ec2VolumeQueryOptions sends DescribeVolumesCommand with ID", async () => {
const queryFn = ec2VolumeQueryOptions("vol-1").queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
VolumeIds: ["vol-1"],
})
})
it("ec2SnapshotsQueryOptions sends DescribeSnapshotsCommand", async () => {
const queryFn = ec2SnapshotsQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
})
it("ec2SnapshotQueryOptions sends DescribeSnapshotsCommand with ID", async () => {
const queryFn = ec2SnapshotQueryOptions("snap-1").queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
SnapshotIds: ["snap-1"],
})
})
it("ec2VpcsQueryOptions sends DescribeVpcsCommand", async () => {
const queryFn = ec2VpcsQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
})
it("ec2VpcQueryOptions sends DescribeVpcsCommand with ID", async () => {
const queryFn = ec2VpcQueryOptions("vpc-1").queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
VpcIds: ["vpc-1"],
})
})
it("ec2SubnetsQueryOptions sends DescribeSubnetsCommand", async () => {
const queryFn = ec2SubnetsQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
})
it("ec2SubnetQueryOptions sends DescribeSubnetsCommand with ID", async () => {
const queryFn = ec2SubnetQueryOptions("subnet-1").queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
SubnetIds: ["subnet-1"],
})
})
it("ec2AvailabilityZonesQueryOptions sends DescribeAvailabilityZonesCommand", async () => {
const queryFn = ec2AvailabilityZonesQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
})
it("ec2RegionsQueryOptions sends DescribeRegionsCommand", async () => {
const queryFn = ec2RegionsQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
})
it("ec2ImagesQueryOptions sends DescribeImagesCommand", async () => {
const queryFn = ec2ImagesQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend).toHaveBeenCalledOnce()
})
it("ec2InstanceTypesQueryOptions sends DescribeInstanceTypesCommand with filter", async () => {
const queryFn = ec2InstanceTypesQueryOptions.queryFn as (
ctx: never,
) => Promise<unknown>
await queryFn({} as never)
expect(mockSend.mock.calls[0]?.[0].input).toEqual({
Filters: [{ Name: "capacity", Values: ["true"] }],
})
})
})
@@ -47,5 +47,10 @@ export default defineConfig({
globals: true,
environment: "jsdom",
setupFiles: "./src/test/setup.ts",
coverage: {
thresholds: {
statements: 70,
},
},
},
})