From ca03d8f4e9c0a6aac2afa235ca9fb8dfe8f79ec0 Mon Sep 17 00:00:00 2001 From: Aleksey Burov Date: Tue, 9 Jan 2018 14:19:02 +0700 Subject: [PATCH] Add more features (#16) Fix #15 Fix #13 * Add dynamic attribute from _links * remove old repsonse.json * Add Atachment object and download method * try to fix test * escape / * add revisions as property * Add more docs * omit test coverage * duplicate test name * source dir to coverage * rtfm codacy manual * Add docs, deploy on develop\master only * star repo --- .codacy.yml | 3 + .travis.yml | 15 +- README.md | 109 +++++------ docs/ADVANCED.md | 80 +++++++++ docs/CONTRIBUTE.md | 19 ++ docs/OTHERS.md | 26 +++ setup.py | 4 +- .../teams/response.json | 10 +- .../_apis/projects/ProjectName/response.json | 2 +- .../_apis/projects/response.json | 2 +- .../changesets/10/workItems/response.json | 4 +- .../_apis/tfvc/changesets/response.json | 50 +++--- .../response.json | 16 +- .../_apis/wit/wiql/response.json | 14 +- .../_apis/wit/workitems/100/response.json | 2 +- .../wit/workitems/100/revisions/response.json | 150 ++++++++++++++++ .../_apis/wit/workitems/response.json | 4 +- .../teams/response.json | 22 --- .../_apis/projects/ProjectName/response.json | 12 -- .../Development/_apis/projects/response.json | 12 -- .../changesets/10/workItems/response.json | 21 --- .../_apis/tfvc/changesets/response.json | 107 ----------- .../response.json | 47 ----- .../Development/_apis/wit/wiql/response.json | 50 ------ .../_apis/wit/workitems/100/response.json | 23 --- .../_apis/wit/workitems/response.json | 50 ------ tests/test_resources.py | 110 +++++++++--- tfs/connection.py | 76 ++++++-- tfs/resources.py | 170 +++++++++++++----- 29 files changed, 667 insertions(+), 543 deletions(-) create mode 100644 .codacy.yml create mode 100644 docs/ADVANCED.md create mode 100644 docs/CONTRIBUTE.md create mode 100644 docs/OTHERS.md create mode 100644 tests/resources/tfs/DefaultCollection/_apis/wit/workitems/100/revisions/response.json delete mode 100644 tests/resources/tfs/Development/_apis/projects/26e73aff-d80b-430d-b95c-76140bf184de/teams/response.json delete mode 100644 tests/resources/tfs/Development/_apis/projects/ProjectName/response.json delete mode 100644 tests/resources/tfs/Development/_apis/projects/response.json delete mode 100644 tests/resources/tfs/Development/_apis/tfvc/changesets/10/workItems/response.json delete mode 100644 tests/resources/tfs/Development/_apis/tfvc/changesets/response.json delete mode 100644 tests/resources/tfs/Development/_apis/wit/wiql/cbbcdcaa-377f-42f7-a544-4d9507f2aa22/response.json delete mode 100644 tests/resources/tfs/Development/_apis/wit/wiql/response.json delete mode 100644 tests/resources/tfs/Development/_apis/wit/workitems/100/response.json delete mode 100644 tests/resources/tfs/Development/_apis/wit/workitems/response.json diff --git a/.codacy.yml b/.codacy.yml new file mode 100644 index 0000000..d3c4016 --- /dev/null +++ b/.codacy.yml @@ -0,0 +1,3 @@ +--- +exclude_paths: + - tests/** diff --git a/.travis.yml b/.travis.yml index 4f8ac17..01eb8b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ script: - coverage run -m py.test tests - coverage xml - python-codacy-coverage -r coverage.xml + deploy: provider: pypi user: devopshq @@ -19,10 +20,22 @@ deploy: secure: "u7kqhFT32wLvGvdXLRg3RtTdfGcSzfFWTQb0p1cdRHWBm/771Q2H4bfvwv8GTVmSz+0txtW4O20/VMuMSULqAgW9ChLoNnpppsiEuwOL/KgFknOMgegM+QqdBU7OyB4c0XBxCEfoe8/+Z8lNlB1+UShwh6aJHjiUvR9U537ebtniMWyj0Nb93f53YQGsh29gbuqDNzIWPePFuSDBhKTRhKEHdBfol11YCgyNs2MXkdTUQ60G+DMtdAOM32mJEXi3n2yQWtnWdnsxApqZ4LLlEO1J7FJ0/6sXEd5Y8aQBoYPdE5RdGjo1gjxpp0tL3WxXisG1TlHdgNShKzO5CT4pUFD5qWqhbzlwDM8eI3xFS39I75bVeoPrQ9jn0MlBs8JQJIEFbn6HDW7G/hezMoQPwH2Sn2ET9/XH9axt3U7Wrqf9I10FuFMdBZ4hD62kml94WfxiC40sCNMgYW/zPYGSUQLXfzWImyFz32K8MTQErWVoiaDz8bx5rjLa+zmmwchhZCX4YdBh4BMIOy793YYx6/jLGUBhKuIyHGYREUF/ZlZg5rYssbKUP9G4TdzPix3dGCBgdtrsYwUZ79Odu/SjwV8uzOfcU2p9E0j1GjEK5BnfwY7b5ZpXeagBze34kDU3U89Jnmwc08eu0S+olv7/4iGn+gvQZOvM9s0CShhMI7I=" distributions: sdist bdist_wheel on: - all_branches: true + branch: master skip_cleanup: true + +deploy: + provider: pypi + user: devopshq + password: + secure: "u7kqhFT32wLvGvdXLRg3RtTdfGcSzfFWTQb0p1cdRHWBm/771Q2H4bfvwv8GTVmSz+0txtW4O20/VMuMSULqAgW9ChLoNnpppsiEuwOL/KgFknOMgegM+QqdBU7OyB4c0XBxCEfoe8/+Z8lNlB1+UShwh6aJHjiUvR9U537ebtniMWyj0Nb93f53YQGsh29gbuqDNzIWPePFuSDBhKTRhKEHdBfol11YCgyNs2MXkdTUQ60G+DMtdAOM32mJEXi3n2yQWtnWdnsxApqZ4LLlEO1J7FJ0/6sXEd5Y8aQBoYPdE5RdGjo1gjxpp0tL3WxXisG1TlHdgNShKzO5CT4pUFD5qWqhbzlwDM8eI3xFS39I75bVeoPrQ9jn0MlBs8JQJIEFbn6HDW7G/hezMoQPwH2Sn2ET9/XH9axt3U7Wrqf9I10FuFMdBZ4hD62kml94WfxiC40sCNMgYW/zPYGSUQLXfzWImyFz32K8MTQErWVoiaDz8bx5rjLa+zmmwchhZCX4YdBh4BMIOy793YYx6/jLGUBhKuIyHGYREUF/ZlZg5rYssbKUP9G4TdzPix3dGCBgdtrsYwUZ79Odu/SjwV8uzOfcU2p9E0j1GjEK5BnfwY7b5ZpXeagBze34kDU3U89Jnmwc08eu0S+olv7/4iGn+gvQZOvM9s0CShhMI7I=" + distributions: sdist bdist_wheel + on: + branch: develop + skip_cleanup: true + after_script: - echo "Deploy to PyPI finished." + env: global: - secure: "d67oNhecPXRl0HiTfcI29PKUPLo657VMaCLAt7BAyPk3LXLSgkz9X0fpz0I2dq3DrtREMrKNcoHjFY5x5FoMemYJfg/93PPk8hRbu3XWKiGVHVdj8xwu2hJSSxl/enmEs25qAs1c3Rss+9CyZ7rP4cY7J0hiVymgBZKWSG/8UL6P2D3iDpvxf3EKapPRrf8FP6l3Nmwk3iVlFrwzq4koBUlC2SEd2Hr1uL+iGHuOdNlH4bksMc0nIeC6f905YJ1x3hHMg46h75RkWBrPmj9nn5eAS3jva8Fg9WrDiieF9JrL6GZ0SpektgDS+SjZuinAgjmDZQOogLZtg8+cyDVSud5x0d1K1OQBatNb1ZWVDqLld2E6/6Pxp1x1Bg52OpQvxL23HZkg7XZtxhZzhOEI4f/TvG4123voygjQXSZXVrdqzLwwAxuGqtxym5lcAe7tRllmnXs/Nty/M5ICQhVU56pxoMvSjwwXySBdP69TC6YBNtLbDY9ySImd3lJpbJcc0ftuo2aU6FJjXMNFTuTjmVfw3g/fKvPcjVsTbHqVWOhyfI/smAJxgJx/ugEm9PFk7i2rIc3JkYtW1AyoIXGJBeytvZRlyDz9ulowYSEPCtKL6Z9tqMGPHUntKwwHKbRTBIGsDhnRLN095MYbb7d7aOagBIfOGSaxY3e/mpyXwQI=" \ No newline at end of file diff --git a/README.md b/README.md index a5f3959..dcdd519 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Microsoft TFS Python Library (TFS API Python client) ------ +# Table of Contents - [Introduction](#introduction) - [Quickstart](#quickstart) - [Installation](#installation) @@ -12,27 +13,27 @@ Microsoft TFS Python Library (TFS API Python client) - [Authorization](#authorization) - [Timeout connection](#timeout-connection) - [Workitem](#workitem) + - [Update workitem](#update-workitem) + - [Workitem attachments](#workitem-attachments) - [Run Saved Queries](#run-saved-queries) - [Run WIQL](#run-wiql) - - [Changesets](#changesets) - - [Project and Team](#project--team) + - [Advanced](#advanced) - [Guide](#guide) - - [Compability](#compability) - - [Development](#development) - - [Tests](#tests) - - [TODO](#todo) + - [Compatibility](#Compatibility) + - [Contribute](#contribute) ------ # Introduction Microsoft Team Foundation Server Python Library is a Microsoft TFS API Python client that can work with Microsoft TFS workflow and workitems. -This tool allows: -1. Get WorkItems (WI). -2. Set WI fields. -3. Run WI search queries. -4. Work with TFVC changesets. -5. Work with TFS Projects. +This python library allows: +1. Get [WorkItems (WI)](#workitem) +2. Set [WI fields](#update-workitem) +3. Run [WI search queries](#run-saved-queries) +4. Run [WIQL](#run-wiql) +4. Work [with TFVC changesets](docs/OTHER.md) +5. Work [with TFS Projects](docs/OTHER.md) ## Installation ``` @@ -90,14 +91,6 @@ print(workitem.field_names) # Case insensetive. Remove space in field name print(workitem['assignedTo']) -# Update field -workitem['state'] = 'Complete' - -# Add comment -print(workitem.history) -workitem['History'] = "Omg, it is goos issue!" -print(workitem.history) - # Workitem Parent Workitem parent = workitem.parent if parent: # Parent is None if Workitem hasn't Parent link @@ -107,6 +100,42 @@ if parent: # Parent is None if Workitem hasn't Parent link childs = workitem.childs if childs: # Child is empty list if Workitem hasn't Child link print("Workitem with id={} have Childs={}".format(workitem.id, ",".join([x.id for x in childs]))) + +# Workitem revisions +revisions = workitem.revisions +``` + +### Update workitem + +```python +# Update field +workitem['state'] = 'Complete' + +# Add comment +print(workitem.history) +workitem['History'] = "Omg, it is goos issue!" +print(workitem.history) +``` + +### Workitem attachments +If workitem has attachments, you can download it and get info about. +```python +attachments = workitem.attachments +attachment = attachments[0] +# Internal TFS UID +print(attachment.id) + +# Filename +print(attachment.name) + +# TFS Download URL +print(attachment.url) + +# You can download file to folder +attachment.download('/home/user/folder') + +# All raw data +print(attachment.data) ``` ## Run Saved Queries @@ -159,39 +188,17 @@ workitems = wiql.workitems print(workitems[0]['Title']) ``` -## Changesets -```python -# Get changesets from 1000 to 1002 -changesets = client.get_changesets(from_=1000, to_=1002) - -# Get changesets and related Workitems -changesets = client.get_changesets(top=1) -linked_workitems = changesets[0].workitems -``` - -## Project & Team -```python -# Get all project -all_projects = client.get_projects() +## Advanced +- [Advanced usage](docs/ADVANCED.md) +- Some [others object available](docs/OTHERS.md) -# Get project -project_name = client.get_project("MyProjectName") +# Guide +If you use this library, [put a star](https://help.github.com/articles/about-stars/) on [this repository](https://github.com/devopshq/tfs). This motivates us and other developers to develop the library :) -# Get project team -project_team = project_name.team -``` - - -## Guide -### Compability +## Compatibility +- Tested with **Python.3.4** - TFS 2015 - TFS 2017 -## Development -### Tests -We use HTTPPrety. For GET-response locate you response.json to folder by URL. E.g: -- http://tfs.tfs.ru/tfs/DefaultCollection/_apis/wit/workitems?ids=anyid&anyflag => **tests/resources/tfs/DefaultCollection/_apis/wit/workitems/response.json** -- http://tfs.tfs.ru/tfs/DefaultCollection/_apis/tfvc/changesets/10/workItems => **tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/10/workItems/response.json** - -### TODO -- Implemented Resources-API (like https://github.com/pycontribs/jira) +## Contribute +[About contribute](docs/CONTRIBUTE.md) diff --git a/docs/ADVANCED.md b/docs/ADVANCED.md new file mode 100644 index 0000000..084ae83 --- /dev/null +++ b/docs/ADVANCED.md @@ -0,0 +1,80 @@ +Advanced usage +-------------- + +# Table of Contents +- [TFSObject](#tfsobject) +- [Workitem](#workitem) + - [Relations](#relations) + - [Links](#links) +- [TFSHTTPClient](#tfshttpclient) + +# TFSObject +All `TFSObject` instances contain raw TFS response (in JSON, which was converted to python-dict) in `self.data` + +```python +workitem = client.get_workitem(100) +print(workitem.data) + +history = workitem.history +print(history.data) + +revisions = workitem.revisions +print(revisions.data) + +attachment = workitem.attachments[0] +print(attachment.data) +``` + +All `TFSObject` instances have `self.url`, `self.uri`: +```python +workitem = client.get_workitem(100) + +# Full URL with https points to API object +print(workitem.url) + +# URI points to API object +print(workitem.uri) + +``` + +# Workitem + +## Relations +Workitem has relation with other object. This library support only `workitem.childs`, `workitem.parent`, and `workitem.attachments` +Read more about [TFS link types](https://docs.microsoft.com/en-us/vsts/work/customize/reference/link-type-element-reference#link-types) + +If you need find other type, you can use `workitem.find_in_relations` method: +```python +workitem = client.get_workitem(100) + +# links is Dict +links = workitem.find_in_relations('Hyperlink') + +# duplicates is Dict +# Really type is System.LinkTypes.Duplicate-Forward, but it will be found +duplicates = workitem.find_in_relations('Duplicate-Forward') +``` + +## Links +Some `TFSObject` have `_links` in their data. You can acces to this data as raw or get new `TFSObject`: +```python +workitem = client.get_workitem(100) + +# This links also in dir() +dir(workitem) + +# Get TFSObject +workitem.workItemHistory # list of object +workitem.workItemRevisions # list of object +workitem.workItemType # TFSObject + +# Get raw data +links = workitem.data['_links'] +print(links) + +``` + +## TFSHTTPClient +**TODO**: Describe how other people can use some usefull function and object from `tfs.connection` +- Get from TFSAPI +- `send_*` methods diff --git a/docs/CONTRIBUTE.md b/docs/CONTRIBUTE.md new file mode 100644 index 0000000..2449557 --- /dev/null +++ b/docs/CONTRIBUTE.md @@ -0,0 +1,19 @@ +# Table of Contents +- [Contribute](#contribute) + - [Development](#development) + - [Tests](#tests) + +# Contribute +We will be grateful to see you in the ranks of the contributors! We have [some esay issue](https://github.com/devopshq/tfs/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22), which will suit as first issue or for junior python + +## Development +Development takes place on GitHub, where the git-flow branch structure is used: + +* ``master`` - contains the latest released code. +* ``develop`` - is used for development of the next release. **Pull request must be in this branch** +* ``feature/XXX`` - feature branches are used for development of new features before they are merged to ``develop``. + +## Tests +We use HTTPPrety. For GET-response locate you response.json to folder by URL. E.g: +- http://tfs.tfs.ru/tfs/DefaultCollection/_apis/wit/workitems?ids=anyid&anyflag => **tests/resources/tfs/DefaultCollection/_apis/wit/workitems/response.json** +- http://tfs.tfs.ru/tfs/DefaultCollection/_apis/tfvc/changesets/10/workItems => **tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/10/workItems/response.json** diff --git a/docs/OTHERS.md b/docs/OTHERS.md new file mode 100644 index 0000000..3c4046b --- /dev/null +++ b/docs/OTHERS.md @@ -0,0 +1,26 @@ +# Table of Contents +- [Changesets](#changesets) +- [Project & Team](#project--team) + + +# Changesets +```python +# Get changesets from 1000 to 1002 +changesets = client.get_changesets(from_=1000, to_=1002) + +# Get changesets and related Workitems +changesets = client.get_changesets(top=1) +linked_workitems = changesets[0].workitems +``` + +# Project & Team +```python +# Get all project +all_projects = client.get_projects() + +# Get project +project_name = client.get_project("MyProjectName") + +# Get project team +project_team = project_name.team +``` diff --git a/setup.py b/setup.py index 2fcc9de..cc8df8d 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ description='Microsoft TFS Python Library (TFS API Python client) that can work with TFS workflow and workitems.', - long_description='You can see detailed user manual here: https://devopshq.github.io/tfs/', + long_description='You can see detailed user manual here: https://github.com/devopshq/tfs/blob/master/README.md', license='MIT', @@ -43,7 +43,7 @@ author_email='allburov@gmail.com', - url='https://devopshq.github.io/tfs/', + url='https://github.com/devopshq/tfs/blob/master/README.md', download_url='https://github.com/devopshq/tfs.git', diff --git a/tests/resources/tfs/DefaultCollection/_apis/projects/26e73aff-d80b-430d-b95c-76140bf184de/teams/response.json b/tests/resources/tfs/DefaultCollection/_apis/projects/26e73aff-d80b-430d-b95c-76140bf184de/teams/response.json index 248b27f..ec87e8c 100644 --- a/tests/resources/tfs/DefaultCollection/_apis/projects/26e73aff-d80b-430d-b95c-76140bf184de/teams/response.json +++ b/tests/resources/tfs/DefaultCollection/_apis/projects/26e73aff-d80b-430d-b95c-76140bf184de/teams/response.json @@ -1,22 +1,22 @@ { "id": "26e73aff-d80b-430d-b95c-76140bf184de", "name": "ProjectName", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de", "state": "wellFormed", "_links": { "self": { - "href": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de" + "href": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de" }, "collection": { - "href": "https:\/\/tfs.tfs.ru\/tfs\/_apis\/projectCollections\/9025d248-2b1b-48a7-bb43-8abf779eeeaa" + "href": "http:\/\/tfs.tfs.ru\/tfs\/_apis\/projectCollections\/9025d248-2b1b-48a7-bb43-8abf779eeeaa" }, "web": { - "href": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/ProjectName" + "href": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/ProjectName" } }, "defaultTeam": { "id": "6475f0ad-b08b-4a74-8576-d80baf80600a", "name": "ProjectName Team", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de\/teams\/6475f0ad-b08b-4a74-8576-d80baf80600a" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de\/teams\/6475f0ad-b08b-4a74-8576-d80baf80600a" } } \ No newline at end of file diff --git a/tests/resources/tfs/DefaultCollection/_apis/projects/ProjectName/response.json b/tests/resources/tfs/DefaultCollection/_apis/projects/ProjectName/response.json index 6e24af8..502c7af 100644 --- a/tests/resources/tfs/DefaultCollection/_apis/projects/ProjectName/response.json +++ b/tests/resources/tfs/DefaultCollection/_apis/projects/ProjectName/response.json @@ -4,7 +4,7 @@ { "id": "26e73aff-d80b-430d-b95c-76140bf184de", "name": "ProjectName", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de", "state": "wellFormed", "revision": 43900539 } diff --git a/tests/resources/tfs/DefaultCollection/_apis/projects/response.json b/tests/resources/tfs/DefaultCollection/_apis/projects/response.json index 6e24af8..502c7af 100644 --- a/tests/resources/tfs/DefaultCollection/_apis/projects/response.json +++ b/tests/resources/tfs/DefaultCollection/_apis/projects/response.json @@ -4,7 +4,7 @@ { "id": "26e73aff-d80b-430d-b95c-76140bf184de", "name": "ProjectName", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de", "state": "wellFormed", "revision": 43900539 } diff --git a/tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/10/workItems/response.json b/tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/10/workItems/response.json index e28aa43..471b3a3 100644 --- a/tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/10/workItems/response.json +++ b/tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/10/workItems/response.json @@ -2,7 +2,7 @@ "count": 2, "value": [ { - "webUrl": "https:\/\/tfs.tfs.ru\/tfs\/web\/wi.aspx?pcguid=9025d248-2b1b-48a7-bb43-8abf779eeeaa&id=100", + "webUrl": "http:\/\/tfs.tfs.ru\/tfs\/web\/wi.aspx?pcguid=9025d248-2b1b-48a7-bb43-8abf779eeeaa&id=100", "id": 100, "title": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c FB", "workItemType": "Task", @@ -10,7 +10,7 @@ "assignedTo": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d " }, { - "webUrl": "https:\/\/tfs.tfs.ru\/tfs\/web\/wi.aspx?pcguid=9025d248-2b1b-48a7-bb43-8abf779eeeaa&id=100", + "webUrl": "http:\/\/tfs.tfs.ru\/tfs\/web\/wi.aspx?pcguid=9025d248-2b1b-48a7-bb43-8abf779eeeaa&id=100", "id": 101, "title": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c FB", "workItemType": "Task", diff --git a/tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/response.json b/tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/response.json index 5bffcb1..0829b8e 100644 --- a/tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/response.json +++ b/tests/resources/tfs/DefaultCollection/_apis/tfvc/changesets/response.json @@ -3,40 +3,40 @@ "value": [ { "changesetId": 10, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18736", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18736", "author": { "id": "831299d4-f278-4858-a188-d1edae64125d", "displayName": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d", "uniqueName": "DOMAIN\\MIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" }, "checkedInBy": { "id": "dc115031-b185-421e-a58d-b2b19903f51a", "displayName": "deploy", "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" }, "createdDate": "2017-06-30T15:43:41.71Z", "comment": "Merge Main into R16.1 (PdqlAssetId)" }, { "changesetId": 11, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18732", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18732", "author": { "id": "831299d4-f278-4858-a188-d1edae64125d", "displayName": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d", "uniqueName": "DOMAIN\\MIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" }, "checkedInBy": { "id": "dc115031-b185-421e-a58d-b2b19903f51a", "displayName": "deploy", "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" }, "createdDate": "2017-06-30T12:16:46.907Z", "comment": "\u0414\u043e\u0431\u0430\u0432\u0438\u043b \u0442\u0435\u0433 allIncidents \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0412\u0441\u0435 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442\u044b + \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u043f\u0440\u043e\u0441\u0442", @@ -44,20 +44,20 @@ }, { "changesetId": 12, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18727", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18727", "author": { "id": "831299d4-f278-4858-a188-d1edae64125d", "displayName": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d", "uniqueName": "DOMAIN\\MIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" }, "checkedInBy": { "id": "dc115031-b185-421e-a58d-b2b19903f51a", "displayName": "deploy", "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" }, "createdDate": "2017-06-30T08:48:18.133Z", "comment": "\u0418\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0445 \u0438\u043d\u0446\u0438\u0434", @@ -65,40 +65,40 @@ }, { "changesetId": 13, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18725", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18725", "author": { "id": "c7b8ae59-8bec-4d47-941e-66814c9dacea", "displayName": "\u041a\u0438\u0440\u0438\u043b\u043b \u0418\u0432\u0430\u043d\u043e\u0432", "uniqueName": "DOMAIN\\KIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/c7b8ae59-8bec-4d47-941e-66814c9dacea", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=c7b8ae59-8bec-4d47-941e-66814c9dacea" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/c7b8ae59-8bec-4d47-941e-66814c9dacea", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=c7b8ae59-8bec-4d47-941e-66814c9dacea" }, "checkedInBy": { "id": "dc115031-b185-421e-a58d-b2b19903f51a", "displayName": "deploy", "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" }, "createdDate": "2017-06-29T10:47:29.287Z", "comment": "\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0433\u0440\u0443\u043f\u043f" }, { "changesetId": 14, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18723", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18723", "author": { "id": "c7b8ae59-8bec-4d47-941e-66814c9dacea", "displayName": "\u041a\u0438\u0440\u0438\u043b\u043b \u0418\u0432\u0430\u043d\u043e\u0432", "uniqueName": "DOMAIN\\KIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/c7b8ae59-8bec-4d47-941e-66814c9dacea", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=c7b8ae59-8bec-4d47-941e-66814c9dacea" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/c7b8ae59-8bec-4d47-941e-66814c9dacea", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=c7b8ae59-8bec-4d47-941e-66814c9dacea" }, "checkedInBy": { "id": "dc115031-b185-421e-a58d-b2b19903f51a", "displayName": "deploy", "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" }, "createdDate": "2017-06-27T15:27:32.347Z", "comment": "\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0433\u0440\u0443\u043f\u043f - \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f" diff --git a/tests/resources/tfs/DefaultCollection/_apis/wit/wiql/cbbcdcaa-377f-42f7-a544-4d9507f2aa22/response.json b/tests/resources/tfs/DefaultCollection/_apis/wit/wiql/cbbcdcaa-377f-42f7-a544-4d9507f2aa22/response.json index f62d06b..1d03210 100644 --- a/tests/resources/tfs/DefaultCollection/_apis/wit/wiql/cbbcdcaa-377f-42f7-a544-4d9507f2aa22/response.json +++ b/tests/resources/tfs/DefaultCollection/_apis/wit/wiql/cbbcdcaa-377f-42f7-a544-4d9507f2aa22/response.json @@ -6,42 +6,42 @@ { "referenceName": "System.Id", "name": "ID", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id" }, { "referenceName": "System.WorkItemType", "name": "Work Item Type", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.WorkItemType" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.WorkItemType" }, { "referenceName": "System.Title", "name": "Title", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Title" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Title" }, { "referenceName": "System.AssignedTo", "name": "Assigned To", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.AssignedTo" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.AssignedTo" }, { "referenceName": "System.State", "name": "State", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.State" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.State" }, { "referenceName": "System.Tags", "name": "Tags", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Tags" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Tags" } ], "workItems": [ { "id": 100, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100" }, { "id": 101, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100" } ] } \ No newline at end of file diff --git a/tests/resources/tfs/DefaultCollection/_apis/wit/wiql/response.json b/tests/resources/tfs/DefaultCollection/_apis/wit/wiql/response.json index 375e16a..5736f68 100644 --- a/tests/resources/tfs/DefaultCollection/_apis/wit/wiql/response.json +++ b/tests/resources/tfs/DefaultCollection/_apis/wit/wiql/response.json @@ -3,17 +3,17 @@ "columns": [ { "name": "ID", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id", "referenceName": "System.Id" }, { "name": "Severity", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", "referenceName": "Microsoft.VSTS.Common.Severity" }, { "name": "Target Version", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", "referenceName": "TargetVersion" } ], @@ -21,7 +21,7 @@ { "field": { "name": "Target Version", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", "referenceName": "TargetVersion" }, "descending": false @@ -29,7 +29,7 @@ { "field": { "name": "Severity", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", "referenceName": "Microsoft.VSTS.Common.Severity" }, "descending": false @@ -37,11 +37,11 @@ ], "workItems": [ { - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100", "id": 100 }, { - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/101", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/101", "id": 101 } ], diff --git a/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/100/response.json b/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/100/response.json index a6275e1..0545a34 100644 --- a/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/100/response.json +++ b/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/100/response.json @@ -19,5 +19,5 @@ "Microsoft.VSTS.Common.Priority": 2, "Microsoft.VSTS.Common.Severity": "3 - Medium" }, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/1370" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/1370" } diff --git a/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/100/revisions/response.json b/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/100/revisions/response.json new file mode 100644 index 0000000..1648d07 --- /dev/null +++ b/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/100/revisions/response.json @@ -0,0 +1,150 @@ +{ + "count": 6, + "value": [ + { + "fields": { + "Microsoft.VSTS.Common.Priority": 2, + "Microsoft.VSTS.Common.StateChangeDate": "2017-03-03T09:12:44.673Z", + "Microsoft.VSTS.Common.ValueArea": "Business", + "System.AreaPath": "PROJECTQA_test\\lolo", + "System.BoardColumn": "New", + "System.ChangedBy": "Dmitry Ivanov ", + "System.ChangedDate": "2017-03-03T09:12:44.673Z", + "System.CreatedBy": "Dmitry Ivanov ", + "System.CreatedDate": "2017-03-03T09:12:44.673Z", + "System.IterationPath": "PROJECTQA_test", + "System.Reason": "New", + "System.State": "New", + "System.TeamProject": "PROJECTQA_test", + "System.Title": "asdasd", + "System.WorkItemType": "User Story", + "WEF_664133C1618A415F8956A8EB6EE71483_Kanban.Column": "New" + }, + "id": 100, + "rev": 1, + "url": "http://tfs.tfs.ru/tfs/DefaultCollection/_apis/wit/workItems/100/revisions/1" + }, + { + "fields": { + "Microsoft.VSTS.Common.Priority": 2, + "Microsoft.VSTS.Common.StackRank": 1000031622.0, + "Microsoft.VSTS.Common.StateChangeDate": "2017-03-03T09:12:44.673Z", + "Microsoft.VSTS.Common.ValueArea": "Business", + "System.AreaPath": "PROJECTQA_test\\lolo", + "System.BoardColumn": "New", + "System.ChangedBy": "Dmitry Ivanov ", + "System.ChangedDate": "2017-03-03T09:12:45.277Z", + "System.CreatedBy": "Dmitry Ivanov ", + "System.CreatedDate": "2017-03-03T09:12:44.673Z", + "System.IterationPath": "PROJECTQA_test", + "System.Reason": "New", + "System.State": "New", + "System.TeamProject": "PROJECTQA_test", + "System.Title": "asdasd", + "System.WorkItemType": "User Story", + "WEF_664133C1618A415F8956A8EB6EE71483_Kanban.Column": "New" + }, + "id": 100, + "rev": 2, + "url": "http://tfs.tfs.ru/tfs/DefaultCollection/_apis/wit/workItems/100/revisions/2" + }, + { + "fields": { + "Microsoft.VSTS.Common.Priority": 2, + "Microsoft.VSTS.Common.StackRank": 1000031622.0, + "Microsoft.VSTS.Common.StateChangeDate": "2017-03-03T09:12:44.673Z", + "Microsoft.VSTS.Common.ValueArea": "Business", + "System.AreaPath": "PROJECTQA_test\\lolo", + "System.BoardColumn": "New", + "System.ChangedBy": "Dmitry Ivanov ", + "System.ChangedDate": "2017-03-03T09:17:42.31Z", + "System.CreatedBy": "Dmitry Ivanov ", + "System.CreatedDate": "2017-03-03T09:12:44.673Z", + "System.IterationPath": "PROJECTQA_test", + "System.Reason": "New", + "System.State": "New", + "System.TeamProject": "PROJECTQA_test", + "System.Title": "Bug test 1", + "System.WorkItemType": "User Story", + "WEF_664133C1618A415F8956A8EB6EE71483_Kanban.Column": "New" + }, + "id": 100, + "rev": 4, + "url": "http://tfs.tfs.ru/tfs/DefaultCollection/_apis/wit/workItems/100/revisions/4" + }, + { + "fields": { + "Microsoft.VSTS.Common.Priority": 2, + "Microsoft.VSTS.Common.StackRank": 1000031622.0, + "Microsoft.VSTS.Common.StateChangeDate": "2017-03-03T09:12:44.673Z", + "Microsoft.VSTS.Common.ValueArea": "Business", + "System.AreaPath": "PROJECTQA_test\\lolo", + "System.BoardColumn": "New", + "System.ChangedBy": "Dmitry Ivanov ", + "System.ChangedDate": "2017-03-03T09:22:04.167Z", + "System.CreatedBy": "Dmitry Ivanov ", + "System.CreatedDate": "2017-03-03T09:12:44.673Z", + "System.IterationPath": "PROJECTQA_test", + "System.Reason": "New", + "System.State": "New", + "System.TeamProject": "PROJECTQA_test", + "System.Title": "Bug test 1", + "System.WorkItemType": "User Story", + "WEF_664133C1618A415F8956A8EB6EE71483_Kanban.Column": "New" + }, + "id": 100, + "rev": 5, + "url": "http://tfs.tfs.ru/tfs/DefaultCollection/_apis/wit/workItems/100/revisions/5" + }, + { + "fields": { + "Microsoft.VSTS.Common.Priority": 2, + "Microsoft.VSTS.Common.StackRank": 1000031622.0, + "Microsoft.VSTS.Common.StateChangeDate": "2017-03-03T09:12:44.673Z", + "Microsoft.VSTS.Common.ValueArea": "Business", + "System.AreaPath": "PROJECTQA_test\\lolo", + "System.BoardColumn": "New", + "System.ChangedBy": "ci_PROJECTProductQA ", + "System.ChangedDate": "2017-03-03T09:24:31Z", + "System.CreatedBy": "Dmitry Ivanov ", + "System.CreatedDate": "2017-03-03T09:12:44.673Z", + "System.History": "\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
Dmitry Ivanov added the test result contains this Defect in DrTest
Plan: R2799Run: R2800Status: Failed
Case: C235987Test: R827663Version: 15.0.0-5555-FB
Test Comment
Воспроизводится ошибка 100.
", + "System.IterationPath": "PROJECTQA_test", + "System.Reason": "New", + "System.State": "New", + "System.TeamProject": "PROJECTQA_test", + "System.Title": "Bug test 1", + "System.WorkItemType": "User Story", + "WEF_664133C1618A415F8956A8EB6EE71483_Kanban.Column": "New" + }, + "id": 100, + "rev": 6, + "url": "http://tfs.tfs.ru/tfs/DefaultCollection/_apis/wit/workItems/100/revisions/6" + }, + { + "fields": { + "Microsoft.VSTS.Common.Priority": 2, + "Microsoft.VSTS.Common.StackRank": 1000031622.0, + "Microsoft.VSTS.Common.StateChangeDate": "2017-03-03T09:12:44.673Z", + "Microsoft.VSTS.Common.ValueArea": "Business", + "System.AreaPath": "PROJECTQA_test\\lolo", + "System.BoardColumn": "New", + "System.ChangedBy": "ci_PROJECTProductQA ", + "System.ChangedDate": "2017-03-03T09:27:27.4Z", + "System.CreatedBy": "Dmitry Ivanov ", + "System.CreatedDate": "2017-03-03T09:12:44.673Z", + "System.History": "\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
Dmitry Ivanov added the test result contains this Defect in DrTest
Plan: R2799Run: R2800Status: Failed
Case: C235987Test: T827663Version: 15.0.0-5555-FB
Test Comment
Воспроизводится ошибка 100.
", + "System.IterationPath": "PROJECTQA_test", + "System.Reason": "New", + "System.State": "New", + "System.TeamProject": "PROJECTQA_test", + "System.Title": "Bug test 1", + "System.WorkItemType": "User Story", + "WEF_664133C1618A415F8956A8EB6EE71483_Kanban.Column": "New" + }, + "id": 100, + "rev": 7, + "url": "http://tfs.tfs.ru/tfs/DefaultCollection/_apis/wit/workItems/100/revisions/7" + } + ] +} diff --git a/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/response.json b/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/response.json index 4411b61..81885d9 100644 --- a/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/response.json +++ b/tests/resources/tfs/DefaultCollection/_apis/wit/workitems/response.json @@ -22,7 +22,7 @@ "Microsoft.VSTS.Common.Priority": 2, "Microsoft.VSTS.Common.Severity": "3 - Medium" }, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/1370" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/1370" }, { "id": 101, @@ -44,7 +44,7 @@ "WEF_241EA9B233DB4EF49F5E03D7B35936E2_Kanban.Column": "New", "WEF_7ED661C40E944216A7573095C3ABE60C_Kanban.Column": "New" }, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/1371" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/1371" } ] } \ No newline at end of file diff --git a/tests/resources/tfs/Development/_apis/projects/26e73aff-d80b-430d-b95c-76140bf184de/teams/response.json b/tests/resources/tfs/Development/_apis/projects/26e73aff-d80b-430d-b95c-76140bf184de/teams/response.json deleted file mode 100644 index 248b27f..0000000 --- a/tests/resources/tfs/Development/_apis/projects/26e73aff-d80b-430d-b95c-76140bf184de/teams/response.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "id": "26e73aff-d80b-430d-b95c-76140bf184de", - "name": "ProjectName", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de", - "state": "wellFormed", - "_links": { - "self": { - "href": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de" - }, - "collection": { - "href": "https:\/\/tfs.tfs.ru\/tfs\/_apis\/projectCollections\/9025d248-2b1b-48a7-bb43-8abf779eeeaa" - }, - "web": { - "href": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/ProjectName" - } - }, - "defaultTeam": { - "id": "6475f0ad-b08b-4a74-8576-d80baf80600a", - "name": "ProjectName Team", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de\/teams\/6475f0ad-b08b-4a74-8576-d80baf80600a" - } -} \ No newline at end of file diff --git a/tests/resources/tfs/Development/_apis/projects/ProjectName/response.json b/tests/resources/tfs/Development/_apis/projects/ProjectName/response.json deleted file mode 100644 index 6e24af8..0000000 --- a/tests/resources/tfs/Development/_apis/projects/ProjectName/response.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "count": 1, - "value": [ - { - "id": "26e73aff-d80b-430d-b95c-76140bf184de", - "name": "ProjectName", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de", - "state": "wellFormed", - "revision": 43900539 - } - ] -} \ No newline at end of file diff --git a/tests/resources/tfs/Development/_apis/projects/response.json b/tests/resources/tfs/Development/_apis/projects/response.json deleted file mode 100644 index 6e24af8..0000000 --- a/tests/resources/tfs/Development/_apis/projects/response.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "count": 1, - "value": [ - { - "id": "26e73aff-d80b-430d-b95c-76140bf184de", - "name": "ProjectName", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/projects\/26e73aff-d80b-430d-b95c-76140bf184de", - "state": "wellFormed", - "revision": 43900539 - } - ] -} \ No newline at end of file diff --git a/tests/resources/tfs/Development/_apis/tfvc/changesets/10/workItems/response.json b/tests/resources/tfs/Development/_apis/tfvc/changesets/10/workItems/response.json deleted file mode 100644 index e28aa43..0000000 --- a/tests/resources/tfs/Development/_apis/tfvc/changesets/10/workItems/response.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "count": 2, - "value": [ - { - "webUrl": "https:\/\/tfs.tfs.ru\/tfs\/web\/wi.aspx?pcguid=9025d248-2b1b-48a7-bb43-8abf779eeeaa&id=100", - "id": 100, - "title": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c FB", - "workItemType": "Task", - "state": "Complete", - "assignedTo": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d " - }, - { - "webUrl": "https:\/\/tfs.tfs.ru\/tfs\/web\/wi.aspx?pcguid=9025d248-2b1b-48a7-bb43-8abf779eeeaa&id=100", - "id": 101, - "title": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c FB", - "workItemType": "Task", - "state": "Complete", - "assignedTo": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d " - } - ] -} \ No newline at end of file diff --git a/tests/resources/tfs/Development/_apis/tfvc/changesets/response.json b/tests/resources/tfs/Development/_apis/tfvc/changesets/response.json deleted file mode 100644 index 5bffcb1..0000000 --- a/tests/resources/tfs/Development/_apis/tfvc/changesets/response.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "count": 5, - "value": [ - { - "changesetId": 10, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18736", - "author": { - "id": "831299d4-f278-4858-a188-d1edae64125d", - "displayName": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d", - "uniqueName": "DOMAIN\\MIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" - }, - "checkedInBy": { - "id": "dc115031-b185-421e-a58d-b2b19903f51a", - "displayName": "deploy", - "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" - }, - "createdDate": "2017-06-30T15:43:41.71Z", - "comment": "Merge Main into R16.1 (PdqlAssetId)" - }, - { - "changesetId": 11, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18732", - "author": { - "id": "831299d4-f278-4858-a188-d1edae64125d", - "displayName": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d", - "uniqueName": "DOMAIN\\MIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" - }, - "checkedInBy": { - "id": "dc115031-b185-421e-a58d-b2b19903f51a", - "displayName": "deploy", - "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" - }, - "createdDate": "2017-06-30T12:16:46.907Z", - "comment": "\u0414\u043e\u0431\u0430\u0432\u0438\u043b \u0442\u0435\u0433 allIncidents \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0412\u0441\u0435 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442\u044b + \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u043f\u0440\u043e\u0441\u0442", - "commentTruncated": true - }, - { - "changesetId": 12, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18727", - "author": { - "id": "831299d4-f278-4858-a188-d1edae64125d", - "displayName": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d", - "uniqueName": "DOMAIN\\MIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" - }, - "checkedInBy": { - "id": "dc115031-b185-421e-a58d-b2b19903f51a", - "displayName": "deploy", - "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" - }, - "createdDate": "2017-06-30T08:48:18.133Z", - "comment": "\u0418\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0445 \u0438\u043d\u0446\u0438\u0434", - "commentTruncated": true - }, - { - "changesetId": 13, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18725", - "author": { - "id": "c7b8ae59-8bec-4d47-941e-66814c9dacea", - "displayName": "\u041a\u0438\u0440\u0438\u043b\u043b \u0418\u0432\u0430\u043d\u043e\u0432", - "uniqueName": "DOMAIN\\KIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/c7b8ae59-8bec-4d47-941e-66814c9dacea", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=c7b8ae59-8bec-4d47-941e-66814c9dacea" - }, - "checkedInBy": { - "id": "dc115031-b185-421e-a58d-b2b19903f51a", - "displayName": "deploy", - "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" - }, - "createdDate": "2017-06-29T10:47:29.287Z", - "comment": "\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0433\u0440\u0443\u043f\u043f" - }, - { - "changesetId": 14, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18723", - "author": { - "id": "c7b8ae59-8bec-4d47-941e-66814c9dacea", - "displayName": "\u041a\u0438\u0440\u0438\u043b\u043b \u0418\u0432\u0430\u043d\u043e\u0432", - "uniqueName": "DOMAIN\\KIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/c7b8ae59-8bec-4d47-941e-66814c9dacea", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=c7b8ae59-8bec-4d47-941e-66814c9dacea" - }, - "checkedInBy": { - "id": "dc115031-b185-421e-a58d-b2b19903f51a", - "displayName": "deploy", - "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" - }, - "createdDate": "2017-06-27T15:27:32.347Z", - "comment": "\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0433\u0440\u0443\u043f\u043f - \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f" - } - ] -} \ No newline at end of file diff --git a/tests/resources/tfs/Development/_apis/wit/wiql/cbbcdcaa-377f-42f7-a544-4d9507f2aa22/response.json b/tests/resources/tfs/Development/_apis/wit/wiql/cbbcdcaa-377f-42f7-a544-4d9507f2aa22/response.json deleted file mode 100644 index f62d06b..0000000 --- a/tests/resources/tfs/Development/_apis/wit/wiql/cbbcdcaa-377f-42f7-a544-4d9507f2aa22/response.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "queryType": "flat", - "queryResultType": "workItem", - "asOf": "2017-07-12T10:49:35.54Z", - "columns": [ - { - "referenceName": "System.Id", - "name": "ID", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id" - }, - { - "referenceName": "System.WorkItemType", - "name": "Work Item Type", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.WorkItemType" - }, - { - "referenceName": "System.Title", - "name": "Title", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Title" - }, - { - "referenceName": "System.AssignedTo", - "name": "Assigned To", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.AssignedTo" - }, - { - "referenceName": "System.State", - "name": "State", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.State" - }, - { - "referenceName": "System.Tags", - "name": "Tags", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Tags" - } - ], - "workItems": [ - { - "id": 100, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100" - }, - { - "id": 101, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100" - } - ] -} \ No newline at end of file diff --git a/tests/resources/tfs/Development/_apis/wit/wiql/response.json b/tests/resources/tfs/Development/_apis/wit/wiql/response.json deleted file mode 100644 index 375e16a..0000000 --- a/tests/resources/tfs/Development/_apis/wit/wiql/response.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "queryResultType": "workItem", - "columns": [ - { - "name": "ID", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id", - "referenceName": "System.Id" - }, - { - "name": "Severity", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", - "referenceName": "Microsoft.VSTS.Common.Severity" - }, - { - "name": "Target Version", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", - "referenceName": "TargetVersion" - } - ], - "sortColumns": [ - { - "field": { - "name": "Target Version", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", - "referenceName": "TargetVersion" - }, - "descending": false - }, - { - "field": { - "name": "Severity", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", - "referenceName": "Microsoft.VSTS.Common.Severity" - }, - "descending": false - } - ], - "workItems": [ - { - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100", - "id": 100 - }, - { - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/101", - "id": 101 - } - ], - "asOf": "2017-07-24T06:59:38.74Z", - "queryType": "flat" -} \ No newline at end of file diff --git a/tests/resources/tfs/Development/_apis/wit/workitems/100/response.json b/tests/resources/tfs/Development/_apis/wit/workitems/100/response.json deleted file mode 100644 index a6275e1..0000000 --- a/tests/resources/tfs/Development/_apis/wit/workitems/100/response.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "id": 100, - "rev": 1, - "fields": { - "System.AreaPath": "Test Agile", - "System.TeamProject": "Test Agile", - "System.IterationPath": "Test Agile\\Current\\Iteration 1", - "System.WorkItemType": "Bug", - "System.State": "Active", - "System.Reason": "Canceled", - "System.CreatedDate": "2015-10-14T07:40:46.96Z", - "System.CreatedBy": "Alexey Ivanov ", - "System.ChangedDate": "2015-10-14T07:40:46.96Z", - "System.ChangedBy": "Alexey Ivanov ", - "System.Title": "\u044c\u0441\u0440\u0442\u043e", - "Microsoft.VSTS.Common.StateChangeDate": "2015-10-14T07:40:46.96Z", - "Microsoft.VSTS.Common.ActivatedDate": "2015-10-14T07:40:46.96Z", - "Microsoft.VSTS.Common.ActivatedBy": "Alexey Ivanov ", - "Microsoft.VSTS.Common.Priority": 2, - "Microsoft.VSTS.Common.Severity": "3 - Medium" - }, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/1370" -} diff --git a/tests/resources/tfs/Development/_apis/wit/workitems/response.json b/tests/resources/tfs/Development/_apis/wit/workitems/response.json deleted file mode 100644 index 4411b61..0000000 --- a/tests/resources/tfs/Development/_apis/wit/workitems/response.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "count": 10, - "value": [ - { - "id": 100, - "rev": 1, - "fields": { - "System.AreaPath": "Test Agile", - "System.TeamProject": "Test Agile", - "System.IterationPath": "Test Agile\\Current\\Iteration 1", - "System.WorkItemType": "Bug", - "System.State": "Active", - "System.Reason": "New", - "System.CreatedDate": "2015-10-14T07:40:46.96Z", - "System.CreatedBy": "Alexey Ivanov ", - "System.ChangedDate": "2015-10-14T07:40:46.96Z", - "System.ChangedBy": "Alexey Ivanov ", - "System.Title": "\u044c\u0441\u0440\u0442\u043e", - "Microsoft.VSTS.Common.StateChangeDate": "2015-10-14T07:40:46.96Z", - "Microsoft.VSTS.Common.ActivatedDate": "2015-10-14T07:40:46.96Z", - "Microsoft.VSTS.Common.ActivatedBy": "Alexey Ivanov ", - "Microsoft.VSTS.Common.Priority": 2, - "Microsoft.VSTS.Common.Severity": "3 - Medium" - }, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/1370" - }, - { - "id": 101, - "rev": 4, - "fields": { - "System.AreaPath": "TestProject", - "System.TeamProject": "TestProject", - "System.IterationPath": "TestProject\\Release 1\\Sprint 1", - "System.WorkItemType": "Product Backlog Item", - "System.State": "New", - "System.Reason": "New backlog item", - "System.CreatedDate": "2015-10-20T12:44:43.567Z", - "System.CreatedBy": "Dmitry Petrov ", - "System.ChangedDate": "2015-10-20T12:54:31.22Z", - "System.ChangedBy": "Dmitry Petrov ", - "System.Title": "\u043f\u0440\u043e\u0434 \u0442\u0430\u0441\u043a US 1", - "System.BoardColumn": "New", - "Microsoft.VSTS.Common.BacklogPriority": 1000000000, - "WEF_241EA9B233DB4EF49F5E03D7B35936E2_Kanban.Column": "New", - "WEF_7ED661C40E944216A7573095C3ABE60C_Kanban.Column": "New" - }, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/1371" - } - ] -} \ No newline at end of file diff --git a/tests/test_resources.py b/tests/test_resources.py index c486802..8db5dd3 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -33,20 +33,20 @@ def workitem_with_child_only(self, tfsapi): "relations": [ { "rel": "System.LinkTypes.Hierarchy-Forward", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/10", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/10", "attributes": { "isLocked": false } }, { "rel": "System.LinkTypes.Hierarchy-Forward", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/11", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/11", "attributes": { "isLocked": false } } ], - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100" }""" data_ = json.loads(data_str) wi = Workitem(data_, tfsapi) @@ -77,16 +77,43 @@ def workitem(self, tfsapi): "Microsoft.VSTS.Common.Severity": "3 - Medium", "Custom.Bug.Type": "Manual Test Case" }, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100", "relations": [ { "rel": "System.LinkTypes.Hierarchy-Reverse", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/110", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/110", "attributes": { "isLocked": false } + }, + { + "attributes": { + "authorizedDate": "2018-01-06T05:43:42.75Z", + "id": 47, + "name": ".gitignore", + "resourceCreatedDate": "2018-01-06T05:43:41.63Z", + "resourceModifiedDate": "2018-01-06T05:43:41.63Z", + "resourceSize": 1276, + "revisedDate": "9999-01-01T00:00:00Z" + }, + "rel": "AttachedFile", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/attachments\/5766cbba-2794-468c-801b-3ede5e3267a0" + } + ], + "_links": { + "self": { + "href": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100" + }, + "html": { + "href": "http:\/\/tfs.tfs.ru\/tfs\/web\/wi.aspx?pcguid=9cd4a217-5ab5-4e09-8116-ec8a6141e5a5&id=100" + }, + "workItemRevisions": { + "href": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workitems\/100\/revisions" + }, + "workItemHistory": { + "href": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100\/history" + } } - ] }""" data_ = json.loads(data_str) wi = Workitem(data_, tfsapi) @@ -129,26 +156,54 @@ def test_workitem_field_names(self, workitem): assert 'Russia' in workitem.field_names assert 'Title' in workitem.field_names + def test_find_in_relation(self, workitem): + assert len(workitem.find_in_relation('Hierarchy-Reverse')) == 1, 'Can not find in relation some link' + + + def test_attachment(self, workitem): + assert len(workitem.attachments) == 1 + attach = workitem.attachments[0] + assert isinstance(attach, Attachment) + assert attach.name == '.gitignore' + + def test_dir_links(self, workitem): + properties_must_be = ['workItemHistory', 'workItemRevisions', 'self', 'html'] + properties = dir(workitem) + for property_name in properties_must_be: + assert property_name in properties, "Workitem object must has attribute '{}'".format(property_name) + + @pytest.mark.httpretty + def test_wi_revisions(self, workitem): + revisions = workitem.workItemRevisions + assert isinstance(revisions[0], TFSObject) + + revisions = workitem.revisions + assert isinstance(revisions[0], TFSObject) + + def test_wi_raise_attribute_error(self, workitem): + with pytest.raises(AttributeError): + _ = workitem.not_exist_attribute + class TestChangeset(object): @pytest.fixture() def changeset(self): data_str = r"""{ "changesetId": 10, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18736", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/tfvc\/changesets\/18736", "author": { "id": "831299d4-f278-4858-a188-d1edae64125d", "displayName": "\u041c\u0438\u0445\u0430\u0438\u043b \u041f\u043e\u043b\u044c\u0433\u0443\u043d", "uniqueName": "DOMAIN\\MIvanov", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/831299d4-f278-4858-a188-d1edae64125d", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=831299d4-f278-4858-a188-d1edae64125d" }, "checkedInBy": { "id": "dc115031-b185-421e-a58d-b2b19903f51a", "displayName": "deploy", "uniqueName": "DOMAIN\\deploy", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", - "imageUrl": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/Identities\/dc115031-b185-421e-a58d-b2b19903f51a", + "imageUrl": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_api\/_common\/identityImage?id=dc115031-b185-421e-a58d-b2b19903f51a" }, "createdDate": "2017-06-30T15:43:41.71Z", "comment": "My Comment" @@ -166,7 +221,6 @@ def test_changeset_fields(self, changeset): def test_changeset_fields_get(self, changeset): assert changeset.get('comment') == "My Comment" - @pytest.mark.httpretty def test_get_changesets_workitem(self, tfsapi): changesets = tfsapi.get_changesets(from_=10, to_=14) @@ -197,13 +251,13 @@ def tfsquery(self, tfsapi): "isPublic": true, "_links": { "self": { - "href": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/9d639e22-e9a9-49d7-8b40-ef94d9607bdb\/_apis\/wit\/queries\/cbbcdcaa-377f-42f7-a544-4d9507f2aa22" + "href": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/9d639e22-e9a9-49d7-8b40-ef94d9607bdb\/_apis\/wit\/queries\/cbbcdcaa-377f-42f7-a544-4d9507f2aa22" }, "html": { - "href": "https:\/\/tfs.tfs.ru\/tfs\/web\/qr.aspx?pguid=9d639e22-e9a9-49d7-8b40-ef94d9607bdb&qid=cbbcdcaa-377f-42f7-a544-4d9507f2aa22" + "href": "http:\/\/tfs.tfs.ru\/tfs\/web\/qr.aspx?pguid=9d639e22-e9a9-49d7-8b40-ef94d9607bdb&qid=cbbcdcaa-377f-42f7-a544-4d9507f2aa22" } }, - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/9d639e22-e9a9-49d7-8b40-ef94d9607bdb\/_apis\/wit\/queries\/cbbcdcaa-377f-42f7-a544-4d9507f2aa22" + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/9d639e22-e9a9-49d7-8b40-ef94d9607bdb\/_apis\/wit\/queries\/cbbcdcaa-377f-42f7-a544-4d9507f2aa22" } """ data_ = json.loads(data_str) @@ -223,7 +277,7 @@ def test_tfsquery_column_names(self, tfsquery): assert "Title" in tfsquery.column_names @pytest.mark.httpretty - def test_tfsquery_column_names(self, tfsquery): + def test_tfsquery_ids(self, tfsquery): assert len(tfsquery.workitems) == 2 assert tfsquery.workitems[0].id == 100 assert tfsquery.workitems[1].id == 101 @@ -237,17 +291,17 @@ def wiql(self, tfsapi): "columns": [ { "name": "ID", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id", "referenceName": "System.Id" }, { "name": "Severity", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", "referenceName": "Microsoft.VSTS.Common.Severity" }, { "name": "Target Version", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", "referenceName": "TargetVersion" } ], @@ -255,7 +309,7 @@ def wiql(self, tfsapi): { "field": { "name": "Target Version", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", "referenceName": "TargetVersion" }, "descending": false @@ -263,7 +317,7 @@ def wiql(self, tfsapi): { "field": { "name": "Severity", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", "referenceName": "Microsoft.VSTS.Common.Severity" }, "descending": false @@ -271,11 +325,11 @@ def wiql(self, tfsapi): ], "workItems": [ { - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/100", "id": 100 }, { - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/101", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/workItems\/101", "id": 101 } ], @@ -293,17 +347,17 @@ def wiql_empty(self, tfsapi): "columns": [ { "name": "ID", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/System.Id", "referenceName": "System.Id" }, { "name": "Severity", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", "referenceName": "Microsoft.VSTS.Common.Severity" }, { "name": "Target Version", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", "referenceName": "TargetVersion" } ], @@ -311,7 +365,7 @@ def wiql_empty(self, tfsapi): { "field": { "name": "Target Version", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/TargetVersion", "referenceName": "TargetVersion" }, "descending": false @@ -319,7 +373,7 @@ def wiql_empty(self, tfsapi): { "field": { "name": "Severity", - "url": "https:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", + "url": "http:\/\/tfs.tfs.ru\/tfs\/DefaultCollection\/_apis\/wit\/fields\/Microsoft.VSTS.Common.Severity", "referenceName": "Microsoft.VSTS.Common.Severity" }, "descending": false diff --git a/tfs/connection.py b/tfs/connection.py index b27b3b7..dd3a584 100644 --- a/tfs/connection.py +++ b/tfs/connection.py @@ -11,8 +11,8 @@ def batch(iterable, n=1): """ - Из списка возращает елементы по N штук (в другом списке) - http://stackoverflow.com/questions/8290397/how-to-split-an-iterable-in-constant-size-chunks + "batch" function that would take as input an iterable and return an iterable of iterables + https://stackoverflow.com/a/8290508/6753144 """ l = len(iterable) for ndx in range(0, l, n): @@ -24,6 +24,7 @@ def __init__(self, server_url, project="DefaultCollection", user=None, password= auth_type=HTTPBasicAuth, connect_timeout=20, read_timeout=180, ): """ + This class must be used to get first object from TFS :param server_url: url to TFS server, e.g. https://tfs.example.com/ :param project: Collection or Collection\\Project :param user: username, or DOMAIN\\username @@ -49,9 +50,9 @@ def get_tfs_object(self, uri, payload=None, object_class=TFSObject, project=Fals # For list results if 'value' in raw: raw = raw['value'] - objects = [object_class(x, self) for x in raw] + objects = [object_class(x, self, uri) for x in raw] else: - objects = object_class(raw, self) + objects = object_class(raw, self, uri) return objects @@ -123,6 +124,12 @@ def run_wiql(self, query): ) return Wiql(wiql, self) + def download_file(self, uri, filename): + # TODO: Use download in stream, not in memory + r = self.rest_client.send_get(uri, json=False) + with open(filename, 'wb') as file: + file.write(r.content) + class TFSClientError(Exception): pass @@ -166,8 +173,8 @@ def get_collection_and_project(project): return collection, project - def send_get(self, uri, payload=None, project=False): - return self.__send_request('GET', uri, None, payload=payload, project=project) + def send_get(self, uri, payload=None, project=False, json=True): + return self.__send_request('GET', uri, None, payload=payload, project=project, json=json) def send_post(self, uri, data, headers, project=False): return self.__send_request('POST', uri, data, headers, project=project) @@ -175,8 +182,25 @@ def send_post(self, uri, data, headers, project=False): def send_patch(self, uri, data, headers, project=False): return self.__send_request('PATCH', uri, data, headers, project=project) - def __send_request(self, method, uri, data, headers=None, payload=None, project=False): - url = (self._url_prj if project else self._url) + uri + def __send_request(self, method, uri, data, headers=None, payload=None, project=False, json=True): + """ + Send request + :param method: + :param uri: + :param data: + :param headers: + :param payload: + :param project: + False - add only collection to uri + True - add Collection/Project to url, some api need it + e.g. WIQL: https://www.visualstudio.com/en-us/docs/integrate/api/wit/wiql + :param json: + True - try to convert response to python-object + False - get as is + :return: + """ + url = self.__prepare_uri(uri=uri, project=project) + if method == 'POST': response = self.http_session.post(url, json=data, verify=self._verify, headers=headers, timeout=self.timeout) @@ -189,12 +213,32 @@ def __send_request(self, method, uri, data, headers=None, payload=None, project= timeout=self.timeout) response.raise_for_status() - try: - result = response.json() + if json: + try: + result = response.json() - if response.status_code != 200: - raise TFSClientError('TFS API returned HTTP %s (%s)' % ( - response.status_code, result['error'] if 'error' in result else response.reason)) - return result - except: - raise TFSClientError('Response is not json: {}'.format(response.text)) + if response.status_code != 200: + raise TFSClientError('TFS API returned HTTP %s (%s)' % ( + response.status_code, result['error'] if 'error' in result else response.reason)) + return result + except: + raise TFSClientError('Response is not json: {}'.format(response.text)) + else: + return response + + def __prepare_uri(self, project, uri): + """ + Convert URI to URL + :param project: + :param uri: + :return: + """ + # TODO: Add get from non-standart collection, + # e.g. workItemTypes: https://www.visualstudio.com/en-us/docs/integrate/api/wit/work-item-types + if uri.startswith('https') or uri.startswith('http'): + # If we use URL (full path) + url = uri + else: + # Add prefix to uri + url = (self._url_prj if project else self._url) + uri + return url diff --git a/tfs/resources.py b/tfs/resources.py index e4f681e..a043df1 100644 --- a/tfs/resources.py +++ b/tfs/resources.py @@ -2,54 +2,86 @@ """ TFS API python 3 version """ +import os from requests.structures import CaseInsensitiveDict -basestring = (str, bytes) - - -def cmp(a, b): - return (a > b) - (a < b) - - -def to_str(a): - return a.decode('utf-8') if isinstance(a, bytes) else str(a) - - -def to_bytes(a): - return a.encode('utf-8') if isinstance(a, str) else a - class TFSObject(object): def __init__(self, data=None, tfs=None, uri=''): # TODO: CaseInsensitive Dict - self._data = data + + self.data = data self.tfs = tfs - self.id = self._data.get('id', None) + self.id = self.data.get('id', None) self.uri = uri + self.url = self.data['url'] if 'url' in self.data else None - def __repr__(self): - _repr = '' - for k, v in self._data.items(): - _repr += to_str(k) + ' = ' + to_str(v) + '\n' - return _repr + self._data = self.data # legacy, some people can use private method + + def __dir__(self): + """ + Extend standart dir() with attribute in `_links` + :return: extended list of attribute name + """ + original = super(TFSObject, self).__dir__() + extend = self.data.get('_links', {}) + extend = list(extend) + new_dir = original + extend + return new_dir + + def __get_object_by_links(self, name): + """ + Dynamically add property for all ``_links`` field in JSON, if exist + """ + links = self.data.get('_links', {}) # or emtpy if _links is not exist + url = links[name]['href'] + return self.tfs.get_tfs_object(url) + + def __getattr__(self, name): + """ + If object have not attribute, try search in `_links` and return new TFSObject + :param name: + :return: TFSObject + """ + if name in self.data.get('_links', {}): + return self.__get_object_by_links(name) + raise AttributeError("'{}' object has not attribute '{}'".format(self.__class__.__name__, name)) + + # TODO: implement better repr + # def __repr__(self): + # _repr = '' + # for k, v in self.data.items(): + # _repr += to_str(k) + ' = ' + to_str(v) + '\n' + # return _repr def __getitem__(self, key): - return self._data[key] + return self.data[key] def __setitem__(self, key, value): + """ + We not implement default behavior, use class for it + :param key: + :param value: + :return: + """ raise NotImplemented def get(self, key, default=None): - return self._data.get(key, default) + return self.data.get(key, default) class Workitem(TFSObject): - def __init__(self, data=None, tfs=None): - super().__init__(data, tfs) - self._fields = CaseInsensitiveDict(self._data['fields']) + def __init__(self, data=None, tfs=None, uri=''): + super().__init__(data, tfs, uri) + + # Use prefix in automatically lookup. + # We don't need use wi['System.History'], we use simple wi['History'] self._system_prefix = 'System.' - self.id = self._data['id'] + + self.id = self.data['id'] + self.fields = CaseInsensitiveDict(self.data['fields']) + self._fields = self.fields def __setitem__(self, key, value): field_path = "/fields/{}".format(key) @@ -58,17 +90,20 @@ def __setitem__(self, key, value): self.__init__(raw, self.tfs) def get(self, key, default=None): - if key in self._fields: - return self._fields[key] + if key in self.fields: + return self.fields[key] + + # try to automatically add prefix key = self._add_prefix(key) - return self._fields.get(key, default) + return self.fields.get(key, default) def __getitem__(self, key): - if key in self._fields: - return self._fields[key] + if key in self.fields: + return self.fields[key] + # try to automatically add prefix key = self._add_prefix(key) - return self._fields[key] + return self.fields[key] def _add_prefix(self, key): if key.startswith(self._system_prefix): @@ -84,22 +119,42 @@ def _remove_prefix(self, key): @property def field_names(self): - return [self._remove_prefix(x) for x in self._fields] + return [self._remove_prefix(x) for x in self.fields] @property def history(self): - return self.tfs.get_tfs_object('wit/workitems/{}/history'.format(self.id)) + return self.workItemHistory + + @property + def revisions(self): + return self.workItemRevisions + + def find_in_relation(self, relation_type): + """ + Get relation by type\name. Auto add + :param relation_type: + :return: + """ + found = [] + for relation in self.data.get('relations', []): + # Find as is, e.g. 'AttachedFile' or more smartly. + # Found 'Hierarchy-Forward' in 'System.LinkTypes.Hierarchy-Forward' + if relation_type == relation.get('rel', '') \ + or relation.get('rel', '').endswith(relation_type): + found.append(relation) + return found def _find_in_relation(self, relation_type, return_one=True): """ Find relation type in relations and return one or list + one use for Parent WI """ ids = [] - for relation in self._data.get('relations', []): - if relation_type in relation.get('rel', ''): - id_ = relation['url'].split('/')[-1] - id_ = int(id_) - ids.append(id_) + relations = self.find_in_relation(relation_type) + for relation in relations: + id_ = relation['url'].split('/')[-1] + id_ = int(id_) + ids.append(id_) if return_one: return ids[0] if ids else None else: @@ -126,11 +181,28 @@ def childs(self): else: return [] + @property + def attachments(self): + list_ = self.find_in_relation('AttachedFile') + attachments_ = [Attachment(x, self.tfs) for x in list_] + return attachments_ + + +class Attachment(TFSObject): + def __init__(self, data=None, tfs=None, uri=''): + super().__init__(data, tfs, uri) + self.id = self.data['url'].split('/')[-1] # Get UUID from url + self.name = self.data['attributes']['name'] + + def download(self, path='.'): + path = os.path.join(path, self.name) + self.tfs.download_file(self.url, path) + class Changeset(TFSObject): - def __init__(self, data=None, tfs=None): - super().__init__(data, tfs) - self.id = self._data['changesetId'] + def __init__(self, data=None, tfs=None, uri=''): + super().__init__(data, tfs, uri) + self.id = self.data['changesetId'] @property def workitems(self): @@ -147,8 +219,8 @@ def team(self): class TFSQuery(TFSObject): - def __init__(self, data=None, tfs=None): - super().__init__(data, tfs) + def __init__(self, data=None, tfs=None, uri=''): + super().__init__(data, tfs, uri) self.result = self.tfs.rest_client.send_get('wit/wiql/{}?api-version=2.2'.format(self.id), project=True) self.columns = tuple(i['referenceName'] for i in self.result['columns']) self.column_names = tuple(i['name'] for i in self.result['columns']) @@ -166,13 +238,13 @@ class Wiql(TFSObject): Work Item Query Language """ - def __init__(self, data=None, tfs=None): - super().__init__(data, tfs) - self.result = self._data + def __init__(self, data=None, tfs=None, uri=''): + super().__init__(data, tfs, uri) + self.result = self.data @property def workitem_ids(self): - ids = [x['id'] for x in self._data['workItems']] + ids = [x['id'] for x in self.data['workItems']] return ids @property