From 7e5a617816f0a7489f44aea166fca062daf95b6c Mon Sep 17 00:00:00 2001 From: Allan Zheng Date: Thu, 9 Jul 2020 01:14:27 -0700 Subject: [PATCH 1/3] test: pick smock test region from env --- clients/client-cognito-identity/e2e/CognitoIdentity.ispec.ts | 2 +- clients/client-s3/e2e/S3.ispec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/client-cognito-identity/e2e/CognitoIdentity.ispec.ts b/clients/client-cognito-identity/e2e/CognitoIdentity.ispec.ts index fdad7741d512..6df6a0a73e33 100644 --- a/clients/client-cognito-identity/e2e/CognitoIdentity.ispec.ts +++ b/clients/client-cognito-identity/e2e/CognitoIdentity.ispec.ts @@ -7,7 +7,7 @@ import { expect } from "chai"; import { CognitoIdentity } from "../index"; // There will be default values of defaultRegion, credentials, and isBrowser variable in browser tests. // Define the values for Node.js tests -const region: string | undefined = (globalThis as any).defaultRegion || undefined; +const region: string | undefined = (globalThis as any).defaultRegion || process?.env?.AWS_SMOKE_TEST_REGION; const IdentityPoolId = (globalThis as any)?.window?.__env__?.AWS_SMOKE_TEST_IDENTITY_POOL_ID || process?.env?.AWS_SMOKE_TEST_IDENTITY_POOL_ID; diff --git a/clients/client-s3/e2e/S3.ispec.ts b/clients/client-s3/e2e/S3.ispec.ts index 271eb80eedb7..979ebe0a4d38 100644 --- a/clients/client-s3/e2e/S3.ispec.ts +++ b/clients/client-s3/e2e/S3.ispec.ts @@ -12,7 +12,7 @@ chai.use(chaiAsPromised); const { expect } = chai; // There will be default values of defaultRegion, credentials, and isBrowser variable in browser tests. // Define the values for Node.js tests -const region: string | undefined = (globalThis as any).defaultRegion || undefined; +const region: string | undefined = (globalThis as any).defaultRegion || process?.env?.AWS_SMOKE_TEST_REGION; const credentials: Credentials | undefined = (globalThis as any).credentials || undefined; const isBrowser: boolean | undefined = (globalThis as any).isBrowser || false; const Bucket = (globalThis as any)?.window?.__env__?.AWS_SMOKE_TEST_BUCKET || process?.env?.AWS_SMOKE_TEST_BUCKET; From f9a1fc079556d8edd218a90d0ee813ceeb12f6c1 Mon Sep 17 00:00:00 2001 From: Allan Zheng Date: Fri, 10 Jul 2020 01:30:24 -0700 Subject: [PATCH 2/3] chore: add global test:e2e script running e2e on changed pkgs --- package.json | 1 + scripts/e2e-test/get-integ-test-resources.js | 36 ++++++++++++++ scripts/e2e-test/index.js | 31 ++++++++++++ scripts/e2e-test/run-e2e-tests.js | 50 ++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 scripts/e2e-test/get-integ-test-resources.js create mode 100644 scripts/e2e-test/index.js create mode 100644 scripts/e2e-test/run-e2e-tests.js diff --git a/package.json b/package.json index 1c1ca5694b44..be77d337eca8 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "test:integration-legacy": "cucumber-js --fail-fast", "test:integration": "jest --config jest.config.integ.js --passWithNoTests", "test:protocols": "yarn build:protocols && lerna run test --scope '@aws-sdk/aws-*'", + "test:e2e": "node ./scripts/e2e-test/index.js", "local-publish": "node ./scripts/verdaccio-publish/index.js" }, "repository": { diff --git a/scripts/e2e-test/get-integ-test-resources.js b/scripts/e2e-test/get-integ-test-resources.js new file mode 100644 index 000000000000..e61fff65892a --- /dev/null +++ b/scripts/e2e-test/get-integ-test-resources.js @@ -0,0 +1,36 @@ +const { CloudFormationClient, DescribeStackResourcesCommand } = require("@aws-sdk/client-cloudformation"); +const { writeFileSync } = require("fs"); +const { normalize } = require("path"); + +const run = async () => { + const client = new CloudFormationClient({}); + const region = await client.config.region(); + + const { StackResources: stackResources } = await client.send( + new DescribeStackResourcesCommand({ StackName: "IntegTestResourcesStack" }) + ); + + const identityPoolId = stackResources.filter((resource) => resource.ResourceType === "AWS::Cognito::IdentityPool")[0] + .PhysicalResourceId; + + const bucketName = stackResources.filter( + (resource) => resource.ResourceType === "AWS::S3::Bucket" && resource.LogicalResourceId.indexOf("IntegTest") === 0 + )[0].PhysicalResourceId; + + const resources = { + AWS_SMOKE_TEST_REGION: region, + AWS_SMOKE_TEST_IDENTITY_POOL_ID: identityPoolId, + AWS_SMOKE_TEST_BUCKET: bucketName, + }; + const stringified = JSON.stringify(resources, null, 2); + console.log(`integration test resources: +${stringified} + +You will need them for beta & product release stack configuration.`); + + const configPath = normalize(process.argv[2]); + console.log(`generated environmental variables needed in integration tests to ${configPath}`); + writeFileSync(configPath, stringified, { flag: "w" }); +}; + +run(); diff --git a/scripts/e2e-test/index.js b/scripts/e2e-test/index.js new file mode 100644 index 000000000000..1e26bd5cc3db --- /dev/null +++ b/scripts/e2e-test/index.js @@ -0,0 +1,31 @@ +const { spawn } = require("child_process"); +const { readFileSync, unlinkSync } = require("fs"); +const { join } = require("path"); + +const spawnPromise = (command, options, spawnOptions) => + new Promise((resolve, reject) => { + const ps = spawn(command, options, { + stdio: "inherit", + ...spawnOptions, + }); + ps.on("error", reject); + ps.on("exit", resolve); + }); + +const run = async () => { + const envFile = "env.json"; + await spawnPromise("node", ["get-integ-test-resources.js", envFile], { + cwd: __dirname, + }); + const integTestResourcesEnv = JSON.parse(readFileSync(join(__dirname, envFile)).toString()); + try { + await spawnPromise("node", ["run-e2e-tests.js"], { + env: { ...process.env, ...integTestResourcesEnv }, + cwd: __dirname, + }); + } finally { + unlinkSync(join(__dirname, envFile)); + } +}; + +run(); diff --git a/scripts/e2e-test/run-e2e-tests.js b/scripts/e2e-test/run-e2e-tests.js new file mode 100644 index 000000000000..1b049189df6e --- /dev/null +++ b/scripts/e2e-test/run-e2e-tests.js @@ -0,0 +1,50 @@ +const { execSync, spawn } = require("child_process"); +const { join } = require("path"); +const { readFileSync, existsSync } = require("fs"); + +const hasE2Etest = (packagePath) => { + const path = join(packagePath, "package.json"); + if (!existsSync(path)) return false; + const pkgJson = JSON.parse(readFileSync(path).toString()); + return Boolean(pkgJson.scripts["test:e2e"]); +}; + +const run = async () => { + /** + * Example output: + /path/to/package:@aws-sdk/client-accessanalyzer:1.0.0-gamma.3 + /path/to/package:@aws-sdk/client-acm-pca:1.0.0-gamma.3 + /path/to/package:@aws-sdk/client-acm:1.0.0-gamma.3 + */ + const changedPackagesRecord = execSync("npx lerna changed --all --parseable --long --loglevel silent"); + // Get array for changed package's path + const changedPackages = changedPackagesRecord + .toString() + .split("\n") + .map((record) => record.split(":").slice(0, 2)); + const packagesToTest = changedPackages.filter((changedPackage) => hasE2Etest(changedPackage[0])); + console.log(`packages to run e2e test: +${packagesToTest.map((package) => package[0]).join("\n")}`); + const test = spawn( + "npx", + [ + "lerna", + "run", + "test:e2e", + "--scope", + `'{${packagesToTest.map((package) => package[1]).join(",")}}'`, // https://github.com/lerna/lerna/issues/1846#issuecomment-451172783 + "--concurrency", + "1", + ], + { + env: process.env, + stdio: "inherit", + } + ); + test.on("close", (code) => { + console.log(`e2e test complete: [${code}]`); + process.exit(code); + }); +}; + +run(); From b4f99e4a35f21e461c043262a789a7ec2a022673 Mon Sep 17 00:00:00 2001 From: Allan Zheng Date: Fri, 10 Jul 2020 14:07:27 -0700 Subject: [PATCH 3/3] chore: refactoring according to feedbacks --- package.json | 2 +- scripts/e2e-test/index.js | 31 ------------------- .../e2e}/get-integ-test-resources.js | 19 ++---------- tests/e2e/index.js | 13 ++++++++ .../e2e-test => tests/e2e}/run-e2e-tests.js | 23 +++++++------- tests/e2e/spawn-promise.js | 17 ++++++++++ 6 files changed, 45 insertions(+), 60 deletions(-) delete mode 100644 scripts/e2e-test/index.js rename {scripts/e2e-test => tests/e2e}/get-integ-test-resources.js (57%) create mode 100644 tests/e2e/index.js rename {scripts/e2e-test => tests/e2e}/run-e2e-tests.js (77%) create mode 100644 tests/e2e/spawn-promise.js diff --git a/package.json b/package.json index be77d337eca8..76f5e7c0c356 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test:integration-legacy": "cucumber-js --fail-fast", "test:integration": "jest --config jest.config.integ.js --passWithNoTests", "test:protocols": "yarn build:protocols && lerna run test --scope '@aws-sdk/aws-*'", - "test:e2e": "node ./scripts/e2e-test/index.js", + "test:e2e": "node ./tests/e2e/index.js", "local-publish": "node ./scripts/verdaccio-publish/index.js" }, "repository": { diff --git a/scripts/e2e-test/index.js b/scripts/e2e-test/index.js deleted file mode 100644 index 1e26bd5cc3db..000000000000 --- a/scripts/e2e-test/index.js +++ /dev/null @@ -1,31 +0,0 @@ -const { spawn } = require("child_process"); -const { readFileSync, unlinkSync } = require("fs"); -const { join } = require("path"); - -const spawnPromise = (command, options, spawnOptions) => - new Promise((resolve, reject) => { - const ps = spawn(command, options, { - stdio: "inherit", - ...spawnOptions, - }); - ps.on("error", reject); - ps.on("exit", resolve); - }); - -const run = async () => { - const envFile = "env.json"; - await spawnPromise("node", ["get-integ-test-resources.js", envFile], { - cwd: __dirname, - }); - const integTestResourcesEnv = JSON.parse(readFileSync(join(__dirname, envFile)).toString()); - try { - await spawnPromise("node", ["run-e2e-tests.js"], { - env: { ...process.env, ...integTestResourcesEnv }, - cwd: __dirname, - }); - } finally { - unlinkSync(join(__dirname, envFile)); - } -}; - -run(); diff --git a/scripts/e2e-test/get-integ-test-resources.js b/tests/e2e/get-integ-test-resources.js similarity index 57% rename from scripts/e2e-test/get-integ-test-resources.js rename to tests/e2e/get-integ-test-resources.js index e61fff65892a..598dc1e162c6 100644 --- a/scripts/e2e-test/get-integ-test-resources.js +++ b/tests/e2e/get-integ-test-resources.js @@ -1,8 +1,6 @@ -const { CloudFormationClient, DescribeStackResourcesCommand } = require("@aws-sdk/client-cloudformation"); -const { writeFileSync } = require("fs"); -const { normalize } = require("path"); +const { CloudFormationClient, DescribeStackResourcesCommand } = require("../../clients/client-cloudformation"); -const run = async () => { +exports.getIntegTestResources = async () => { const client = new CloudFormationClient({}); const region = await client.config.region(); @@ -17,20 +15,9 @@ const run = async () => { (resource) => resource.ResourceType === "AWS::S3::Bucket" && resource.LogicalResourceId.indexOf("IntegTest") === 0 )[0].PhysicalResourceId; - const resources = { + return { AWS_SMOKE_TEST_REGION: region, AWS_SMOKE_TEST_IDENTITY_POOL_ID: identityPoolId, AWS_SMOKE_TEST_BUCKET: bucketName, }; - const stringified = JSON.stringify(resources, null, 2); - console.log(`integration test resources: -${stringified} - -You will need them for beta & product release stack configuration.`); - - const configPath = normalize(process.argv[2]); - console.log(`generated environmental variables needed in integration tests to ${configPath}`); - writeFileSync(configPath, stringified, { flag: "w" }); }; - -run(); diff --git a/tests/e2e/index.js b/tests/e2e/index.js new file mode 100644 index 000000000000..1e2c4dd01aca --- /dev/null +++ b/tests/e2e/index.js @@ -0,0 +1,13 @@ +const { getIntegTestResources } = require("./get-integ-test-resources"); +const { runE2ETests } = require("./run-e2e-tests"); + +const run = async () => { + try { + const integTestResourcesEnv = await getIntegTestResources(); + await runE2ETests(integTestResourcesEnv); + } catch (e) { + process.exit(1); + } +}; + +run(); diff --git a/scripts/e2e-test/run-e2e-tests.js b/tests/e2e/run-e2e-tests.js similarity index 77% rename from scripts/e2e-test/run-e2e-tests.js rename to tests/e2e/run-e2e-tests.js index 1b049189df6e..f915b7febf7f 100644 --- a/scripts/e2e-test/run-e2e-tests.js +++ b/tests/e2e/run-e2e-tests.js @@ -1,6 +1,7 @@ const { execSync, spawn } = require("child_process"); const { join } = require("path"); const { readFileSync, existsSync } = require("fs"); +const { spawnPromise } = require("./spawn-promise"); const hasE2Etest = (packagePath) => { const path = join(packagePath, "package.json"); @@ -9,14 +10,16 @@ const hasE2Etest = (packagePath) => { return Boolean(pkgJson.scripts["test:e2e"]); }; -const run = async () => { +exports.runE2ETests = async (resourcesEnv) => { /** * Example output: /path/to/package:@aws-sdk/client-accessanalyzer:1.0.0-gamma.3 /path/to/package:@aws-sdk/client-acm-pca:1.0.0-gamma.3 /path/to/package:@aws-sdk/client-acm:1.0.0-gamma.3 */ - const changedPackagesRecord = execSync("npx lerna changed --all --parseable --long --loglevel silent"); + const changedPackagesRecord = execSync( + "./node_modules/.bin/lerna changed --all --parseable --long --loglevel silent" + ); // Get array for changed package's path const changedPackages = changedPackagesRecord .toString() @@ -25,10 +28,9 @@ const run = async () => { const packagesToTest = changedPackages.filter((changedPackage) => hasE2Etest(changedPackage[0])); console.log(`packages to run e2e test: ${packagesToTest.map((package) => package[0]).join("\n")}`); - const test = spawn( - "npx", + await spawnPromise( + "./node_modules/.bin/lerna", [ - "lerna", "run", "test:e2e", "--scope", @@ -37,14 +39,11 @@ ${packagesToTest.map((package) => package[0]).join("\n")}`); "1", ], { - env: process.env, + env: { + ...process.env, + ...resourcesEnv, + }, stdio: "inherit", } ); - test.on("close", (code) => { - console.log(`e2e test complete: [${code}]`); - process.exit(code); - }); }; - -run(); diff --git a/tests/e2e/spawn-promise.js b/tests/e2e/spawn-promise.js new file mode 100644 index 000000000000..3bfcd83851df --- /dev/null +++ b/tests/e2e/spawn-promise.js @@ -0,0 +1,17 @@ +const { spawn } = require("child_process"); + +exports.spawnPromise = (command, options, spawnOptions) => + new Promise((resolve, reject) => { + const ps = spawn(command, options, { + stdio: "inherit", + ...spawnOptions, + }); + ps.on("error", reject); + ps.on("exit", (code) => { + if (code !== 0) { + reject(new Error(`Unexpected exit code [${code}]`)); + } else { + resolve(); + } + }); + });