From 712e20a8b8478eac66823e7da5d5fdddbcfcf93f Mon Sep 17 00:00:00 2001 From: Kush Saraiya Date: Wed, 28 Aug 2024 19:43:12 +0530 Subject: [PATCH 1/4] feat: Run npm test if specified during build --- .../workflows/nodejs_npm/actions.py | 23 ++++ .../workflows/nodejs_npm/workflow.py | 8 ++ .../workflows/nodejs_npm/test_nodejs_npm.py | 32 ++++++ .../testdata/empty-test-script/package.json | 11 ++ .../test-script-to-create-file/package.json | 11 ++ .../unit/workflows/nodejs_npm/test_actions.py | 28 +++++ .../workflows/nodejs_npm/test_workflow.py | 103 ++++++++++-------- 7 files changed, 172 insertions(+), 44 deletions(-) create mode 100644 tests/integration/workflows/nodejs_npm/testdata/empty-test-script/package.json create mode 100644 tests/integration/workflows/nodejs_npm/testdata/test-script-to-create-file/package.json diff --git a/aws_lambda_builders/workflows/nodejs_npm/actions.py b/aws_lambda_builders/workflows/nodejs_npm/actions.py index 2b7dc656c..dc7a9db8f 100644 --- a/aws_lambda_builders/workflows/nodejs_npm/actions.py +++ b/aws_lambda_builders/workflows/nodejs_npm/actions.py @@ -321,3 +321,26 @@ def execute(self): except OSError as ex: raise ActionFailedError(str(ex)) + +class NodejsNpmTestAction(NodejsNpmInstallOrUpdateBaseAction): + """ + A Lambda Builder Action that runs tests in NPM project + """ + + NAME = "NpmTest" + DESCRIPTION = "Running tests from NPM" + + def execute(self): + """ + Runs the action. + + :raises lambda_builders.actions.ActionFailedError: when NPM execution fails + """ + try: + LOG.debug("NODEJS running tests in: %s", self.install_dir) + + command = ["test", "--if-present"] + self.subprocess_npm.run(command, cwd=self.install_dir) + + except NpmExecutionError as ex: + raise ActionFailedError(str(ex)) diff --git a/aws_lambda_builders/workflows/nodejs_npm/workflow.py b/aws_lambda_builders/workflows/nodejs_npm/workflow.py index 894045cee..4d87cfce4 100644 --- a/aws_lambda_builders/workflows/nodejs_npm/workflow.py +++ b/aws_lambda_builders/workflows/nodejs_npm/workflow.py @@ -22,6 +22,7 @@ NodejsNpmPackAction, NodejsNpmrcAndLockfileCopyAction, NodejsNpmrcCleanUpAction, + NodejsNpmTestAction, NodejsNpmUpdateAction, ) from aws_lambda_builders.workflows.nodejs_npm.npm import SubprocessNpm @@ -123,6 +124,13 @@ def __init__(self, source_dir, artifacts_dir, scratch_dir, manifest_path, runtim ) ) + self.actions.append( + NodejsNpmTestAction( + install_dir=self.manifest_dir if is_building_in_source and is_external_manifest else self.build_dir, + subprocess_npm=subprocess_npm + ) + ) + if is_building_in_source and is_external_manifest: # Since we run `npm install` in the manifest directory, so we need to link the node_modules directory in # the source directory. diff --git a/tests/integration/workflows/nodejs_npm/test_nodejs_npm.py b/tests/integration/workflows/nodejs_npm/test_nodejs_npm.py index d27f8a2d6..a9431f4d0 100644 --- a/tests/integration/workflows/nodejs_npm/test_nodejs_npm.py +++ b/tests/integration/workflows/nodejs_npm/test_nodejs_npm.py @@ -776,3 +776,35 @@ def test_builds_project_with_manifest_outside_root_and_local_dependencies_with_d # expected dependencies in source directory source_modules = set(os.listdir(os.path.join(source_dir, "node_modules"))) self.assertTrue(all(expected_module in source_modules for expected_module in expected_modules)) + + @parameterized.expand([("nodejs16.x",), ("nodejs18.x",), ("nodejs20.x",)]) + def test_runs_test_script_if_specified(self, runtime): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "test-script-to-create-file") + + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "package.json"), + runtime=runtime, + ) + + expected_files = {"package.json", "copied.js"} + output_files = set(os.listdir(self.artifacts_dir)) + self.assertEqual(expected_files, output_files) + + @parameterized.expand([("nodejs16.x",), ("nodejs18.x",), ("nodejs20.x",)]) + def test_does_not_raise_error_if_empty_test_script(self, runtime): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "empty-test-script") + + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "package.json"), + runtime=runtime, + ) + + expected_files = {"package.json"} + output_files = set(os.listdir(self.artifacts_dir)) + self.assertEqual(expected_files, output_files) diff --git a/tests/integration/workflows/nodejs_npm/testdata/empty-test-script/package.json b/tests/integration/workflows/nodejs_npm/testdata/empty-test-script/package.json new file mode 100644 index 000000000..f71e08637 --- /dev/null +++ b/tests/integration/workflows/nodejs_npm/testdata/empty-test-script/package.json @@ -0,0 +1,11 @@ +{ + "name": "testscript", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "" + }, + "keywords": [], + "author": "", + "license": "APACHE2.0" +} diff --git a/tests/integration/workflows/nodejs_npm/testdata/test-script-to-create-file/package.json b/tests/integration/workflows/nodejs_npm/testdata/test-script-to-create-file/package.json new file mode 100644 index 000000000..623407e0e --- /dev/null +++ b/tests/integration/workflows/nodejs_npm/testdata/test-script-to-create-file/package.json @@ -0,0 +1,11 @@ +{ + "name": "testscript", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "touch copied.js" + }, + "keywords": [], + "author": "", + "license": "APACHE2.0" +} diff --git a/tests/unit/workflows/nodejs_npm/test_actions.py b/tests/unit/workflows/nodejs_npm/test_actions.py index d7b779922..c80eb8183 100644 --- a/tests/unit/workflows/nodejs_npm/test_actions.py +++ b/tests/unit/workflows/nodejs_npm/test_actions.py @@ -11,6 +11,7 @@ NodejsNpmrcCleanUpAction, NodejsNpmLockFileCleanUpAction, NodejsNpmCIAction, + NodejsNpmTestAction ) from aws_lambda_builders.workflows.nodejs_npm.npm import NpmExecutionError @@ -219,3 +220,30 @@ def test_raises_action_failed_when_removing_fails(self, OSUtilMock): with self.assertRaises(ActionFailedError): action.execute() + +class TestNodejsNpmTestAction(TestCase): + @patch("aws_lambda_builders.workflows.nodejs_npm.npm.SubprocessNpm") + def test_runs_npm_test_for_npm_project(self, SubprocessNpmMock): + subprocess_npm = SubprocessNpmMock.return_value + + action = NodejsNpmTestAction(install_dir="tests", subprocess_npm=subprocess_npm) + + action.execute() + + expected_args = ["test", "--if-present"] + + subprocess_npm.run.assert_called_with(expected_args, cwd="tests") + + @patch("aws_lambda_builders.workflows.nodejs_npm.npm.SubprocessNpm") + def test_raises_action_failed_when_npm_test_fails(self, SubprocessNpmMock): + subprocess_npm = SubprocessNpmMock.return_value + + builder_instance = SubprocessNpmMock.return_value + builder_instance.run.side_effect = NpmExecutionError(message="boom!") + + action = NodejsNpmTestAction("artifacts", subprocess_npm=subprocess_npm) + + with self.assertRaises(ActionFailedError) as raised: + action.execute() + + self.assertEqual(raised.exception.args[0], "NPM Failed: boom!") diff --git a/tests/unit/workflows/nodejs_npm/test_workflow.py b/tests/unit/workflows/nodejs_npm/test_workflow.py index 302c75b68..85133dc76 100644 --- a/tests/unit/workflows/nodejs_npm/test_workflow.py +++ b/tests/unit/workflows/nodejs_npm/test_workflow.py @@ -21,6 +21,7 @@ NodejsNpmLockFileCleanUpAction, NodejsNpmCIAction, NodejsNpmUpdateAction, + NodejsNpmTestAction, ) @@ -57,13 +58,14 @@ def test_workflow_sets_up_npm_actions_with_download_dependencies_without_depende workflow = NodejsNpmWorkflow("source", "artifacts", "scratch_dir", "source/manifest", osutils=self.osutils) - self.assertEqual(len(workflow.actions), 6) + self.assertEqual(len(workflow.actions), 7) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) self.assertIsInstance(workflow.actions[3], NodejsNpmInstallAction) - self.assertIsInstance(workflow.actions[4], NodejsNpmrcCleanUpAction) - self.assertIsInstance(workflow.actions[5], NodejsNpmLockFileCleanUpAction) + self.assertIsInstance(workflow.actions[4], NodejsNpmTestAction) + self.assertIsInstance(workflow.actions[5], NodejsNpmrcCleanUpAction) + self.assertIsInstance(workflow.actions[6], NodejsNpmLockFileCleanUpAction) def test_workflow_sets_up_npm_actions_with_download_dependencies_without_dependencies_dir_external_manifest(self): self.osutils.dirname.return_value = "not_source" @@ -73,7 +75,7 @@ def test_workflow_sets_up_npm_actions_with_download_dependencies_without_depende workflow = NodejsNpmWorkflow("source", "artifacts", "scratch_dir", "not_source/manifest", osutils=self.osutils) - self.assertEqual(len(workflow.actions), 7) + self.assertEqual(len(workflow.actions), 8) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) @@ -82,8 +84,10 @@ def test_workflow_sets_up_npm_actions_with_download_dependencies_without_depende self.assertEqual(workflow.actions[3].dest_dir, "artifacts") self.assertIsInstance(workflow.actions[4], NodejsNpmInstallAction) self.assertEqual(workflow.actions[4].install_dir, "artifacts") - self.assertIsInstance(workflow.actions[5], NodejsNpmrcCleanUpAction) - self.assertIsInstance(workflow.actions[6], NodejsNpmLockFileCleanUpAction) + self.assertIsInstance(workflow.actions[5], NodejsNpmTestAction) + self.assertEqual(workflow.actions[5].install_dir, "artifacts") + self.assertIsInstance(workflow.actions[6], NodejsNpmrcCleanUpAction) + self.assertIsInstance(workflow.actions[7], NodejsNpmLockFileCleanUpAction) @patch("aws_lambda_builders.workflows.nodejs_npm.workflow.NodejsNpmWorkflow.can_use_install_links") def test_workflow_sets_up_npm_actions_with_download_dependencies_without_dependencies_dir_external_manifest_and_build_in_source( @@ -100,7 +104,7 @@ def test_workflow_sets_up_npm_actions_with_download_dependencies_without_depende "source", "artifacts", "scratch_dir", "not_source/manifest", osutils=self.osutils, build_in_source=True ) - self.assertEqual(len(workflow.actions), 8) + self.assertEqual(len(workflow.actions), 9) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) @@ -109,13 +113,15 @@ def test_workflow_sets_up_npm_actions_with_download_dependencies_without_depende self.assertEqual(workflow.actions[3].dest_dir, "artifacts") self.assertIsInstance(workflow.actions[4], NodejsNpmUpdateAction) self.assertEqual(workflow.actions[4].install_dir, "not_source") - self.assertIsInstance(workflow.actions[5], LinkSinglePathAction) - self.assertEqual(workflow.actions[5]._source, os.path.join("not_source", "node_modules")) - self.assertEqual(workflow.actions[5]._dest, os.path.join("source", "node_modules")) + self.assertIsInstance(workflow.actions[5], NodejsNpmTestAction) + self.assertEqual(workflow.actions[5].install_dir, "not_source") self.assertIsInstance(workflow.actions[6], LinkSinglePathAction) - self.assertEqual(workflow.actions[6]._source, os.path.join("source", "node_modules")) - self.assertEqual(workflow.actions[6]._dest, os.path.join("artifacts", "node_modules")) - self.assertIsInstance(workflow.actions[7], NodejsNpmrcCleanUpAction) + self.assertEqual(workflow.actions[6]._source, os.path.join("not_source", "node_modules")) + self.assertEqual(workflow.actions[6]._dest, os.path.join("source", "node_modules")) + self.assertIsInstance(workflow.actions[7], LinkSinglePathAction) + self.assertEqual(workflow.actions[7]._source, os.path.join("source", "node_modules")) + self.assertEqual(workflow.actions[7]._dest, os.path.join("artifacts", "node_modules")) + self.assertIsInstance(workflow.actions[8], NodejsNpmrcCleanUpAction) def test_workflow_sets_up_npm_actions_without_download_dependencies_with_dependencies_dir(self): self.osutils.file_exists.return_value = True @@ -145,14 +151,15 @@ def test_workflow_sets_up_npm_actions_without_bundler_if_manifest_doesnt_request workflow = NodejsNpmWorkflow("source", "artifacts", "scratch_dir", "source/manifest", osutils=self.osutils) - self.assertEqual(len(workflow.actions), 6) + self.assertEqual(len(workflow.actions), 7) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) self.assertIsInstance(workflow.actions[3], NodejsNpmInstallAction) - self.assertIsInstance(workflow.actions[4], NodejsNpmrcCleanUpAction) - self.assertIsInstance(workflow.actions[5], NodejsNpmLockFileCleanUpAction) + self.assertIsInstance(workflow.actions[4], NodejsNpmTestAction) + self.assertIsInstance(workflow.actions[5], NodejsNpmrcCleanUpAction) + self.assertIsInstance(workflow.actions[6], NodejsNpmLockFileCleanUpAction) def test_workflow_sets_up_npm_actions_with_download_dependencies_and_dependencies_dir(self): self.osutils.file_exists.side_effect = [True, False, False] @@ -167,17 +174,18 @@ def test_workflow_sets_up_npm_actions_with_download_dependencies_and_dependencie osutils=self.osutils, ) - self.assertEqual(len(workflow.actions), 9) + self.assertEqual(len(workflow.actions), 10) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) self.assertIsInstance(workflow.actions[3], NodejsNpmInstallAction) - self.assertIsInstance(workflow.actions[4], CleanUpAction) - self.assertIsInstance(workflow.actions[5], CopyDependenciesAction) - self.assertIsInstance(workflow.actions[6], NodejsNpmrcCleanUpAction) - self.assertIsInstance(workflow.actions[7], NodejsNpmLockFileCleanUpAction) + self.assertIsInstance(workflow.actions[4], NodejsNpmTestAction) + self.assertIsInstance(workflow.actions[5], CleanUpAction) + self.assertIsInstance(workflow.actions[6], CopyDependenciesAction) + self.assertIsInstance(workflow.actions[7], NodejsNpmrcCleanUpAction) self.assertIsInstance(workflow.actions[8], NodejsNpmLockFileCleanUpAction) + self.assertIsInstance(workflow.actions[9], NodejsNpmLockFileCleanUpAction) def test_workflow_sets_up_npm_actions_without_download_dependencies_and_without_dependencies_dir(self): workflow = NodejsNpmWorkflow( @@ -212,17 +220,18 @@ def test_workflow_sets_up_npm_actions_without_combine_dependencies(self): osutils=self.osutils, ) - self.assertEqual(len(workflow.actions), 9) + self.assertEqual(len(workflow.actions), 10) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) self.assertIsInstance(workflow.actions[3], NodejsNpmInstallAction) - self.assertIsInstance(workflow.actions[4], CleanUpAction) - self.assertIsInstance(workflow.actions[5], MoveDependenciesAction) - self.assertIsInstance(workflow.actions[6], NodejsNpmrcCleanUpAction) - self.assertIsInstance(workflow.actions[7], NodejsNpmLockFileCleanUpAction) + self.assertIsInstance(workflow.actions[4], NodejsNpmTestAction) + self.assertIsInstance(workflow.actions[5], CleanUpAction) + self.assertIsInstance(workflow.actions[6], MoveDependenciesAction) + self.assertIsInstance(workflow.actions[7], NodejsNpmrcCleanUpAction) self.assertIsInstance(workflow.actions[8], NodejsNpmLockFileCleanUpAction) + self.assertIsInstance(workflow.actions[9], NodejsNpmLockFileCleanUpAction) def test_must_validate_architecture(self): self.osutils.is_windows.side_effect = [False, False] @@ -258,13 +267,14 @@ def test_workflow_uses_npm_ci_if_shrinkwrap_exists_and_npm_ci_enabled(self): options={"use_npm_ci": True}, ) - self.assertEqual(len(workflow.actions), 6) + self.assertEqual(len(workflow.actions), 7) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) self.assertIsInstance(workflow.actions[3], NodejsNpmCIAction) - self.assertIsInstance(workflow.actions[4], NodejsNpmrcCleanUpAction) - self.assertIsInstance(workflow.actions[5], NodejsNpmLockFileCleanUpAction) + self.assertIsInstance(workflow.actions[4], NodejsNpmTestAction) + self.assertIsInstance(workflow.actions[5], NodejsNpmrcCleanUpAction) + self.assertIsInstance(workflow.actions[6], NodejsNpmLockFileCleanUpAction) self.osutils.file_exists.assert_has_calls( [call("source/package-lock.json"), call("source/npm-shrinkwrap.json")] ) @@ -281,13 +291,14 @@ def test_workflow_uses_npm_ci_if_lockfile_exists_and_npm_ci_enabled(self): options={"use_npm_ci": True}, ) - self.assertEqual(len(workflow.actions), 6) + self.assertEqual(len(workflow.actions), 7) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) self.assertIsInstance(workflow.actions[3], NodejsNpmCIAction) - self.assertIsInstance(workflow.actions[4], NodejsNpmrcCleanUpAction) - self.assertIsInstance(workflow.actions[5], NodejsNpmLockFileCleanUpAction) + self.assertIsInstance(workflow.actions[4], NodejsNpmTestAction) + self.assertIsInstance(workflow.actions[5], NodejsNpmrcCleanUpAction) + self.assertIsInstance(workflow.actions[6], NodejsNpmLockFileCleanUpAction) self.osutils.file_exists.assert_has_calls([call("source/package-lock.json")]) @patch("aws_lambda_builders.workflows.nodejs_npm.workflow.NodejsNpmWorkflow.can_use_install_links") @@ -327,16 +338,18 @@ def test_build_in_source_with_download_dependencies(self, can_use_links_mock): build_in_source=True, ) - self.assertEqual(len(workflow.actions), 6) + self.assertEqual(len(workflow.actions), 7) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) self.assertIsInstance(workflow.actions[3], NodejsNpmUpdateAction) self.assertEqual(workflow.actions[3].install_dir, source_dir) - self.assertIsInstance(workflow.actions[4], LinkSinglePathAction) - self.assertEqual(workflow.actions[4]._source, os.path.join(source_dir, "node_modules")) - self.assertEqual(workflow.actions[4]._dest, os.path.join(artifacts_dir, "node_modules")) - self.assertIsInstance(workflow.actions[5], NodejsNpmrcCleanUpAction) + self.assertIsInstance(workflow.actions[4], NodejsNpmTestAction) + self.assertEqual(workflow.actions[4].install_dir, source_dir) + self.assertIsInstance(workflow.actions[5], LinkSinglePathAction) + self.assertEqual(workflow.actions[5]._source, os.path.join(source_dir, "node_modules")) + self.assertEqual(workflow.actions[5]._dest, os.path.join(artifacts_dir, "node_modules")) + self.assertIsInstance(workflow.actions[6], NodejsNpmrcCleanUpAction) @patch("aws_lambda_builders.workflows.nodejs_npm.workflow.NodejsNpmWorkflow.can_use_install_links") def test_build_in_source_with_download_dependencies_and_dependencies_dir(self, can_use_links_mock): @@ -354,18 +367,20 @@ def test_build_in_source_with_download_dependencies_and_dependencies_dir(self, c dependencies_dir="dep", ) - self.assertEqual(len(workflow.actions), 8) + self.assertEqual(len(workflow.actions), 9) self.assertIsInstance(workflow.actions[0], NodejsNpmPackAction) self.assertIsInstance(workflow.actions[1], NodejsNpmrcAndLockfileCopyAction) self.assertIsInstance(workflow.actions[2], CopySourceAction) self.assertIsInstance(workflow.actions[3], NodejsNpmUpdateAction) self.assertEqual(workflow.actions[3].install_dir, source_dir) - self.assertIsInstance(workflow.actions[4], LinkSinglePathAction) - self.assertEqual(workflow.actions[4]._source, os.path.join(source_dir, "node_modules")) - self.assertEqual(workflow.actions[4]._dest, os.path.join(artifacts_dir, "node_modules")) - self.assertIsInstance(workflow.actions[5], CleanUpAction) - self.assertIsInstance(workflow.actions[6], CopyDependenciesAction) - self.assertIsInstance(workflow.actions[7], NodejsNpmrcCleanUpAction) + self.assertIsInstance(workflow.actions[4], NodejsNpmTestAction) + self.assertEqual(workflow.actions[4].install_dir, source_dir) + self.assertIsInstance(workflow.actions[5], LinkSinglePathAction) + self.assertEqual(workflow.actions[5]._source, os.path.join(source_dir, "node_modules")) + self.assertEqual(workflow.actions[5]._dest, os.path.join(artifacts_dir, "node_modules")) + self.assertIsInstance(workflow.actions[6], CleanUpAction) + self.assertIsInstance(workflow.actions[7], CopyDependenciesAction) + self.assertIsInstance(workflow.actions[8], NodejsNpmrcCleanUpAction) @patch("aws_lambda_builders.workflows.nodejs_npm.workflow.NodejsNpmWorkflow.can_use_install_links") def test_build_in_source_with_dependencies_dir(self, can_use_links_mock): From ce825bf4379e941cfea3ed047134754c4f60dcd4 Mon Sep 17 00:00:00 2001 From: Kush Saraiya Date: Thu, 5 Sep 2024 10:32:42 +0530 Subject: [PATCH 2/4] feat: Fix js file name in test in npm integration test --- tests/integration/workflows/nodejs_npm/test_nodejs_npm.py | 2 +- .../nodejs_npm/testdata/test-script-to-create-file/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/workflows/nodejs_npm/test_nodejs_npm.py b/tests/integration/workflows/nodejs_npm/test_nodejs_npm.py index a9431f4d0..2af286242 100644 --- a/tests/integration/workflows/nodejs_npm/test_nodejs_npm.py +++ b/tests/integration/workflows/nodejs_npm/test_nodejs_npm.py @@ -789,7 +789,7 @@ def test_runs_test_script_if_specified(self, runtime): runtime=runtime, ) - expected_files = {"package.json", "copied.js"} + expected_files = {"package.json", "created.js"} output_files = set(os.listdir(self.artifacts_dir)) self.assertEqual(expected_files, output_files) diff --git a/tests/integration/workflows/nodejs_npm/testdata/test-script-to-create-file/package.json b/tests/integration/workflows/nodejs_npm/testdata/test-script-to-create-file/package.json index 623407e0e..64de691d4 100644 --- a/tests/integration/workflows/nodejs_npm/testdata/test-script-to-create-file/package.json +++ b/tests/integration/workflows/nodejs_npm/testdata/test-script-to-create-file/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "description": "", "scripts": { - "test": "touch copied.js" + "test": "touch created.js" }, "keywords": [], "author": "", From 253b8e1180b1e8ede2bbf138e1ff27927eb1e1c3 Mon Sep 17 00:00:00 2001 From: Kush Saraiya Date: Thu, 5 Sep 2024 13:47:47 +0530 Subject: [PATCH 3/4] feat: Run lint fix --- aws_lambda_builders/workflows/nodejs_npm/actions.py | 1 + aws_lambda_builders/workflows/nodejs_npm/workflow.py | 2 +- tests/unit/workflows/nodejs_npm/test_actions.py | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/aws_lambda_builders/workflows/nodejs_npm/actions.py b/aws_lambda_builders/workflows/nodejs_npm/actions.py index dc7a9db8f..c77e2fba1 100644 --- a/aws_lambda_builders/workflows/nodejs_npm/actions.py +++ b/aws_lambda_builders/workflows/nodejs_npm/actions.py @@ -322,6 +322,7 @@ def execute(self): except OSError as ex: raise ActionFailedError(str(ex)) + class NodejsNpmTestAction(NodejsNpmInstallOrUpdateBaseAction): """ A Lambda Builder Action that runs tests in NPM project diff --git a/aws_lambda_builders/workflows/nodejs_npm/workflow.py b/aws_lambda_builders/workflows/nodejs_npm/workflow.py index 4d87cfce4..83aab8165 100644 --- a/aws_lambda_builders/workflows/nodejs_npm/workflow.py +++ b/aws_lambda_builders/workflows/nodejs_npm/workflow.py @@ -127,7 +127,7 @@ def __init__(self, source_dir, artifacts_dir, scratch_dir, manifest_path, runtim self.actions.append( NodejsNpmTestAction( install_dir=self.manifest_dir if is_building_in_source and is_external_manifest else self.build_dir, - subprocess_npm=subprocess_npm + subprocess_npm=subprocess_npm, ) ) diff --git a/tests/unit/workflows/nodejs_npm/test_actions.py b/tests/unit/workflows/nodejs_npm/test_actions.py index c80eb8183..5e95cfe6f 100644 --- a/tests/unit/workflows/nodejs_npm/test_actions.py +++ b/tests/unit/workflows/nodejs_npm/test_actions.py @@ -11,7 +11,7 @@ NodejsNpmrcCleanUpAction, NodejsNpmLockFileCleanUpAction, NodejsNpmCIAction, - NodejsNpmTestAction + NodejsNpmTestAction, ) from aws_lambda_builders.workflows.nodejs_npm.npm import NpmExecutionError @@ -221,6 +221,7 @@ def test_raises_action_failed_when_removing_fails(self, OSUtilMock): with self.assertRaises(ActionFailedError): action.execute() + class TestNodejsNpmTestAction(TestCase): @patch("aws_lambda_builders.workflows.nodejs_npm.npm.SubprocessNpm") def test_runs_npm_test_for_npm_project(self, SubprocessNpmMock): From ac8f66c9962a098c578f11677a1285a4b6197ebc Mon Sep 17 00:00:00 2001 From: saraiyakush <52939390+saraiyakush@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:07:24 +0530 Subject: [PATCH 4/4] Run npm test if env variable set to true --- .../workflows/nodejs_npm/actions.py | 16 +++++++++++----- tests/unit/workflows/nodejs_npm/test_actions.py | 14 +++++++++++++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/aws_lambda_builders/workflows/nodejs_npm/actions.py b/aws_lambda_builders/workflows/nodejs_npm/actions.py index c77e2fba1..f6d76e0f4 100644 --- a/aws_lambda_builders/workflows/nodejs_npm/actions.py +++ b/aws_lambda_builders/workflows/nodejs_npm/actions.py @@ -3,6 +3,7 @@ """ import logging +import os from typing import Optional from aws_lambda_builders.actions import ActionFailedError, BaseAction, Purpose @@ -333,15 +334,20 @@ class NodejsNpmTestAction(NodejsNpmInstallOrUpdateBaseAction): def execute(self): """ - Runs the action. + Runs the action if environment variable `SAM_NPM_RUN_TEST_WITH_BUILD` is `true`. :raises lambda_builders.actions.ActionFailedError: when NPM execution fails """ try: - LOG.debug("NODEJS running tests in: %s", self.install_dir) - - command = ["test", "--if-present"] - self.subprocess_npm.run(command, cwd=self.install_dir) + is_run_test_with_build = os.getenv("SAM_NPM_RUN_TEST_WITH_BUILD", "False") + if is_run_test_with_build == "true": + LOG.debug("NODEJS running tests in: %s", self.install_dir) + + command = ["test", "--if-present"] + self.subprocess_npm.run(command, cwd=self.install_dir) + else: + LOG.debug("NODEJS skipping tests") + LOG.debug("Add env variable 'SAM_NPM_RUN_TEST_WITH_BUILD=true' to run tests with build") except NpmExecutionError as ex: raise ActionFailedError(str(ex)) diff --git a/tests/unit/workflows/nodejs_npm/test_actions.py b/tests/unit/workflows/nodejs_npm/test_actions.py index 5e95cfe6f..ca33237f5 100644 --- a/tests/unit/workflows/nodejs_npm/test_actions.py +++ b/tests/unit/workflows/nodejs_npm/test_actions.py @@ -224,7 +224,8 @@ def test_raises_action_failed_when_removing_fails(self, OSUtilMock): class TestNodejsNpmTestAction(TestCase): @patch("aws_lambda_builders.workflows.nodejs_npm.npm.SubprocessNpm") - def test_runs_npm_test_for_npm_project(self, SubprocessNpmMock): + @patch.dict("os.environ", {"SAM_NPM_RUN_TEST_WITH_BUILD": "true"}, clear=True) + def test_runs_npm_test_for_npm_project_if_env_var_true(self, SubprocessNpmMock): subprocess_npm = SubprocessNpmMock.return_value action = NodejsNpmTestAction(install_dir="tests", subprocess_npm=subprocess_npm) @@ -236,6 +237,17 @@ def test_runs_npm_test_for_npm_project(self, SubprocessNpmMock): subprocess_npm.run.assert_called_with(expected_args, cwd="tests") @patch("aws_lambda_builders.workflows.nodejs_npm.npm.SubprocessNpm") + def test_does_not_run_npm_test_for_npm_project_if_no_env_var(self, SubprocessNpmMock): + subprocess_npm = SubprocessNpmMock.return_value + + action = NodejsNpmTestAction(install_dir="tests", subprocess_npm=subprocess_npm) + + action.execute() + + assert not subprocess_npm.run.called + + @patch("aws_lambda_builders.workflows.nodejs_npm.npm.SubprocessNpm") + @patch.dict("os.environ", {"SAM_NPM_RUN_TEST_WITH_BUILD": "true"}, clear=True) def test_raises_action_failed_when_npm_test_fails(self, SubprocessNpmMock): subprocess_npm = SubprocessNpmMock.return_value