Skip to content

Commit

Permalink
Added more automation. Updated scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
vhuseinova-msft committed Sep 20, 2024
1 parent 33d27c3 commit 77f4ba2
Show file tree
Hide file tree
Showing 22 changed files with 755 additions and 147 deletions.
84 changes: 59 additions & 25 deletions scripts/ui-library-run-playwright-tests.mjs
Original file line number Diff line number Diff line change
@@ -1,58 +1,92 @@
// Script to automate testing for various chat UI library samples.
// This script prompts the user to select a project and optionally installs dependencies
// before running end-to-end tests using Playwright. The test will open a browser window and
// run the initial steps for the samples. The user can continue testing in the same window.
// The session is set to be closed after 10 minutes.
// Please make sure to CLOSE the browser tab or window after the test is complete.
// Otherwise, the process will continue running and you might need to kill it manually.
//
// Usage: Change to the scripts directory
// Run `node ui-library-run-playwright-tests.mjs [--install]`
// Optionally, use `--install` to install the dependencies before running the tests.

import { exec } from "child_process";
import { select } from "@inquirer/prompts";

// Define the options
// The options for the user to choose from
const options = [
{
name: "ui-library-starting-with-chat-stateful",
value: "ui-library-starting-with-chat-stateful",
},
{
name: "ui-library-quickstart-teams-interop-meeting-chat",
value: "ui-library-quickstart-teams-interop-meeting-chat",
},
{
value: "ui-library-filesharing-chat-composite",
},
{
value: "ui-library-filesharing-ui-components",
},
{ value: "ui-library-quickstart-composites-with-dependency-isolation" },
];

