diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index db9d87c0cc3d521e4345f81088df2a220dfb83bc..c08b26ec402be9b63741a44adee323354e69f60a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -37,6 +37,7 @@ test_py37:
         --cov=eossr
         --cov-report=xml
         --cov-report=term
+        --capture=no
     <<: *junit_definition
 
 build_docker:
diff --git a/eossr/api/zenodo/__init__.py b/eossr/api/zenodo/__init__.py
index 7b7bf7cbd0f9272ec502f026c7f6508b6182ab9a..e5d8010421d447964c37ef736746fbba383fec7d 100644
--- a/eossr/api/zenodo/__init__.py
+++ b/eossr/api/zenodo/__init__.py
@@ -9,7 +9,8 @@ from pathlib import Path
 from urllib.parse import urlencode
 from urllib.request import urlopen
 import warnings
-from ...metadata.codemeta2zenodo import parse_codemeta_and_write_zenodo_metadata_file
+from zipfile import ZipFile
+from ...metadata.codemeta2zenodo import parse_codemeta_and_write_zenodo_metadata_file, converter
 from . import http_status
 from bs4 import BeautifulSoup
 
@@ -20,10 +21,8 @@ __all__ = [
     'http_status',
 ]
 
-
-
 zenodo_api_url = "https://zenodo.org/api"
-zenodo_sandobx_api_url = "https://sandbox.zenodo.org/api"
+zenodo_sandbox_api_url = "https://sandbox.zenodo.org/api"
 
 
 class ZenodoAPI:
@@ -55,18 +54,22 @@ class ZenodoAPI:
         """
 
         if sandbox:
-            self.api_url = zenodo_sandobx_api_url
+            self.api_url = zenodo_sandbox_api_url
+            self.sandbox = True
         else:
             self.api_url = zenodo_api_url
+            self.sandbox = False
 
         self.access_token = access_token
         self.parameters = {'access_token': self.access_token}
+        self._root_dir = Path(proj_root_dir)
 
-        self.proj_root_dir = Path(proj_root_dir)
-        self.exist_codemeta_file = False
-        self.path_codemeta_file = self.proj_root_dir
-        self.exist_zenodo_metadata_file = False
-        self.path_zenodo_metadata_file = self.proj_root_dir
+    @property
+    def root_dir(self):
+        return Path(self._root_dir)
+
+    def set_root_dir(self, path):
+        self._root_dir = Path(path)
 
     def fetch_user_entries(self):
         """
@@ -206,7 +209,7 @@ class ZenodoAPI:
         """
         url = f"{self.api_url}/deposit/depositions/{entry_id}/files/{file_id}"
         req = requests.delete(url, params=self.parameters)
-        http_status.ZenodoHTTPStatus(req.status_code, req.json())
+        http_status.ZenodoHTTPStatus(req.status_code)
         return req
 
     def publish_entry(self, entry_id):
@@ -305,49 +308,111 @@ class ZenodoAPI:
         return [entry['metadata']['title'] for entry in
                 self.fetch_community_entries(community_name, results_per_query).json()['hits']['hits']]
 
-    def search_codemeta_file(self):
-        """Check if a `codemeta.json` files exists in the ROOT directory of the project"""
+    @property
+    def path_codemeta_file(self):
+        return self.root_dir.joinpath('codemeta.json')
+
+    @property
+    def path_zenodo_file(self):
+        return self.root_dir.joinpath('.zenodo.json')
 
-        # root_dir = find_root_directory()
-        root_dir = self.proj_root_dir
-        print(f'\nProject root directory {abspath(root_dir)}')  # DEBUG
+    def conversion_codemeta2zenodo(self):
+        """Perform the codemeta2zenodo conversion if a codemeta.json file is found"""
 
-        codemeta_file = root_dir / 'codemeta.json'
+        if self.path_codemeta_file.exists():
+            print("\n * Creating a .zenodo.json file from your codemeta.json file...")
 
-        if codemeta_file.exists():
-            print("\n * Found codemeta.json file within the project !")
-            self.exist_codemeta_file = True
-            self.path_codemeta_file = codemeta_file
+            parse_codemeta_and_write_zenodo_metadata_file(self.path_codemeta_file,
+                                                          self.path_zenodo_file)
         else:
-            print("\n ! codemeta.json file NOT found in the root directory of the  project !")
+            print("\n ! NO codemeta.json file found. \n"
+                  "     Please add one to the ROOT directory of your project to ble able to perform the conversion.")
 
-    def search_zenodo_json_file(self):
-        """Check if a `.zenodo.json` files exists in the ROOT directory of the project"""
+    def zip_root_dir(self):
+        """
+        zip the content of `self.root_dir` into `{self.root_dir.name}.zip`
 
