Skip to content

CLI-1162 Consolidate repetitive test cases into parameterized tests - #785

Merged
damien-urruty-sonarsource merged 2 commits into
masterfrom
remediate-master-20260907-050105-c6016a87
Sep 25, 2026
Merged

damien-urruty-sonarsource merged 2 commits into
masterfrom
remediate-master-20260907-050105-c6016a87

Conversation

@sonarqube-agent

Copy link
Copy Markdown
Contributor

This PR was automatically created by the Remediation Agent's Scheduled backlog remediation feature.

Why these issues? All five issues share the same SonarQube rule (typescript:S5976) with uniform MAJOR severity and apply the same refactoring pattern consistently across multiple test suites. This creates a cohesive, automatable group where addressing them together delivers high ROI through significant test file cleanup and improved test quality in a single change.

This change consolidates 18 repetitive test cases across 5 test files into 5 parameterized tests using it.each, eliminating code duplication and improving test maintainability. By replacing structurally identical tests that differ only in literal values with table-driven parameterized tests, the code becomes more concise, easier to modify, and aligns with testing best practices.

View Project in SonarCloud


Fixed Issues

typescript:S5976 - Replace these 4 tests with a single Parameterized one. • MAJOR • View issue

Location: tests/unit/core/host/connectivity/network-config.test.ts:350

Why is this an issue?

When several tests have the same structure and differ only by a few hardcoded values, they are harder to maintain as separate tests. A table-driven test makes the common behavior explicit and keeps the varying data in one place.

What changed

Replaces the four separate test declarations with a single it.each parameterized test. The test table encodes the varying data (description suffix, noProxy value, and URL) for each of the original four tests: exact hostname match, suffix match, wildcard *, and * in a comma-separated list. This directly addresses the code smell about having multiple tests with the same structure that should be consolidated into one parameterized test.

