Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,16 @@ Reading the result:
mutated code. If the mutant cannot change observable behaviour (an equivalent
mutant, such as a redundant guard), simplify the code instead, or as a last
resort disable that mutator on the line with a
`// Stryker disable next-line <mutator>: <reason>` comment.
`// Stryker disable next-line <mutator>: <reason>` comment. The directive
attaches to the statement, declaration or expression that starts on the next
line; for an `else if` test put the comment inline inside the parentheses, and
for a node in the middle of a call chain or template literal wrap the
enclosing statement in `// Stryker disable <mutator>: <reason>` and
`// Stryker restore <mutator>` instead. A mutant that is already Ignored in
the report has been triaged this way and does not need an issue.
- `stryker.config.mjs` excludes the `ArrayDeclaration` mutator (`[]` to
`["Stryker was here"]`): every instance that survived on main seeded an
accumulator or fallback whose contents are unobservable.

The tests run in Stryker's instrumented copy of the source, so a test that reads
a `src/` or `scripts/lib/` file as text fails there for reasons unrelated to any
Expand Down
1 change: 1 addition & 0 deletions src/components/ArchitectureFilters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export function filterArchitectures(architectures, filters) {
const { query, industry, project, organization } = filters;
const normalizedQuery = query.trim().toLowerCase();
return architectures.filter((architecture) => {
// Stryker disable next-line ConditionalExpression: an empty query matches every architecture
if (normalizedQuery) {
const searchable =
`${architecture.organization} ${architecture.title} ${architecture.summary}`.toLowerCase();
Expand Down
1 change: 1 addition & 0 deletions src/components/AwardsTimeline/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function WinnerCard({ entry }) {
talkUrl,
} = entry;
const primaryUrl = announcementUrl || talkUrl;
// Stryker disable next-line StringLiteral: the fallback URL is never rendered when logo is absent
const logoUrl = useBaseUrl(logo || '');
return (
<article className={styles.card}>
Expand Down
1 change: 1 addition & 0 deletions src/components/CNCFProjectCard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default function CNCFProjectCard({
version,
description,
}) {
// Stryker disable next-line StringLiteral: the fallback URL is never rendered when logo is absent
const logoUrl = useBaseUrl(logo || '');
return (
<a className={styles.card} href={href} target="_blank" rel="noreferrer">
Expand Down
6 changes: 4 additions & 2 deletions src/components/MemberDirectory/DirectoryFreshness.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ export function DirectoryFreshness() {
const landscape = membersData?.sources?.landscape;
const architecturesDate = formatDate(metrics?.generatedAt);
const landscapeDate = formatDate(landscape?.collectedAt);
// Stryker disable next-line OptionalChaining: landscapeDate is only truthy when landscape is an object
const landscapeSourceUrl = landscape?.sourceUrl;
const awardsDate = formatDate(awardsData?.verifiedAt);
if (!landscapeDate && !architecturesDate && !awardsDate) return null;
return (
<p className={styles.freshnessNote}>
{landscapeDate && (
<>
Directory membership data last synced from{' '}
{landscape?.sourceUrl ? (
<a href={landscape.sourceUrl} target="_blank" rel="noreferrer">
{landscapeSourceUrl ? (
<a href={landscapeSourceUrl} target="_blank" rel="noreferrer">
cncf/landscape
</a>
) : (
Expand Down
1 change: 1 addition & 0 deletions src/components/MemberDirectory/MemberCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import styles from './styles.module.css';
export function MemberCard({ member }) {
const [open, setOpen] = useState(false);
const triggerRef = useRef(null);
// Stryker disable next-line StringLiteral: the fallback URL is never rendered when the logo is absent
const logoUrl = useBaseUrl(member.logo || '');

return (
Expand Down
1 change: 1 addition & 0 deletions src/components/MemberDirectory/MemberProfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { initials, formatCount, membershipLabel } from './utils';
import styles from './styles.module.css';

export function MemberProfile({ member, onClose, triggerRef }) {
// Stryker disable next-line StringLiteral: the fallback URL is never rendered when the logo is absent
const logoUrl = useBaseUrl(member.logo || '');

return (
Expand Down
1 change: 1 addition & 0 deletions src/components/ReferenceArchitectures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function ArchitectureCard({ architecture }) {
const logoAsset = architecture.assets?.find((asset) =>
/logo|wordmark/i.test(asset),
);
// Stryker disable next-line StringLiteral: the fallback URL is never rendered when the logo is absent
const logoUrl = useBaseUrl(logoAsset || '');
return (
<Link to={`/architectures/${id}`} className={styles.card}>
Expand Down
1 change: 1 addition & 0 deletions src/lib/profile-links.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export function profileUrl(value, type) {
export function websiteUrl(value) {
if (typeof value !== 'string') return null;
const trimmed = value.trim();
// Stryker disable next-line ConditionalExpression: an empty trimmed value fails every later pattern and returns null
if (!trimmed) return null;

const url = isSafeUrl(trimmed, {
Expand Down
7 changes: 7 additions & 0 deletions stryker.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ export default {
},
coverageAnalysis: 'perTest',
mutate: ['src/**/*.{js,mjs}', 'scripts/lib/**/*.mjs'],
// Replacing an empty literal with `["Stryker was here"]` is the only mutation
// of this kind that survives on main: every surviving instance was an
// accumulator or fallback whose seed contents are unobservable. The mutants
// that did pin behavior are already covered by the type checks and
// assertions on the populated arrays, so the whole kind is excluded instead
// of annotating each site.
mutator: { excludedMutations: ['ArrayDeclaration'] },
concurrency: 4,
reporters: ['clear-text', 'progress', 'html', 'json'],
// `break` fails the run below this mutation score. It was set from the full
Expand Down
Loading