def test_api_create_reference_002(server): """Create one Reference resource. Send POST /references to create a new reference. Created resource is sent in the POST method resource ``data`` attribute as object. The HTTP response must send the created resource in the resource ``data`` attribute as list of objects. """ storage = {'data': [Storage.gitlog]} storage['data'][0]['uuid'] = Content.UUID1 request_body = { 'data': { 'type': 'reference', 'attributes': Request.gitlog } } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '580' } expect_body = { 'data': [{ 'type': 'reference', 'id': Content.UUID1, 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/references', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_search_solution_008(server): """Search solution with GET. Send GET /solutions to return only defined attributes. In this case the fields are defined by setting the 'fields' parameter multiple times. """ expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '205' } expect_body = { 'meta': { 'count': 1, 'limit': 1, 'offset': 0, 'total': 2 }, 'data': [{ 'type': 'solution', 'id': Solution.NGINX_UUID, 'attributes': { field: Storage.dnginx[field] for field in ['brief', 'category'] } }] } result = testing.TestClient(server.server.api).simulate_get( path='/api/snippy/rest/solutions', headers={'accept': 'application/json'}, query_string= 'sall=debug&limit=1&sort=-brief&fields=brief&fields=category') assert result.status == falcon.HTTP_200 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body)
def test_cli_import_reference_012(snippy): """Import reference based on message digest. Import defined reference based on message digest. In this case the content category is accidentally specified as 'snippet'. This should still import the content in reference category. """ content = {'data': [Content.deepcopy(Reference.GITLOG)]} content['data'][0]['links'] = ('https://updated-link.html', ) content['data'][0]['updated'] = Content.PYTEST_TIME content['data'][0][ 'digest'] = 'fafd46eca7ca239bcbff8f1ba3e8cf806cadfbc9e267cdf6ccd3e23e356f9f8d' file_content = Content.get_file_content(Content.TEXT, content) with mock.patch('snippy.content.migrate.open', file_content, create=True) as mock_file: cause = snippy.run([ 'snippy', 'import', '--scat', 'snippet', '-d', '5c2071094dbfaa33', '-f', 'one-reference.text' ]) assert cause == Cause.ALL_OK Content.assert_storage(content) mock_file.assert_called_once_with('one-reference.text', 'r')
def test_debug_print_001(capsys): """Test printing the content. Test printing content with print. This is a development test which must directly print the snippets with the test case helper method. """ output = ( '1. Remove all docker containers with volumes @docker [54e41e9b52a02b63]', '', ' $ docker rm --volumes $(docker ps --all --quiet)', '', ' # cleanup,container,docker,docker-ce,moby', ' > https://docs.docker.com/engine/reference/commandline/rm/', '', ' ! category : snippet', ' ! created : 2017-10-14T19:56:31.000001+00:00', ' ! description : ', ' ! digest : 54e41e9b52a02b631b5c65a6a053fcbabc77ccd42b02c64fdfbc76efdb18e319 (True)', ' ! filename : ', ' ! id : a1cd5827-b6ef-4067-b5ac-3ceac07dde9f', ' ! languages : ', ' ! name : ', ' ! source : ', ' ! updated : 2017-10-14T19:56:31.000001+00:00', ' ! uuid : 11cd5827-b6ef-4067-b5ac-3ceac07dde9f', ' ! versions : ', '', '2. Remove docker image with force @docker [53908d68425c61dc]', '', ' $ docker rm --force redis', '', ' # cleanup,container,docker,docker-ce,moby', ' > https://docs.docker.com/engine/reference/commandline/rm/', ' > https://www.digitalocean.com/community/tutorials/how-to-remove-docker-images-containers-and-volumes', '', ' ! category : snippet', ' ! created : 2017-10-14T19:56:31.000001+00:00', ' ! description : ', ' ! digest : 53908d68425c61dc310c9ce49d530bd858c5be197990491ca20dbe888e6deac5 (True)', ' ! filename : ', ' ! id : a2cd5827-b6ef-4067-b5ac-3ceac07dde9f', ' ! languages : ', ' ! name : ', ' ! source : ', ' ! updated : 2017-10-14T19:56:31.000001+00:00', ' ! uuid : 12cd5827-b6ef-4067-b5ac-3ceac07dde9f', ' ! versions : ', '', '# collection meta', ' ! total : 2') print(Content.output()) # Part of the test. out, err = capsys.readouterr() out = Helper.remove_ansi(out) assert Const.NEWLINE.join(output) in out assert not err
def create_defaults(snippy): """Add default snippets for testing purposes.""" file_content = Content.get_file_content(Content.TEXT, {'data': [Snippet.REMOVE]}) with mock.patch('snippy.content.migrate.open', file_content, create=True): cause = snippy.run(['snippy', 'import', '-f', 'remove.txt'] + Content.db_cli_params()) assert cause == Cause.ALL_OK file_content = Content.get_file_content(Content.TEXT, {'data': [Snippet.FORCED]}) with mock.patch('snippy.content.migrate.open', file_content, create=True): cause = snippy.run(['snippy', 'import', '-f', 'forced.txt'] + Content.db_cli_params()) assert cause == Cause.ALL_OK file_content = Content.get_file_content(Content.TEXT, {'data': [Solution.BEATS]}) with mock.patch('snippy.content.migrate.open', file_content, create=True): cause = snippy.run(['snippy', 'import', '-f', 'beats.txt'] + Content.db_cli_params()) assert cause == Cause.ALL_OK file_content = Content.get_file_content(Content.TEXT, {'data': [Solution.NGINX]}) with mock.patch('snippy.content.migrate.open', file_content, create=True): cause = snippy.run(['snippy', 'import', '-f', 'nginx.txt'] + Content.db_cli_params()) assert cause == Cause.ALL_OK
def test_api_update_reference_002(server): """Update one reference with PUT request. Send PUT /references/{id} to update existing resource. The PUT request contains only the mandatory links attribute. All other attributes must be set to their default values in the HTTP response. """ storage = { 'data': [{ 'category': 'reference', 'data': (), 'brief': '', 'description': '', 'name': '', 'groups': ('default', ), 'tags': (), 'links': Reference.PYTEST['links'], 'source': '', 'versions': (), 'languages': (), 'filename': '', 'created': Content.GITLOG_TIME, 'updated': Content.PYTEST_TIME, 'uuid': Reference.GITLOG_UUID, 'digest': '4a868cc74e3d32a4340e1a2fd17d0df815777c67f827aeedbb35869b740dd720' }] } request_body = { 'data': { 'type': 'snippet', 'attributes': { 'links': storage['data'][0]['links'], } } } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '667' } expect_body = { 'links': { 'self': 'http://falconframework.org/api/snippy/rest/references/' + Reference.GITLOG_UUID }, 'data': { 'type': 'reference', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] } } result = testing.TestClient(server.server.api).simulate_put( path='/api/snippy/rest/references/5c2071094dbfaa33', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_200 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_cli_create_snippet_012(snippy, editor_data): """Create snippet with editor. Create a new snippet and define tags and brief already from command line interface. Other fields must have the default template content that is normally presented for the user when content is created with editor. The groups, links and description default values are not changed from default examples. These values must result tool internal defaults when content is stored. User fills the content data from editor so the content is stored. Editor must be used by default. """ content = { 'data': [{ 'category': 'snippet', 'data': ('docker rm --volumes $(docker ps --all --quiet)', ), 'brief': 'Brief from cli', 'description': '', 'name': '', 'groups': ('default', ), 'tags': ('cli', 'from', 'tags'), 'links': (), 'source': '', 'versions': (), 'languages': (), 'filename': '', 'created': '2017-10-14T19:56:31.000001+00:00', 'updated': '2017-10-14T19:56:31.000001+00:00', 'uuid': 'a1cd5827-b6ef-4067-b5ac-3ceac07dde9f', 'digest': 'a020eb12a278e4426169360af1e124fb989747fd8a9192c293c938cea05798fa' }] } template = ( '# Brief from cli @groups', '', '> Add a description that defines the content in one chapter.', '', '> [1] https://www.example.com/add-links-here.html', '', '`$ Markdown commands are defined between backtics and prefixed by a dollar sign`', '', '## Meta', '', '> category : snippet ', 'created : 2017-10-14T19:56:31.000001+00:00 ', 'digest : 023dc3bf754064bc5c3692cf535a769f402b187e14ebfb7e64273f6caf03ec6e ', 'filename : example-content.md ', 'languages : example-language ', 'name : example content handle ', 'source : https://www.example.com/source.md ', 'tags : cli,from,tags ', 'updated : 2017-10-14T19:56:31.000001+00:00 ', 'uuid : a1cd5827-b6ef-4067-b5ac-3ceac07dde9f ', 'versions : example=3.9.0,python>=3 ', '') edited = ( '# Brief from cli @groups', '', '> Add a description that defines the content in one chapter.', '', '> [1] https://www.example.com/add-links-here.html', '', '`$ docker rm --volumes $(docker ps --all --quiet)`', '', '## Meta', '', '> category : snippet ', 'created : 2017-10-14T19:56:31.000001+00:00 ', 'digest : fdbf285d091a8c46cf491da675ecfeda38f7796ef034124b357f49737963cd19 ', 'filename : ', 'language : ', 'name : ', 'source : ', 'tags : cli,from,tags ', 'updated : 2017-10-14T19:56:31.000001+00:00 ', 'uuid : a1cd5827-b6ef-4067-b5ac-3ceac07dde9f ', 'versions : ', '') editor_data.return_value = Const.NEWLINE.join(edited) cause = snippy.run([ 'snippy', 'create', '-t', 'tags,from,cli', '-b', 'Brief from cli' ]) assert cause == Cause.ALL_OK editor_data.assert_called_with(Const.NEWLINE.join(template)) Content.assert_storage(content)
def test_api_create_solution_009(server): """Create one solution from API. Send POST /solutions to create a new resource. In this case every attribute has additional leading and trailing whitespaces. Trimming must be done all fields with the exception of data field. In case of data field, there must be only one newline at the end of solution and the extra white spaces must be left as is. The ``tags`` and ``links`` attributes must be sorted when stored. """ storage = { 'data': [{ 'category': 'solution', 'data': (' first row ', ' second row ', ''), 'brief': 'short brief', 'description': 'long description', 'name': 'short name', 'groups': ('python', ), 'tags': ('atabs', 'bspaces'), 'links': ('alink2', 'blink1'), 'source': 'short source link', 'versions': ('versions==1.1-alpha', ), 'filename': 'shortfilename.yaml', 'created': Content.REGEXP_TIME, 'updated': Content.REGEXP_TIME, 'uuid': Content.UUID1, 'digest': '2fba73d95146c736a2717e18758fd1871ccb9aa68171614435365f5ad5075ba8' }] } request_body = { 'data': [{ 'type': 'solution', 'attributes': { 'data': [' first row ', ' second row ', '', '', ''], 'brief': ' short brief ', 'description': ' long description ', 'name': ' short name ', 'groups': [ ' python ', ], 'tags': [' bspaces ', ' atabs '], 'links': [' blink1 ', ' alink2 '], 'source': ' short source link ', 'versions': [' versions==1.1-alpha '], 'filename': ' shortfilename.yaml ' } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '658' } expect_body = { 'data': [{ 'type': 'solution', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/solutions', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_cli_update_snippet_017(snippy, editor_data): """Update snippet with editor. Update existing snippet directly from command line. In this case the snippet contains multiple comments which are same. The update is made in Markdown format and editor must be able to show the content. There are no changes and the parser must notice that the content was not updated. """ Content.store({ 'category': Content.SNIPPET, 'data': [ "find . -iregex '.*\\(py\\|robot\\)' # Find files.", "find . -iregex '.*\\(py\\|robot\\)' -print0 | wc -l --files0-from=- # Find files and count lines.", "find . -iregex '.*\\(py\\|robot\\)' -print0 | wc -l --files0-from=- | tail -n 1", "find . -name '*.py' -print0 | wc -l --files0-from=- # Find files and count lines.", "find . -name '*.py' -print0 | wc -l --files0-from=- | tail -n 1", "find . -name '*.py' -exec cat {} + | wc -l # Find files and count lines." ], 'brief': 'Find files and count lines', 'description': 'Find files with or without regexp pattern and count lines.', 'groups': ['linux'], 'tags': ['find', 'linux', 'regexp'], 'digest': 'dae4e22c3c3858b5616a29be11916112a16994e30bc3e4b93b069bc9a772d889' }) content = { 'data': [{ 'category': 'snippet', 'data': ("find . -iregex '.*\\(py\\|robot\\)' # Find files.", "find . -iregex '.*\\(py\\|robot\\)' -print0 | wc -l --files0-from=- # Find files and count lines.", "find . -iregex '.*\\(py\\|robot\\)' -print0 | wc -l --files0-from=- | tail -n 1", "find . -name '*.py' -print0 | wc -l --files0-from=- # Find files and count lines.", "find . -name '*.py' -print0 | wc -l --files0-from=- | tail -n 1", "find . -name '*.py' -exec cat {} + | wc -l # Find files and count lines." ), 'brief': 'Find files and count lines', 'description': 'Find files with or without regexp pattern and count lines.', 'name': '', 'groups': ('linux', ), 'tags': ('find', 'linux', 'regexp'), 'links': (), 'source': '', 'versions': (), 'filename': '', 'created': '2018-03-02T02:02:02.000001+00:00', 'updated': '2018-03-02T02:02:02.000001+00:00', 'uuid': 'a1cd5827-b6ef-4067-b5ac-3ceac07dde9f', 'digest': 'dae4e22c3c3858b5616a29be11916112a16994e30bc3e4b93b069bc9a772d889' }] } template = ( '# Find files and count lines @linux', '', '> Find files with or without regexp pattern and count lines.', '', '> ', '', '- Find files.', '', ' `$ find . -iregex \'.*\\(py\\|robot\\)\'`', '', '- Find files and count lines.', '', ' `$ find . -iregex \'.*\\(py\\|robot\\)\' -print0 | wc -l --files0-from=-`', '', '- <not documented>', '', ' `$ find . -iregex \'.*\\(py\\|robot\\)\' -print0 | wc -l --files0-from=- | tail -n 1` ', '', '- Find files and count lines.', '', ' `$ find . -name \'*.py\' -print0 | wc -l --files0-from=-`', '', '- <not documented>', '', ' `$ find . -name \'*.py\' -print0 | wc -l --files0-from=- | tail -n 1` ', '', '- Find files and count lines.', '', ' `$ find . -name \'*.py\' -exec cat {} + | wc -l`', '', '## Meta', '', '> category : snippet ', 'created : 2018-03-02T02:02:02.000001+00:00 ', 'digest : dae4e22c3c3858b5616a29be11916112a16994e30bc3e4b93b069bc9a772d889 ', 'filename : ', 'name : ', 'source : ', 'tags : find,linux,regexp ', 'updated : 2018-03-02T02:02:02.000001+00:00 ', 'uuid : a1cd5827-b6ef-4067-b5ac-3ceac07dde9f ', 'versions : ', '') editor_data.return_value = '\n'.join(template) cause = snippy.run(['snippy', 'update', '-d', 'dae4e22c3c3858b5']) assert cause == Cause.ALL_OK editor_data.assert_called_with('\n'.join(template)) Content.assert_storage(content)
def test_api_update_snippet_003(server): """Update one snippet with PUT request. Send PUT /snippets/{id} to update existing resource with specified digest. The PUT request contains only the mandatory data attribute. All other attributes must be set to their default values. """ storage = { 'data': [{ 'category': 'snippet', 'data': Snippet.REMOVE['data'], 'brief': '', 'description': '', 'name': '', 'groups': ('default', ), 'tags': (), 'links': (), 'source': '', 'versions': (), 'filename': '', 'created': Content.FORCED_TIME, 'updated': Content.REMOVE_TIME, 'uuid': '12cd5827-b6ef-4067-b5ac-3ceac07dde9f', 'digest': '26128ea95707a3a2623bb2613a17f50e29a5ab5232b8ba7ca7f1c96cb1ea5c58' }] } request_body = { 'data': { 'type': 'snippet', 'attributes': { 'data': Snippet.REMOVE['data'], } } } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '643' } expect_body = { 'links': { 'self': 'http://falconframework.org/api/snippy/rest/snippets/' + Snippet.FORCED_UUID }, 'data': { 'type': 'snippet', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] } } result = testing.TestClient(server.server.api).simulate_put( path='/api/snippy/rest/snippets/53908d68425c61dc', headers={'accept': 'application/vnd.api+json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_200 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_create_snippet_023(server): """Create one snippet with POST. Send POST /snippets to create a new resource. The ``groups`` field is not defined at all in the HTTP request. The default value for this attribute must be always added if no value is provided by client. """ storage = { 'data': [{ 'category': 'snippet', 'data': ('test', ), 'brief': '', 'description': '', 'name': '', 'groups': ('default', ), 'tags': (), 'links': (), 'source': '', 'versions': (), 'filename': '', 'created': '2017-10-14T19:56:31.000001+00:00', 'updated': '2017-10-14T19:56:31.000001+00:00', 'uuid': Content.UUID1, 'digest': '4531ade7232dda7debd7ec3a20b2669afb57d665bd058184155442de203c76af', }] } request_body = { 'data': [{ 'type': 'snippet', 'attributes': { 'data': ['test'] } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '492' } expect_body = { 'data': [{ 'type': 'snippet', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/snippets', headers={'accept': 'application/json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_create_snippet_022(server): """Create new snippet with duplicated content field values. Send POST /snippets to create a new resource. In this case the resource attributes contain duplicated values. For example, there is a tag 'python' included twice in the ``tags`` attribute. Only unique values in attributes in array context must be added. """ storage = { 'data': [{ 'category': 'snippet', 'data': ('duplicated field values', ), 'brief': 'short brief', 'description': '', 'name': '', 'groups': ('docker', 'python'), 'tags': ('pypy', 'swarm'), 'links': ('http://www.dot.com/link1', 'http://www.dot.com/link2'), 'source': '', 'versions': ('docker-ce>17.09.2', ), 'filename': '', 'created': '2017-10-14T19:56:31.000001+00:00', 'updated': '2017-10-14T19:56:31.000001+00:00', 'uuid': Content.UUID1, 'digest': '800af62696ab9592c23dd5674642b91854e73a0c23f7659ac553de7fc66400d5' }] } request_body = { 'data': [{ 'type': 'snippet', 'attributes': { 'data': ['duplicated field values'], 'brief': 'short brief', 'description': '', 'groups': ['docker', 'docker', 'python'], 'tags': ['swarm', 'swarm', 'pypy'], 'links': [ 'http://www.dot.com/link2', 'http://www.dot.com/link2', 'http://www.dot.com/link1' ], 'versions': ['docker-ce>17.09.2'] } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '619' } expect_body = { 'data': [{ 'type': 'snippet', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/snippets', headers={ 'accept': 'application/vnd.api+json', 'content-type': 'application/vnd.api+json; charset=UTF-8' }, body=json.dumps(request_body, ensure_ascii=False)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_create_snippet_021(server): """Create one Snippet resource. Send POST /snippets to create new resource with data that have line breaks in the middle of the snippet which must not be interpolated to newlines. """ storage = { 'data': [{ 'category': 'snippet', 'data': ('docker rm $(docker\\nps \\n --all -q -f status=exited)', ), 'brief': '', 'description': '', 'name': '', 'groups': ('default', ), 'tags': (), 'links': (), 'source': '', 'versions': (), 'filename': '', 'created': '2017-10-14T19:56:31.000001+00:00', 'updated': '2017-10-14T19:56:31.000001+00:00', 'uuid': Content.UUID1, 'digest': 'c10b8614d264ed75ad3b671526efb9718895974291627b4fd21307051c6928c1' }] } request_body = { 'data': [{ 'type': 'snippet', 'attributes': { 'data': [ 'docker rm $(docker\\nps \\n --all -q -f status=exited)\n' ] } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '542' } expect_body = { 'data': [{ 'type': 'snippet', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/snippets', headers={'accept': 'application/json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_create_snippet_020(server): """Create one Snippet resource. Send POST /snippets to create new resource. In this case all fields have unnecessary leading and trailing whitespaces which are removed. Tags and links must be sorted. """ storage = { 'data': [{ 'category': 'snippet', 'data': ('first row', 'second row'), 'brief': 'short brief', 'description': 'long description', 'name': 'short name', 'groups': ('python', ), 'tags': ('spaces', 'tabs'), 'links': ('link1', 'link2'), 'source': 'short source link', 'versions': ('version==1.1.1', ), 'filename': 'shortfilename.yaml', 'created': Content.REGEXP_TIME, 'updated': Content.REGEXP_TIME, 'uuid': Content.UUID1, 'digest': 'b04d8c1f2913fc3c501e129505265986f1294da0cd3e9f758561cf5443ccf69f' }] } request_body = { 'data': [{ 'type': 'snippet', 'attributes': { 'data': [' first row ', ' second row '], 'brief': ' short brief ', 'description': ' long description ', 'name': ' short name ', 'groups': [ ' python ', ], 'tags': [' tabs ', ' spaces '], 'links': [' link2 ', ' link1 '], 'source': ' short source link ', 'versions': [' version==1.1.1 '], 'filename': ' shortfilename.yaml ' } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '630' } expect_body = { 'data': [{ 'type': 'snippet', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/snippets', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_cli_performance(self, snippy_perf, capsys, caplog): """Test CLI performance. Verify performance of the tool on a rough scale. The intention is to keep a reference test that is just iterated few times and the time consumed is measured. This is more for manual analysis than automation as of now. Reference PC: 1 loop : 0.0252 / 55 loop : 1.0865 / 100 loop : 1.9484 Reference PC: 880 loop : 17.6897 / 1000 loop : 19.6802 The reference is with sqlite database in memory as with all tests. There is naturally jitter in results and the values are as of now hand picked from few examples. Note that when run on Python2, will use sqlite database in disk that is naturally slower than memory database. No errors should be printed and the runtime should be below 10 seconds. The runtime is intentionally set 15 times higher value than with the reference PC to cope with slow test envrironments. """ start = time.time() for _ in range(55): self.create_defaults(snippy_perf) Content.assert_storage_size(4) # Search all content. cause = snippy_perf.run( ['snippy', 'search', '--scat', 'all', '--sall', '.'] + Content.db_cli_params()) assert cause == Cause.ALL_OK # Delete all content. cause = snippy_perf.run( ['snippy', 'delete', '-d', '54e41e9b52a02b63'] + Content.db_cli_params()) assert cause == Cause.ALL_OK cause = snippy_perf.run( ['snippy', 'delete', '-d', '53908d68425c61dc'] + Content.db_cli_params()) assert cause == Cause.ALL_OK cause = snippy_perf.run( ['snippy', 'delete', '-d', '4346ba4c79247430'] + Content.db_cli_params()) assert cause == Cause.ALL_OK cause = snippy_perf.run( ['snippy', 'delete', '-d', '6cfe47a8880a8f81'] + Content.db_cli_params()) assert cause == Cause.ALL_OK Content.assert_storage(None) runtime = time.time() - start out, err = capsys.readouterr() print("====================================") print("Runtime %.4f" % runtime) print("There are %d rows in stdout" % len(out)) print("There are %d rows in stderr" % len(err)) print("====================================") assert not err assert not caplog.records[:] assert runtime < 15
def test_api_create_reference_013(server): """Create two References with two POST methods. Send POST /references twice to create two new references. In this case the HTTP response for each POST request must contain only the created resource. """ storage = {'data': [Storage.gitlog]} storage['data'][0]['uuid'] = Content.UUID1 request_body = { 'data': { 'type': 'reference', 'attributes': Request.gitlog } } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '597' } expect_body = { 'data': [{ 'type': 'reference', 'id': Content.UUID1, 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/references', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage) storage = {'data': [Storage.pytest, Storage.gitlog]} storage['data'][0]['uuid'] = Content.UUID2 storage['data'][1]['uuid'] = Content.UUID1 request_body = { 'data': { 'type': 'reference', 'attributes': Request.pytest } } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '604' } expect_body = { 'data': [{ 'type': 'reference', 'id': Content.UUID2, 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/references', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_cli_create_solution_007(snippy, editor_data): """Create solution from editor. Create a new solution by using the prefilled default Markdown template in editor. The template presented in editor is manually defined in this test case on purpose. This tries to verity that the testing framework does not hide problems compared to situation where the template would be generated automatically by the testing framework. When content is created, the timestamp is allocated once for created and updated timestamps. The timestamp must not be updated from what is presented in the editor. """ content = { 'data': [ Content.deepcopy(Solution.KAFKA_MKDN) ] } template = ( '# Add brief title for content @groups', '', '> Add a description that defines the content in one chapter.', '', '> ', '', '## Description', '', '## References', '', '## Commands', '', '## Configurations', '', '## Solutions', '', '## Whiteboard', '', '## Meta', '', '> category : solution ', 'created : 2019-01-04T10:54:49.265512+00:00 ', 'digest : 5facdc16dc81851c2f65b112a0921eb2f2db206c7756714efb45ba0026471f11 ', 'filename : example-content.md ', 'languages : example-language ', 'name : example content handle ', 'source : https://www.example.com/source.md ', 'tags : example,tags ', 'updated : 2019-01-04T10:54:49.265512+00:00 ', 'uuid : a1cd5827-b6ef-4067-b5ac-3ceac07dde9f ', 'versions : example=3.9.0,python>=3 ', '' ) edited = ( '# Testing docker log drivers @docker', '', '> Investigate docker log drivers and the logs2kafka log plugin', '', '>', '', '## Description', '', 'Investigate docker log drivers.', '', '## Solutions', '', '## Whiteboard', '', '## Meta', '', '> category : solution ', 'created : 2019-01-04T10:54:49.265512+00:00 ', 'digest : 18473ec207798670c302fb711a40df6555e8973e26481e4cd6b2ed205f5e633c ', 'filename : kubernetes-docker-log-driver-kafka.mkdn ', 'languages : ', 'name : ', 'source : ', 'tags : docker,driver,kafka,kubernetes,logging,logs2kafka,moby,plugin ', 'updated : 2019-01-04T10:54:49.265512+00:00 ', 'uuid : a1cd5827-b6ef-4067-b5ac-3ceac07dde9f ', 'versions : ', '') content['data'][0]['data'] = ( '## Description', '', 'Investigate docker log drivers.', '', '## Solutions', '', '## Whiteboard', '' ) content['data'][0]['description'] = 'Investigate docker log drivers and the logs2kafka log plugin' content['data'][0]['links'] = () content['data'][0]['updated'] = '2019-01-04T10:54:49.265512+00:00' content['data'][0]['uuid'] = Content.UUID1 content['data'][0]['digest'] = '7941851522a23d3651f223b6d69441f77649ccb7ae1e72c6709890f2caf6401a' editor_data.return_value = '\n'.join(edited) cause = snippy.run(['snippy', 'create', '--scat', 'solution']) editor_data.assert_called_with('\n'.join(template)) assert cause == Cause.ALL_OK Content.assert_storage(content)
def test_api_create_snippet_006(server): """Create one Snippet with POST. Send POST /snippets to create a new resource. In this case the request resource has only the ``data`` attribute. """ storage = { 'data': [{ 'category': 'snippet', 'data': ('docker rm $(docker ps --all -q -f status=exited)', ), 'brief': '', 'description': '', 'name': '', 'groups': ('default', ), 'tags': (), 'links': (), 'source': '', 'versions': (), 'filename': '', 'created': '2017-10-14T19:56:31.000001+00:00', 'updated': '2017-10-14T19:56:31.000001+00:00', 'uuid': Content.UUID1, 'digest': '3d855210284302d58cf383ea25d8abdea2f7c61c4e2198da01e2c0896b0268dd' }] } request_body = { 'data': [{ 'type': 'snippet', 'attributes': { 'data': ['docker rm $(docker ps --all -q -f status=exited)\n'] } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '536' } expect_body = { 'data': [{ 'type': 'snippet', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/snippets', headers={'accept': 'application/json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_update_snippet_002(server): """Update one snippet with PUT request. Send PUT /snippets/{id} to update existing resource with specified digest. Only partial set of attributes that can be modified is sent in request. """ storage = { 'data': [{ 'category': 'snippet', 'data': Snippet.REMOVE['data'], 'brief': '', 'description': '', 'name': '', 'groups': Snippet.REMOVE['groups'], 'tags': (), 'links': Snippet.REMOVE['links'], 'source': '', 'versions': (), 'filename': '', 'created': Content.FORCED_TIME, 'updated': Content.REMOVE_TIME, 'uuid': '12cd5827-b6ef-4067-b5ac-3ceac07dde9f', 'digest': 'e56c2183edcc3a67cab99e6064439495a8af8a1d0b78bc538acd6079c841f27f' }] } request_body = { 'data': { 'type': 'snippet', 'attributes': { 'data': storage['data'][0]['data'], 'groups': storage['data'][0]['groups'], 'links': storage['data'][0]['links'] } } } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '700' } expect_body = { 'links': { 'self': 'http://falconframework.org/api/snippy/rest/snippets/' + Snippet.FORCED_UUID }, 'data': { 'type': 'snippet', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] } } result = testing.TestClient(server.server.api).simulate_put( path='/api/snippy/rest/snippets/53908d68425c61dc', headers={'accept': 'application/vnd.api+json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_200 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_create_snippet_015(server): """Update snippet with POST that maps to PATCH. Send POST /snippets with the ``X-HTTP-Method-Override`` header to update a resource. All resource attributes are tried to be updated. This must generate HTTP error because it is not possible to update for example the ``uuid`` attribute by client. """ storage = {'data': [Storage.forced]} request_body = { 'data': { 'type': 'snippet', 'attributes': { 'categeory': 'solution', 'data': 'data row1\ndata row2', 'brief': 'brief description', 'description': 'long description', 'name': 'runme', 'groups': 'solution', 'tags': 'tag1,tag2', 'links': 'link1\nlink2', 'source': 'http://testing/snippets.html', 'versions': 'version==1.1', 'filename': 'filename.txt', 'created': 'invalid time', 'updated': 'invalid time', 'uuid': Snippet.EXITED_UUID, 'digest': 'invalid digest' } } } expect_headers_p3 = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '1784' } expect_headers_p2 = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '1875' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': 'json media validation failed' }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/snippets/53908d68425c61dc', headers={ 'accept': 'application/vnd.api+json', 'X-HTTP-Method-Override': 'PATCH' }, body=json.dumps(request_body)) assert result.status == falcon.HTTP_400 assert result.headers in (expect_headers_p2, expect_headers_p3) Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_cli_update_snippet_018(snippy, edited_remove): """Update snippet with editor. Update existing text formatted snippet first in text format, then in Markdown format and then again in text format without making any changes. The content must not change when updated between different formats. Each update must generate different timestamp in content ``updated`` attribute. In this case the updates are given from editor and the last update must produce the same content as the first update. The content in editor is explicitly defined in the test to avoid false positives from the test helpers that actually use the code itself. """ edited_text = ( '# Commented lines will be ignored.', '#', '# Add mandatory snippet below.', 'docker rm --volumes $(docker ps --all --quiet)', '', '# Add optional brief description below.', 'Remove all docker containers', '', '# Add optional description below.', '', '', '# Add optional name below.', '', '', '# Add optional comma separated list of groups below.', 'docker', '', '# Add optional comma separated list of tags below.', 'cleanup,container,docker,docker-ce,moby', '', '# Add optional links below one link per line.', 'https://docs.docker.com/engine/reference/commandline/rm/', '', '# Add optional source reference below.', '', '', '# Add optional comma separated list of key-value versions below.', '', '', '# Add optional filename below.', '') edited_mkdn = ( '# Remove all docker containers again @docker', '', '> ', '', '> [1] https://docs.docker.com/engine/reference/commandline/rm/', '', '`$ docker rm --volumes $(docker ps --all --quiet)`', '', '## Meta', '', '> category : snippet ', 'created : 2017-10-14T19:56:31.000001+00:00 ', 'digest : 54e41e9b52a02b631b5c65a6a053fcbabc77ccd42b02c64fdfbc76efdb18e319 ', 'filename : ', 'name : ', 'source : ', 'tags : cleanup,container,docker,docker-ce,moby ', 'updated : 2017-10-14T19:56:31.000001+00:00 ', 'uuid : 11cd5827-b6ef-4067-b5ac-3ceac07dde9f ', 'versions : ', '') content = { 'data': [ Content.deepcopy(Snippet.REMOVE), ] } content['data'][0]['brief'] = 'Remove all docker containers' content['data'][0][ 'digest'] = 'ef734194f551eaa165767fc6aa081ca0c66894fd51eef5cfbc5a26ab3e808d06' edited_remove.return_value = '\n'.join(edited_text) cause = snippy.run([ 'snippy', 'update', '--digest', '54e41e9b52a0', '--format', 'text', '--editor' ]) assert cause == Cause.ALL_OK Content.assert_storage(content) content['data'][0]['brief'] = 'Remove all docker containers again' content['data'][0][ 'digest'] = 'ff16d0f4fdbe1f863e6b81189672d33d29fb436235f3a2243449aca651e8eb49' edited_remove.return_value = '\n'.join(edited_mkdn) content['data'][0]['updated'] = '2017-11-14T19:56:31.000001+00:00' cause = snippy.run([ 'snippy', 'update', '--digest', 'ef734194f551', '--format', 'mkdn', '--editor' ]) assert cause == Cause.ALL_OK Content.assert_storage(content) content['data'][0]['brief'] = 'Remove all docker containers' content['data'][0][ 'digest'] = 'ef734194f551eaa165767fc6aa081ca0c66894fd51eef5cfbc5a26ab3e808d06' edited_remove.return_value = '\n'.join(edited_text) content['data'][0]['updated'] = '2017-12-14T19:56:31.000001+00:00' cause = snippy.run([ 'snippy', 'update', '--digest', 'ff16d0f4fdbe', '--format', 'text', '--editor' ]) assert cause == Cause.ALL_OK Content.assert_storage(content)
def test_api_create_snippet_019(server): """Create and search snippet with unicode characters. Send POST /snippets to create a new resource. In this case resource contains unicode characters in string and list fields. The content must be also returned correctly when searching with unicode characters. """ storage = { 'data': [{ 'category': 'snippet', 'data': (u'Sîne klâwen durh die wolken sint geslagen', u'er stîget ûf mit grôzer kraft'), 'brief': u'Tagelied of Wolfram von Eschenbach Sîne klâwen', 'description': u'Tagelied of Wolfram von Eschenbach Sîne klâwen', 'name': '', 'groups': (u'Düsseldorf', ), 'tags': (u'έδωσαν', u'γλώσσα', u'ελληνική'), 'links': (u'http://www.чухонца.edu/~fdc/utf8/', ), 'source': '', 'versions': (), 'filename': '', 'created': '2017-10-14T19:56:31.000001+00:00', 'updated': '2017-10-14T19:56:31.000001+00:00', 'uuid': Content.UUID1, 'digest': 'c267233096b6977ea4dd9ef41faa1559d3886ad550d8932ddb4513eae5b84fbf' }] } request_body = { 'data': [{ 'type': 'snippet', 'attributes': { 'data': [ u'Sîne klâwen durh die wolken sint geslagen', u'er stîget ûf mit grôzer kraft' ], 'brief': u'Tagelied of Wolfram von Eschenbach Sîne klâwen', 'description': u'Tagelied of Wolfram von Eschenbach Sîne klâwen', 'groups': [u'Düsseldorf'], 'tags': [u'έδωσαν', u'γλώσσα', u'ελληνική'], 'links': [u'http://www.чухонца.edu/~fdc/utf8/'] } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '907' } expect_body = { 'data': [{ 'type': 'snippet', 'id': Content.UUID1, 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/snippets', headers={ 'accept': 'application/vnd.api+json', 'content-type': 'application/vnd.api+json; charset=UTF-8' }, body=json.dumps(request_body, ensure_ascii=False)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage) expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '967' } expect_body = { 'meta': { 'count': 1, 'limit': 20, 'offset': 0, 'total': 1 }, 'data': [{ 'type': 'snippet', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_get( path='/api/snippy/rest/snippets', headers={ 'accept': 'application/vnd.api+json', 'content-type': 'application/vnd.api+json; charset=UTF-8' }, query_string='sall=Düsseldorf&limit=20&sort=brief') assert result.status == falcon.HTTP_200 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body)
def test_api_create_solution_003(server): """Update Solution with POST that maps to PUT. Send POST /solutions/{id} to update existing resource with the ``X-HTTP-Method-Override`` header that overrides the operation as PUT. In this case the created timestamp must remain in initial value and the updated timestamp must be updated to reflect the update time. In this case the resource ``created`` attribute must remain in the initial value and the ``updated`` attribute must be set to reflect the update time. The ``uuid`` attribute must not be changed from it's initial value. Because the HTTP method is PUT, it overrides attributes that are not defined with default values. The ``filename`` attribute is set to empty value because of this. """ storage = {'data': [Storage.dnginx]} storage['data'][0]['filename'] = '' storage['data'][0]['updated'] = Content.NGINX_TIME storage['data'][0]['uuid'] = Solution.BEATS_UUID storage['data'][0][ 'digest'] = '6d102b92af89d6bd6cb65e8d2a6e486dcff2d0fed015ba6b6afde0c99e74b9bc' request_body = { 'data': { 'type': 'solution', 'attributes': { 'data': storage['data'][0]['data'], 'brief': storage['data'][0]['brief'], 'description': storage['data'][0]['description'], 'groups': storage['data'][0]['groups'], 'tags': storage['data'][0]['tags'], 'links': storage['data'][0]['links'] } } } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '2760' } expect_body = { 'links': { 'self': 'http://falconframework.org/api/snippy/rest/solutions/' + Solution.BEATS_UUID }, 'data': { 'type': 'solution', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] } } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/solutions/4346ba4c79247430', headers={ 'accept': 'application/vnd.api+json; charset=UTF-8', 'X-HTTP-Method-Override': 'PUT' }, body=json.dumps(request_body)) assert result.status == falcon.HTTP_200 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_create_reference_008(server_db, used_database): """Try to create a Reference resource. Try to POST new resource when database throws an unique constraint violation error from the ``uuid`` attribute. In this case there is no stored resources and digest in generated error message cannot filled fromi database. The database tries to insert the content twice once batched and then one by one. Both of the inserts result same unique constraint violation. """ request_body = { 'data': [{ 'type': 'reference', 'attributes': Request.gitlog }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '583' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '500', 'statusString': '500 Internal Server Error', 'module': 'snippy.testing.testing:123', 'title': 'internal error when searching content possibly violating database unique constraints' }, { 'status': '500', 'statusString': '500 Internal Server Error', 'module': 'snippy.testing.testing:123', 'title': 'content: uuid :already exist with digest: not found' }] } server = server_db[0] db_connect = server_db[1] if used_database in (Helper.DB_SQLITE, Helper.DB_IN_MEMORY): db_connect.return_value.commit.side_effect = [ sqlite3.IntegrityError( 'UNIQUE constraint failed: contents.uuid'), sqlite3.IntegrityError( 'UNIQUE constraint failed: contents.uuid') ] elif used_database == Helper.DB_POSTGRESQL: db_connect.return_value.commit.side_effect = [ sqlite3.IntegrityError( 'duplicate key value violates unique constraint "contents_data_key"\n' + 'DETAIL: Key (uuid)=11cd5827-b6ef-4067-b5ac-3ceac07dde9f already exists.' ), sqlite3.IntegrityError( 'duplicate key value violates unique constraint "contents_data_key"\n' + 'DETAIL: Key (uuid)=11cd5827-b6ef-4067-b5ac-3ceac07dde9f already exists.' ), ] result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/references', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_500 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(None)
def test_cli_create_snippet_007(snippy, capsys): """Create snippet with unicode characters from CLI. Every field that can be given from command line contains unicode characters. The same content must be found by searching it with keyword that contains unicode characters. """ content = { 'data': [{ 'category': 'snippet', 'data': (u'Sîne klâwen durh die wolken sint geslagen', u'er stîget ûf mit grôzer kraft'), 'brief': u'Tagelied of Wolfram von Eschenbach Sîne klâwen', 'description': '', 'name': '', 'groups': (u'Düsseldorf', ), 'tags': (u'έδωσαν', u'γλώσσα', u'ελληνική'), 'links': (u'http://www.чухонца.edu/~fdc/utf8/', ), 'source': '', 'versions': (), 'languages': (), 'filename': '', 'created': Content.REMOVE_TIME, 'updated': Content.REMOVE_TIME, 'uuid': Content.UUID1, 'digest': 'a74d83df95d5729aceffc472433fea4d5e3fd2d87b510112fac264c741f20438' }] } data = Const.DELIMITER_DATA.join(content['data'][0]['data']) brief = content['data'][0]['brief'] groups = Const.DELIMITER_GROUPS.join(content['data'][0]['groups']) tags = Const.DELIMITER_TAGS.join(content['data'][0]['tags']) links = Const.DELIMITER_LINKS.join(content['data'][0]['links']) cause = snippy.run(['snippy', 'create', '--content', data, '--brief', brief, '--groups', groups, '--tags', tags, '--links', links]) # pylint: disable=line-too-long assert cause == Cause.ALL_OK Content.assert_storage(content) output = ( u'1. Tagelied of Wolfram von Eschenbach Sîne klâwen @Düsseldorf [a74d83df95d5729a]', u'', u' $ Sîne klâwen durh die wolken sint geslagen', u' $ er stîget ûf mit grôzer kraft', u'', u' # έδωσαν,γλώσσα,ελληνική', u' > http://www.чухонца.edu/~fdc/utf8/', u'', u'OK', u'') out, err = capsys.readouterr() cause = snippy.run( ['snippy', 'search', '--sall', 'klâwen', '--no-ansi']) out, err = capsys.readouterr() assert cause == Cause.ALL_OK assert out == Const.NEWLINE.join(output) assert not err
def test_api_create_reference_010(server): """Create one Reference resource. Send POST /references to create a new resource. In this case every attribute has additional leading and trailing whitespaces that must be trimmed when stored. """ storage = { 'data': [{ 'category': 'reference', 'data': (), 'brief': 'short brief', 'description': 'longer description', 'name': 'short name', 'groups': ('python', ), 'tags': ('spaces', 'tabs'), 'links': ('link1', 'link2'), 'source': 'short source link', 'versions': ('kafka==1.0.0', ), 'languages': ('python', ), 'filename': 'shortfilename.yaml', 'created': Content.REGEXP_TIME, 'updated': Content.REGEXP_TIME, 'uuid': Content.UUID1, 'digest': 'f68078e62794f6e1e00ccff301fb83ea01b7587959d6ab7b444c18b637f6e61b' }] } request_body = { 'data': [{ 'type': 'reference', 'attributes': { 'data': [' first row ', ' second row '], 'brief': ' short brief ', 'description': ' longer description ', 'name': ' short name ', 'groups': [ ' python ', ], 'tags': [' spaces ', ' tabs '], 'links': [' link1 ', ' link2 '], 'source': ' short source link ', 'versions': [' kafka==1.0.0 '], 'languages': [' python '], 'filename': ' shortfilename.yaml ' } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '634' } expect_body = { 'data': [{ 'type': 'reference', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/references', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_update_reference_009(server): """Update reference with PUT request. Send PUT /references/{id} to replace existing resource with digest. The PUT sets all but the mandatory ``links`` attribute to empty values. """ storage = {'data': [Storage.gitlog]} storage['data'][0]['brief'] = '' storage['data'][0]['description'] = '' storage['data'][0]['name'] = '' storage['data'][0]['groups'] = () storage['data'][0]['tags'] = () storage['data'][0]['source'] = '' storage['data'][0]['versions'] = () storage['data'][0]['languages'] = () storage['data'][0]['filename'] = '' storage['data'][0]['created'] = Content.GITLOG_TIME storage['data'][0]['updated'] = Content.PYTEST_TIME storage['data'][0][ 'digest'] = '54c493ade0f808e3d1b16bb606484a51bb0f7eb9c0592c46aea5196bd891881c' request_body = { 'data': { 'type': 'reference', 'attributes': { 'links': storage['data'][0]['links'], 'brief': '', 'description': '', 'name': '', 'groups': (), 'tags': (), 'source': '', 'versions': (), 'languages': (), 'filename': '' } } } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '651' } expect_body = { 'links': { 'self': 'http://falconframework.org/api/snippy/rest/references/' + Reference.GITLOG_UUID }, 'data': { 'type': 'reference', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] } } result = testing.TestClient(server.server.api).simulate_put( path='/api/snippy/rest/references/5c2071094dbfaa33', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_200 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_create_reference_011(server): """Create one Reference resource. Send POST /references to create a new resource. In this case only the mandatory ``links`` attribute for Reference resource is defined. """ storage = { 'data': [{ 'category': 'reference', 'data': (), 'brief': '', 'description': '', 'name': '', 'groups': ('default', ), 'tags': (), 'links': ('link1', 'link2'), 'source': '', 'versions': (), 'languages': (), 'filename': '', 'created': Content.REGEXP_TIME, 'updated': Content.REGEXP_TIME, 'uuid': Content.UUID1, 'digest': 'b978df98e539644f9861a13803c19345d286544302ccedfd98c36cf16724eb80' }] } request_body = { 'data': [{ 'type': 'reference', 'attributes': { 'links': ['link1', 'link2'], } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '523' } expect_body = { 'data': [{ 'type': 'reference', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/references', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def teardown_class(cls): """Teardown class.""" Content.delete()
def test_api_create_reference_012(server): """Create new reference with duplicated content field values. Send POST /references to create a new resource. In this case the resource attributes contain duplicated values. For example, there is a tag 'python' included twice in the ``tags`` attribute. Only unique values in attributes in array context must be added. Links are not sorted because the order is assumed to convey relevant information related to link importance in case of Reference resource. Because of this, removal of duplicated values in ``links`` attribute must not change the order which links are added. """ storage = { 'data': [{ 'category': 'reference', 'data': (), 'brief': 'short brief', 'description': '', 'name': '', 'groups': ('docker', 'python'), 'tags': ('pypy', 'swarm'), 'links': ('http://www.dot.com/link2', 'http://www.dot.com/link1'), 'source': '', 'versions': (), 'languages': (), 'filename': '', 'created': '2018-06-22T13:11:13.678729+00:00', 'updated': '2018-06-22T13:11:13.678729+00:00', 'uuid': Content.UUID1, 'digest': 'aa6aa8c9a94f1959c9935d7bc6aca060edd5369ae5a24d26ce2960852751d09d' }] } request_body = { 'data': [{ 'type': 'reference', 'attributes': { 'brief': 'short brief', 'description': '', 'groups': ['docker', 'docker', 'python'], 'tags': ['swarm', 'swarm', 'pypy'], 'links': [ 'http://www.dot.com/link2', 'http://www.dot.com/link2', 'http://www.dot.com/link1' ], 'versions': [], 'languages': [] } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '596' } expect_body = { 'data': [{ 'type': 'reference', 'id': storage['data'][0]['uuid'], 'attributes': storage['data'][0] }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/references', headers={ 'accept': 'application/vnd.api+json', 'content-type': 'application/vnd.api+json; charset=UTF-8' }, body=json.dumps(request_body, ensure_ascii=False)) assert result.status == falcon.HTTP_201 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)