--- a/tests/unit/core/host/connectivity/network-config.test.ts
+++ b/tests/unit/core/host/connectivity/network-config.test.ts
@@ -350,1 +350,6 @@ describe('buildFetchNetworkOptions', () => {
-    it('skips proxy when hostname matches noProxy exactly', () => {
+    it.each([
+      ['hostname matches exactly', 'sonar.internal.corp.com', 'https://sonar.internal.corp.com/api'],
+      ['hostname matches suffix', 'corp.com', 'https://sonar.corp.com/api'],
+      ['noProxy is wildcard *', '*', 'https://sonar.example.com/api'],
+      ['* in comma-separated list', 'localhost,*', 'https://anything.example.com/api'],
+    ])('skips proxy when %s', (_, noProxy, url) => {
typescript:S5976 - Replace these 3 tests with a single Parameterized one. • MAJOR • View issue

Location: tests/unit/commands/integrate/antigravity/health.test.ts:69

Why is this an issue?

When several tests have the same structure and differ only by a few hardcoded values, they are harder to maintain as separate tests. A table-driven test makes the common behavior explicit and keeps the varying data in one place.

What changed

This hunk replaces the first of three structurally identical tests with a single parameterized it.each test. The three original tests ('returns configured when sonar-secrets block and script exist', 'returns not_configured when the sonar-secrets block is disabled', and 'returns invalid when the PreToolUse matcher is not view_file') differed only in the enabled flag, the matcher value, and the expected result. This hunk consolidates them into one table-driven test with parameters [expected, enabled, matcher], directly addressing the code smell about replacing three repetitive tests that share the same structure with a single parameterized test. The parameterized values (enabled: true/false, matcher: 'view_file'/'edit_file', and expected results 'configured'/'not_configured'/'invalid') capture all the variation that previously existed across the separate tests.

--- a/tests/unit/commands/integrate/antigravity/health.test.ts
+++ b/tests/unit/commands/integrate/antigravity/health.test.ts
@@ -69,21 +69,28 @@ describe('checkAntigravitySecretsHookFile', () => {
-  it('returns configured when sonar-secrets block and script exist (absolute command path)', () => {
-    tempDir = mkdtempSync(join(tmpdir(), 'sonar-antigravity-health-'));
-    const scriptPath = join(tempDir, hookScriptName());
-    writeFileSync(scriptPath, '#!/bin/bash\n');
-    writeFileSync(
-      join(tempDir, 'hooks.json'),
-      JSON.stringify({
-        'sonar-secrets': {
-          enabled: true,
-          PreToolUse: [
-            {
-              matcher: 'view_file',
-              hooks: [{ command: formatAntigravityHookCommand(scriptPath) }],
-            },
-          ],
-        },
-      }),
-    );
-
-    expect(checkAntigravitySecretsHookFile(join(tempDir, 'hooks.json'))).toBe('configured');
-  });
+  it.each([
+    ['configured', true, 'view_file'],
+    ['not_configured', false, 'view_file'],
+    ['invalid', true, 'edit_file'],
+  ] as const)(
+    'returns %s when enabled=%s and matcher=%s',
+    (expected, enabled, matcher) => {
+      tempDir = mkdtempSync(join(tmpdir(), 'sonar-antigravity-health-'));
+      const scriptPath = join(tempDir, hookScriptName());
+      writeFileSync(scriptPath, '#!/bin/bash\n');
+      writeFileSync(
+        join(tempDir, 'hooks.json'),
+        JSON.stringify({
+          'sonar-secrets': {
+            enabled,
+            PreToolUse: [
+              {
+                matcher,
+                hooks: [{ command: formatAntigravityHookCommand(scriptPath) }],
+              },
+            ],
+          },
+        }),
+      );
+
+      expect(checkAntigravitySecretsHookFile(join(tempDir, 'hooks.json'))).toBe(expected);
+    },
+  );
typescript:S5976 - Replace these 4 tests with a single Parameterized one. • MAJOR • View issue

Location: tests/integration/specs/run/mcp.test.ts:160

Why is this an issue?

When several tests have the same structure and differ only by a few hardcoded values, they are harder to maintain as separate tests. A table-driven test makes the common behavior explicit and keeps the varying data in one place.

What changed

This hunk replaces four separate test cases (for --debug, --read-only, --toolsets, and --toolsets with cag/vortex) with a single parameterized it.each test. It defines the parameter table with the varying values (flag, envFlag, envValue) and sets up the parameterized test signature, directly addressing the code smell about replacing duplicated tests with a single parameterized test.

--- a/tests/integration/specs/run/mcp.test.ts
+++ b/tests/integration/specs/run/mcp.test.ts
@@ -159,39 +159,8 @@ describe('run mcp', () => {
-  it(
-    'passes SONARQUBE_DEBUG_ENABLED=true to docker when --debug is set',
-    async () => {
-      const server = await harness.newFakeServer().withAuthToken('test-token').start();
-      harness.withAuth(server.baseUrl(), 'test-token');
-      const fakeBinDir = setupFakeDocker();
-
-      const result = await harness.run('run mcp --debug', {
-        extraEnv: { PATH: `${fakeBinDir}${PATH_SEP}${process.env.PATH ?? ''}` },
-      });
-
-      expect(result.exitCode).toBe(0);
-      expect(result.stdout).toContain('-e SONARQUBE_DEBUG_ENABLED');
-      expect(result.stdout).toContain('ENV_DEBUG_ENABLED=true');
-    },
-    { timeout: 15000 },
-  );
-
-  it(
-    'passes SONARQUBE_READ_ONLY=true to docker when --read-only is set',
-    async () => {
-      const server = await harness.newFakeServer().withAuthToken('test-token').start();
-      harness.withAuth(server.baseUrl(), 'test-token');
-      const fakeBinDir = setupFakeDocker();
-
-      const result = await harness.run('run mcp --read-only', {
-        extraEnv: { PATH: `${fakeBinDir}${PATH_SEP}${process.env.PATH ?? ''}` },
-      });
-
-      expect(result.exitCode).toBe(0);
-      expect(result.stdout).toContain('-e SONARQUBE_READ_ONLY');
-      expect(result.stdout).toContain('ENV_READ_ONLY=true');
-    },
-    { timeout: 15000 },
-  );
-
-  it(
-    'passes SONARQUBE_TOOLSETS to docker when --toolsets is set',
-    async () => {
+  it.each([
+    ['--debug', '-e SONARQUBE_DEBUG_ENABLED', 'ENV_DEBUG_ENABLED=true'],
+    ['--read-only', '-e SONARQUBE_READ_ONLY', 'ENV_READ_ONLY=true'],
+    ['--toolsets issues,rules', '-e SONARQUBE_TOOLSETS', 'ENV_TOOLSETS=issues,rules'],
+    ['--toolsets cag,vortex,issues', '-e SONARQUBE_TOOLSETS', 'ENV_TOOLSETS=cag,vortex,issues'],
+  ])(
+    'passes correct env var to docker for: %s',
+    async (flag, envFlag, envValue) => {
typescript:S5976 - Replace these 3 tests with a single Parameterized one. • MAJOR • View issue

Location: tests/integration/specs/api/api.test.ts:50

Why is this an issue?

When several tests have the same structure and differ only by a few hardcoded values, they are harder to maintain as separate tests. A table-driven test makes the common behavior explicit and keeps the varying data in one place.

What changed

This hunk replaces three separate test cases ('exits with code 2 for an invalid HTTP method', 'exits with code 2 when endpoint does not start with /', and 'exits with code 2 when --data is not valid JSON') with a single parameterized it.each(...) test. It defines the data table containing the varying values (description suffix, command string, and expected error message) and sets up the parameterized test signature, directly addressing the code smell about replacing three structurally identical tests with a single parameterized one.

--- a/tests/integration/specs/api/api.test.ts
+++ b/tests/integration/specs/api/api.test.ts
@@ -49,16 +49,19 @@ describe('api', () => {
-  it(
-    'exits with code 2 for an invalid HTTP method',
-    async () => {
-      harness.withAuth('http://localhost:19999', 'fake-token');
-
-      const result = await harness.run('api trace /api/system/status');
-
-      expect(result.exitCode).toBe(2);
-      expect(result.stdout + result.stderr).toContain("Invalid HTTP method 'trace'");
-    },
-    { timeout: 15000 },
-  );
-
-  it(
-    'exits with code 2 when endpoint does not start with /',
-    async () => {
+  it.each([
+    [
+      'for an invalid HTTP method',
+      'api trace /api/system/status',
+      "Invalid HTTP method 'trace'",
+    ],
+    [
+      'when endpoint does not start with /',
+      'api get api/system/status',
+      "Endpoint must start with '/'",
+    ],
+    [
+      'when --data is not valid JSON',
+      'api post /api/system/status --data not-json',
+      '--data must be valid JSON',
+    ],
+  ])(
+    'exits with code 2 %s',
+    async (_, command, expectedError) => {
typescript:S5976 - Replace these 3 tests with a single Parameterized one. • MAJOR • View issue

Location: tests/integration/specs/list/list-issues.test.ts:252

Why is this an issue?

When several tests have the same structure and differ only by a few hardcoded values, they are harder to maintain as separate tests. A table-driven test makes the common behavior explicit and keeps the varying data in one place.

What changed

This hunk replaces the beginning of the first individual test ('exits with code 2 when --page-size is greater than 500') with an it.each([...]) parameterized test. It defines a data table containing the three sets of varying values (description, command, expectedError) for the page-size, severities, and statuses validation tests. This consolidates three structurally identical tests into a single parameterized test, directly addressing the code smell about replacing duplicated tests that differ only in hardcoded literal values with a single parameterized test using it.each.

--- a/tests/integration/specs/list/list-issues.test.ts
+++ b/tests/integration/specs/list/list-issues.test.ts
@@ -251,3 +251,19 @@ describe('list issues — argument validation', () => {
-  it(
-    'exits with code 2 when --page-size is greater than 500',
-    async () => {
+  it.each([
+    [
+      '--page-size is greater than 500',
+      'list issues --project my-project --page-size 501',
+      'Invalid --page-size',
+    ],
+    [
+      '--severities is not a recognised value',
+      'list issues --project my-project --severities UNKNOWN',
+      'Invalid severity',
+    ],
+    [
+      '--statuses is not a recognised value',
+      'list issues --project my-project --statuses UNKNOWN',
+      'Invalid status(es)',
+    ],
+  ])(
+    'exits with code 2 when %s',
+    async (_, command, expectedError) => {

Have a suggestion or found an issue? Share your feedback here.


SonarQube Remediation Agent uses AI. Check for mistakes.

@netlify

netlify Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for sonarqube-cli canceled.

Name Link
🔨 Latest commit 8c9f7f9
🔍 Latest deploy log https://app.netlify.com/projects/sonarqube-cli/deploys/6ab617947586f2000809b168

@hashicorp-vault-sonar-prod hashicorp-vault-sonar-prod Bot changed the title Consolidate repetitive test cases into parameterized tests CLI-1162 Consolidate repetitive test cases into parameterized tests Sep 25, 2026
@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

CLI-1162

sonarqube-agent AI and others added 2 commits September 25, 2026 08:40
Fixed issues:
- AZ-uhBkQLZzEXrPCyHIv for typescript:S5976 rule
- AZ-uhCAkLZzEXrPCyHJ0 for typescript:S5976 rule
- AZ-uhCCFLZzEXrPCyHJ2 for typescript:S5976 rule
- AZ-uhB32LZzEXrPCyHJN for typescript:S5976 rule
- AZ-uhCBpLZzEXrPCyHJ1 for typescript:S5976 rule

Generated by SonarQube Agent (task: e074e3ee-ff7c-4837-b6f7-d371b015b158)
@damien-urruty-sonarsource
damien-urruty-sonarsource force-pushed the remediate-master-20260907-050105-c6016a87 branch from c5c9a76 to 8c9f7f9 Compare September 25, 2026 06:41
@sonarqubecloud

Copy link
Copy Markdown

@damien-urruty-sonarsource
damien-urruty-sonarsource merged commit 53a9b3d into master Sep 25, 2026
20 checks passed
@damien-urruty-sonarsource
damien-urruty-sonarsource deleted the remediate-master-20260907-050105-c6016a87 branch September 25, 2026 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants