Ejemplo n.º 1
0
    def test_unpublish_reverts_changes_if_approval_fails(
            self, rs_urls, rs_settings, requestsmock):
        recipe = RecipeFactory(name="Test", approver=UserFactory())
        baseline_record_url = rs_urls["workspace"]["baseline"][
            "record"].format(recipe.id)
        capabilities_record_url = rs_urls["workspace"]["capabilities"][
            "record"].format(recipe.id)
        # Deleting the record works.
        requestsmock.request("delete",
                             baseline_record_url,
                             json={"data": {
                                 "deleted": True
                             }})
        requestsmock.request("delete",
                             capabilities_record_url,
                             json={"data": {
                                 "deleted": True
                             }})

        requestsmock.request("patch",
                             rs_urls["workspace"]["baseline"]["collection"],
                             json={"data": {}})
        requestsmock.register_uri(
            "patch",
            rs_urls["workspace"]["capabilities"]["collection"],
            [
                # Approving fails.
                {
                    "status_code": 403
                },
                # Rollback succeeds.
                {
                    "status_code": 200,
                    "json": {
                        "data": {}
                    }
                },
            ],
        )

        remotesettings = exports.RemoteSettings()
        with pytest.raises(kinto_http.KintoException):
            remotesettings.unpublish(recipe)

        requests = requestsmock.request_history
        assert len(requests) == 5
        # Unpublish the recipe in both collections
        assert requests[0].url == capabilities_record_url
        assert requests[0].method == "DELETE"
        assert requests[1].url == baseline_record_url
        assert requests[1].method == "DELETE"
        # Try (and fail) to approve the capabilities change
        assert requests[2].url == rs_urls["workspace"]["capabilities"][
            "collection"]
        assert requests[2].method == "PATCH"
        # so it rollsback both collections
        assert requests[3].method == "PATCH"
        assert requests[3].url == rs_urls["workspace"]["capabilities"][
            "collection"]
        assert requests[4].method == "PATCH"
        assert requests[4].url == rs_urls["workspace"]["baseline"][
            "collection"]
Ejemplo n.º 2
0
 def test_cant_change_signature_and_other_fields(self):
     recipe = RecipeFactory(name="unchanged", signed=False)
     recipe.signature = SignatureFactory()
     with pytest.raises(ValidationError) as exc_info:
         recipe.revise(name="changed")
     assert exc_info.value.message == "Signatures must change alone"
Ejemplo n.º 3
0
 def test_recipe_force_revise(self):
     recipe = RecipeFactory(name="my name")
     revision_id = recipe.revision_id
     recipe.revise(name="my name", force=True)
     assert revision_id != recipe.revision_id
Ejemplo n.º 4
0
def console_log(message, **kwargs):
    return RecipeFactory(action=Action.objects.get(name='console-log'),
                         arguments={'message': message},
                         **kwargs)
Ejemplo n.º 5
0
    def test_filter_expression(self):
        r = RecipeFactory(extra_filter_expression="", filter_object_json=None)
        assert r.filter_expression == ""

        r = RecipeFactory(extra_filter_expression="2 + 2 == 4", filter_object_json=None)
        assert r.filter_expression == "2 + 2 == 4"
Ejemplo n.º 6
0
 def test_it_serves_revisions(self, api_client):
     recipe = RecipeFactory()
     res = api_client.get('/api/v2/recipe_revision/%s/' %
                          recipe.latest_revision.id)
     assert res.status_code == 200
     assert res.data['id'] == recipe.latest_revision.id
Ejemplo n.º 7
0
 def test_revision_id_changes(self):
     """Ensure that the revision id is incremented on each save"""
     recipe = RecipeFactory()
     revision_id = recipe.revision_id
     recipe.revise(action=ActionFactory())
     assert recipe.revision_id != revision_id
Ejemplo n.º 8
0
 def test_it_works(self, api_client):
     recipe = RecipeFactory()
     res = api_client.get(f"/api/v1/recipe/{recipe.id}/")
     assert res.status_code == 200, res.data
     assert res.data["id"] == recipe.id
