import { render, screen } from '@testing-library/react';
import React from 'react';
import { AnnotationCustomSections } from './AnnotationCustomSections';
describe('', () => {
it('renders text annotations under section groups', () => {
render(
,
);
expect(screen.getByRole('heading', { name: 'deployment details' })).toBeInTheDocument();
expect(screen.getByRole('heading', { name: 'support' })).toBeInTheDocument();
expect(screen.getByText('owner name')).toBeInTheDocument();
expect(screen.getByText('Delivery Platform')).toBeInTheDocument();
expect(screen.getByText('contact')).toBeInTheDocument();
expect(screen.getByText('On call')).toBeInTheDocument();
});
it('sanitizes HTML annotations while enforcing rel on targeted links', () => {
const { container } = render(
RunbookDashboard',
})}
resource={resource()}
/>,
);
const links = screen.getAllByRole('link');
expect(links).toHaveLength(2);
links.forEach((link) => {
expect(link).toHaveAttribute('target', '_blank');
expect(link).toHaveAttribute('rel', 'noopener noreferrer');
expect(link).not.toHaveAttribute('onclick');
});
expect(screen.getByRole('link', { name: 'Runbook' })).toBeInTheDocument();
expect(screen.getByRole('link', { name: 'Dashboard' })).toBeInTheDocument();
expect(container.querySelector('[target="dashboard"]')).not.toBeInTheDocument();
expect(container.querySelector('script')).not.toBeInTheDocument();
});
it('escapes interpolated resource values in HTML annotations', () => {
const { container } = render(
Owner: {{ displayName }}',
})}
resource={resource({
displayName: 'Evil',
})}
/>,
);
expect(screen.getByText('Owner:')).toBeInTheDocument();
expect(container).toHaveTextContent('Evil');
expect(container.querySelector('a[href="https://evil.example"]')).not.toBeInTheDocument();
});
it('interpolates path placeholders against resource and manifest values', () => {
render(
,
);
expect(screen.getByText('frontend in production from frontend-manifest')).toBeInTheDocument();
});
it('leaves non-path expression placeholders unresolved', () => {
render(
'frontend',
})}
/>,
);
expect(screen.getByText('{{ displayName | uppercase }} {{ getDisplayName() }}')).toBeInTheDocument();
});
it('leaves prototype-chain path placeholders unresolved', () => {
const { container } = render(
,
);
const text = container.textContent || '';
expect(text).toContain(
'{{ constructor }} {{ resource.constructor }} {{ resource["constructor"] }} {{ resource.__proto__ }} {{ resource.prototype }} frontend',
);
expect(text).not.toContain('function Object');
expect(text).not.toContain('[object Object]');
});
it('treats inherited function path values as missing', () => {
const { container } = render(
,
);
const text = container.textContent || '';
expect(text).toContain('before after frontend');
expect(text).not.toContain('function toString');
expect(text).not.toContain('[native code]');
});
it('strips target attributes from sanitized non-anchor elements', () => {
const { container } = render(
ContainerRunbook',
})}
resource={resource()}
/>,
);
const content = screen.getByText('Container');
const link = screen.getByRole('link', { name: 'Runbook' });
expect(content).not.toHaveAttribute('target');
expect(link).toHaveAttribute('target', '_blank');
expect(link).toHaveAttribute('rel', 'noopener noreferrer');
expect(container.querySelector('div[target]')).not.toBeInTheDocument();
});
it('renders text entries before HTML entries within the same section', () => {
const { container } = render(
Runbook',
'runbook.details.spinnaker.io/summary': 'Read this first',
})}
resource={resource()}
/>,
);
const sectionText = container.querySelector('.content-body')?.textContent || '';
expect(sectionText.indexOf('Read this first')).toBeLessThan(sectionText.indexOf('Runbook'));
});
});
const manifestWithAnnotations = (annotations: { [key: string]: string }) => ({
metadata: {
name: 'frontend-manifest',
annotations,
},
});
const resource = (overrides: any = {}) =>
({
apiVersion: 'apps/v1',
displayName: 'frontend',
kind: 'Deployment',
namespace: 'default',
...overrides,
} as any);