-        # root_dir = find_root_directory()
-        root_dir = self.proj_root_dir
+        :return: zip_filename: path to the zip archive
+        """
+        # prepare zip archive
+        zip_filename = self.root_dir.joinpath(f'{self.root_dir.name}.zip')
+        print(f"Zipping the content of {self.root_dir} into {zip_filename}")
 
-        zenodo_metadata_file = root_dir / '.zenodo.json'
+        with ZipFile(zip_filename, 'w') as zo:
+            for file in self.root_dir.iterdir():
+                zo.write(file)
+        print(f"zipping done: {zip_filename}")
+        return zip_filename
 
-        if zenodo_metadata_file.exists():
-            print("\n * Found .zenodo.json file within the project !")
-            self.exist_zenodo_metadata_file = True
-            self.path_zenodo_metadata_file = zenodo_metadata_file
-        else:
-            print("\n ! .zenodo.json file NOT found in the root directory of the  project !")
 
-    def conversion_codemeta2zenodo(self):
-        """Perform the codemeta2zenodo conversion if a codemeta.json file is found"""
+    def upload_dir_content(self, record_id=None, metadata=None, erase_previous_files=True, publish=True):
+        """
+        Package the project root directory as a zip archive and upload it to Zenodo.
+        If a `record_id` is passed, a new version of that record is created. Otherwise a new record is created.
 
-        if self.exist_codemeta_file:
-            print("\n * Creating a .zenodo.json file from your codemeta.json file...")
-            self.path_zenodo_metadata_file = self.path_codemeta_file.parent / '.zenodo.json'
+        :param record_id: str, int of None
+        :param metadata: dict or None
+            dictionnary of zenodo metadata
+            if None, the metadata will be read from a `.zenodo.json` file or a `codemeta.json` file in `self.root_dir`
+        """
 
-            parse_codemeta_and_write_zenodo_metadata_file(self.path_codemeta_file,
-                                                          self.path_zenodo_metadata_file)
+        # prepare new record version
+        if record_id is not None:
+            record = Record.from_id(record_id, sandbox=self.sandbox)
+            record_id = record.last_version_id
+            new_entry = self.new_version_entry(record_id)
+            new_record_id = new_entry.json()['links']['latest_draft'].rsplit('/')[-1]
+            print(f"Preparing a new version of record {record_id}")
+            # TODO: log
+            if erase_previous_files:
+                old_files_ids = [file['id'] for file in new_entry.json()['files']]
+                for file_id in old_files_ids:
+                    self.erase_file_entry(
+                        new_record_id,
+                        file_id
+                    )
+                    print(f"file {file_id} erased")
         else:
-            print("\n ! NO codemeta.json file found. \n"
-                  "     Please add one to the ROOT directory of your project to ble able to perform the conversion.")
+            new_entry = self.create_new_entry()
+            new_record_id = new_entry.json()['id']
+            print(f"Preparing a new record")
+        print(f"New record id: {new_record_id}")
+
+        # get metadata
+        if metadata is not None:
+            print(f"Record metadata based on provided metadata: {metadata}")
+        elif self.path_zenodo_file.exists():
+            print(f"Record metadata based on zenodo file {self.path_codemeta_file}")
+            with open(self.path_zenodo_file) as file:
+                metadata = json.load(file)
+
+        elif self.path_codemeta_file.exists():
+            print(f"Record metadata based on codemeta file {self.path_codemeta_file}")
+            with open(self.path_codemeta_file) as file:
+                codemeta = json.load(file)
+            metadata = converter(codemeta)
+        else:
+            raise FileNotFoundError("No metadata provided")
+
+        # upload files
+        for file in self.root_dir.iterdir():
+            self.upload_file_entry(entry_id=new_record_id,
+                                   name_file=file.name,
+                                   path_file=file)
+            print(f" * {file.name} uploaded")
+
+        self.update_metadata_entry(entry_id=new_record_id, json_metadata=metadata)
+        print("metadata updated successfully")
+
+        # publish new record
+        if publish:
+            self.publish_entry(new_record_id)
+            print(f" * New version of {record_id} published at {new_record_id} !")
+            print(f" * The new doi should be 10.5281/{new_record_id}")
+
+        print(f" * Check the upload at {self.api_url[:-4]}/deposit/{new_record_id} *")
+
+        return new_record_id
 
     def check_upload_to_zenodo(self):
         """
