diff --git a/README.md b/README.md index 98286b8..1b23c38 100644 --- a/README.md +++ b/README.md @@ -145,10 +145,12 @@ As well as testing individual packages you can also test all packages found in v * `test_pipfile()` - returns an IssueSet for all Python dependencies in a `Pipfile` * `test_gemfilelock()` - returns an IssueSet for all Ruby dependencies in a `Gemfile` -* `test_packagejson()` - returns an IssueSet for all Javascript dependencies in a `package.json` file +* `test_packagejson(, ())` - returns an IssueSet for all Javascript dependencies in a `package.json` file. Optionally takes a `package.lock` file * `test_gradlefile()` - returns an IssueSet for all dependencies in a `Gradlefile` * `test_sbt()` - returns an IssueSet for all dependencies defined in a `.sbt` file * `test_pom()` - returns an IssueSet for all dependencies in a Maven `pom.xml` file +* `test_yarn(, )` - returns an IssueSet for all dependencies in Yarn `package.json` and `yarn.lock` files +* `test_composer(, )` - returns an IssueSet for all dependencies in Composer `composer.json` and `composer.lock` files For example, here we are testing a Python `Pipfile`. diff --git a/snyk/models.py b/snyk/models.py index 43c69f1..238e6ce 100644 --- a/snyk/models.py +++ b/snyk/models.py @@ -164,7 +164,7 @@ def notification_settings(self): def invite(self, email: str, admin: bool = False): raise SnykNotImplementedError # pragma: no cover - def _test(self, path, contents=None): + def _test(self, path, contents=None, additional=None): if contents: # Check for a file-like object, allows us to support files # and strings in the same interface @@ -176,6 +176,15 @@ def _test(self, path, contents=None): "encoding": "base64", "files": {"target": {"contents": encoded}}, } + + # Some test methods carry a second file, often a lock file + if additional: + read = getattr(additional, "read", None) + if callable(read): + additional = additional.read() + encoded = base64.b64encode(additional.encode()).decode() + post_body["files"]["additional"] = {"contents": encoded} + resp = self.client.post(path, post_body) else: resp = self.client.get(path) @@ -212,9 +221,9 @@ def test_gemfilelock(self, contents): path = "test/rubygems?org=%s" % self.id return self._test(path, contents) - def test_packagejson(self, contents): + def test_packagejson(self, contents, lock=None): path = "test/npm?org=%s" % self.id - return self._test(path, contents) + return self._test(path, contents, lock) def test_gradlefile(self, contents): path = "test/gradle?org=%s" % self.id @@ -228,6 +237,14 @@ def test_pom(self, contents): path = "test/maven?org=%s" % self.id return self._test(path, contents) + def test_composer(self, contents, lock): + path = "test/composer?org=%s" % self.id + return self._test(path, contents, lock) + + def test_yarn(self, contents, lock): + path = "test/yarn?org=%s" % self.id + return self._test(path, contents, lock) + @dataclass class Integration(DataClassJSONMixin): diff --git a/snyk/test_models.py b/snyk/test_models.py index d0bfc2a..c70b2b3 100644 --- a/snyk/test_models.py +++ b/snyk/test_models.py @@ -139,6 +139,13 @@ def test_packagejson_test_with_file( requests_mock.post("%s/test/npm" % base_url, json=blank_test) assert organization.test_packagejson(fake_file) + def test_packagejson_test_with_files( + self, organization, base_url, blank_test, fake_file, requests_mock + ): + + requests_mock.post("%s/test/npm" % base_url, json=blank_test) + assert organization.test_packagejson(fake_file, fake_file) + def test_gradlefile_test_with_file( self, organization, base_url, blank_test, fake_file, requests_mock ): @@ -160,6 +167,20 @@ def test_pom_test_with_file( requests_mock.post("%s/test/maven" % base_url, json=blank_test) assert organization.test_pom(fake_file) + def test_composer_with_files( + self, organization, base_url, blank_test, fake_file, requests_mock + ): + + requests_mock.post("%s/test/composer" % base_url, json=blank_test) + assert organization.test_composer(fake_file, fake_file) + + def test_yarn_with_files( + self, organization, base_url, blank_test, fake_file, requests_mock + ): + + requests_mock.post("%s/test/yarn" % base_url, json=blank_test) + assert organization.test_yarn(fake_file, fake_file) + def test_missing_package_test(self, organization, base_url, requests_mock): requests_mock.get("%s/test/rubygems/puppet/4.0.0" % base_url, status_code=404) with pytest.raises(SnykError):