n8n-nodes-awx
Version:
n8n node to interact with Ansible AWX/Tower with improved type safety
283 lines • 11.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const HostResources_1 = require("../src/resources/HostResources");
const mockApiClient = {
get: jest.fn(),
post: jest.fn(),
put: jest.fn(),
delete: jest.fn(),
};
const createMockHost = (overrides = {}) => ({
id: 1,
type: 'host',
url: '/api/v2/hosts/1/',
related: {
created_by: '/api/v2/users/1/',
modified_by: '/api/v2/users/1/',
variable_data: {},
inventory: '/api/v2/inventories/1/',
groups: '/api/v2/hosts/1/groups/',
all_groups: '/api/v2/hosts/1/all_groups/',
job_events: '/api/v2/hosts/1/job_events/',
job_host_summaries: '/api/v2/hosts/1/job_host_summaries/',
activity_stream: '/api/v2/hosts/1/activity_stream/',
},
summary_fields: {
inventory: {
id: 1,
name: 'Test Inventory',
description: 'Test inventory for unit testing',
},
created_by: {
id: 1,
username: 'admin',
first_name: '',
last_name: '',
},
modified_by: {
id: 1,
username: 'admin',
first_name: '',
last_name: '',
},
user_capabilities: {
edit: true,
delete: true,
},
},
created: '2023-01-01T00:00:00.000Z',
modified: '2023-01-01T00:00:00.000Z',
name: 'test-host',
description: 'Test host',
inventory: 1,
enabled: true,
instance_id: '',
variables: '{}',
has_active_failures: false,
has_inventory_sources: false,
last_job: null,
last_job_host_summary: null,
ansible_facts: {},
ansible_facts_modified: null,
...overrides,
});
describe('HostResources', () => {
let hostResources;
beforeEach(() => {
jest.clearAllMocks();
hostResources = new HostResources_1.HostResources(mockApiClient);
mockApiClient.get.mockImplementation((url) => {
if (url.includes('/api/v2/hosts/')) {
if (url.includes('name=')) {
return Promise.resolve({
data: {
count: 1,
next: null,
previous: null,
results: [createMockHost()]
}
});
}
else if (url.match(/\/api\/v2\/hosts\/\d+\/$/)) {
return Promise.resolve({
data: createMockHost()
});
}
return Promise.resolve({
data: {
count: 1,
next: null,
previous: null,
results: [createMockHost()]
}
});
}
return Promise.resolve({ data: createMockHost() });
});
mockApiClient.post.mockImplementation(() => {
return Promise.resolve({
data: createMockHost({ id: 2, name: 'New Host' })
});
});
mockApiClient.put.mockImplementation(() => {
return Promise.resolve({
data: createMockHost({ name: 'Updated Host' })
});
});
mockApiClient.delete.mockImplementation(() => {
return Promise.resolve();
});
});
describe('list', () => {
it('should list all hosts', async () => {
const hosts = await hostResources.list();
expect(Array.isArray(hosts)).toBe(true);
expect(hosts.length).toBeGreaterThan(0);
expect(hosts[0]).toHaveProperty('id');
expect(hosts[0]).toHaveProperty('name');
expect(hosts[0]).toHaveProperty('inventory');
expect(mockApiClient.get).toHaveBeenCalledWith('/api/v2/hosts/');
});
it('should pass query parameters to the API', async () => {
const params = { inventory: 1 };
await hostResources.list(params);
expect(mockApiClient.get).toHaveBeenCalledWith(expect.stringContaining('inventory=1'));
});
});
describe('get', () => {
it('should get a host by ID', async () => {
const host = await hostResources.get(1);
expect(host).toBeDefined();
expect(host.id).toBe(1);
expect(mockApiClient.get).toHaveBeenCalledWith('/api/v2/hosts/1/');
});
it('should throw an error when ID is not provided', async () => {
await expect(hostResources.get(0)).rejects.toThrow('Host ID is required');
});
});
describe('getByName', () => {
it('should get a host by name', async () => {
const host = await hostResources.getByName('test-host');
expect(host).toBeDefined();
expect(host === null || host === void 0 ? void 0 : host.id).toBe(1);
expect(mockApiClient.get).toHaveBeenCalledWith('/api/v2/hosts/?name=test-host');
});
it('should return null when no host is found', async () => {
mockApiClient.get.mockResolvedValueOnce({
data: {
count: 0,
next: null,
previous: null,
results: []
}
});
const host = await hostResources.getByName('nonexistent-host');
expect(host).toBeNull();
});
it('should throw an error when multiple hosts are found', async () => {
mockApiClient.get.mockResolvedValueOnce({
data: {
count: 2,
next: null,
previous: null,
results: [
createMockHost({ id: 1, name: 'duplicate-host' }),
createMockHost({ id: 2, name: 'duplicate-host' })
]
}
});
await expect(hostResources.getByName('duplicate-host'))
.rejects.toThrow('Multiple hosts found with name: duplicate-host');
});
it('should include inventory ID in the request when provided', async () => {
await hostResources.getByName('test-host', 123);
expect(mockApiClient.get).toHaveBeenCalledWith('/api/v2/hosts/?name=test-host&inventory=123');
});
});
describe('create', () => {
it('should create a new host', async () => {
const hostData = {
name: 'new-host',
inventory: 1,
description: 'New test host',
enabled: true,
variables: '{}'
};
const host = await hostResources.create(hostData);
expect(host).toBeDefined();
expect(host.name).toBe('New Host');
expect(host.id).toBe(2);
expect(mockApiClient.post).toHaveBeenCalledWith('/api/v2/hosts/', hostData);
});
it('should require name and inventory', async () => {
const invalidHostData = { description: 'Missing required fields' };
await expect(hostResources.create(invalidHostData)).rejects.toThrow('Missing required fields: name, inventory');
});
});
describe('update', () => {
it('should update an existing host', async () => {
const updateData = { name: 'updated-host' };
const host = await hostResources.update(1, updateData);
expect(host).toBeDefined();
expect(host.name).toBe('Updated Host');
expect(mockApiClient.put).toHaveBeenCalledWith('/api/v2/hosts/1/', updateData);
});
it('should throw an error when ID is not provided', async () => {
await expect(hostResources.update(0, {})).rejects.toThrow('Host ID is required');
});
});
describe('delete', () => {
it('should delete a host', async () => {
await hostResources.delete(1);
expect(mockApiClient.delete).toHaveBeenCalledWith('/api/v2/hosts/1/');
});
it('should throw an error when ID is not provided', async () => {
await expect(hostResources.delete(0)).rejects.toThrow('Host ID is required');
});
});
describe('buildUrl', () => {
const testBuildUrl = (hostResources, path, params) => {
const resourcesWithPrivate = hostResources;
return resourcesWithPrivate.buildUrl(path, params);
};
it('should return the base URL when no params are provided', () => {
const result = testBuildUrl(hostResources, '/api/v2/hosts/');
expect(result).toBe('/api/v2/hosts/');
});
it('should handle empty params object', () => {
const result = testBuildUrl(hostResources, '/api/v2/hosts/', {});
expect(result).toBe('/api/v2/hosts/');
});
it('should handle undefined and null params', () => {
const result1 = testBuildUrl(hostResources, '/api/v2/hosts/', undefined);
expect(result1).toBe('/api/v2/hosts/');
const result2 = testBuildUrl(hostResources, '/api/v2/hosts/', null);
expect(result2).toBe('/api/v2/hosts/');
});
it('should append query parameters correctly', () => {
const result = testBuildUrl(hostResources, '/api/v2/hosts/', {
name: 'test host',
inventory: 1,
page: 1,
page_size: 10
});
expect(result).toContain('name=test%20host');
expect(result).toContain('inventory=1');
expect(result).toContain('page=1');
expect(result).toContain('page_size=10');
expect(result).toMatch(/^\/api\/v2\/hosts\/\?.*/);
});
it('should handle special characters in parameters', () => {
const result = testBuildUrl(hostResources, '/api/v2/hosts/', {
name: 'host@test',
description: 'Test host with special chars & spaces'
});
expect(result).toContain('name=host%40test');
expect(result).toContain('description=Test%20host%20with%20special%20chars%20%26%20spaces');
});
it('should filter out undefined, null, and empty string values', () => {
const result = testBuildUrl(hostResources, '/api/v2/hosts/', {
name: 'test',
status: undefined,
description: null,
inventory: 0,
emptyString: ''
});
expect(result).toContain('name=test');
expect(result).toContain('inventory=0');
expect(result).not.toContain('status=');
expect(result).not.toContain('description=');
expect(result).not.toContain('emptyString=');
});
it('should return base URL when all parameters are filtered out', () => {
const result = testBuildUrl(hostResources, '/api/v2/hosts/', {
status: undefined,
description: null,
emptyString: ''
});
expect(result).toBe('/api/v2/hosts/');
expect(result).not.toContain('?');
});
});
});
//# sourceMappingURL=HostResources.test.js.map