@@ -366,19 +431,16 @@ class ZenodoAPI:
             - The provided zenodo metadata can be digested, and not errors appear
             - Finally erases the test entry - because IT HAS NOT BEEN PUBLISHED !
         """
-        # Search for the codemeta.json and the .zenodo.json files within the project
-        self.search_codemeta_file()
-        self.search_zenodo_json_file()
-
-        if not self.exist_zenodo_metadata_file:
+        if not self.path_zenodo_file.exists():
 
-            if self.exist_codemeta_file:
+            if self.path_codemeta_file.exists():
+                print(f"zenodo file created from codemeta file {self.path_codemeta_file}")
                 self.conversion_codemeta2zenodo()
             else:
-                # No codemeta.json nor .zenodo.json
-                sys.exit(-1)
+                raise FileNotFoundError(f"No codemeta {self.path_codemeta_file} "
+                                        f"nor zenodo {self.path_zenodo_file()} files.")
 
-        print("\n * Using the .zenodo.json file to simulate a new upload to Zenodo... \n")
+        print(f"\n * Using {self.path_zenodo_file} file to simulate a new upload to Zenodo... \n")
 
         # 1 - Test connection
         print("1 --> Testing communication with Zenodo...")
@@ -400,7 +462,7 @@ class ZenodoAPI:
         print("3 --> Testing the ingestion of the Zenodo metadata...")
 
         test_entry_id = new_entry.json()['id']
-        with open(self.path_zenodo_metadata_file) as file:
+        with open(self.path_zenodo_file) as file:
             metadata_entry = json.load(file)
         update_metadata = self.update_metadata_entry(test_entry_id, json_metadata=metadata_entry)
 
@@ -430,7 +492,7 @@ class ZenodoAPI:
 
     def get_user_records(self):
         request = self.fetch_user_entries()
-        return [Record[hit] for hit in request.json()]
+        return [Record(hit) for hit in request.json()]
 
 
 class Record:
@@ -462,6 +524,18 @@ class Record:
     def title(self):
         return self.data['metadata']['title']
 
+    @property
+    def last_version_id(self):
+        return self.data['metadata']['relations']['version'][0]['last_child']['pid_value']
+
+    def get_last_version(self):
+        if self.data['metadata']['relations']['version'][0]['is_last']:
+            return self
+        else:
+            record_id = self.last_version_id
+            url = Path(self.data['links']['self']).parent.joinpath(str(record_id))
+            return Record(requests.get(url).json())
+
     def print_info(self):
         metadata = self.data['metadata']
         descrp = BeautifulSoup(metadata['description']).text
@@ -473,8 +547,8 @@ class Record:
         print('\n')
 
     @classmethod
-    def from_id(cls, record_id):
-        record = get_record(record_id=record_id)
+    def from_id(cls, record_id, sandbox=False):
+        record = get_record(record_id=record_id, sandbox=sandbox)
         return record
 
     def get_codemeta(self):
@@ -549,7 +623,7 @@ def get_zenodo_records(search='', sandbox=False, **kwargs):
         if param_name in kwargs:
             params[param_name] = lowercase(kwargs[param_name])
 
-    api_url = zenodo_sandobx_api_url if sandbox else zenodo_api_url
+    api_url = zenodo_sandbox_api_url if sandbox else zenodo_api_url
     url = api_url + "/records?" + urlencode(params, doseq=True)
 
     recs = [Record(hit) for hit in requests.get(url).json()["hits"]["hits"]]
@@ -567,7 +641,7 @@ def get_record(record_id, sandbox=False):
     :param record_id: int
     :return: Record
     """