// Prompt the user to choose an option
const promptUser = async () => {
const promptUser = async (installDependencies) => {
const answer = await select({
message: "Choose a quickstart to set up:",
message:
"Choose a quickstart to set up below. You ALWAYS need to close the tab or browser where test is run to finish the test. Otherwise, you will stuck with running process for the app.",
choices: options.map((option) => ({
name: option.name,
value: option.value,
})),
});

const selectedOption = answer;

// Define the commands for each option
// add dependencies install command based on the user input
const appDepsInstall = installDependencies ? "&& npm install" : "";
const appAndAPIDepsInstall = installDependencies
? "&& npm install && cd ./app && npm install && cd ../api && npm install && cd .."
: "";

// The commands for each option
const commands = {
"ui-library-starting-with-chat-stateful":
"cd ../ui-library-starting-with-chat-stateful && npm run test:e2e",
"ui-library-quickstart-teams-interop-meeting-chat":
"cd ../ui-library-quickstart-teams-interop-meeting-chat && npm run test:e2e",
"ui-library-starting-with-chat-stateful": `cd ../ui-library-starting-with-chat-stateful ${appDepsInstall} && npm run test:e2e`,
"ui-library-quickstart-teams-interop-meeting-chat": `cd ../ui-library-quickstart-teams-interop-meeting-chat ${appDepsInstall} && npm run test:e2e`,
"ui-library-filesharing-chat-composite": `cd ../ui-library-filesharing-chat-composite ${appAndAPIDepsInstall} && npm run test:e2e`,
"ui-library-filesharing-ui-components": `cd ../ui-library-filesharing-ui-components ${appAndAPIDepsInstall} && npm run test:e2e`,
"ui-library-quickstart-composites-with-dependency-isolation": `cd ../ui-library-quickstart-composites-with-dependency-isolation ${appDepsInstall} && npm run test:e2e`,
};

// Run the command for the selected option
const command = commands[selectedOption];
if (command) {
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing command: ${error.message}`);
return;
}
if (stderr) {
console.error(`Error output: ${stderr}`);
return;
}
console.log(`Command output: ${stdout}`);
console.log(`Executing command: ${command}`);
const child = exec(command);

// Capture and log stdout
child.stdout.on("data", (data) => {
console.log(`${data}`);
});

// Capture and log stderr
child.stderr.on("data", (data) => {
console.error(`${data}`);
});

// Handle command completion
child.on("close", (code) => {
console.log(`Command finished with exit code ${code}`);
});
} else {
console.error("Invalid option selected.");
}
};

// Run the prompt
promptUser().catch((error) => {
console.error(`Error: ${error.message}`);
});
const runPrompt = async (installDependencies) => {
await promptUser(installDependencies).catch((error) => {
console.error(`Error: ${error.message}`);
});
};

// Check if the script should also install dependencies
runPrompt(process.argv.includes("--install"));
144 changes: 77 additions & 67 deletions scripts/ui-library-set-variables-values.mjs
Original file line number Diff line number Diff line change
@@ -1,38 +1,15 @@
// Script to automate updating variables in various UI library sample files.
// This script prompts the user for input values and updates specified variables
// in the listed files. It handles both single-line and multi-line strings, ensuring
// that multi-line strings are updated correctly by removing the next line if needed.
//
// Usage: Change to the scripts directory
// Run `node ui-library-set-variables-values.mjs`
// Optionally, use `--restore` to restore default values

import fs from "fs";
import readline from "readline";

// Function to update the file content
function updateFileContent(filePath, replacements) {
fs.readFile(filePath, "utf8", (err, data) => {
if (err) {
console.error(`Error reading file ${filePath}:`, err);
return;
}

let updatedContent = data
.split("\n")
.map((line) => {
for (const [pattern, value] of Object.entries(replacements)) {
// console.log(`line`, line);
if (line.includes(pattern)) {
console.log(`Replacing ${pattern} with ${value}`);
return updateLine(line, value);
}
}
return line;
})
.join("\n");

fs.writeFile(filePath, updatedContent, "utf8", (err) => {
if (err) {
console.error(`Error writing file ${filePath}:`, err);
} else {
console.log(`File ${filePath} updated successfully.`);
}
});
});
}

// List of files to be updated
const filesToUpdate = [
// ui-library-filesharing-chat-composite
Expand All @@ -49,9 +26,31 @@ const filesToUpdate = [
// ui-library-quickstart-teams-interop-meeting-chat
"../ui-library-quickstart-teams-interop-meeting-chat/src/App.tsx",

// ui-library-quickstart-composites-with-dependency-isolation
"../ui-library-quickstart-composites-with-dependency-isolation/src/App.tsx",

// Add more file paths as needed
];

// Make changes in the line
const updateLine = (line, value, isMultiline) => {
const lastChar = line[line.length - 1];
// check if last char is a comma or semicolon to add it back if needed
const shouldAddLastChar = /[,;]/.test(lastChar);
// check if the line uses equal sign or colon
const usesEqualSign = line.includes(" =");
// get the key from the line
const [key] = usesEqualSign ? line.split("=") : line.split(":");
// return the updated line
// {usesEqualSign ? "=" : ":"} - use "=" vs ":" depending which one was already used in the line
// shouldAddLastChar ? lastChar : isMultiline && usesEqualSign ? ";" : "" -
// if there was a comma or semicolon at the end of the line, add it back.
// For multiline strings that use equal sign, always add a semicolon at the end
return `${key}${usesEqualSign ? "=" : ":"} \"${value}\"${
shouldAddLastChar ? lastChar : isMultiline && usesEqualSign ? ";" : ""
}`;
};

// Function to prompt the user for input
function promptUser(query) {
const rl = readline.createInterface({
Expand Down Expand Up @@ -94,11 +93,10 @@ async function main() {
"const TEAMS_MEETING_LINK =": teamsMeetingLink,
"const THREAD_ID =": threadId,
};
filesToUpdate.forEach((filePath) => {
updateFileContent(filePath, replacements);
});
updateFiles(filesToUpdate, replacements);
}

// Default values to restore the files
const defaultValues = {
"const ENDPOINT_URL =": "<Azure Communication Services Resource Endpoint>",
"const TOKEN =": "<Azure Communication Services Resource Access Token>",
Expand All @@ -109,44 +107,56 @@ const defaultValues = {
"const THREAD_ID =": "<Get thread id from chat service>",
};

const updateLine = (line, value) => {
const lastChar = line[line.length - 1];
// check if last char is a comma or semicolon to add it back if needed
const shouldAddLastChar = /[,;]/.test(lastChar);
const usesEqualSign = line.includes(" = ");

const [key] = usesEqualSign ? line.split("=") : line.split(":");
return `${key}${usesEqualSign ? "=" : ":"} \"${value}\"${
shouldAddLastChar ? lastChar : ""
}`;
};

// Function to restore files from backups
function restoreBackups() {
filesToUpdate.forEach((filePath) => {
const currentContent = fs.readFileSync(filePath, "utf8").split("\n");
const patterns = Object.keys(defaultValues);

const restoredContent = currentContent
.map((line) => {
const matchingPattern = patterns.find((pattern) =>
line.includes(pattern)
);
if (matchingPattern) {
return updateLine(line, defaultValues[matchingPattern]);
function updateFiles(files, replacements) {
files.forEach((filePath) => {
fs.readFile(filePath, "utf8", (err, data) => {
if (err) {
console.error(`Error reading file ${filePath}:`, err);
return;
}
// delete the next line after the update if it's multiLine string
let shouldDeleteNextLine = false;

let updatedContent = data
.split("\n")
.map((line) => {
for (const [pattern, value] of Object.entries(replacements)) {
if (shouldDeleteNextLine) {
// we don't need this line anymore
shouldDeleteNextLine = false;
return "[TO BE REMOVED]";
}
if (line.includes(pattern)) {
// check for multiLine string
if (
line[line.length - 1] === ":" ||
line[line.length - 1] === "="
) {
shouldDeleteNextLine = true;
}
return updateLine(line, value, shouldDeleteNextLine);
}
}
return line;
})
.filter((line) => line !== "[TO BE REMOVED]")
.join("\n");

fs.writeFile(filePath, updatedContent, "utf8", (err) => {
if (err) {
console.error(`Error writing file ${filePath}:`, err);
} else {
console.log(`File ${filePath} updated successfully.`);
}
return line;
})
.join("\n");

fs.writeFileSync(filePath, restoredContent, "utf8");
console.log(`Constants in ${filePath} restored to default values.`);
});
});
});
}

// Check if the script should restore backups
if (process.argv.includes("--restore")) {
restoreBackups();
// restoreBackups();
updateFiles(filesToUpdate, defaultValues);
} else {
main();
}
4 changes: 2 additions & 2 deletions ui-library-filesharing-chat-composite/app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ function App(): JSX.Element {
userId: fromFlatCommunicationIdentifier(
USER_ID
) as CommunicationUserIdentifier,
DISPLAY_NAME,
displayName: DISPLAY_NAME,
credential,
THREAD_ID,
threadId: THREAD_ID,
}),
[USER_ID, DISPLAY_NAME, credential, THREAD_ID]
);
Expand Down
Loading

0 comments on commit 77f4ba2

Please sign in to comment.