PromucFlow_constructor/app/client/cypress/scripts/cypress-local-setup.js

281 lines
8.7 KiB
JavaScript
Raw Normal View History

const { exec, execSync } = require("child_process");
const { existsSync, readFileSync, writeFileSync } = require("fs");
const path = require("path");
const prompt = require("prompt-sync")();
function isContainerRunning(containerName) {
try {
const output = execSync(
`docker ps --filter "name=^/${containerName}$" --format '{{.Names}}'`,
);
return output.length > 0;
} catch (error) {
return false;
}
}
// Helper function to execute commands and return a Promise
async function execCommand(command, options) {
return new Promise((resolve, reject) => {
exec(command, options, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve({ stdout, stderr });
}
});
});
}
function checkDockerCompose() {
try {
execSync("docker-compose --version", { stdio: "ignore" });
return true;
} catch (error) {
console.error(
"ERROR: docker-compose is not installed. Please install Docker Compose.",
);
process.exit(1);
}
}
async function runLocalServer() {
try {
let user_input = prompt(
`Do you wish to continue without setting up the local server with docker? (yes/no): `,
);
user_input = (user_input || "").trim().toLowerCase();
if (user_input === "yes" || user_input === "y") {
console.log(
"INFO",
"Continuing without setting up local backend docker based server.",
);
} else {
// Adjust the path to point to the correct directory
const dockerDir = path.join(__dirname, "../../../../deploy/docker");
if (!existsSync(dockerDir)) {
console.error(`ERROR: Directory ${dockerDir} does not exist.`);
process.exit(1); // Exit if the directory is missing
}
await checkDockerCompose(); // Ensure Docker Compose is available
console.log("INFO: Starting local server using Docker Compose...");
execSync(`cd ${dockerDir} && pwd && docker-compose up -d`, {
stdio: "inherit",
});
// Wait for the services to be fully up and running
let servicesRunning = false;
const maxRetries = 30;
const retryInterval = 7000; // 7 seconds
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const { stdout } = await execCommand("docker-compose ps", {
cwd: dockerDir,
});
if (stdout.includes("Up")) {
servicesRunning = true;
break;
}
} catch (error) {
console.error("ERROR: Error checking service status:", error.message);
process.exit(1); // Exit if checking service status fails
}
console.log(
`INFO: Waiting for services to be fully up and running... (attempt ${attempt}/${maxRetries})`,
);
await new Promise((resolve) => setTimeout(resolve, retryInterval));
}
if (servicesRunning) {
console.log("INFO: Local server is up and running.");
return true;
} else {
console.error(
"ERROR: Services did not become available within the expected time.",
);
process.exit(1); // Exit if services are not up
}
}
} catch (error) {
console.error("ERROR: Error starting local server:", error.message);
process.exit(1); // Exit if starting local server fails
}
}
function ensureTEDIsRunning() {
// Check if TED is running. If not, then ask user if they wish to pull and run the TED container
const isTedRunning = isContainerRunning("ted");
if (isTedRunning) {
console.log("INFO", "TED (TestEventDriver) is already running");
} else {
try {
let user_input = prompt(
"TED (TestEventDriver) is not running. Do you want to pull & run the latest Docker container for TED (TestEventDriver)? (yes/no): ",
);
user_input = user_input.trim().toLowerCase();
switch (user_input) {
case "yes":
case "y":
console.log(
"INFO",
"Running the Docker container for TED (TestEventDriver)",
);
try {
execSync(
"docker run --name ted --rm -d --pull always -p 2022:22 -p 5001:5001 -p 3306:3306 -p 28017:27017 -p 5433:5432 -p 25:25 -p 4200:4200 appsmith/test-event-driver",
{ stdio: "inherit" },
);
console.log(
"INFO",
"Please check https://github.com/appsmithorg/TestEventDriver for more details and functionalities of TED",
);
} catch (error) {
console.error("ERROR", `Error installing TED: ${error.message}`);
}
break;
case "no":
case "n":
console.log("INFO", "Proceeding without TED");
break;
default:
console.log("ERROR", "Invalid input. Please enter yes or no.");
process.exit(1);
}
} catch (error) {
console.error("ERROR", `Error: ${error.message}`);
process.exit(1);
}
}
}
async function checkIfAppsmithIsRunning(baseUrl) {
// Check if appsmith is running. If it's not running, check if we want the user to continue without it.
let isDevAppsmithAccessible;
try {
const response = await fetch(baseUrl);
isDevAppsmithAccessible = response.ok;
} catch (error) {
console.error(
"ERROR",
`Error checking availability of dev.appsmith.com: ${error.message}`,
);
isDevAppsmithAccessible = false;
}
if (!isDevAppsmithAccessible) {
let user_input = prompt(
`https://dev.appsmith.com is not accessible. Do you wish to continue without setting it up? (yes/no): `,
);
user_input = user_input.trim().toLowerCase();
switch (user_input) {
case "yes":
case "y":
console.log("INFO", "Continuing without setting up dev.appsmith.com");
break;
case "no":
case "n":
process.exit(1);
default:
console.log("ERROR", "Invalid input. Please enter yes or no.");
process.exit(1);
}
}
}
function getBaseUrl(repoRoot) {
try {
const cypressConfig = readFileSync(`${repoRoot}/cypress.config.ts`, "utf8");
const baseUrlMatch = cypressConfig.match(/baseUrl\s*:\s*"([^"]+)"/);
if (baseUrlMatch) {
baseUrl = baseUrlMatch[1];
console.log(
"INFO",
`Base url is ${baseUrl}. Please verify if it is correct. If not, please update it in cypress.config.ts file.`,
);
return baseUrl;
} else {
console.error(
"ERROR",
"Base url not found in cypress.config.ts. Please configure `baseUrl` property in cypress.config.ts file.",
);
process.exit(1);
}
} catch (err) {
if (err.code === "ENOENT") {
console.error("ERROR", "cypress.config.ts file not found");
} else {
console.error("ERROR", "Error reading cypress.config.ts file:", err);
}
process.exit(1);
}
}
function ensureCypressEnvFileExists(repoRoot) {
// Check if cypress.env.json file exists. If not, create it.
const filePath = `${repoRoot}/cypress.env.json`;
if (!existsSync(filePath)) {
const testEnvData = {
USERNAME: "testUser@test.com",
PASSWORD: "testPass",
TESTUSERNAME1: "viewerappsmith@test.com",
TESTPASSWORD1: "viewerPass",
TESTUSERNAME2: "developerappsmith@test.com",
TESTPASSWORD2: "developerPass",
};
writeFileSync(filePath, JSON.stringify(testEnvData, null, 2));
console.log("INFO", `${repoRoot}/cypress.env.json file created`);
} else {
console.log("INFO", `${repoRoot}/cypress.env.json file already exists`);
}
}
async function setupCypress() {
// Get the baseUrl from cypress.config.ts file
let repoRoot = path.join(__dirname, "..", "..");
let baseUrl = getBaseUrl(repoRoot);
await runLocalServer();
await checkIfAppsmithIsRunning(baseUrl);
// Install Cypress using yarn install on the app/client repository
console.log("INFO", "Installing Cypress..");
try {
execSync("yarn install", { cwd: `${repoRoot}` });
} catch (error) {
console.error("ERROR", `Error installing Cypress: ${error.message}`);
}
ensureCypressEnvFileExists(repoRoot);
console.log(
"INFO",
"Please add APPSMITH_GIT_ROOT=./container-volumes/git-storage into server-side .env for running Git cases locally along with the server.",
);
ensureTEDIsRunning();
console.log(
"INFO",
"Please start cypress using the command: npx cypress open",
);
console.log(
"INFO",
`In order to run single spec, please use the command: cd ${repoRoot} && npx cypress run --spec <specpath> --browser chrome`,
);
console.log(
"INFO",
"For more details check https://github.com/appsmithorg/appsmith/blob/master/contributions/ClientSetup.md#integration-tests",
);
}
async function main() {
await setupCypress();
process.exit(0);
}
main();