-    api_url = zenodo_sandobx_api_url if sandbox else zenodo_api_url
+    api_url = zenodo_sandbox_api_url if sandbox else zenodo_api_url
     url = f"{api_url}/records/{record_id}"
     json = requests.get(url).json()
     if 'status' in json.keys():
diff --git a/eossr/api/zenodo/tests/test_zenodo.py b/eossr/api/zenodo/tests/test_zenodo.py
index 7393e93a0fceac8173f9ea005ad13b7c9b39798a..2a626d7bcb2dd5e8a3c368b4f4d62eb94008bda4 100644
--- a/eossr/api/zenodo/tests/test_zenodo.py
+++ b/eossr/api/zenodo/tests/test_zenodo.py
@@ -1,139 +1,118 @@
 #!/usr/bin/env python
 import os
 import json
+import shutil
 import unittest
 import requests
 import pytest
 from pathlib import Path
 import tempfile
-from os import remove
-from os.path import dirname, realpath, join
-from eossr.api.zenodo import ZenodoAPI, get_zenodo_records, get_record
+from eossr.api.zenodo import ZenodoAPI, get_zenodo_records, get_record, Record
 
-ROOT_DIR = dirname(realpath("codemeta.json"))
 
+ROOT_DIR = Path('codemeta.json').parent
+eossr_test_lib_id = 930570  # test library in sandbox (owner: T. Vuillaume)
 
 class TestZenodoApiSandbox(unittest.TestCase):
