import { fireEvent, render, screen } from '@testing-library/react';
import React from 'react';
import type { Application } from '@spinnaker/core';
import { CollapsibleSectionStateCache } from '@spinnaker/core';
import {
createCustomMockLaunchTemplate,
mockLaunchTemplate,
mockLaunchTemplateData,
mockServerGroup,
} from '@spinnaker/mocks';
import { LaunchTemplateDetailsSection } from './LaunchTemplateDetailsSection';
import { MultipleInstanceTypesSubSection } from './MultipleInstanceTypesSubSection';
import type { IAmazonMixedInstancesPolicy, IAmazonServerGroupView, IScalingPolicy } from '../../../domain';
describe('Launch template details', () => {
const app = {} as Application;
const expectValue = (label: string, value: string) => {
const term = screen.getByText(label, { selector: 'dt' });
expect(term.nextElementSibling).toHaveTextContent(value);
};
const expand = () => fireEvent.click(screen.getByText('Launch Template'));
const baseServerGroupWithLt = {
...mockServerGroup,
launchTemplate: createCustomMockLaunchTemplate('test123', {
...mockLaunchTemplateData,
kernelId: 'kernal-abc',
ramDiskId: 'ramDisk-123',
userData: btoa('test user data'),
instanceMarketOptions: {
spotOptions: {
maxPrice: '0.50',
},
},
}),
image: {
description: 'ancestor_name=testBaseImage',
imageLocation: 'location',
},
scalingPolicies: [] as IScalingPolicy[],
} as IAmazonServerGroupView;
const baseServerGroupWithMipOverrides = {
...mockServerGroup,
image: {
description: 'ancestor_name=testBaseImage',
imageLocation: 'location',
},
scalingPolicies: [] as IScalingPolicy[],
mixedInstancesPolicy: {
allowedInstanceTypes: ['some.type.medium', 'some.type.large'],
instancesDistribution: {
onDemandAllocationStrategy: 'prioritized',
onDemandBaseCapacity: 1,
onDemandPercentageAboveBaseCapacity: 50,
spotAllocationStrategy: 'capacity-optimized',
spotMaxPrice: '1.5',
},
launchTemplates: [
{
createdBy: 'testuser@test.com',
createdTime: 1588787656527,
defaultVersion: true,
launchTemplateData: { ...mockLaunchTemplateData, userData: btoa('test user data') },
launchTemplateId: '123456',
launchTemplateName: 'testLaunchTemplatev001',
versionDescription: 'Test purposes',
versionNumber: 1,
},
],
launchTemplateOverridesForInstanceType: [
{
instanceType: 'some.type.medium',
weightedCapacity: '2',
},
{
instanceType: 'some.type.large',
weightedCapacity: '4',
},
],
} as IAmazonMixedInstancesPolicy,
} as IAmazonServerGroupView;
beforeEach(() => vi.spyOn(CollapsibleSectionStateCache, 'isSet').mockReturnValue(false));
it('should not render if no launch template', () => {
const testServerGroup = {
...mockServerGroup,
scalingPolicies: [] as IScalingPolicy[],
} as IAmazonServerGroupView;
const { container } = render();
expect(container).toBeEmptyDOMElement();
});
it('should render base info', () => {
render();
expand();
expectValue('Name', 'test123');
expectValue('Image ID', 'ami-0123456789');
expectValue('Instance Type', 'm5.large');
expectValue('IAM Profile', 'testapplicationInstanceProfile');
expectValue('Instance Monitoring', 'disabled');
});
it('should render launch template details for server group with launchTemplate', () => {
const testServerGroup = {
...mockServerGroup,
launchTemplate: createCustomMockLaunchTemplate('ltWithCredits', {
...mockLaunchTemplateData,
instanceMarketOptions: {
spotOptions: {
maxPrice: '0.50',
},
},
creditSpecification: {
cpuCredits: 'unlimited',
},
keyName: 'test',
kernelId: 'kernal-abc',
ramDiskId: 'ramDisk-123',
userData: btoa('test user data'),
}),
image: {
description: 'ancestor_name=testBaseImage',
imageLocation: 'location',
},
} as IAmazonServerGroupView;
const expectedLabels = new Map([
['Name', 'ltWithCredits'],
['Image ID', 'ami-0123456789'],
['Image Name', 'location'],
['Base Image Name', 'testBaseImage'],
['Instance Type', 'm5.large'],
['CPU Credit Specification', 'unlimited'],
['IAM Profile', 'testapplicationInstanceProfile'],
['Instance Monitoring', 'disabled'],
['Max Spot Price', '0.50'],
['Key Name', 'test'],
['Kernel ID', 'kernal-abc'],
['Ramdisk ID', 'ramDisk-123'],
['User Data', ''],
]);
render();
expand();
expectedLabels.forEach((value, key) => value && expectValue(key, value));
expect(screen.getByText('User Data', { selector: 'dt' })).toBeInTheDocument();
});
it('should conditionally render launch template details for server group with mixedInstancesPolicy', () => {
const testServerGroup = baseServerGroupWithMipOverrides;
render();
expand();
expectValue('Name', 'testLaunchTemplatev001');
expectValue('Image ID', 'ami-0123456789');
expectValue('Image Name', 'location');
expectValue('Base Image Name', 'testBaseImage');
expectValue('IAM Profile', 'testapplicationInstanceProfile');
expectValue('Instance Monitoring', 'disabled');
expectValue('Max Spot Price', '1.5');
expect(screen.getByRole('cell', { name: 'some.type.medium' })).toBeInTheDocument();
expect(screen.getByRole('cell', { name: '2' })).toBeInTheDocument();
expect(screen.getByRole('cell', { name: 'some.type.large' })).toBeInTheDocument();
expect(screen.getByRole('cell', { name: '4' })).toBeInTheDocument();
});
it('should conditionally render image information', () => {
const { rerender } = render();
expand();
expect(screen.getByText('Image Name', { selector: 'dt' })).toBeInTheDocument();
expect(screen.getByText('Base Image Name', { selector: 'dt' })).toBeInTheDocument();
const newServerGroup = {
...baseServerGroupWithLt,
};
delete newServerGroup.image;
rerender();
expect(screen.queryByText('Image Name', { selector: 'dt' })).not.toBeInTheDocument();
expect(screen.queryByText('Base Image Name', { selector: 'dt' })).not.toBeInTheDocument();
});
it('should conditionally render additional info', () => {
const { rerender } = render();
expand();
['Max Spot Price', 'Key Name', 'Kernel ID', 'Ramdisk ID', 'User Data'].forEach((label) =>
expect(screen.getByText(label, { selector: 'dt' })).toBeInTheDocument(),
);
const newServerGroup = {
...baseServerGroupWithLt,
launchTemplate: mockLaunchTemplate,
};
delete newServerGroup.launchTemplate.launchTemplateData.userData;
delete newServerGroup.launchTemplate.launchTemplateData.keyName;
rerender();
['Max Spot Price', 'Key Name', 'Kernel ID', 'Ramdisk ID', 'User Data'].forEach((label) =>
expect(screen.queryByText(label, { selector: 'dt' })).not.toBeInTheDocument(),
);
});
it('should not render multiple instance types subsection when overrides are not specified', () => {
const { container } = render();
expect(container).toBeEmptyDOMElement();
});
});