Skip to content

Commit

Permalink
feat: automaattitestin sisäänkirjautuminen (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
haapamakim authored Jan 31, 2022
1 parent c51b84d commit 1834f8d
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 60 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120
81 changes: 28 additions & 53 deletions deployment/bin/setupEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,36 +97,39 @@ export type HassuSSMParameters = {
SMTPSecret: string;
};

async function readParametersForEnv(environment: string, region: Region): Promise<HassuSSMParameters> {
export async function readParametersByPath(path: string, region: Region): Promise<Record<string, string>> {
let ssmClient: SSMClient;
if (region === Region.EU_WEST_1) {
ssmClient = euWestSSMClient;
} else {
ssmClient = usEastSSMClient;
}
const variables: any = {};
let nextToken;
do {
// noinspection JSUnusedAssignment
const output: GetParametersByPathCommandOutput = await ssmClient.send(
new GetParametersByPathCommand({ Path: path, WithDecryption: true, NextToken: nextToken })
);
output.Parameters?.forEach((param) => {
if (param.Name && param.Value) {
variables[param.Name.replace(path, "")] = param.Value;
}
});
nextToken = output.NextToken;
} while (nextToken);
return variables;
}

const results: Record<string, string> = {};

async function readParametersByPath(path: string) {
let nextToken;
do {
// noinspection JSUnusedAssignment
const output: GetParametersByPathCommandOutput = await ssmClient.send(
new GetParametersByPathCommand({ Path: path, WithDecryption: true, NextToken: nextToken })
);
output.Parameters?.forEach((param) => {
if (param.Name && param.Value) {
results[param.Name.replace(path, "")] = param.Value;
}
});
nextToken = output.NextToken;
} while (nextToken);
}

await readParametersByPath("/"); // Read global parameters from root
await readParametersByPath("/" + environment + "/"); // Then override with environment specific ones if provided

return results as HassuSSMParameters;
export async function readParametersForEnv<T extends Record<string, string>>(
environment: string,
region: Region
): Promise<T> {
const results: Record<string, string> = {
...(await readParametersByPath("/", region)), // Read global parameters from root
...(await readParametersByPath("/" + environment + "/", region)), // Then override with environment specific ones if provided
};
return results as T;
}

function writeEnvFile(fileName: string, variables: { [p: string]: string }) {
Expand All @@ -140,20 +143,9 @@ function writeEnvFile(fileName: string, variables: { [p: string]: string }) {
fs.writeFileSync(fileName, envFile);
}

function writePyEnvFile(fileName: string, variables: { [p: string]: string }) {
let envFile = "# This file is automatically generated\n";
for (const key in variables) {
if (variables.hasOwnProperty(key) && variables[key]) {
envFile += `${key}="${variables[key]}"\n`;
}
}

fs.writeFileSync(fileName, envFile);
}

export async function getEnvironmentVariablesFromSSM(variables?: HassuSSMParameters) {
if (!variables) {
variables = await readParametersForEnv(BaseConfig.infraEnvironment, Region.EU_WEST_1);
variables = await readParametersForEnv<HassuSSMParameters>(BaseConfig.infraEnvironment, Region.EU_WEST_1);
}

return {
Expand Down Expand Up @@ -181,7 +173,7 @@ async function main() {
const searchStackOutputs = await readSearchStackOutputs();
const backendStackOutputs = await readBackendStackOutputs();
const frontendStackOutputs = await readFrontendStackOutputs();
const variables = await readParametersForEnv(BaseConfig.infraEnvironment, Region.EU_WEST_1);
const variables = await readParametersForEnv<HassuSSMParameters>(BaseConfig.infraEnvironment, Region.EU_WEST_1);
const environmentVariables = await getEnvironmentVariablesFromSSM(variables);
writeEnvFile(".env.test", {
SEARCH_DOMAIN: searchStackOutputs.SearchDomainOutput,
Expand All @@ -195,23 +187,6 @@ async function main() {
INTERNAL_BUCKET_NAME: Config.internalBucketName,
FRONTEND_DOMAIN_NAME: frontendStackOutputs.CloudfrontPrivateDNSName,
});

let server;
if (BaseConfig.isPermanentEnvironment()) {
server =
"https://" +
variables.basicAuthenticationUsername +
":" +
variables.basicAuthenticationPassword +
"@" +
variables.FrontendDomainName;
} else {
// For local testing
server = "http://host.docker.internal:3000";
}
writePyEnvFile("robotenv.py", {
SERVER: server,
});
}

main().catch((e) => {
Expand Down
60 changes: 60 additions & 0 deletions deployment/bin/setupRobotEnvironment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* tslint:disable:no-console */
// This script examines stack outputs and parameter store parameters, and writes .env.local and .env.test files

import { BaseConfig } from "../../common/BaseConfig";
import * as fs from "fs";
import { HassuSSMParameters, readParametersByPath, readParametersForEnv, Region } from "./setupEnvironment";

function writePyEnvFile(fileName: string, variables: { [p: string]: string }) {
let envFile = "import os\n# This file is automatically generated\n";
for (const key in variables) {
if (variables.hasOwnProperty(key) && variables[key]) {
envFile += `${key} = "${variables[key]}"\n`;
}
}
envFile += 'if os.getenv("DOCKER") == "false":\n' + " SERVER = NO_DOCKER_SERVER\n";

fs.writeFileSync(fileName, envFile);
}

async function main() {
const variables = await readParametersForEnv<HassuSSMParameters>(BaseConfig.infraEnvironment, Region.EU_WEST_1);

const robotVariables: any = {};

if (BaseConfig.isPermanentEnvironment()) {
robotVariables.SERVER =
"https://" +
variables.basicAuthenticationUsername +
":" +
variables.basicAuthenticationPassword +
"@" +
variables.FrontendDomainName;
robotVariables.NO_DOCKER_SERVER = robotVariables.SERVER;
robotVariables.LOCAL_SERVER = "false";
} else {
// For local testing
robotVariables.SERVER = "http://host.docker.internal:3000";
robotVariables.NO_DOCKER_SERVER = "http://localhost:3000";
robotVariables.LOCAL_SERVER = "true";
}

const testUsers = await readParametersByPath("/testusers/", Region.EU_WEST_1);
for (const user in testUsers) {
if (testUsers.hasOwnProperty(user)) {
const [username, password, roles] = testUsers[user].split(" ");
robotVariables[`${user}_USERNAME`] = username;
robotVariables[`${user}_PASSWORD`] = password;
robotVariables[`${user}_ROLES`] = roles || "Atunnukset,hassu_admin";
}
}

writePyEnvFile("robotenv.py", robotVariables);
}

main().catch((e) => {
console.log(e);
process.exit(1);
});
// "Atunnukset",
// "hassu_admin"
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,9 @@
"deleteVelhoProjekti": "ts-node --project=tsconfig.backend.json -r dotenv/config ./backend/bin/deleteVelhoProjekti dotenv_config_path=.env.test",
"robot:build": "./tools/robot/updateRobotImage.sh",
"robot:pull": "cross-env docker pull 283563576583.dkr.ecr.eu-west-1.amazonaws.com/hassu-robot:latest",
"robot": "cross-env docker run --rm --add-host=host.docker.internal:host-gateway -v $(pwd):/work 283563576583.dkr.ecr.eu-west-1.amazonaws.com/hassu-robot:latest",
"robot:setup": "ts-node --project=tsconfig.cdk.json deployment/bin/setupRobotEnvironment.ts",
"robot": "cross-env docker run --rm --add-host=host.docker.internal:host-gateway -v $(pwd):/work -e TEST_SUITE 283563576583.dkr.ecr.eu-west-1.amazonaws.com/hassu-robot:latest",
"robot:browser": "cross-env ROBOT_OPEN_BROWSER=true ./tools/robot/run_suite_local.sh robot --console verbose --outputdir ./test/.report",
"ecrLogin": "aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin 283563576583.dkr.ecr.eu-west-1.amazonaws.com"
},
"browserslist": {
Expand Down
33 changes: 29 additions & 4 deletions src/services/api/developerApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import awsExports from "../../aws-exports";
import { createAuthLink } from "aws-appsync-auth-link";
import { createHttpLink } from "apollo-link-http";
import { API } from "@services/api/commonApi";
import { setContext } from "apollo-link-context";

const AWS = require("aws-sdk");
AWS.config.update({
Expand All @@ -17,18 +18,42 @@ if (typeof window !== "undefined") {
}),
});
}

function getParamOrDefault(params: URLSearchParams | undefined, name: string, defaultValue: string | undefined) {
if (params) {
if (params.has(name)) {
const value = params.get(name) || "";
localStorage.setItem(name, value);
return value;
}
}
const valueFromStorage = localStorage.getItem(name);
if (!!valueFromStorage) {
return valueFromStorage;
}
return defaultValue;
}

const links = [
setContext((_, { headers }) => {
if (typeof window !== "undefined") {
const params = window.location?.search ? new URLSearchParams(window.location.search) : undefined;
return {
headers: {
...headers,
"x-hassudev-uid": getParamOrDefault(params, "x-hassudev-uid", process.env["x-hassudev-uid"]),
"x-hassudev-roles": getParamOrDefault(params, "x-hassudev-roles", process.env["x-hassudev-roles"]),
},
};
}
}),
createAuthLink({
url: awsExports.aws_appsync_graphqlEndpoint,
region: awsExports.aws_appsync_region,
auth: { type: "AWS_IAM", credentials: AWS.config.credentials },
}),
createHttpLink({
uri: awsExports.aws_appsync_graphqlEndpoint,
headers: {
"x-hassudev-uid": process.env["x-hassudev-uid"],
"x-hassudev-roles": process.env["x-hassudev-roles"],
},
}),
];

Expand Down
10 changes: 9 additions & 1 deletion test/suites/lib/setup.robot
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@ ${TMP_PATH} /tmp

*** Keywords ***
Avaa selain
Start Virtual Display 1920 1080
Run Keyword If "%{ROBOT_SELENIUM_SPEED=}"!="" Set Selenium Speed %{ROBOT_SELENIUM_SPEED}
Run Keyword If "%{ROBOT_OPEN_BROWSER=}"!="true" Start Virtual Display 1920 1080
${options} Evaluate sys.modules['selenium.webdriver'].ChromeOptions() sys, selenium.webdriver
Call Method ${options} add_argument --no-sandbox
${prefs} Create Dictionary download.default_directory=${TMP_PATH}
Call Method ${options} add_experimental_option prefs ${prefs}
Create Webdriver Chrome chrome_options=${options}

Sulje selain
Run Keyword If All Tests Passed Close All Browsers if running headless

Close All Browsers if running headless
Run Keyword If "%{ROBOT_OPEN_BROWSER=}"!="true" Close All Browsers

Selain on avattu kansalaisen etusivulle
Log "Avaa selain ${SERVER}"
GoTo ${SERVER}
29 changes: 29 additions & 0 deletions test/suites/login_tests/kirjaudu.robot
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
*** Settings ***
Resource ../lib/setup.robot

Suite Setup Avaa selain

Test Teardown Run Keyword If Test Failed Capture Page Screenshot

Suite Teardown Sulje selain

*** Variables ***

*** Test Cases ***
Kirjaudu yllapitoon
Kirjaudu yllapitoon kayttajana A1

*** Keywords ***
Kirjaudu yllapitoon kayttajana ${username}
IF "${LOCAL_SERVER}"=="true"
${URL} Set Variable ${SERVER}/yllapito?x-hassudev-uid=${${username}_USERNAME}&x-hassudev-roles=${${username}_ROLES}
Log "Avaa selain ${URL}"
GoTo ${URL}
ELSE
${URL} Set Variable ${SERVER}/yllapito/kirjaudu
GoTo ${URL}
Input Text id=username text=${${username}_USERNAME}
Input Text id=password text=${${username}_PASSWORD}
Click Button css=.submit
END
Wait Until Element Is Visible xpath=//a[@href='/yllapito/perusta']
2 changes: 1 addition & 1 deletion test/suites/login_tests/mytest.robot
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Suite Setup Avaa selain

Test Teardown Run Keyword If Test Failed Capture Page Screenshot

Suite Teardown Close All Browsers
Suite Teardown Sulje selain

*** Variables ***

Expand Down
1 change: 1 addition & 0 deletions tools/robot/run_suite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ if [ -z "$TEST_SUITE" ]; then
TEST_SUITE=""
fi

export DOCKER=true
CMD="robot --console verbose --outputdir /work/test/.report /work/test/suites/$TEST_SUITE"

echo ${CMD}
Expand Down
14 changes: 14 additions & 0 deletions tools/robot/run_suite_local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -e

# Run an individual test suite if the TEST_SUITE environmental variable is set.
if [ -z "$TEST_SUITE" ]; then
TEST_SUITE=""
fi

export DOCKER=false
CMD="robot --console verbose --outputdir ./test/.report ./test/suites/$TEST_SUITE"

echo ${CMD}

``${CMD}``

0 comments on commit 1834f8d

Please sign in to comment.