Skip to content

Conversation

@pandeymangg
Copy link
Contributor

Adds tests for the js package code and the actions for testing, sonarqube scan analysis and releasing the package

@coderabbitai
Copy link

coderabbitai bot commented Sep 24, 2025

Walkthrough

Adds GitHub Actions workflows: build, test, SonarQube, and release (Node.js 22.x, pnpm, frozen lockfile; release publishes packages/js to npm using a secret token and --provenance). Adds sonar-project.properties and VSCode SonarLint connected-mode settings. Introduces test and coverage scripts at root and in packages/js, adds vitest and @vitest/coverage-v8, updates vite, and adds Vitest test configuration to vite.config.ts. Adds comprehensive unit tests for the JS proxy and loader (packages/js/src/*.test.ts) and new TurboRepo tasks: test, test:coverage, @formbricks/js:test, and playground:build.

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly summarizes the main additions of this pull request by noting the inclusion of tests, SonarQube configuration, and workflows, which directly reflects the files and functionality introduced.
Description Check ✅ Passed The description clearly states that tests, testing workflows, SonarQube scanning, and release actions are being added, which aligns directly with the modifications in the changeset.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35ae0d4 and c63d38f.

📒 Files selected for processing (2)
  • .github/workflows/sonarqube.yml (1 hunks)
  • .github/workflows/test.yml (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: pandeymangg
PR: formbricks/js#6
File: turbo.json:20-23
Timestamp: 2025-09-24T16:57:19.802Z
Learning: Package-scoped task names like "formbricks/js:test" are valid and functional syntax in Turborepo's root turbo.json configuration, contrary to previous understanding that task keys must be plain task names.
Learnt from: pandeymangg
PR: formbricks/js#6
File: .github/workflows/build.yml:14-16
Timestamp: 2025-09-24T16:54:10.943Z
Learning: For the formbricks/js repository, the maintainer prefers to keep GitHub Actions build workflows simple with a single Node.js version rather than using matrix strategies to test multiple Node.js versions.
📚 Learning: 2025-09-24T16:54:10.943Z
Learnt from: pandeymangg
PR: formbricks/js#6
File: .github/workflows/build.yml:14-16
Timestamp: 2025-09-24T16:54:10.943Z
Learning: For the formbricks/js repository, the maintainer prefers to keep GitHub Actions build workflows simple with a single Node.js version rather than using matrix strategies to test multiple Node.js versions.

Applied to files:

  • .github/workflows/test.yml
🔇 Additional comments (4)
.github/workflows/test.yml (1)

18-39: Workflow setup looks solid.

Nice job keeping the runner steps lean and aligned with our single Node.js 22.x preference while still locking installs and running the pnpm test suite end to end.

.github/workflows/sonarqube.yml (3)

13-46: Fix SonarCloud job: wrong action + missing fork guard block the scan

Still unresolved from the earlier review: sonar-project.properties declares sonar.organization, so this job is clearly meant for SonarCloud, yet it keeps the self-hosted SonarQube action and omits SONAR_HOST_URL. The workflow will fail as soon as it reaches the scan step. Additionally, without guarding against forked PRs, the job is triggered where SONAR_TOKEN is unavailable, so fork contributions hit a hard failure too. Please switch to the SonarCloud GitHub Action and add the fork guard so the scan only runs when secrets exist.

   sonarqube:
     name: SonarQube
     runs-on: ubuntu-latest
+    if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
@@
-      - name: SonarQube Scan
-        uses: SonarSource/sonarqube-scan-action@2500896589ef8f7247069a56136f8dc177c27ccf
+      - name: SonarCloud Scan
+        uses: SonarSource/sonarcloud-github-action@v2
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

24-26: Fetch full git history for accurate Sonar analysis

SonarCloud expects full history to compute blame and decorate PRs; with the default shallow checkout the analysis lacks that data. Please set fetch-depth: 0 on the checkout step as previously requested.

       - name: Checkout code
         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          fetch-depth: 0

27-34: Enable pnpm caching on setup-node

Reiterating the earlier nit: enabling the built-in pnpm cache on actions/setup-node saves minutes on every run.

       - name: Setup Node.js 22.x
         uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
         with:
           node-version: 22.x
+          cache: pnpm

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 544aa92 and e83eea2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • .github/workflows/build.yml (1 hunks)
  • .github/workflows/release.yml (1 hunks)
  • .github/workflows/sonarqube.yml (1 hunks)
  • .github/workflows/test.yml (1 hunks)
  • .vscode/settings.json (1 hunks)
  • package.json (1 hunks)
  • packages/js/package.json (1 hunks)
  • packages/js/src/__tests__/index.test.ts (1 hunks)
  • packages/js/src/__tests__/load-formbricks.test.ts (1 hunks)
  • packages/js/src/__tests__/setup.ts (1 hunks)
  • packages/js/vite.config.ts (2 hunks)
  • sonar-project.properties (1 hunks)
  • turbo.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/js/src/__tests__/load-formbricks.test.ts (1)
packages/js/src/lib/load-formbricks.ts (1)
  • loadFormbricksToProxy (119-130)
🔇 Additional comments (5)
packages/js/vite.config.ts (2)

2-2: Correct import for Vitest config.

Switching to vitest/config is appropriate to enable the test block.


19-24: DTS plugin usage looks good.

rollupTypes: true and bundledPackages are set correctly for publishing types.

.vscode/settings.json (1)

7-10: SonarLint connected mode config LGTM.

Connection and project key entries are correctly placed at root.

package.json (1)

9-11: Approve Turbo test scripts configuration
Turbo tasks "test" and "test:coverage" are defined in turbo.json (lines 29, 32) and implemented in packages/js/package.json (lines 40–41).

packages/js/src/__tests__/load-formbricks.test.ts (1)

115-137: Nice coverage of script injection and setup path

Validates script attributes and that setup is called; good end-to-end behavior check.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e83eea2 and 9d16cab.

📒 Files selected for processing (4)
  • .github/workflows/build.yml (1 hunks)
  • .github/workflows/release.yml (1 hunks)
  • .github/workflows/sonarqube.yml (1 hunks)
  • .github/workflows/test.yml (1 hunks)
🔇 Additional comments (10)
.github/workflows/release.yml (4)

18-23: Enable pnpm cache and always-auth on setup-node

Speeds installs and ensures npm auth on all requests.

       - name: Setup Node.js 22.x
         uses: actions/setup-node@v4
         with:
           node-version: 22.x
           registry-url: "https://registry.npmjs.org"
+          cache: "pnpm"
+          always-auth: true

24-26: Pin pnpm runtime version for reproducibility

Prevents CI breakage on new pnpm releases.

       - name: Install pnpm
-        uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
+        uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
+        with:
+          version: 9

30-34: Use working-directory instead of cd for build

More idiomatic and avoids path/subshell pitfalls.

-      - name: Build package
-        run: |
-          cd packages/js
-          pnpm build
+      - name: Build package
+        working-directory: packages/js
+        run: pnpm build

38-43: Add version guard and use working-directory for publish

Prevents publishing when tag and package.json version diverge; simplifies path handling.

-      - name: Publish to npm
-        run: |
-          cd packages/js
-          npm publish --access public --provenance
-        env:
-          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+      - name: Verify tag matches package version
+        id: version_check
+        working-directory: packages/js
+        run: |
+          PKG_VERSION=$(node -p "require('./package.json').version")
+          TAG="${GITHUB_REF#refs/tags/}"
+          if [ "$PKG_VERSION" != "$TAG" ] && [ "v$PKG_VERSION" != "$TAG" ]; then
+            echo "Release tag ($TAG) does not match packages/js version ($PKG_VERSION)"
+            exit 1
+          fi
+
+      - name: Publish to npm
+        if: ${{ success() }}
+        working-directory: packages/js
+        run: npm publish --access public --provenance
+        env:
+          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
.github/workflows/build.yml (2)

14-25: Add Node version matrix and pnpm cache

Build against supported Node versions and speed up CI.

 jobs:
   build:
     runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        node: [18.x, 20.x, 22.x]
@@
-      - name: Setup Node.js 22.x
+      - name: Setup Node.js
         uses: actions/setup-node@v4
         with:
-          node-version: 22.x
+          node-version: ${{ matrix.node }}
+          cache: 'pnpm'

26-27: Pin pnpm runtime version

Avoids surprises from pnpm upgrades.

       - name: Install pnpm
-        uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
+        uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
+        with:
+          version: 9
.github/workflows/test.yml (2)

14-25: Test on Node matrix and enable pnpm cache

Covers consumer environments and speeds installs.

 jobs:
   test:
     runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        node: [18.x, 20.x, 22.x]
@@
-      - name: Setup Node.js 22.x
+      - name: Setup Node.js
         uses: actions/setup-node@v4
         with:
-          node-version: 22.x
+          node-version: ${{ matrix.node }}
+          cache: 'pnpm'

25-26: Pin pnpm runtime version

Lock pnpm version for reproducible CI.

       - name: Install pnpm
-        uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
+        uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
+        with:
+          version: 9
.github/workflows/sonarqube.yml (2)

13-40: Switch to SonarCloud action and gate forked PRs (or add SONAR_HOST_URL for SonarQube)

Current setup mixes SonarCloud properties with SonarQube action and lacks fork-PR guard for secrets.

Option A (SonarCloud, recommended):

 jobs:
   sonarqube:
     name: SonarQube
     runs-on: ubuntu-latest
+    if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
@@
-      - name: SonarQube Scan
-        uses: SonarSource/sonarqube-scan-action@2500896589ef8f7247069a56136f8dc177c27ccf
+      - name: SonarCloud Scan
+        uses: SonarSource/sonarcloud-github-action@v2
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

Option B (Self-hosted SonarQube):

 jobs:
   sonarqube:
     name: SonarQube
     runs-on: ubuntu-latest
+    if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
@@
       - name: SonarQube Scan
         uses: SonarSource/sonarqube-scan-action@2500896589ef8f7247069a56136f8dc177c27ccf
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

32-35: Verify coverage report path
sonar.javascript.lcov.reportPaths is set to packages/js/coverage/lcov.info; run pnpm test:coverage and confirm the lcov.info is generated there (or update the path/config if it’s emitted elsewhere).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d16cab and d4f6a44.

📒 Files selected for processing (2)
  • packages/js/src/index.test.ts (1 hunks)
  • packages/js/src/lib/load-formbricks.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: pandeymangg
PR: formbricks/js#6
File: .github/workflows/build.yml:14-16
Timestamp: 2025-09-24T16:54:10.943Z
Learning: For the formbricks/js repository, the maintainer prefers to keep GitHub Actions build workflows simple with a single Node.js version rather than using matrix strategies to test multiple Node.js versions.
🧬 Code graph analysis (1)
packages/js/src/lib/load-formbricks.test.ts (1)
packages/js/src/lib/load-formbricks.ts (1)
  • loadFormbricksToProxy (119-130)
🔇 Additional comments (6)
packages/js/src/index.test.ts (5)

4-6: Good ESM‑safe module mock (hoisted)
Mock is declared before importing SUT; Vitest will hoist it. Looks correct.


12-20: Typed mock extraction and reset look solid
Using vi.mocked and resetting resolved value in beforeEach is clean and reliable.


149-160: Dynamic method forwarding is covered well
Good validation of arbitrary method passthrough via the proxy.


180-202: Concurrency behavior check LGTM
Parallel calls with Promise.all and call count assertions are appropriate.


124-127: Clarify init support
The proxy handler dynamically forwards init via loadFormbricksToProxy — no explicit export needed. Keep this test if init remains supported; otherwise remove it.

packages/js/src/lib/load-formbricks.test.ts (1)

247-256: Queueing warning verified
Accurately asserts the warn message and queuing behavior pre‑init.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d4f6a44 and 778b615.

📒 Files selected for processing (4)
  • .github/workflows/build.yml (1 hunks)
  • .github/workflows/release.yml (1 hunks)
  • packages/js/src/lib/load-formbricks.test.ts (1 hunks)
  • sonar-project.properties (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-09-24T16:54:20.602Z
Learnt from: pandeymangg
PR: formbricks/js#6
File: .github/workflows/release.yml:30-34
Timestamp: 2025-09-24T16:54:20.602Z
Learning: In the formbricks/js repository, the user pandeymangg prefers using `cd` commands in GitHub Actions workflow run steps rather than using the `working-directory` attribute, even when it might be considered less idiomatic.

Applied to files:

  • .github/workflows/release.yml
  • .github/workflows/build.yml
📚 Learning: 2025-09-24T17:04:00.699Z
Learnt from: pandeymangg
PR: formbricks/js#6
File: packages/js/src/lib/load-formbricks.test.ts:96-114
Timestamp: 2025-09-24T17:04:00.699Z
Learning: The formbricks/js project uses happy-dom as the test environment in Vitest configuration, not jsdom. This is configured in packages/js/vite.config.ts and works well for DOM-dependent tests.

Applied to files:

  • packages/js/src/lib/load-formbricks.test.ts
📚 Learning: 2025-09-24T17:04:00.699Z
Learnt from: pandeymangg
PR: formbricks/js#6
File: packages/js/src/lib/load-formbricks.test.ts:96-114
Timestamp: 2025-09-24T17:04:00.699Z
Learning: The formbricks/js project uses happy-dom as the test environment in Vitest configuration (packages/js/vite.config.ts), not jsdom. This configuration works well for DOM-dependent tests and is faster than jsdom.

Applied to files:

  • packages/js/src/lib/load-formbricks.test.ts
📚 Learning: 2025-09-24T17:03:14.121Z
Learnt from: pandeymangg
PR: formbricks/js#6
File: packages/js/src/index.test.ts:27-103
Timestamp: 2025-09-24T17:03:14.121Z
Learning: In packages/js/src/index.test.ts, the maintainer prefers individual test functions for proxy-forwarding tests rather than table-driven tests, valuing explicit and independently readable test cases.

Applied to files:

  • packages/js/src/lib/load-formbricks.test.ts
📚 Learning: 2025-09-24T16:54:10.943Z
Learnt from: pandeymangg
PR: formbricks/js#6
File: .github/workflows/build.yml:14-16
Timestamp: 2025-09-24T16:54:10.943Z
Learning: For the formbricks/js repository, the maintainer prefers to keep GitHub Actions build workflows simple with a single Node.js version rather than using matrix strategies to test multiple Node.js versions.

Applied to files:

  • .github/workflows/build.yml
🧬 Code graph analysis (1)
packages/js/src/lib/load-formbricks.test.ts (1)
packages/js/src/lib/load-formbricks.ts (1)
  • loadFormbricksToProxy (119-130)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (8)
.github/workflows/release.yml (1)

48-52: Add a tag vs. package version guard before publishing.

Publishing without confirming that the release tag matches packages/js/package.json lets an incorrect artifact hit npm and is painful to roll back. Please fail fast if the versions diverge.

       - name: Run tests
         run: pnpm test:coverage

+      - name: Verify tag matches package version
+        run: |
+          cd packages/js
+          PKG_VERSION=$(node -p "require('./package.json').version")
+          TAG="${GITHUB_REF##refs/tags/}"
+          if [ "$PKG_VERSION" != "$TAG" ] && [ "v$PKG_VERSION" != "$TAG" ]; then
+            echo "Release tag ($TAG) does not match packages/js version ($PKG_VERSION)"
+            exit 1
+          fi
+
       - name: Publish to npm
         run: |
           cd packages/js
           npm publish --access public --provenance
         env:
sonar-project.properties (2)

2-3: Confirm Sonar project key/org

Verify sonar.projectKey and sonar.organization match your SonarCloud project to avoid “project not found” in CI.


16-19: Remove deprecated TS coverage key
sonar.javascript.lcov.reportPaths covers both JavaScript and TypeScript coverage; sonar.typescript.lcov.reportPaths is deprecated.

Likely an incorrect or invalid review comment.

packages/js/src/lib/load-formbricks.test.ts (5)

167-183: Also assert no duplicate script injection when already loaded

Strengthen the test by asserting the script count remains unchanged.

const before = document.querySelectorAll('script[src*="formbricks"]').length;
await loadFormbricksToProxy("setup", setupArgs);
const after = document.querySelectorAll('script[src*="formbricks"]').length;
expect(after).toBe(before);

227-244: Make console error assertion resilient to minor message changes

-        expect(consoleSpy).toHaveBeenCalledWith(
-          "🧱 Formbricks - Error: setup failed",
-          expect.any(Error)
-        );
+        const [msg, err] = consoleSpy.mock.calls[0];
+        expect(String(msg)).toMatch(/🧱 Formbricks - Error: setup failed/i);
+        expect(err).toBeInstanceOf(Error);

80-87: Use Vitest fake timers instead of overriding global setTimeout

Replace the helper with fake timers to avoid global mutation and double-restore.

-const mockSetTimeoutImmediate = () => {
-  const originalSetTimeout = globalThis.setTimeout;
-  vi.spyOn(globalThis, "setTimeout").mockImplementation(
-    immediateTimeoutCallback
-  );
-  return originalSetTimeout;
-};
+// Use vi.useFakeTimers()/vi.useRealTimers() within tests that need timer control.

3-5: Strongly type loadFormbricksToProxy instead of any

Use a type-only import of the function type.

-import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
+import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
+type LoadFormbricksToProxyFn = typeof import("./load-formbricks").loadFormbricksToProxy;
 
 // We need to import the module after each reset
-let loadFormbricksToProxy: any;
+let loadFormbricksToProxy: LoadFormbricksToProxyFn;

197-207: Refactor timeout test to fake timers (no manual restore)

-        const originalSetTimeout = mockSetTimeoutImmediate();
-
-        await loadFormbricksToProxy("setup", setupArgs);
-
-        expect(consoleSpy).toHaveBeenCalledWith(
-          "🧱 Formbricks - Error: Failed to load Formbricks SDK"
-        );
-
-        // Restore setTimeout
-        globalThis.setTimeout = originalSetTimeout;
+        vi.useFakeTimers();
+        await loadFormbricksToProxy("setup", setupArgs);
+        vi.runAllTimers();
+        expect(consoleSpy).toHaveBeenCalledWith(
+          "🧱 Formbricks - Error: Failed to load Formbricks SDK"
+        );
+        vi.useRealTimers();

@sonarqubecloud
Copy link

Copy link
Member

@mattinannt mattinannt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good now; thanks for making the changes :-)

@pandeymangg pandeymangg added this pull request to the merge queue Sep 25, 2025
Merged via the queue into main with commit 0288b21 Sep 25, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants