diff --git a/.github/workflows/pr-title-check.yml b/.github/workflows/pr-title-check.yml new file mode 100644 index 0000000000..78cddd6de7 --- /dev/null +++ b/.github/workflows/pr-title-check.yml @@ -0,0 +1,46 @@ +name: PR Title Check + +on: + pull_request: + types: + - opened + - edited + - synchronize + +jobs: + check-pr-title: + name: Validate PR Title + runs-on: ubuntu-latest + + steps: + - name: Check PR Title Format + run: | + PR_TITLE="${{ github.event.pull_request.title }}" + + # Rule 1: PR title must not be empty + if [ -z "$PR_TITLE" ]; then + echo "❌ PR title cannot be empty." + exit 1 + fi + + # Rule 2: PR title must follow Conventional Commits format + # Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert + PATTERN="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .+" + if ! echo "$PR_TITLE" | grep -Eq "$PATTERN"; then + echo "❌ PR title does not follow the required format." + echo "" + echo "Expected format: : " + echo " or: (scope): " + echo "" + echo "Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert" + echo "" + echo "Examples:" + echo " feat: add new block palette" + echo " fix: resolve audio issue" + echo " docs: update contributing guidelines" + echo "" + echo "Your title: \"$PR_TITLE\"" + exit 1 + fi + + echo "✅ PR title is valid: \"$PR_TITLE\"" diff --git a/cypress/e2e/main.cy.js b/cypress/e2e/main.cy.js index 7f95577f49..ac2b82059d 100644 --- a/cypress/e2e/main.cy.js +++ b/cypress/e2e/main.cy.js @@ -14,7 +14,9 @@ describe("MusicBlocks Application", () => { describe("Loading and Initial Render", () => { it("should display the loading animation and then the main content", () => { cy.get("#loading-image-container").should("be.visible"); - cy.contains("#loadingText", "Loading Complete!", { timeout: 20000 }).should("be.visible"); + cy.contains("#loadingText", "Loading Complete!", { timeout: 20000 }).should( + "be.visible" + ); cy.wait(10000); cy.get("#canvas", { timeout: 10000 }).should("be.visible"); }); @@ -27,7 +29,7 @@ describe("MusicBlocks Application", () => { describe("Audio Controls", () => { it("should have a functional play button", () => { cy.get("#play").should("be.visible").click(); - cy.window().then((win) => { + cy.window().then(win => { const audioContext = win.Tone.context; cy.wrap(audioContext.state).should("eq", "running"); }); @@ -81,9 +83,7 @@ describe("MusicBlocks Application", () => { }); it('should click the New File button and verify "New Project" appears', () => { - cy.get("#newFile > .material-icons") - .should("exist") - .and("be.visible"); + cy.get("#newFile > .material-icons").should("exist").and("be.visible"); cy.get("#newFile > .material-icons").click(); cy.wait(500); cy.contains("New project").should("be.visible"); @@ -99,7 +99,7 @@ describe("MusicBlocks Application", () => { "#Decrease\\ block\\ size > img", "#Increase\\ block\\ size > img" ]; - + bottomBarElements.forEach(selector => { cy.get(selector).should("exist").and("be.visible"); }); @@ -111,21 +111,14 @@ describe("MusicBlocks Application", () => { "tr > :nth-child(2) > img", "tr > :nth-child(3) > img" ]; - + sidebarElements.forEach(selector => { - cy.get(selector) - .should("exist") - .and("be.visible") - .click(); + cy.get(selector).should("exist").and("be.visible").click(); }); }); it("should verify that Grid, Clear, and Collapse elements exist and are visible", () => { - const elements = [ - "#Grid > img", - "#Clear", - "#Collapse > img" - ]; + const elements = ["#Grid > img", "#Clear", "#Collapse > img"]; elements.forEach(selector => { cy.get(selector).should("exist").and("be.visible"); }); @@ -149,12 +142,12 @@ describe("MusicBlocks Application", () => { .and("have.attr", "src") .and("not.be.empty"); - cy.get("#planet-iframe").then(($iframe) => { + cy.get("#planet-iframe").then($iframe => { const iframeSrc = $iframe.attr("src"); cy.log("Iframe source:", iframeSrc); }); - cy.window().then((win) => { + cy.window().then(win => { win.document.getElementById("planet-iframe").style.display = "block"; }); });