def test_publish_invalid(self):
        # GIVEN datapackage that can be treated as valid by the dpm
        self.valid_dp = datapackage.DataPackage(
            {
                "name":
                "some-datapackage",
                "resources": [{
                    "name": "some-resource",
                    "path": "./data/some_data.csv",
                }]
            },
            default_base_path='.')
        patch('dpm.client.DataPackage', lambda *a: self.valid_dp).start()
        patch('dpm.client.exists', lambda *a: True).start()

        # AND the server that accepts any user
        responses.add(responses.POST,
                      'http://127.0.0.1:5000/api/auth/token',
                      json={'token': 'blabla'},
                      status=200)
        # AND server rejects any datapackage as invalid
        responses.add(
            responses.PUT,
            'http://127.0.0.1:5000/api/package/user/some-datapackage',
            json={'message': 'invalid datapackage json'},
            status=400)

        # AND the client
        client = Client(dp1_path, self.config)

        # WHEN publish() is invoked
        try:
            result = client.publish()
        except Exception as e:
            result = e

        # THEN HTTPStatusError should be raised
        assert isinstance(result, HTTPStatusError)
        # AND 'invalid datapackage json' should be printed to stdout
        self.assertRegexpMatches(str(result), 'invalid datapackage json')
    def test_publish_success(self):
        # name from fixture data package
        dp_name = 'abc'
        username = '******'
        config = {
            'username': username,
            'server': 'https://example.com',
            'access_token': 'access_token'
        }
        client = Client(dp1_path, config)
        # GIVEN the registry server that accepts any user
        responses.add(responses.POST,
                      'https://example.com/api/auth/token',
                      json={'token': 'blabla'},
                      status=200)

        # AND registry server gives bitstore upload url
        responses.add(responses.POST,
                      'https://example.com/api/datastore/authorize',
                      json={
                          'filedata': {
                              'datapackage.json': {
                                  'upload_url':
                                  'https://s3.fake/put_here_datapackege',
                                  'upload_query': {
                                      'key': 'k'
                                  }
                              },
                              'README.md': {
                                  'upload_url':
                                  'https://s3.fake/put_here_readme',
                                  'upload_query': {
                                      'key': 'k'
                                  }
                              },
                              'data/some-data.csv': {
                                  'upload_url':
                                  'https://s3.fake/put_here_resource',
                                  'upload_query': {
                                      'key': 'k'
                                  }
                              }
                          }
                      },
                      status=200)
        # AND s3 server allows data upload for datapackage
        responses.add(responses.POST,
                      'https://s3.fake/put_here_datapackege',
                      json={'message': 'OK'},
                      status=200)
        # AND s3 server allows data upload for readme
        responses.add(responses.POST,
                      'https://s3.fake/put_here_readme',
                      json={'message': 'OK'},
                      status=200)
        # AND s3 server allows data upload for resource
        responses.add(responses.POST,
                      'https://s3.fake/put_here_resource',
                      json={'message': 'OK'},
                      status=200)
        # AND registry server successfully finalizes upload
        responses.add(responses.POST,
                      'https://example.com/api/package/upload',
                      json={'status': 'queued'},
                      status=200)

        # WHEN publish() is invoked
        result = client.publish(publisher='testpub')

        # 6 requests should be sent
        self.assertEqual(
            [(x.request.method, x.request.url, jsonify(x.request))
             for x in responses.calls],
            [
                # POST authorization
                ('POST', 'https://example.com/api/auth/token', {
                    "username": "******",
                    "secret": "access_token"
                }),
                # POST authorize presigned url for s3 upload
                ('POST', 'https://example.com/api/datastore/authorize', {
                    'metadata': {
                        'owner': 'user',
                        'name': 'abc'
                    },
                    'filedata': {
                        "README.md": {
                            "md5": '2ODaQHCqodO2B/cbf03lgA==',
                            "size": 24,
                            "type": 'binary/octet-stream',
                            'name': 'README.md'
                        },
                        "datapackage.json": {
                            "md5": 'mDmEykSS++mJF3SaWW56kw==',
                            "size": 120,
                            "type": 'application/json',
                            'name': 'datapackage.json'
                        },
                        "data/some-data.csv": {
                            "md5": 'Nlu4VmSF8ZT6wK4QjL8iyw==',
                            "size": 12,
                            "type": 'binary/octet-stream',
                            'name': 'data/some-data.csv'
                        }
                    }
                }),
                # POST data to s3
                ('POST', 'https://s3.fake/put_here_datapackege', ''),
                ('POST', 'https://s3.fake/put_here_readme', ''),
                ('POST', 'https://s3.fake/put_here_resource', ''),
                # POST finalize upload
                ('POST', 'https://example.com/api/package/upload', {
                    'datapackage': 'https://s3.fake/put_here_datapackege/k'
                })
            ])