This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-7183-2388b8573836f3f1a84aa808ed7b3a999e3626bf
in repository https://gitbox.apache.org/repos/asf/texera.git

commit 64e978be9ae7983d402fd0ddf9034497f6a52a31
Author: Meng Wang <[email protected]>
AuthorDate: Fri Jul 31 17:21:21 2026 -0700

    test(amber): add unit test coverage for PublicProjectResource (#7183)
    
    ### What changes were proposed in this PR?
    
    Adds `PublicProjectResourceSpec`, the first spec for
    `PublicProjectResource`
    (previously ~0% coverage). It runs against embedded Postgres via
    `MockTexeraDB`,
    seeding a user + projects through the jOOQ DAOs, with 6 tests:
    
    - `getType` — reports a project with no public flag as `Private`.
    - `makePublic` — flags a project public; `getType` then reports
    `Public`.
    - `makePrivate` — reverts it; `getType` reports `Private` again.
    - `listPublicProjects` — empty when nothing is public; otherwise returns
    only the
    currently-public projects, with the joined project name and owner name.
    - `addPublicProjects` — grants the caller READ access to each listed
    project.
    
    Note: `addPublicProjects` is named as if it marks projects public, but
    the code
    actually inserts a `ProjectUserAccess` (READ) row per project and does
    not touch
    the public flag — the test asserts that observed behavior (the granted
    rows,
    `getType` still `Private`).
    
    ### Any related issues, documentation, discussions?
    
    Closes #7177.
    
    ### How was this PR tested?
    
    `sbt "WorkflowExecutionService/testOnly *PublicProjectResourceSpec"` — 6
    succeeded, 0 failed. `Test/scalafmtCheck` and `Test/scalafix --check`
    clean. Failure path verified by breaking an assertion (→ 1 failed,
    non-zero exit) and restoring.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 4.8 [1M context])
---
 .../user/project/PublicProjectResourceSpec.scala   | 146 +++++++++++++++++++++
 1 file changed, 146 insertions(+)

diff --git 
a/amber/src/test/scala/org/apache/texera/web/resource/dashboard/user/project/PublicProjectResourceSpec.scala
 