Ejemplo n.º 9
0
 def test_it_unsigns_disabled_recipes(self, mocked_autograph):
     r = RecipeFactory(approver=UserFactory(), signed=True)
     call_command("update_recipe_signatures")
     r.refresh_from_db()
     assert r.signature is None
Ejemplo n.º 10
0
 def test_signed_false(self):
     r = RecipeFactory(signed=False)
     assert r.signature is None
Ejemplo n.º 11
0
 def test_signed_true(self):
     r = RecipeFactory(approver=UserFactory(), signed=True)
     assert r.signature is not None
     assert r.signature.signature == hashlib.sha256(
         r.canonical_json()).hexdigest()
     assert isinstance(r.signature.timestamp, datetime)
Ejemplo n.º 12
0
 def test_it_unsigns_disabled_recipes(self, mocked_autograph):
     r = RecipeFactory(enabled=False, signed=True)
     call_command('update_recipe_signatures')
     r.refresh_from_db()
     assert r.signature is None
Ejemplo n.º 13
0
 def test_it_signs_unsigned_enabled_recipes(self, mocked_autograph):
     r = RecipeFactory(approver=UserFactory(), enabled=True, signed=False)
     call_command('update_recipe_signatures')
     r.refresh_from_db()
     assert r.signature is not None
Ejemplo n.º 14
0
    def test_publish_and_unpublish_baseline_recipe_to_both_collections(
            self, rs_settings, rs_urls, requestsmock):
        ws_urls = rs_urls["workspace"]

        recipe = RecipeFactory()
        rs_settings.BASELINE_CAPABILITIES |= recipe.capabilities
        assert recipe.uses_only_baseline_capabilities()

        # Expect publish calls to both collections
        requestsmock.put(ws_urls["baseline"]["record"].format(recipe.id),
                         json={"data": {}},
                         status_code=201)
        requestsmock.put(ws_urls["capabilities"]["record"].format(recipe.id),
                         json={"data": {}},
                         status_code=201)
        # Expect both workspaces to be approved
        requestsmock.patch(ws_urls["baseline"]["collection"],
                           json={"data": {}})
        requestsmock.patch(ws_urls["capabilities"]["collection"],
                           json={"data": {}})

        remotesettings = exports.RemoteSettings()
        remotesettings.publish(recipe)

        requests = requestsmock.request_history
        assert len(requests) == 4
        # First it publishes a recipe to both collections
        assert requests[0].method == "PUT"
        assert requests[0].url == ws_urls["capabilities"]["record"].format(
            recipe.id)
        assert requests[1].method == "PUT"
        assert requests[1].url == ws_urls["baseline"]["record"].format(
            recipe.id)
        # and then approves both changes
        assert requests[2].method == "PATCH"
        assert requests[2].url == rs_urls["workspace"]["capabilities"][
            "collection"]
        assert requests[3].method == "PATCH"
        assert requests[3].url == rs_urls["workspace"]["baseline"][
            "collection"]

        # reset request history
        requestsmock._adapter.request_history = []

        # Expect delete calls
        requestsmock.delete(ws_urls["baseline"]["record"].format(recipe.id),
                            json={"data": {}})
        requestsmock.delete(ws_urls["capabilities"]["record"].format(
            recipe.id),
                            json={"data": {}})

        remotesettings.unpublish(recipe)

        requests = requestsmock.request_history
        assert len(requests) == 4
        # First it removes the recipe from both collections
        assert requests[0].method == "DELETE"
        assert requests[0].url == ws_urls["capabilities"]["record"].format(
            recipe.id)
        assert requests[1].method == "DELETE"
        assert requests[1].url == ws_urls["baseline"]["record"].format(
            recipe.id)
        # and then approves both changes
        assert requests[2].method == "PATCH"
        assert requests[2].url == rs_urls["workspace"]["capabilities"][
            "collection"]
        assert requests[3].method == "PATCH"
        assert requests[3].url == rs_urls["workspace"]["baseline"][
            "collection"]
Ejemplo n.º 15
0
 def test_recipe_force_update(self):
     recipe = RecipeFactory(name='my name')
     revision_id = recipe.revision_id
     recipe.update(name='my name', force=True)
     assert revision_id != recipe.revision_id