-    def test_initialization_sandbox(self):
-        token = 'FakeToken'
-        z = ZenodoAPI(access_token=token,
+
+    def __init__(self, *args, **kwargs):
+        super(TestZenodoApiSandbox, self).__init__(*args, **kwargs)
+        self.token = 'FakeToken'
+        self.zenodo = ZenodoAPI(access_token=self.token,
                       sandbox=True,
                       proj_root_dir=ROOT_DIR)
 
-        assert isinstance(z, ZenodoAPI)
-        assert z.api_url == 'https://sandbox.zenodo.org/api'
-        assert z.access_token == token
-        assert type(z.exist_codemeta_file) == bool
-        assert type(z.exist_zenodo_metadata_file) == bool
-        assert z.proj_root_dir == Path(ROOT_DIR)
-        assert z.path_codemeta_file == z.proj_root_dir
-        assert z.path_zenodo_metadata_file == z.proj_root_dir
-        assert isinstance(z.proj_root_dir, (Path, str))
-
+    def test_initialization_sandbox(self):
+        assert isinstance(self.zenodo, ZenodoAPI)
+        assert self.zenodo.api_url == 'https://sandbox.zenodo.org/api'
+        assert self.zenodo.access_token == self.token
+        assert self.zenodo.root_dir == ROOT_DIR
+        assert self.zenodo.path_codemeta_file == self.zenodo.root_dir.joinpath('codemeta.json')
+        assert self.zenodo.path_zenodo_file == self.zenodo.root_dir.joinpath('.zenodo.json')
+        assert isinstance(self.zenodo.root_dir, (Path, str))
+
+    def test_fetch_community_entries(self):
+        community_entries = self.zenodo.fetch_community_entries()
+        assert isinstance(community_entries, requests.models.Response)
 
-class TestZenodoAPI(unittest.TestCase):
-    def test_initialization(self):
+    def test_conversion_codemeta2zenodo_and_search_zenodo_file(self):
         token = 'FakeToken'
         z = ZenodoAPI(access_token=token,
                       sandbox=False,
                       proj_root_dir=ROOT_DIR)
 
-        assert isinstance(z, ZenodoAPI)
-        assert z.api_url == 'https://zenodo.org/api'
-        assert z.access_token == token
-        assert type(z.exist_codemeta_file) == bool
-        assert type(z.exist_zenodo_metadata_file) == bool
-        assert z.proj_root_dir == Path(ROOT_DIR)
-        assert z.path_codemeta_file == z.proj_root_dir
-        assert z.path_zenodo_metadata_file == z.proj_root_dir
-        assert isinstance(z.proj_root_dir, (Path, str))
-
-    @pytest.mark.skipif(os.getenv('SANDBOX_ZENODO_TOKEN') is None, reason="SANDBOX_ZENODO_TOKEN not defined")
-    def test_zenodo_api_methods(self):
-        token = os.getenv('SANDBOX_ZENODO_TOKEN')
-        z = ZenodoAPI(access_token=token, sandbox=True, proj_root_dir=ROOT_DIR)
-
-        test_id = '927064'
-        z.search_codemeta_file()
-        test_filename = join(ROOT_DIR, z.path_codemeta_file)
-
-        _, path_test_filename = tempfile.mkstemp(text='Hello World')
-
-        fetch_user_entry = z.fetch_user_entries()
-        create_new_entry = z.create_new_entry()
-        fetch_single_entry = z.fetch_entry(entry_id=test_id)
+        assert z.path_codemeta_file.exists()
+        z.conversion_codemeta2zenodo()
 
-        upload_file_entry = z.upload_file_entry(entry_id=test_id, name_file=test_filename, path_file=path_test_filename)
+        assert z.path_zenodo_file.exists()
+        assert z.path_zenodo_file == z.root_dir.joinpath('.zenodo.json')
+        with open(z.path_zenodo_file) as f:
+            zenodo_meta = json.load(f)
 
-        upload_metadata_entry = z.update_metadata_entry(entry_id=test_id, json_metadata=test_filename)
-        erase_entry = z.erase_entry(entry_id=test_id)
-        erase_file_entry = z.erase_file_entry(entry_id=test_id, file_id=test_id)
-        publish_entry = z.publish_entry(entry_id=test_id)
-        new_version_entry = z.new_version_entry(entry_id=test_id)
+        os.remove(z.path_zenodo_file)
 
-        community_entries = z.fetch_community_entries()
-        fetch_ids = z.fetch_community_entries_per_id()
-        fetch_filenames = z.fetch_community_entries_per_title()
 
-        assert isinstance(fetch_user_entry, requests.models.Response)
-        assert isinstance(create_new_entry, requests.models.Response)
-        assert isinstance(fetch_single_entry, requests.models.Response)
-        assert isinstance(upload_file_entry, requests.models.Response)
-        assert isinstance(upload_metadata_entry, requests.models.Response)
-        assert isinstance(erase_entry, requests.models.Response)
-        assert isinstance(erase_file_entry, requests.models.Response)
-        assert isinstance(publish_entry, requests.models.Response)
-        assert isinstance(new_version_entry, requests.models.Response)
-        assert isinstance(community_entries, requests.models.Response)
-        assert isinstance(fetch_ids, list)
-        assert isinstance(fetch_filenames, list)
+class TestZenodoAPINoToken(unittest.TestCase):
 
-    def test_search_codemeta_file(self):
-        token = 'FakeToken'
-        z = ZenodoAPI(access_token=token,
+    def __init__(self, *args, **kwargs):
+        super(TestZenodoAPINoToken, self).__init__(*args, **kwargs)
+        self.token = 'FakeToken'
+        self.zenodo = ZenodoAPI(access_token=self.token,
                       sandbox=False,
                       proj_root_dir=ROOT_DIR)
 
-        assert z.exist_codemeta_file is False
-        z.search_codemeta_file()
-        assert z.exist_codemeta_file is True
+    def test_initialization(self):
+        assert isinstance(self.zenodo, ZenodoAPI)
+        assert self.zenodo.api_url == 'https://zenodo.org/api'
+        assert self.zenodo.access_token == self.token
+        assert self.zenodo.root_dir == ROOT_DIR
+        assert isinstance(self.zenodo.root_dir, (Path, str))
 
-        codemeta_file_path = Path(ROOT_DIR) / 'codemeta.json'
-        assert z.path_codemeta_file == codemeta_file_path
-        assert codemeta_file_path.is_file()
-        print(z.path_codemeta_file, type(z.path_codemeta_file))
-        with open(z.path_codemeta_file) as f:
-            json.load(f)
 
-    def test_search_zenodo_json_file(self):
-        token = 'FakeToken'
-        z = ZenodoAPI(access_token=token,
-                      sandbox=False,
-                      proj_root_dir=ROOT_DIR)
+@pytest.mark.skipif(os.getenv('SANDBOX_ZENODO_TOKEN') is None, reason="SANDBOX_ZENODO_TOKEN not defined")
+class TestZenodoAPIToken(unittest.TestCase):
+    def __init__(self, *args, **kwargs):
+        super(TestZenodoAPIToken, self).__init__(*args, **kwargs)
+        self.root_dir = ROOT_DIR
+        self.token = os.getenv('SANDBOX_ZENODO_TOKEN')
+        self.zenodo = ZenodoAPI(access_token=self.token, sandbox=True, proj_root_dir=ROOT_DIR)
 
-        assert z.exist_zenodo_metadata_file is False
-        z.search_zenodo_json_file()
-        assert z.exist_zenodo_metadata_file is False
+    def test_init(self):
+        self.zenodo.access_token == os.getenv('SANDBOX_ZENODO_TOKEN')
 
-    def test_conversion_codemeta2zenodo_and_search_zenodo_file(self):
-        token = 'FakeToken'
-        z = ZenodoAPI(access_token=token,
-                      sandbox=False,
-                      proj_root_dir=ROOT_DIR)
+    def test_get_user_records(self):
+        records = self.zenodo.get_user_records()
+        assert isinstance(records[0], Record)
 
-        z.search_codemeta_file()
-        z.conversion_codemeta2zenodo()
+    def test_fetch_user_entries(self):
+        self.zenodo.fetch_user_entries()
 
-        z.search_zenodo_json_file()
-        assert z.exist_zenodo_metadata_file is True
+    def test_create_erase_new_entry(self):
+        create_new_entry = self.zenodo.create_new_entry()
+        assert isinstance(create_new_entry, requests.models.Response)
+        record_id = create_new_entry.json()['id']
+        erase_entry = self.zenodo.erase_entry(record_id)
+        assert isinstance(erase_entry, requests.models.Response)
 
-        zenodo_file_path = Path(ROOT_DIR) / '.zenodo.json'
-        assert z.path_zenodo_metadata_file == zenodo_file_path
-        assert zenodo_file_path.is_file()
-        with open(z.path_zenodo_metadata_file) as f:
-            json.load(f)
+    def test_upload_package(self):
+        # prepare upload in a tmpdir
+        with tempfile.TemporaryDirectory() as tmpdirname:
+            print(f"tmpdir {tmpdirname}")
+            shutil.copy(ROOT_DIR.joinpath('codemeta.json'), tmpdirname)
+            _, filename = tempfile.mkstemp(dir=tmpdirname)
+            Path(filename).write_text('Hello from eossr unit tests')
+            self.zenodo.set_root_dir(tmpdirname)
+
+            # create new record
+            new_record_id = self.zenodo.upload_dir_content(publish=False)
+            self.zenodo.erase_entry(new_record_id)
+            print(f"{new_record_id} created and deleted")
+
+            # update existing one
+            new_record_id = self.zenodo.upload_dir_content(record_id=eossr_test_lib_id, publish=False)
+            self.zenodo.erase_entry(new_record_id)
+            print(f"{new_record_id} created and deleted")
 
-        remove(z.path_zenodo_metadata_file)
 
 
 def test_get_zenodo_records():
diff --git a/eossr/metadata/codemeta2zenodo.py b/eossr/metadata/codemeta2zenodo.py
index 373c9be07bddfc837198159c1cd7f8c474c23be4..bb5475d3093c43d145ed00820dcb7ad419b55972 100644
--- a/eossr/metadata/codemeta2zenodo.py
+++ b/eossr/metadata/codemeta2zenodo.py
@@ -194,14 +194,17 @@ def find_matching_metadata(codemeta_json):
 
 class CodeMeta2ZenodoController(object):
     """Control the conversion of a codemeta file to a zenodo file"""
-    def __init__(self):
-        self.codemeta_data = {}
+    def __init__(self, codemeta_dict):
+        assert isinstance(codemeta_dict, dict)
+        self.codemeta_data = codemeta_dict
         self.zenodo_data = {}
 
-    def load_codemeta(self, codemeta_filename):
+    @classmethod
+    def from_file(cls, codemeta_filename):
         """Load `codemeta_filename` into the converter"""
         with open(codemeta_filename) as infile:
-            self.codemeta_data = json.load(infile)
+            controller = cls(json.load(infile))
+        return controller
 
     def convert_license(self):
         license = self.codemeta_data.get('license', None)
@@ -241,8 +244,25 @@ class CodeMeta2ZenodoController(object):
             json.dump(self.zenodo_data, outfile, indent=4, sort_keys=True)
 
 
-def parse_codemeta_and_write_zenodo_metadata_file(codemeta_filename,
-                                                  zenodo_outname):
+def converter(codemeta_dict, add_escape2020=True):
+    """
+    Convert codemeta metadata into zendoo metadata
+
+    :param codemeta_dict: dict
+    :param add_escape2020: bool
+        if True, add escape2020 community and grant
+    :return: dict
+        zenodo metadata
+    """
+    converter = CodeMeta2ZenodoController(codemeta_dict)
+    converter.convert()
+    if add_escape2020:
+        converter.add_escape2020_community()
+        converter.add_escape2020_grant()
+    return converter.zenodo_data
+
+
+def parse_codemeta_and_write_zenodo_metadata_file(codemeta_filename, zenodo_outname, add_escape2020=True):
     """
     Reads the codemeta.json file and creates a new `.zenodo.json` file.  This
     file will contain the SAME information that in the codemeta.json file but
@@ -255,9 +275,9 @@ def parse_codemeta_and_write_zenodo_metadata_file(codemeta_filename,
         NOT TO BE CHANGED. The file must be named `.zenodo.json` and be stored
         in the root directory of the library.
     """
-    converter = CodeMeta2ZenodoController()
-    converter.load_codemeta(codemeta_filename)
+    converter = CodeMeta2ZenodoController.from_file(codemeta_filename)
     converter.convert()
-    converter.add_escape2020_community()
-    converter.add_escape2020_grant()
+    if add_escape2020:
+        converter.add_escape2020_community()
+        converter.add_escape2020_grant()
     converter.write_zenodo(zenodo_outname)
diff --git a/eossr/metadata/tests/test_codemeta2zenodo.py b/eossr/metadata/tests/test_codemeta2zenodo.py
index 13cbb4ff767820686022c13b4b19d75373bb17c8..9772cf3b71288af242921416b195930d14bfa40c 100644
--- a/eossr/metadata/tests/test_codemeta2zenodo.py
+++ b/eossr/metadata/tests/test_codemeta2zenodo.py
@@ -61,13 +61,8 @@ zenodo_entries = [
 
 
 def test_Codemeta2ZenodoController():
-
-    converter = codemeta2zenodo.CodeMeta2ZenodoController()
-    assert converter.codemeta_data == {}
-    assert converter.zenodo_data == {}
-
     codemeta_file = join(ROOT_DIR, "codemeta.json")
-    converter.load_codemeta(codemeta_file)
+    converter = codemeta2zenodo.CodeMeta2ZenodoController.from_file(codemeta_file)
     assert converter.codemeta_data != {}
     assert all(key in converter.codemeta_data.keys() for key in codemeta_entries)
 
@@ -126,6 +121,13 @@ def test_parse_person_schema_property():
 
 
 class TestConverting(unittest.TestCase):
+
+    def test_converter(self):
+        with open(join(SAMPLES_DIR, "codemeta_sample1.json")) as file:
+            codemeta = json.load(file)
+        zenodo = codemeta2zenodo.converter(codemeta)
+        assert zenodo['communities'][0]['identifier'] == 'escape2020'
+
     def test_sample_file_conversion(self):
 
         outfile = tempfile.NamedTemporaryFile(delete=True)
@@ -147,7 +149,7 @@ class TestConverting(unittest.TestCase):
 class TestLicense(unittest.TestCase):
     def test_license1(self):
 
-        converter = codemeta2zenodo.CodeMeta2ZenodoController()
+        converter = codemeta2zenodo.CodeMeta2ZenodoController({})
         converter.convert_license()
         assert 'license' not in converter.zenodo_data