Skip to content
Open
74 changes: 74 additions & 0 deletions test/e2e/tests/deployments.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,87 @@
).should("exist");
});

it("Last selected deployment loads on initialization", () => {
// Regression test for https://github.com/posit-dev/publisher/issues/2473
// Verifies that the last selected deployment is restored after reload.

const deploymentTitle = "last-selection-test";

// Ensure Publisher is in the expected initial state
cy.expectInitialPublisherState();

// Create a deployment (this also selects it)
cy.createPCSDeployment(
Copy link
Collaborator

Choose a reason for hiding this comment

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

May have to clear up with deployment after the test runs to get other e2e tests passing

"static",
"index.html",
deploymentTitle,
(tomlFiles) => {
const { contents: config } = tomlFiles.config;
expect(config.title).to.equal(deploymentTitle);
},
);

// Verify deployment is currently selected (entrypoint-label visible, not select-deployment)
cy.retryWithBackoff(
() => cy.findInPublisherWebview('[data-automation="entrypoint-label"]'),
5,
500,
).should("exist");

// Reload the page to simulate VS Code restart
cy.reload();

// Re-open the Publisher sidebar (matching beforeEach pattern)
cy.getPublisherSidebarIcon().click();
cy.waitForPublisherIframe();
cy.debugIframes();

// Wait for the Publisher webview to fully initialize after reload.
// The extension needs time to: load saved state, restore last selection.
// Use a longer retry with more attempts to handle slow CI environments.
cy.retryWithBackoff(
() =>
cy.publisherWebview().then(($webview) => {
// Check if either entrypoint-label OR select-deployment is visible
// This tells us the webview has finished initializing
const entrypoint = $webview.find(
'[data-automation="entrypoint-label"]',
);
const selectBtn = $webview.find(
'[data-automation="select-deployment"]',
);
if (entrypoint.length > 0 || selectBtn.length > 0) {
return cy.wrap($webview);
}
return Cypress.$();
}),
15,
1000,
).should("exist");

// Now verify the last selected deployment is automatically loaded
// If working correctly: entrypoint-label should show with the deployment title
// If broken: select-deployment would show with "Select..." instead
cy.findInPublisherWebview('[data-automation="entrypoint-label"]')
.should("exist")
.and("contain.text", deploymentTitle);

// Also verify the deployment section is present
cy.findInPublisherWebview(
'[data-automation="publisher-deployment-section"]',
).should("exist");

// Explicit cleanup to ensure other tests aren't affected
cy.clearupDeployments("static");
});

// Unable to run this,
// as we will need to install the renv package - install.packages("renv")
// as well as call renv::restore(), before we can deploy. This will use
// the current version of R within our code-server image, so we'll have an
// extra bit of work when we want to change that version around to different
// ones.
it.skip("PCS ShinyApp Content Deployment", () => {

Check warning on line 135 in test/e2e/tests/deployments.cy.js

View workflow job for this annotation

GitHub Actions / e2e / e2e (preview)

Unexpected pending mocha test

Check warning on line 135 in test/e2e/tests/deployments.cy.js

View workflow job for this annotation

GitHub Actions / e2e / e2e (release)

Unexpected pending mocha test

Check warning on line 135 in test/e2e/tests/deployments.cy.js

View workflow job for this annotation

GitHub Actions / e2e / e2e (2025.03.0)

Unexpected pending mocha test

Check warning on line 135 in test/e2e/tests/deployments.cy.js

View workflow job for this annotation

GitHub Actions / e2e / e2e (2023.03.0)

Unexpected pending mocha test
cy.createPCSDeployment("shinyapp", "app.R", "ShinyApp", (tomlFiles) => {
const config = tomlFiles.config.contents;
expect(config.title).to.equal("ShinyApp");
Expand Down
32 changes: 24 additions & 8 deletions test/e2e/tests/error-err-config.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,18 @@ describe("Detect errors in config", () => {
cy.get(".quick-input-widget").should("be.visible");
cy.get(".quick-input-titlebar").should("have.text", "Select Deployment");

// select our error case
cy.get(".quick-input-widget")
.contains("Unknown Title • Error in quarto-project-8G2B")
.click();
// select our error case (retry to allow list to populate)
cy.retryWithBackoff(
() =>
cy.get("body", { timeout: 0 }).then(($body) => {
const match = $body.find(
'.quick-input-widget .monaco-list-row:contains("Unknown Title • Error in quarto-project-8G2B")',
);
return match.length > 0 ? cy.wrap(match) : Cypress.$();
}),
10,
500,
).click();

// confirm that the selector shows the error
cy.findUniqueInPublisherWebview(
Expand Down Expand Up @@ -73,10 +81,18 @@ describe("Detect errors in config", () => {
cy.get(".quick-input-widget").should("be.visible");
cy.get(".quick-input-titlebar").should("have.text", "Select Deployment");

// select our error case
cy.get(".quick-input-widget")
.contains("Unknown Title Due to Missing Config fastapi-simple-DHJL")
.click();
// select our error case (retry to allow list to populate)
cy.retryWithBackoff(
() =>
cy.get("body", { timeout: 0 }).then(($body) => {
const match = $body.find(
'.quick-input-widget .monaco-list-row:contains("Unknown Title Due to Missing Config fastapi-simple-DHJL")',
);
return match.length > 0 ? cy.wrap(match) : Cypress.$();
}),
10,
500,
).click();

// confirm that the selector shows the error
cy.findUniqueInPublisherWebview(
Expand Down
Loading