test: cover custom port persistence

This commit is contained in:
Kasra Bigdeli committed 2026-09-20 20:01:10 -07:00
1 parent 9bab411e93
commit a1682fa614
1 file changed
+285
+285
View File
@@ -0,0 +1,285 @@
import AppsDataStore from '../src/datastore/AppsDataStore'
import DockerApi from '../src/docker/DockerApi'
describe('custom port persistence', () => {
test('preserves protocol and publishMode when updating an app definition', async () => {
const appsDataStore = new AppsDataStore({} as any, 'captain')
const existingApp = {
description: '',
deployedVersion: 0,
notExposeAsWebApp: false,
hasPersistentData: false,
hasDefaultSubDomainSsl: false,
captainDefinitionRelativeFilePath: './captain-definition',
forceSsl: false,
websocketSupport: false,
instanceCount: 1,
networks: ['captain-overlay-network'],
customDomain: [],
ports: [],
volumes: [],
envVars: [],
versions: [],
} as any
jest.spyOn(appsDataStore, 'getAppDefinition').mockResolvedValue(
existingApp
)
const saveApp = jest
.fn()
.mockResolvedValue(undefined)
;(appsDataStore as any).saveApp = saveApp
const ports = [
{
containerPort: 3000,
hostPort: 8000,
protocol: 'tcp' as const,
publishMode: 'host' as const,
},
{
containerPort: 3001,
hostPort: 8001,
protocol: 'udp' as const,
publishMode: 'ingress' as const,
},
{
containerPort: 3002,
hostPort: 8002,
},
]
await appsDataStore.updateAppDefinitionInDb(
'test-app',
undefined,
'',
1,
'./captain-definition',
[],
[],
[],
'',
false,
80,
undefined,
false,
ports,
undefined as any,
{} as any,
'',
'',
'',
'',
false,
{ enabled: false }
)
expect(saveApp).toHaveBeenCalledWith(
'test-app',
expect.objectContaining({
ports: [
{
containerPort: 3000,
hostPort: 8000,
protocol: 'tcp',
publishMode: 'host',
},
{
containerPort: 3001,
hostPort: 8001,
protocol: 'udp',
publishMode: 'ingress',
},
{
containerPort: 3002,
hostPort: 8002,
},
],
})
)
})
test('creates Docker port mappings with protocol and publish mode intact', async () => {
const dockerApi = new DockerApi({} as any)
const createService = jest.fn().mockResolvedValue({})
;(dockerApi as any).dockerode = { createService }
await dockerApi.createServiceOnNodeId(
'nginx:latest',
'test-service',
[
{
containerPort: 3000,
hostPort: 8000,
protocol: 'tcp',
publishMode: 'host',
},
{
containerPort: 3001,
hostPort: 8001,
protocol: 'udp',
publishMode: 'ingress',
},
{
containerPort: 3002,
hostPort: 8002,
publishMode: 'host',
},
{
containerPort: 3003,
hostPort: 8003,
protocol: 'tcp',
},
],
undefined,
undefined,
undefined
)
expect(createService).toHaveBeenCalledWith(
expect.objectContaining({
EndpointSpec: {
Ports: [
{
Protocol: 'tcp',
TargetPort: 3000,
PublishedPort: 8000,
PublishMode: 'host',
},
{
Protocol: 'udp',
TargetPort: 3001,
PublishedPort: 8001,
PublishMode: 'ingress',
},
{
Protocol: 'tcp',
TargetPort: 3002,
PublishedPort: 8002,
PublishMode: 'host',
},
{
Protocol: 'udp',
TargetPort: 3002,
PublishedPort: 8002,
PublishMode: 'host',
},
{
Protocol: 'tcp',
TargetPort: 3003,
PublishedPort: 8003,
},
],
},
})
)
})
test('updates Docker port mappings with protocol and publish mode intact', async () => {
jest.useFakeTimers()
const dockerApi = new DockerApi({} as any)
const update = jest.fn().mockResolvedValue({})
const service = {
inspect: jest.fn().mockResolvedValue({
Version: { Index: 1 },
Spec: {
TaskTemplate: {
ContainerSpec: {},
Placement: { Constraints: [] },
},
EndpointSpec: { Ports: [] },
Mode: { Replicated: { Replicas: 1 } },
Labels: {},
},
}),
update,
}
;(dockerApi as any).dockerode = {
getService: jest.fn().mockReturnValue(service),
}
jest.spyOn(dockerApi, 'pruneContainers').mockResolvedValue(undefined)
await dockerApi.updateService(
'test-service',
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
[
{
containerPort: 3000,
hostPort: 8000,
protocol: 'tcp',
publishMode: 'host',
},
{
containerPort: 3001,
hostPort: 8001,
protocol: 'udp',
publishMode: 'ingress',
},
{
containerPort: 3002,
hostPort: 8002,
publishMode: 'host',
},
{
containerPort: 3003,
hostPort: 8003,
protocol: 'tcp',
},
],
undefined,
undefined,
undefined,
undefined
)
expect(update).toHaveBeenCalledWith(
expect.objectContaining({
EndpointSpec: {
Ports: [
{
Protocol: 'tcp',
TargetPort: 3000,
PublishedPort: 8000,
PublishMode: 'host',
},
{
Protocol: 'udp',
TargetPort: 3001,
PublishedPort: 8001,
PublishMode: 'ingress',
},
{
Protocol: 'tcp',
TargetPort: 3002,
PublishedPort: 8002,
PublishMode: 'host',
},
{
Protocol: 'udp',
TargetPort: 3002,
PublishedPort: 8002,
PublishMode: 'host',
},
{
Protocol: 'tcp',
TargetPort: 3003,
PublishedPort: 8003,
},
],
},
})
)
jest.runOnlyPendingTimers()
jest.useRealTimers()
})
})