Ejemplo n.º 16
0
 def test_latest_revision_changes(self):
     """Ensure that a new revision is created on each save"""
     recipe = RecipeFactory()
     revision_id = recipe.latest_revision.id
     recipe.revise(action=ActionFactory())
     assert recipe.latest_revision.id != revision_id
Ejemplo n.º 17
0
 def test_detail_sets_no_cookies(self, api_client):
     recipe = RecipeFactory()
     res = api_client.get('/api/v2/recipe/{id}/'.format(id=recipe.id))
     assert res.status_code == 200
     assert res.client.cookies == {}
Ejemplo n.º 18
0
 def test_uses_extra_capabilities(self):
     recipe = RecipeFactory(extra_capabilities=["test.foo", "test.bar"])
     assert "test.foo" in recipe.latest_revision.capabilities
     assert "test.bar" in recipe.latest_revision.capabilities
Ejemplo n.º 19
0
    def test_it_serves_recipes(self, api_client):
        recipe = RecipeFactory()

        res = api_client.get('/api/v2/recipe/')
        assert res.status_code == 200
        assert res.data['results'][0]['name'] == recipe.name
Ejemplo n.º 20
0
 def test_action_name_is_automatically_included(self):
     action = ActionFactory()
     recipe = RecipeFactory(action=action)
     assert set(action.capabilities) <= set(
         recipe.latest_revision.capabilities)
Ejemplo n.º 21
0
 def test_revise_arguments(self):
     recipe = RecipeFactory(arguments_json="[]")
     recipe.revise(arguments=[{"id": 1}])
     assert recipe.arguments_json == '[{"id": 1}]'
Ejemplo n.º 22
0
 def test_filter_object_capabilities_are_automatically_included(self):
     filter_object = StableSampleFilter.create(input=["A"], rate=0.1)
     recipe = RecipeFactory(filter_object=[filter_object])
     assert filter_object.capabilities
     assert filter_object.capabilities <= recipe.latest_revision.capabilities
Ejemplo n.º 23
0
def show_heartbeat(**kwargs):
    return RecipeFactory(action=Action.objects.get(name='show-heartbeat'),
                         **kwargs)
Ejemplo n.º 24
0
        def test_it_serves_recipes(self, api_client):
            recipe = RecipeFactory()

            res = api_client.get("/api/v1/recipe/")
            assert res.status_code == 200
            assert res.data[0]["name"] == recipe.name
Ejemplo n.º 25
0
 def test_signature_is_correct_on_creation_if_autograph_available(self, mocked_autograph):
     recipe = RecipeFactory(approver=UserFactory(), enabler=UserFactory())
     expected_sig = fake_sign([recipe.canonical_json()])[0]["signature"]
     assert recipe.signature.signature == expected_sig
Ejemplo n.º 26
0
 def test_signature_is_correct_on_creation_if_autograph_available(
         self, mocked_autograph):
     recipe = RecipeFactory()
     expected_sig = hashlib.sha256(recipe.canonical_json()).hexdigest()
     assert recipe.signature.signature == expected_sig
Ejemplo n.º 27
0
 def test_recipe_revise_arguments(self):
     recipe = RecipeFactory(arguments_json="{}")
     recipe.revise(arguments={"something": "value"})
     assert recipe.arguments_json == '{"something": "value"}'
Ejemplo n.º 28
0
 def test_recipe_update_arguments(self):
     recipe = RecipeFactory(arguments_json='')
     recipe.update(arguments={'something': 'value'})
     assert recipe.arguments_json == '{"something": "value"}'
Ejemplo n.º 29
0
 def test_update_logging(self, mock_logger):
     recipe = RecipeFactory(name="my name")
     recipe.revise(name="my name", force=True)
     mock_logger.info.assert_called_with(
         Whatever.contains(str(recipe.id)), extra={"code": INFO_CREATE_REVISION}
     )
Ejemplo n.º 30
0
 def test_resolve_all_recipes(self, gql_client):
     r = RecipeFactory()
     res = gql_client.execute(GQ().query.allRecipes.fields("id"))
     assert res == {"data": {"allRecipes": [{"id": str(r.id)}]}}