def test_hash(self, storage): xpi = WebExtensionFileFactory() f = xpi.open() hashed = hashlib.sha256(f.read()).hexdigest() f.close() extension = ExtensionFactory(xpi__from_func=xpi.open) assert extension.hash == hashed
def test_webext_bad_manifest(self): xpi = WebExtensionFileFactory(signed=False) xpi.add_file("manifest.json", b"") with pytest.raises(ValidationError) as exc: ExtensionFactory(xpi__from_func=xpi.open) assert len(exc.value.error_dict["xpi"]) == 1 assert exc.value.error_dict["xpi"][0].message == "Web extension manifest is corrupt."
def test_webext_bad_manifest(self): xpi = WebExtensionFileFactory(signed=False) xpi.add_file("manifest.json", b"") with pytest.raises(ValidationError) as exc: ExtensionFactory(xpi__from_func=xpi.open) assert len(exc.value.error_dict["xpi"]) == 1 assert exc.value.error_dict["xpi"][ 0].message == "Web extension manifest is corrupt."
def test_webext_no_version(self): xpi = WebExtensionFileFactory() manifest = xpi.manifest del manifest["version"] xpi.replace_manifest(manifest) with pytest.raises(ValidationError) as exc: ExtensionFactory(xpi__from_func=xpi.open) assert len(exc.value.error_dict["xpi"]) == 1 assert (exc.value.error_dict["xpi"][0].message == 'Web extensions must have a manifest key "version".')
def test_uploaded_webexts_must_have_id(self, api_client, storage): # NB: This is a fragile test. It uses a unsigned webext, and # so it relies on the ID check happening before the signing # check, so that the error comes from the former. xpi = WebExtensionFileFactory() xpi.update_manifest({"applications": {"gecko": {}}}) res = self._upload_extension(api_client, xpi.path) assert res.status_code == 400 # Client error assert res.data == { "xpi": 'Web extensions must have a manifest key "applications.gecko.id".' }
def test_cannot_update_extension_duplicate_filename(self, api_client, storage): xpi1 = WebExtensionFileFactory() ExtensionFactory(xpi__from_func=xpi1.open) xpi2 = WebExtensionFileFactory() e = ExtensionFactory(xpi__from_func=xpi2.open) with transaction.atomic(): res = self._update_extension(api_client, e.id, xpi1.path) assert res.status_code == 400 assert res.data == {"xpi": "An extension with this filename already exists."}
def test_webext_no_version(self): xpi = WebExtensionFileFactory() manifest = xpi.manifest del manifest["version"] xpi.replace_manifest(manifest) with pytest.raises(ValidationError) as exc: ExtensionFactory(xpi__from_func=xpi.open) assert len(exc.value.error_dict["xpi"]) == 1 assert ( exc.value.error_dict["xpi"][0].message == 'Web extensions must have a manifest key "version".' )
def test_can_update_without_xpi(self, api_client, storage): xpi = WebExtensionFileFactory() e = ExtensionFactory(xpi__from_func=xpi.open) res = api_client.patch(f"/api/v3/extension/{e.id}/", {"name": "new name"}) assert res.status_code == 200 e.refresh_from_db() assert e.name == "new name"
def test_uploads_must_be_signed_webext(self, api_client, storage): xpi = WebExtensionFileFactory(signed=False) res = self._upload_extension(api_client, xpi.path) assert res.status_code == 400 # Client error assert res.data == { "xpi": [ExtensionFileField.default_error_messages["not_signed"]] }
def test_cannot_create_extension_duplicate_filename(self, api_client, storage): xpi = WebExtensionFileFactory() ExtensionFactory(xpi__from_func=xpi.open) with transaction.atomic(): res = self._upload_extension(api_client, xpi.path) assert res.status_code == 400 assert res.data == {"xpi": "An extension with this filename already exists."} assert Extension.objects.count() == 1
def test_can_update_xpi(self, api_client, storage): legacy = LegacyAddonFileFactory() e = ExtensionFactory(xpi__from_func=legacy.open) webext = WebExtensionFileFactory() _, filename = os.path.split(webext.path) res = self._update_extension(api_client, e.id, webext.path) assert res.status_code == 200 e.refresh_from_db() assert e.xpi.name.endswith(filename)
def test_can_delete_extensions_no_longer_in_use(self, api_client, storage): xpi = WebExtensionFileFactory() e = ExtensionFactory(xpi__from_func=xpi.open) a = ActionFactory(name="opt-out-study") r = RecipeFactory(action=a, arguments={"extensionId": e.id}) r.revise(arguments=OptOutStudyArgumentsFactory(extensionId=e.id + 1)) res = api_client.delete(f"/api/v3/extension/{e.id}/") assert res.status_code == 204 assert Extension.objects.count() == 0
def test_cannot_delete_in_use_extension(self, api_client, storage): xpi = WebExtensionFileFactory() e = ExtensionFactory(xpi__from_func=xpi.open) a = ActionFactory(name="opt-out-study") RecipeFactory(action=a, arguments={"extensionId": e.id}) res = api_client.delete(f"/api/v3/extension/{e.id}/") assert res.status_code == 400 assert res.data == ["Extension cannot be updated while in use by a recipe."] assert Extension.objects.count() == 1
def test_can_update_extensions_no_longer_in_use(self, api_client, storage): xpi = WebExtensionFileFactory() e = ExtensionFactory(xpi__from_func=xpi.open) a = ActionFactory(name="opt-out-study") r = RecipeFactory(action=a, arguments={"extensionId": e.id}) r.revise(arguments={"extensionId": 0}) res = api_client.patch(f"/api/v3/extension/{e.id}/", {"name": "new name"}) assert res.status_code == 200 assert res.data["name"] == "new name"
def test_read_only(self, api_client, storage): xpi = WebExtensionFileFactory() with open(xpi.path, "rb") as f: res = api_client.post("/api/v1/extension/", { "name": "test extension", "xpi": f }, format="multipart") assert res.status_code == 405
def test_cannot_update_in_use_extension(self, api_client, storage): xpi = WebExtensionFileFactory() e = ExtensionFactory(xpi__from_func=xpi.open) a = ActionFactory(name="opt-out-study") RecipeFactory(action=a, arguments={"extensionId": e.id}) res = api_client.patch(f"/api/v3/extension/{e.id}/", {"name": "new name"}) assert res.status_code == 400 assert res.data == ["Extension cannot be updated while in use by a recipe."] e.refresh_from_db() assert e.name != "new name"
def test_webext_no_id(self): xpi = WebExtensionFileFactory( signed=False, overwrite_data={"applications": { "gecko": {} }}) with pytest.raises(ValidationError) as exc: ExtensionFactory(xpi__from_func=xpi.open) assert len(exc.value.error_dict["xpi"]) == 1 assert ( exc.value.error_dict["xpi"][0].message == 'Web extensions must have a manifest key "applications.gecko.id".')
def test_xpi_must_be_signed(self): xpi = WebExtensionFileFactory(signed=False) with pytest.raises(ValidationError) as exc: ExtensionFactory(xpi__from_func=xpi.open) assert len(exc.value.error_dict["xpi"]) == 1 assert exc.value.error_dict["xpi"][ 0].message == "Extension file must be signed." xpi = LegacyAddonFileFactory(signed=False) with pytest.raises(ValidationError) as exc: ExtensionFactory(xpi__from_func=xpi.open) assert len(exc.value.error_dict["xpi"]) == 1 assert exc.value.error_dict["xpi"][ 0].message == "Extension file must be signed."
def test_upload_works_webext(self, api_client, storage): xpi = WebExtensionFileFactory() res = self._upload_extension(api_client, xpi.path) assert res.status_code == 201 # created Extension.objects.filter(id=res.data["id"]).exists()
def test_uploads_must_be_signed_webext(self, api_client, storage): xpi = WebExtensionFileFactory(signed=False) res = self._upload_extension(api_client, xpi.path) assert res.status_code == 400 # Client error assert res.data == {"xpi": "Extension file must be signed."}
def test_no_duplicate_files(self, storage): xpi = WebExtensionFileFactory() ExtensionFactory(xpi__from_func=xpi.open) with transaction.atomic(), pytest.raises(FileExistsError): ExtensionFactory(xpi__from_func=xpi.open) assert Extension.objects.count() == 1
def test_extension_id(self, storage): xpi = WebExtensionFileFactory( gecko_id="*****@*****.**") extension = ExtensionFactory(xpi__from_func=xpi.open) assert extension.extension_id == "*****@*****.**"
def test_version(self, storage): xpi = WebExtensionFileFactory(overwrite_data={"version": "0.1"}) extension = ExtensionFactory(xpi__from_func=xpi.open) assert extension.version == "0.1"