b/amber/src/test/scala/org/apache/texera/web/resource/dashboard/user/project/PublicProjectResourceSpec.scala
new file mode 100644
index 0000000000..4d532a9d44
--- /dev/null
+++ 
b/amber/src/test/scala/org/apache/texera/web/resource/dashboard/user/project/PublicProjectResourceSpec.scala
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.texera.web.resource.dashboard.user.project
+
+import org.apache.texera.auth.SessionUser
+import org.apache.texera.dao.MockTexeraDB
+import org.apache.texera.dao.jooq.generated.Tables.{PROJECT, 
PROJECT_USER_ACCESS, PUBLIC_PROJECT}
+import org.apache.texera.dao.jooq.generated.enums.{PrivilegeEnum, UserRoleEnum}
+import org.apache.texera.dao.jooq.generated.tables.daos.{ProjectDao, UserDao}
+import org.apache.texera.dao.jooq.generated.tables.pojos.{Project, User}
+import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach}
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+import java.util
+import java.util.UUID
+import scala.jdk.CollectionConverters._
+
+class PublicProjectResourceSpec
+    extends AnyFlatSpec
+    with Matchers
+    with BeforeAndAfterAll
+    with BeforeAndAfterEach
+    with MockTexeraDB {
+
+  // MockTexeraDB gives each suite its own database, so a fixed uid is 
isolated and reproducible.
+  private val testUid = 90001
+  private var projectDao: ProjectDao = _
+  private var sessionUser: SessionUser = _
+  private val resource = new PublicProjectResource
+
+  private def makeUser(uid: Int, name: String): User = {
+    val user = new User
+    user.setUid(uid)
+    user.setName(name)
+    user.setEmail(
+      s"public_project_spec_${uid}_${UUID.randomUUID().toString.substring(0, 
8)}@example.com"
+    )
+    user.setPassword("password")
+    user.setRole(UserRoleEnum.ADMIN)
+    user
+  }
+
+  override protected def beforeAll(): Unit = {
+    initializeDBAndReplaceDSLContext()
+    val user = makeUser(testUid, "public_project_owner")
+    new UserDao(getDSLContext.configuration()).insert(user)
+    sessionUser = new SessionUser(user)
+    projectDao = new ProjectDao(getDSLContext.configuration())
+  }
+
+  override protected def afterAll(): Unit = closeConnectionPool()
+
+  // Remove the per-test project rows (children before parents) after each 
test; the owner
+  // user seeded once in beforeAll is intentionally kept for the whole suite.
+  override protected def afterEach(): Unit = {
+    
getDSLContext.deleteFrom(PUBLIC_PROJECT).where(PUBLIC_PROJECT.UID.eq(testUid)).execute()
+    getDSLContext
+      .deleteFrom(PROJECT_USER_ACCESS)
+      .where(PROJECT_USER_ACCESS.UID.eq(testUid))
+      .execute()
+    
getDSLContext.deleteFrom(PROJECT).where(PROJECT.OWNER_ID.eq(testUid)).execute()
+  }
+
+  // Insert a project owned by the test user; the generated pid is populated 
on the pojo.
+  private def seedProject(name: String): Project = {
+    val project = new Project(null, name, null, Integer.valueOf(testUid), 
null, null)
+    projectDao.insert(project)
+    project
+  }
+
+  "getType" should "report a project without a public flag as Private" in {
+    val project = seedProject("p_private")
+    resource.getType(project.getPid) shouldBe "Private"
+  }
+
+  "makePublic" should "flag a project public so getType reports Public" in {
+    val project = seedProject("p_makepublic")
+    resource.makePublic(project.getPid, sessionUser)
+    resource.getType(project.getPid) shouldBe "Public"
+  }
+
+  "makePrivate" should "revert a public project so getType reports Private 
again" in {
+    val project = seedProject("p_makeprivate")
+    resource.makePublic(project.getPid, sessionUser)
+    resource.getType(project.getPid) shouldBe "Public"
+
+    resource.makePrivate(project.getPid)
+    resource.getType(project.getPid) shouldBe "Private"
+  }
+
+  "listPublicProjects" should "return an empty list when no project is public" 
in {
+    seedProject("p_still_private")
+    resource.listPublicProjects().asScala shouldBe empty
+  }
+
+  it should "return only the currently-public projects with their name and 
owner" in {
+    val publicProject = seedProject("p_public")
+    seedProject("p_hidden")
+    resource.makePublic(publicProject.getPid, sessionUser)
+
+    val listed = resource.listPublicProjects().asScala
+    listed.map(_.pid) shouldBe Seq(publicProject.getPid)
+    listed.head.name shouldBe "p_public"
+    listed.head.owner shouldBe "public_project_owner"
+  }
+
+  // NOTE: despite the name, addPublicProjects does NOT set the public flag — 
it grants the
+  // caller READ access to each project (a ProjectUserAccess row) and leaves 
getType Private.
+  "addPublicProjects" should "grant the caller READ access to each listed 
project" in {
+    val p1 = seedProject("p_add1")
+    val p2 = seedProject("p_add2")
+
+    resource.addPublicProjects(util.Arrays.asList(p1.getPid, p2.getPid), 
sessionUser)
+
+    val grantedPids = getDSLContext
+      .select(PROJECT_USER_ACCESS.PID)
+      .from(PROJECT_USER_ACCESS)
+      .where(
+        PROJECT_USER_ACCESS.UID
+          .eq(testUid)
+          .and(PROJECT_USER_ACCESS.PRIVILEGE.eq(PrivilegeEnum.READ))
+      )
+      .fetchInto(classOf[Integer])
+      .asScala
+    grantedPids should contain allOf (p1.getPid, p2.getPid)
+    resource.getType(p1.getPid) shouldBe "Private" // access grant is not the 
public flag
+  }
+}

Reply via email to