def test_stories_list(self): phase_request = ZenRequest("fake_url").projects(12).phases(12) stories = phase_request.stories() responses.add(responses.GET, "https://agilezen.com/api/v1/projects/12/phases/12/stories", content_type="application/json", status=200, body="{}") stories.send()
def test_update_phase(self): phase_request = ZenRequest("fake_key").projects(12).phases() update_request = phase_request.update("name", "description", 1, 12) responses.add(responses.PUT, "https://agilezen.com/api/v1/projects/12/phases/", content_type="application/json", status=200, body="{}") update_request.send()
def test_add_request(self): story_request = ZenRequest("fake_key").projects(12).stories() responses.add(responses.POST, "https://agilezen.com/api/v1/projects/12/stories/", content_type="application/json", status=200, body="{}") story_request.add("New story", details="More on that later")
def test_update_request(self): story_request = ZenRequest("fake_key").projects(12).stories() responses.add(responses.PUT, "https://agilezen.com/api/v1/projects/12/stories/", content_type="application/json", status=200, body="{}") story_request.update(status="blocked", blocked_reason="Why not")
def test_list_phase(self): phase_request = ZenRequest("fake_key").projects(12).phases() responses.add(responses.GET, "https://agilezen.com/api/v1/projects/12/phases/", content_type="application/json", status=200, body="{}") phase_request.send()
def test_members_url(self): request = ZenRequest("fake_key").projects(12).members(12) members_url = "https://agilezen.com/api/v1/projects/12/members/12" responses.add(responses.GET, members_url, status=200, content_type="application/json", body="{}") request.send()
def __init__(self, config_path=None): """ Args: config_path: full path to the config file, by default '~/.kaizen.yaml' is used """ config_path = config_path or os.path.expanduser("~/.kaizen.yaml") self._config = get_config(config_path) self._zen_request = ZenRequest(self._config["api_key"])
def test_update_project(self): body = {"name": "name", "description": "description", "details": "details", "owner": 1} project = ZenRequest("fake_key").projects(12).update("name", "description", "details", 1) responses.add(responses.PUT, "https://agilezen.com/api/v1/projects/12", content_type="application/json", status=200, body=json.dumps(body)) project.send()
def test_from_zen_request(self): zen_request = ZenRequest("fake_key").update_url("/fake_url")\ .update_params({"k": "v"})\ .update_verb(VERBS.POST)\ .update_data({"x": "y"}) project_request = ProjectRequest.from_zen_request(zen_request) self.assertEqual(project_request.get_api_key(), zen_request.get_api_key()) self.assertEqual(project_request.url, "/fake_url/projects/") self.assertEqual(project_request.verb, VERBS.POST) self.assertEqual(project_request.params, {"k": "v"}) self.assertEqual(project_request.data, {"x": "y"})
def test_phase_list_url(self): phase_data = { "id": 12, "name": "Phase", "description": "Contains stories", "index": 2 } phase_url = "https://agilezen.com/api/v1/projects/12/phases/12" request = ZenRequest("fake_key").projects(12).phases(12) responses.add(responses.GET, phase_url, status=200, content_type='application/json', body=json.dumps(phase_data)) request.send()
def test_update_project(self): body = { "name": "name", "description": "description", "details": "details", "owner": 1 } project = ZenRequest("fake_key").projects(12).update( "name", "description", "details", 1) responses.add(responses.PUT, "https://agilezen.com/api/v1/projects/12", content_type="application/json", status=200, body=json.dumps(body)) project.send()
def test_projects_sets_url(self): request = ZenRequest("fake_key").projects(12) self.assertIn("projects", request.url) self.assertIn("12", request.url)
def test_add_data(self): story_request = ZenRequest("fake_key").projects(12).stories() add_request = story_request.add("New story", owner=12) self.assertEqual({"text": "New story", "owner": 12}, add_request.data)
class ZenApi(object): """Simplify access to the AgileZen API.""" @create_parser(Self, str) def __init__(self, config_path=None): """ Args: config_path: full path to the config file, by default '~/.kaizen.yaml' is used """ config_path = config_path or os.path.expanduser("~/.kaizen.yaml") self._config = get_config(config_path) self._zen_request = ZenRequest(self._config["api_key"]) @create_parser(Self) def list_projects(self, phases=False, members=False, metrics=False): """List all Projects you have access to. Args: phase: add the phases to the Project object members: add the members to the Project object metrics: add the metrics to the Project object """ request = self._zen_request.projects() enrichments = [name for name, value in [("phases", phases), ("members", members), ("metrics", metrics)] if value] if enrichments: request = request.with_enrichments(*enrichments) return request.send() @create_parser(Self, int, bool, bool, int, int) def list_stories(self, project_id=None, tasks=False, tags=False, page=1, size=100): """List stories in the Project specified by the given id. Args: project_id: id of the Project you want to list Stories tasks: should the tasks be included in the stories tags: should the tags be included in the stories page: page number to display, defaults to the first page size: max number of stories to return, defaults to 100 """ project_id = project_id or self._config["project_id"] request = self._zen_request.projects(project_id).stories() enrichments = [name for name, value in [("tasks", tasks), ("tags", tags)] if value] if enrichments: request = request.with_enrichments(*enrichments) return request.paginate(page, size).send() @create_parser(Self, int) def list_phases(self, project_id=None, stories=False, page=1, size=100): """List phases in the Project specified by the given id. Args: project_id: id of the Project you want to list Stories stories: should the stories be included in the phases page: page number to display, defaults to the first page size: max number of stories to return, defaults to 100 """ project_id = project_id or self._config["project_id"] request = self._zen_request.projects(project_id).phases() if stories: request = request.with_enrichments("stories") return request.paginate(page, size).send() @create_parser(Self, int, str, str, int, int) def add_phase(self, name, description, project_id=None, index=None, limit=None): """Add a Phase to the Project specified by the given id. Args: name: name of the newly created Phase description: description of the newly created Phase project_id: id of the Project to add the Phase to index: the zero based index into the list of phases limit: Work in progress limit for phase """ project_id = project_id or self._config["project_id"] return self._zen_request.projects(project_id).phases()\ .add(name, description, index, limit).send() def _get_next_phase_id(self, phase_name, project_id): # We can assume we won't need to paginate and go over more than 100 Phases phases = self.list_phases(project_id)["items"] if phases[-1]["name"] == phase_name: raise ValueError("Story is already in the last phase '%s'" % phase_name) for (idx, phase) in enumerate(phases): if phase["name"] == phase_name: return phases[idx + 1]["id"] raise ValueError("Unknown phase '%s'" % phase_name) @create_parser(Self, int, int, name="bump-phase") def move_story_to_next_phase(self, story_id, project_id=None): """The Story will be moved to the next Phase. Args: story_id: id of the Story to move project_id: id of the Project """ project_id = project_id or self._config["project_id"] request = self._zen_request.projects(project_id) story_request = request.stories(story_id) story = story_request.send() try: phase_id = self._get_next_phase_id(story["phase"]["name"], project_id) except ValueError as error: return error.message return story_request.update(phase_id=phase_id).send()
def test_projects_return_project_request(self): self.assertEqual(type(ZenRequest("fake_key").projects()), ProjectRequest)