// Node.js script that implements an Appium client which will launch // Simply Sign Desktop app and log a user in. Once logged in it should // be possible to use tools like signtool.exe to sign Windows EXE/MSI files // with the Certum certificate. import { Key, remote } from 'webdriverio'; import { exec } from 'child_process'; import { TOTP } from 'totp-generator'; async function screenshot(driver, filename) { // uncomment to save .png screenshots //await driver.saveScreenshot(filename); return } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function executeCommand(command) { try { let { stdout, stderr } = await exec(command); return stdout; } catch (error) { console.error(`Error executing command: ${command}`); console.error(`Error details: ${error}`); throw error; } } async function runSSD() { const opts = { port: 4723, logLevel: "silent", capabilities: { platformName: "Windows", "appium:app": "C:\\Program Files\\Certum\\SimplySign Desktop\\SimplySignDesktop.exe", "appium:automationName": "Windows", }, }; let driver; try { driver = await remote(opts); // Github Actions Win ARM64 is stuck on a OOB screen that steals focus // These enter / escapes should dismiss it. const runner_arch = process.env.RUNNER_ARCH; if ( runner_arch === "ARM64" ) { console.log('Running on ARM64...'); //await sleep(3000); // Pause execution for 3 seconds //await screenshot(driver, 'oob1.png'); //await driver.sendKeys([Key.Enter]); //await sleep(3000); // Pause execution for 3 seconds //await screenshot(driver, 'oob2.png'); //await driver.sendKeys([Key.Enter]); //await sleep(3000); // Pause execution for 3 seconds //await screenshot(driver, 'oob3.png'); //await driver.sendKeys([Key.Escape]); //await screenshot(driver, 'oob6.png'); } else { console.log('NOT running on ARM64'); } // Execute SSD again to open login dialog exec('"C:\\Program Files\\Certum\\SimplySign Desktop\\SimplySignDesktop.exe"', (error, stdout, stderr) => { if (error) { console.error(`exec error: ${error}`); return; } }); await sleep(3000); // Login const windows = await driver.getWindowHandles(); const login_window = windows[0] await driver.switchWindow(login_window); //await screenshot(driver, 'login01.png'); const id_value = 'jay0lee@gmail.com'; const id_arr = [...id_value]; await driver.sendKeys(id_arr); //await screenshot(driver, 'login02.png'); await driver.sendKeys([Key.Tab]); console.log('Our secret is ' + process.env.TOTP_SECRET.length + ' characters.'); // We wait until the last possible second to generate // our TOTP to ensure it's still valid. const { otp } = await TOTP.generate(process.env.TOTP_SECRET, {algorithm: 'SHA-256'}); console.log('Our token is ' + otp.length + ' characters.'); const otp_arr = [...otp]; await driver.sendKeys(otp_arr); //await screenshot(driver, 'login03.png'); await driver.sendKeys([Key.Enter]); // TODO: it's expected that on successful login the window // will close and these screenshots will error out. Figure // out how to handle that gracefully. await screenshot(driver, 'login04.png'); await sleep(500); await screenshot(driver, 'login05.png'); await sleep(500); await screenshot(driver, 'login06.png'); await sleep(500); await screenshot(driver, 'login07.png'); await sleep(500); await screenshot(driver, 'login08.png'); await sleep(500); await screenshot(driver, 'login09.png'); await sleep(500); await screenshot(driver, 'login10.png'); await sleep(500); await screenshot(driver, 'login11.png'); await sleep(500); await screenshot(driver, 'login12.png'); } catch (error) { console.error(error); //console.error("Error during Appium run:"); } // INTENTIONAL Keep driver open so tray icon for Certum doesn't close // finally { // if (driver) { // await driver.deleteSession(); // Close the Appium session // } //} } runSSD();