2025-11-16 22:50:19 +00:00
|
|
|
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
|
|
|
import { SmartRequest } from '../ts/client/index.js';
|
|
|
|
|
import { CoreRequest } from '../ts/core_deno/index.js';
|
|
|
|
|
|
|
|
|
|
// Check if Docker socket exists (common unix socket for testing)
|
|
|
|
|
const dockerSocketPath = '/var/run/docker.sock';
|
|
|
|
|
let dockerAvailable = false;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const fileInfo = await Deno.stat(dockerSocketPath);
|
|
|
|
|
dockerAvailable = fileInfo.isFile || fileInfo.isSymlink;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log(
|
|
|
|
|
'Docker socket not available - skipping unix socket tests. To enable, ensure Docker is running.',
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tap.test('deno: should detect unix socket URLs correctly', async () => {
|
|
|
|
|
expect(CoreRequest.isUnixSocket('unix:/var/run/docker.sock:/version')).toBeTrue();
|
|
|
|
|
expect(CoreRequest.isUnixSocket('http://unix:/var/run/docker.sock:/version')).toBeTrue();
|
|
|
|
|
expect(CoreRequest.isUnixSocket('https://unix:/var/run/docker.sock:/version')).toBeTrue();
|
|
|
|
|
expect(CoreRequest.isUnixSocket('http://example.com')).toBeFalse();
|
|
|
|
|
expect(CoreRequest.isUnixSocket('https://example.com')).toBeFalse();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
tap.test('deno: should parse unix socket URLs correctly', async () => {
|
|
|
|
|
const result = CoreRequest.parseUnixSocketUrl('unix:/var/run/docker.sock:/v1.24/version');
|
2025-11-16 23:41:24 +00:00
|
|
|
expect(result.socketPath).toEqual('/var/run/docker.sock');
|
2025-11-16 22:50:19 +00:00
|
|
|
expect(result.path).toEqual('/v1.24/version');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (dockerAvailable) {
|
|
|
|
|
tap.test('deno: should connect to Docker via unix socket (unix: protocol)', async () => {
|
|
|
|
|
const response = await SmartRequest.create()
|
|
|
|
|
.url('http://unix:/var/run/docker.sock:/version')
|
|
|
|
|
.get();
|
|
|
|
|
|
|
|
|
|
expect(response.ok).toBeTrue();
|
|
|
|
|
expect(response.status).toEqual(200);
|
|
|
|
|
|
|
|
|
|
const body = await response.json();
|
|
|
|
|
expect(body).toHaveProperty('Version');
|
|
|
|
|
console.log(`Docker version: ${body.Version}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
tap.test('deno: should connect to Docker via socketPath option', async () => {
|
|
|
|
|
const response = await CoreRequest.create('http://localhost/version', {
|
|
|
|
|
socketPath: '/var/run/docker.sock',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
expect(response.ok).toBeTrue();
|
|
|
|
|
expect(response.status).toEqual(200);
|
|
|
|
|
|
|
|
|
|
const body = await response.json();
|
|
|
|
|
expect(body).toHaveProperty('Version');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
tap.test('deno: should connect to Docker via HttpClient', async () => {
|
|
|
|
|
const client = Deno.createHttpClient({
|
|
|
|
|
proxy: {
|
|
|
|
|
url: 'unix:///var/run/docker.sock',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const response = await CoreRequest.create('http://localhost/version', {
|
|
|
|
|
client,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
expect(response.ok).toBeTrue();
|
|
|
|
|
expect(response.status).toEqual(200);
|
|
|
|
|
|
|
|
|
|
const body = await response.json();
|
|
|
|
|
expect(body).toHaveProperty('Version');
|
|
|
|
|
|
|
|
|
|
// Clean up client
|
|
|
|
|
client.close();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
tap.test('deno: should handle unix socket with query parameters', async () => {
|
|
|
|
|
const response = await SmartRequest.create()
|
|
|
|
|
.url('http://unix:/var/run/docker.sock:/containers/json')
|
|
|
|
|
.query({ all: 'true' })
|
|
|
|
|
.get();
|
|
|
|
|
|
|
|
|
|
expect(response.ok).toBeTrue();
|
|
|
|
|
expect(response.status).toEqual(200);
|
|
|
|
|
|
|
|
|
|
const body = await response.json();
|
|
|
|
|
expect(Array.isArray(body)).toBeTrue();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
tap.test('deno: should handle unix socket with POST requests', async () => {
|
|
|
|
|
// Test POST to Docker API (this specific endpoint may require permissions)
|
|
|
|
|
const response = await SmartRequest.create()
|
|
|
|
|
.url('http://unix:/var/run/docker.sock:/containers/json')
|
|
|
|
|
.query({ all: 'true', limit: '1' })
|
|
|
|
|
.get();
|
|
|
|
|
|
|
|
|
|
expect(response.status).toBeGreaterThanOrEqual(200);
|
|
|
|
|
expect(response.status).toBeLessThan(500);
|
|
|
|
|
|
|
|
|
|
await response.text(); // Consume body
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
tap.test('deno: should cache HttpClient for reuse', async () => {
|
|
|
|
|
// First request creates a client
|
|
|
|
|
const response1 = await SmartRequest.create()
|
|
|
|
|
.url('http://unix:/var/run/docker.sock:/version')
|
|
|
|
|
.get();
|
|
|
|
|
|
|
|
|
|
expect(response1.ok).toBeTrue();
|
|
|
|
|
await response1.text();
|
|
|
|
|
|
|
|
|
|
// Second request should reuse the cached client
|
|
|
|
|
const response2 = await SmartRequest.create()
|
|
|
|
|
.url('http://unix:/var/run/docker.sock:/version')
|
|
|
|
|
.get();
|
|
|
|
|
|
|
|
|
|
expect(response2.ok).toBeTrue();
|
|
|
|
|
await response2.text();
|
|
|
|
|
|
|
|
|
|
// Clean up cache
|
|
|
|
|
CoreRequest.clearClientCache();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
tap.test('deno: should clear HttpClient cache', async () => {
|
|
|
|
|
const response = await SmartRequest.create()
|
|
|
|
|
.url('http://unix:/var/run/docker.sock:/version')
|
|
|
|
|
.get();
|
|
|
|
|
|
|
|
|
|
expect(response.ok).toBeTrue();
|
|
|
|
|
await response.text();
|
|
|
|
|
|
|
|
|
|
// Clear cache - should not throw
|
|
|
|
|
CoreRequest.clearClientCache();
|
|
|
|
|
|
|
|
|
|
// Subsequent request should create new client
|
|
|
|
|
const response2 = await SmartRequest.create()
|
|
|
|
|
.url('http://unix:/var/run/docker.sock:/version')
|
|
|
|
|
.get();
|
|
|
|
|
|
|
|
|
|
expect(response2.ok).toBeTrue();
|
|
|
|
|
await response2.text();
|
|
|
|
|
|
|
|
|
|
// Clean up
|
|
|
|
|
CoreRequest.clearClientCache();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
tap.skip.test(
|
|
|
|
|
'deno: unix socket tests skipped - Docker socket not available',
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default tap.start();
|