From d47f7388fa1efa71f9f831b853b063fd63fbe806 Mon Sep 17 00:00:00 2001 From: f-idiris <112618970+f-idiris@users.noreply.github.com> Date: Wed, 25 Oct 2023 10:19:11 +0200 Subject: [PATCH] Update the way to handle spectra type (#133) * Map data types and spectra layouts * FIx: process lower/mixed case data types --- chem_spectra/__init__.py | 15 +++ chem_spectra/controller/refresh_token_api.py | 19 +++ chem_spectra/controller/spectra_layout_api.py | 65 ++++++++++ chem_spectra/lib/converter/jcamp/base.py | 116 ++++++----------- .../lib/converter/jcamp/data_type.json | 19 +++ .../converter/jcamp/data_type.json.example | 19 +++ chem_spectra/lib/converter/jcamp/ni.py | 65 +++++----- requirements.txt | 2 + tests/controller/test_refresh_token_api.py | 21 ++++ tests/controller/test_spectra_layout_api.py | 117 ++++++++++++++++++ tests/fixtures/test_data_types.json | 17 +++ 11 files changed, 359 insertions(+), 116 deletions(-) create mode 100644 chem_spectra/controller/refresh_token_api.py create mode 100644 chem_spectra/controller/spectra_layout_api.py create mode 100644 chem_spectra/lib/converter/jcamp/data_type.json create mode 100644 chem_spectra/lib/converter/jcamp/data_type.json.example create mode 100644 tests/controller/test_refresh_token_api.py create mode 100644 tests/controller/test_spectra_layout_api.py create mode 100644 tests/fixtures/test_data_types.json diff --git a/chem_spectra/__init__.py b/chem_spectra/__init__.py index d79c0886..66fc9719 100644 --- a/chem_spectra/__init__.py +++ b/chem_spectra/__init__.py @@ -1,6 +1,8 @@ import os from flask import Flask +from flask_jwt_extended import JWTManager +from datetime import timedelta import logging @@ -23,6 +25,11 @@ def create_app(test_config=None): except OSError: pass + app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(days=1) + app.config["JWT_REFRESH_TOKEN_EXPIRES"] = timedelta(days=30) + + jwt = JWTManager(app) + #create logging logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -39,6 +46,10 @@ def create_app(test_config=None): @app.route('/ping') def ping(): return 'pong' + + # Refresh token api + from chem_spectra.controller.refresh_token_api import refresh_token_api + app.register_blueprint(refresh_token_api) # file api from chem_spectra.controller.file_api import file_api @@ -52,4 +63,8 @@ def ping(): from chem_spectra.controller.transform_api import trans_api app.register_blueprint(trans_api) + # spectra layout api + from chem_spectra.controller.spectra_layout_api import spectra_layout_api + app.register_blueprint(spectra_layout_api) + return app diff --git a/chem_spectra/controller/refresh_token_api.py b/chem_spectra/controller/refresh_token_api.py new file mode 100644 index 00000000..2b43fc96 --- /dev/null +++ b/chem_spectra/controller/refresh_token_api.py @@ -0,0 +1,19 @@ +from flask import jsonify, Blueprint +from flask_jwt_extended import jwt_required, create_access_token, get_jwt_identity, create_refresh_token + + +refresh_token_api = Blueprint('refresh_token_api', __name__) + +@refresh_token_api.route("/api/v1/chemspectra/login", methods=["POST"]) +def login(): + access_token = create_access_token(identity="user") + refresh_token = create_refresh_token(identity="user") + return jsonify(access_token=access_token, refresh_token=refresh_token) + + +@refresh_token_api.route("/api/v1/chemspectra/refresh", methods=["POST"]) +@jwt_required(refresh=True) +def refresh(): + identity = get_jwt_identity() + access_token = create_access_token(identity=identity) + return jsonify(access_token=access_token) \ No newline at end of file diff --git a/chem_spectra/controller/spectra_layout_api.py b/chem_spectra/controller/spectra_layout_api.py new file mode 100644 index 00000000..c63d74e1 --- /dev/null +++ b/chem_spectra/controller/spectra_layout_api.py @@ -0,0 +1,65 @@ +import json +from flask import jsonify, Blueprint, request +import os +import shutil +from flask_jwt_extended import jwt_required + +spectra_layout_api = Blueprint('spectra_layout_api', __name__) +script_dir = os.path.dirname(__file__) +data_type_json_path = os.path.join(script_dir, '../lib/converter/jcamp/data_type.json') + +def load_data_types(): + try: + with open(data_type_json_path, 'r') as mapping_file: + return json.load(mapping_file) + except FileNotFoundError: + example_json_path = os.path.join(script_dir, '../lib/converter/jcamp/data_type.json.example') + shutil.copy(example_json_path, data_type_json_path) + with open(data_type_json_path, 'r') as mapping_file: + return json.load(mapping_file) + +def save_data_types(data_types): + with open(data_type_json_path, 'w') as mapping_file: + json.dump(data_types, mapping_file, indent=4) + +@spectra_layout_api.route('/api/v1/chemspectra/spectra_layouts', methods=['GET', 'PUT', 'DELETE']) +@jwt_required() +def update_or_fetch_mapping(): + if request.method == 'GET': + existing_data_types = load_data_types() + return jsonify(existing_data_types["datatypes"]), 200 + + elif request.method == 'PUT': + request_data = request.get_json() + new_data_type_mapping = request_data.get("new_data_type") + existing_data_types = load_data_types() + + for layout, data_type in new_data_type_mapping.items(): + if data_type == '': + return jsonify({"message": "Invalid Data Type"}), 400 + elif layout in existing_data_types["datatypes"] and data_type not in existing_data_types['datatypes'][layout]: + existing_data_types["datatypes"][layout].append(data_type) + elif layout in existing_data_types["datatypes"] and data_type in existing_data_types['datatypes'][layout]: + return jsonify({"message": f"Data type '{data_type}' already exists"}), 400 + else: + return jsonify({"message": f"Layout '{layout}' does not exist"}), 400 + + save_data_types(existing_data_types) + return jsonify({"message": "Data type created successfully"}), 200 + + elif request.method == 'DELETE': + request_data = request.get_json() + data_type_mapping = request_data.get("data_type") + existing_data_types = load_data_types() + for layout, data_type in data_type_mapping.items(): + if layout in existing_data_types["datatypes"]: + if data_type in existing_data_types['datatypes'][layout]: + existing_data_types['datatypes'][layout].remove(data_type) + save_data_types(existing_data_types) + return jsonify({"message": f"Data type '{data_type}' deleted successfully"}), 200 + else: + return jsonify({"message": f"Data type '{data_type}' not found in layout '{layout}'"}), 404 + else: + return jsonify({"message": f"Layout '{layout}' does not exist"}), 400 + else: + return jsonify({"message": "Method not allowed"}), 405 diff --git a/chem_spectra/lib/converter/jcamp/base.py b/chem_spectra/lib/converter/jcamp/base.py index ee80506d..d6351176 100644 --- a/chem_spectra/lib/converter/jcamp/base.py +++ b/chem_spectra/lib/converter/jcamp/base.py @@ -1,6 +1,10 @@ import nmrglue as ng +import json from chem_spectra.lib.converter.share import parse_params, parse_solvent +import os + +data_type_json = os.path.join(os.path.dirname(__file__), 'data_type.json') class JcampBaseConverter: @@ -43,82 +47,36 @@ def __read(self, path): def __set_datatype(self): dts = self.datatypes - if 'NMR SPECTRUM' in dts: - return 'NMR SPECTRUM' - elif 'NMRSPECTRUM' in dts: # MNova - return 'NMR SPECTRUM' - elif 'INFRARED SPECTRUM' in dts: - return 'INFRARED SPECTRUM' - elif 'RAMAN SPECTRUM' in dts: - return 'RAMAN SPECTRUM' - elif 'MASS SPECTRUM' in dts: - return 'MASS SPECTRUM' - elif 'HPLC UV/VIS SPECTRUM' in dts: - return 'HPLC UV/VIS SPECTRUM' - elif 'HPLC UV-VIS' in dts: - return 'HPLC UV/VIS SPECTRUM' - elif 'UV/VIS SPECTRUM' in dts: - return 'UV/VIS SPECTRUM' - elif 'UV-VIS' in dts: - return 'UV/VIS SPECTRUM' - elif 'ULTRAVIOLET SPECTRUM' in dts: - return 'UV/VIS SPECTRUM' - elif 'THERMOGRAVIMETRIC ANALYSIS' in dts: - return 'THERMOGRAVIMETRIC ANALYSIS' - elif 'X-RAY DIFFRACTION' in dts: - return 'X-RAY DIFFRACTION' - elif 'CYCLIC VOLTAMMETRY' in dts: - return 'CYCLIC VOLTAMMETRY' - elif 'SIZE EXCLUSION CHROMATOGRAPHY' in dts: - return 'SIZE EXCLUSION CHROMATOGRAPHY' - elif 'CIRCULAR DICHROISM SPECTROSCOPY' in dts: - return 'CIRCULAR DICHROISM SPECTROSCOPY' - elif 'SORPTION-DESORPTION MEASUREMENT' in dts: - return 'SORPTION-DESORPTION MEASUREMENT' - elif 'Emissions' in dts or 'EMISSIONS' in dts or 'FLUORESCENCE SPECTRUM' in dts or 'FL SPECTRUM' in dts: - return 'Emissions' - elif 'DLS ACF' in dts: - return 'DLS ACF' - elif 'DLS INTENSITY' in dts or 'DLS intensity' in dts: - return 'DLS intensity' + dt_dict = { + 'NMR': 'NMR SPECTRUM', + 'INFRARED': 'INFRARED SPECTRUM', + 'RAMAN': 'RAMAN SPECTRUM', + 'MS': 'MASS SPECTRUM', + 'HPLC UVVIS': 'HPLC UV/VIS SPECTRUM', + 'UVVIS': 'UV/VIS SPECTRUM', + } + + with open(data_type_json, 'r') as mapping_file: + data_type_mappings = json.load(mapping_file)["datatypes"] + for key, values in data_type_mappings.items(): + values = [value.upper() for value in values] + for dt in dts: + if dt in values and key in dt_dict: + return dt_dict[key] + elif dt in values and not key in dt_dict: + return key return '' def __typ(self): dt = self.datatype - if 'NMR SPECTRUM' == dt: - return 'NMR' - elif 'NMRSPECTRUM' == dt: # MNova - return 'NMR' - elif 'INFRARED SPECTRUM' == dt: - return 'INFRARED' # TBD - elif 'RAMAN SPECTRUM' == dt: - return 'RAMAN' # TBD - elif 'MASS SPECTRUM' == dt: - return 'MS' - elif 'HPLC UV/VIS SPECTRUM' == dt: - return 'HPLC UVVIS' - elif 'HPLC UV-VIS' == dt: - return 'HPLC UVVIS' - elif 'UV/VIS SPECTRUM' == dt or 'UV-VIS' == dt or 'ULTRAVIOLET SPECTRUM' == dt: - return 'UVVIS' - elif 'THERMOGRAVIMETRIC ANALYSIS' == dt: - return 'THERMOGRAVIMETRIC ANALYSIS' - elif 'X-RAY DIFFRACTION' == dt: - return 'X-RAY DIFFRACTION' - elif 'CYCLIC VOLTAMMETRY' in dt: - return 'CYCLIC VOLTAMMETRY' - elif 'SIZE EXCLUSION CHROMATOGRAPHY' in dt: - return 'SIZE EXCLUSION CHROMATOGRAPHY' - elif 'CIRCULAR DICHROISM SPECTROSCOPY' in dt: - return 'CIRCULAR DICHROISM SPECTROSCOPY' - elif 'SORPTION-DESORPTION MEASUREMENT' in dt: - return 'SORPTION-DESORPTION MEASUREMENT' - elif 'Emissions' in dt or 'EMISSIONS' in dt or 'FLUORESCENCE SPECTRUM' in dt or 'FL SPECTRUM' in dt: - return 'Emissions' - elif 'DLS ACF' in dt: - return 'DLS ACF' - elif 'DLS INTENSITY' in dt or 'DLS intensity' in dt: - return 'DLS intensity' + + with open(data_type_json, 'r') as mapping_file: + data_type_mappings = json.load(mapping_file)["datatypes"] + + for key, values in data_type_mappings.items(): + values = [value.upper() for value in values] + if dt.upper() in values: + return key return '' def __set_dataclass(self): @@ -140,12 +98,10 @@ def __is_em_wave(self): return self.typ in ['INFRARED', 'RAMAN', 'UVVIS'] def __non_nmr(self): - return self.typ in [ - 'INFRARED', 'RAMAN', 'UVVIS', 'HPLC UVVIS', - 'THERMOGRAVIMETRIC ANALYSIS', 'MS', 'X-RAY DIFFRACTION', - 'CYCLIC VOLTAMMETRY', 'SIZE EXCLUSION CHROMATOGRAPHY', - 'CIRCULAR DICHROISM SPECTROSCOPY', 'SORPTION-DESORPTION MEASUREMENT', 'Emissions', - 'DLS ACF', 'DLS intensity'] + with open(data_type_json, 'r') as mapping_file: + data_type_mappings = json.load(mapping_file).get("datatypes") + dts = [dt for dt in data_type_mappings.keys() if dt != 'NMR'] + return self.typ in dts def __is_ir(self): return self.typ in ['INFRARED'] @@ -175,13 +131,13 @@ def __is_aif(self): return self.typ in ['SORPTION-DESORPTION MEASUREMENT'] def __is_emissions(self): - return self.typ in ['Emissions', 'EMISSIONS', 'FLUORESCENCE SPECTRUM', 'FL SPECTRUM'] + return self.typ in ['Emissions'] def __is_dls_acf(self): return self.typ in ['DLS ACF'] def __is_dls_intensity(self): - return self.typ in ['DLS INTENSITY', 'DLS intensity'] + return self.typ in ['DLS intensity'] def __ncl(self): try: diff --git a/chem_spectra/lib/converter/jcamp/data_type.json b/chem_spectra/lib/converter/jcamp/data_type.json new file mode 100644 index 00000000..5c135ad6 --- /dev/null +++ b/chem_spectra/lib/converter/jcamp/data_type.json @@ -0,0 +1,19 @@ +{ + "datatypes": { + "NMR": ["NMR SPECTRUM", "NMRSPECTRUM"], + "INFRARED": ["INFRARED SPECTRUM"], + "RAMAN": ["RAMAN SPECTRUM"], + "MS": ["MASS SPECTRUM"], + "HPLC UVVIS": ["HPLC UV/VIS SPECTRUM", "HPLC UV-VIS"], + "UVVIS": ["UV/VIS SPECTRUM", "UV-VIS", "ULTRAVIOLET SPECTRUM"], + "THERMOGRAVIMETRIC ANALYSIS": ["THERMOGRAVIMETRIC ANALYSIS"], + "X-RAY DIFFRACTION": ["X-RAY DIFFRACTION"], + "CYCLIC VOLTAMMETRY": ["CYCLIC VOLTAMMETRY"], + "SIZE EXCLUSION CHROMATOGRAPHY": ["SIZE EXCLUSION CHROMATOGRAPHY"], + "CIRCULAR DICHROISM SPECTROSCOPY": ["CIRCULAR DICHROISM SPECTROSCOPY"], + "SORPTION-DESORPTION MEASUREMENT": ["SORPTION-DESORPTION MEASUREMENT"], + "Emissions": ["Emissions", "EMISSIONS", "FLUORESCENCE SPECTRUM", "FL SPECTRUM"], + "DLS ACF": ["DLS ACF"], + "DLS intensity": ["DLS INTENSITY", "DLS intensity"] + } +} diff --git a/chem_spectra/lib/converter/jcamp/data_type.json.example b/chem_spectra/lib/converter/jcamp/data_type.json.example new file mode 100644 index 00000000..5c135ad6 --- /dev/null +++ b/chem_spectra/lib/converter/jcamp/data_type.json.example @@ -0,0 +1,19 @@ +{ + "datatypes": { + "NMR": ["NMR SPECTRUM", "NMRSPECTRUM"], + "INFRARED": ["INFRARED SPECTRUM"], + "RAMAN": ["RAMAN SPECTRUM"], + "MS": ["MASS SPECTRUM"], + "HPLC UVVIS": ["HPLC UV/VIS SPECTRUM", "HPLC UV-VIS"], + "UVVIS": ["UV/VIS SPECTRUM", "UV-VIS", "ULTRAVIOLET SPECTRUM"], + "THERMOGRAVIMETRIC ANALYSIS": ["THERMOGRAVIMETRIC ANALYSIS"], + "X-RAY DIFFRACTION": ["X-RAY DIFFRACTION"], + "CYCLIC VOLTAMMETRY": ["CYCLIC VOLTAMMETRY"], + "SIZE EXCLUSION CHROMATOGRAPHY": ["SIZE EXCLUSION CHROMATOGRAPHY"], + "CIRCULAR DICHROISM SPECTROSCOPY": ["CIRCULAR DICHROISM SPECTROSCOPY"], + "SORPTION-DESORPTION MEASUREMENT": ["SORPTION-DESORPTION MEASUREMENT"], + "Emissions": ["Emissions", "EMISSIONS", "FLUORESCENCE SPECTRUM", "FL SPECTRUM"], + "DLS ACF": ["DLS ACF"], + "DLS intensity": ["DLS INTENSITY", "DLS intensity"] + } +} diff --git a/chem_spectra/lib/converter/jcamp/ni.py b/chem_spectra/lib/converter/jcamp/ni.py index 234c0cd0..3486ed2d 100644 --- a/chem_spectra/lib/converter/jcamp/ni.py +++ b/chem_spectra/lib/converter/jcamp/ni.py @@ -4,7 +4,8 @@ from chem_spectra.lib.converter.datatable import DatatableModel from chem_spectra.lib.shared.calc import to_float from chem_spectra.lib.converter.jcamp.data_parse import make_ni_data_ys, make_ni_data_xs - +import json +import os THRESHOLD_IR = 0.93 THRESHOLD_RAMAN = 0.07 @@ -14,7 +15,7 @@ THRESHOLD_TGA = 1.05 THRESHOLD_XRD = 1.00 THRESHOLD_EMISSION = 0.5 - +data_type_json = os.path.join(os.path.dirname(__file__), 'data_type.json') class JcampNIConverter: # nmr & IR def __init__(self, base): @@ -74,42 +75,34 @@ def __init__(self, base): def __thres(self): dt = self.datatype - if 'NMR SPECTRUM' == dt: - return THRESHOLD_NMR - elif 'NMRSPECTRUM' == dt: # MNova - return THRESHOLD_NMR - elif 'INFRARED SPECTRUM' == dt: - return THRESHOLD_IR - elif 'RAMAN SPECTRUM' == dt: - return THRESHOLD_RAMAN - elif 'MASS SPECTRUM' == dt: - return THRESHOLD_MS - elif 'HPLC UV/VIS SPECTRUM' == dt: - return THRESHOLD_UVVIS - elif 'HPLC UV-VIS' == dt: - return THRESHOLD_UVVIS - elif dt in ['UV/VIS SPECTRUM', 'UV-VIS', 'ULTRAVIOLET SPECTRUM']: - return THRESHOLD_UVVIS - elif dt in ['THERMOGRAVIMETRIC ANALYSIS', 'DLS ACF']: - return THRESHOLD_TGA - elif dt in ['X-RAY DIFFRACTION', 'CIRCULAR DICHROISM SPECTROSCOPY', 'CYCLIC VOLTAMMETRY', 'SORPTION-DESORPTION MEASUREMENT', - 'DLS INTENSITY', 'DLS intensity']: - return THRESHOLD_XRD - elif dt in ['Emissions', 'EMISSIONS', 'FLUORESCENCE SPECTRUM', 'FL SPECTRUM']: - return THRESHOLD_EMISSION - return 0.5 + threshold_values = { + "NMR": THRESHOLD_NMR, + "INFRARED": THRESHOLD_IR, + "RAMAN": THRESHOLD_RAMAN, + "MS": THRESHOLD_MS, + "HPLC UVVIS": THRESHOLD_UVVIS, + "UVVIS": THRESHOLD_UVVIS, + "THERMOGRAVIMETRIC ANALYSIS": THRESHOLD_TGA, + "DLS ACF": THRESHOLD_TGA, + "X-RAY DIFFRACTION": THRESHOLD_XRD, + "CIRCULAR DICHROISM SPECTROSCOPY": THRESHOLD_XRD, + "CYCLIC VOLTAMMETRY": THRESHOLD_XRD, + "SORPTION-DESORPTION MEASUREMENT": THRESHOLD_XRD, + "DLS intensity": THRESHOLD_XRD, + "Emissions": THRESHOLD_EMISSION + } + with open(data_type_json, 'r') as mapping_file: + data_type_mappings = json.load(mapping_file)["datatypes"] + key = next((k for k, v in data_type_mappings.items() if dt in v), None) + + return threshold_values.get(key, 0.5) + def __index_target(self): - target_topics = [ - 'NMR SPECTRUM', 'NMRSPECTRUM', - 'INFRARED SPECTRUM', 'RAMAN SPECTRUM', - 'MASS SPECTRUM', 'UV/VIS SPECTRUM', 'UV-VIS', 'ULTRAVIOLET SPECTRUM', - 'HPLC UV-VIS', 'HPLC UV/VIS SPECTRUM', - 'THERMOGRAVIMETRIC ANALYSIS', 'X-RAY DIFFRACTION', - 'CYCLIC VOLTAMMETRY', 'SIZE EXCLUSION CHROMATOGRAPHY', - 'CIRCULAR DICHROISM SPECTROSCOPY', 'SORPTION-DESORPTION MEASUREMENT', - 'Emissions', 'EMISSIONS', 'FLUORESCENCE SPECTRUM', 'FL SPECTRUM', 'DLS ACF', 'DLS INTENSITY', 'DLS intensity' - ] + with open(data_type_json, 'r') as mapping_file: + target = json.load(mapping_file).get("datatypes").values() + target_topics = [value.upper() for values in target for value in values] + for tp in target_topics: if tp in self.datatypes: idx = self.datatypes.index(tp) diff --git a/requirements.txt b/requirements.txt index dad9cddb..bee4887d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,3 +42,5 @@ urllib3==1.26.5 Werkzeug==2.2.3 zipp==0.5.2 pyopenms==2.6.0 +PyJWT==2.8.0 +flask-jwt-extended==4.5.2 diff --git a/tests/controller/test_refresh_token_api.py b/tests/controller/test_refresh_token_api.py new file mode 100644 index 00000000..977352ac --- /dev/null +++ b/tests/controller/test_refresh_token_api.py @@ -0,0 +1,21 @@ +def test_login(client): + response = client.post('/api/v1/chemspectra/login') + data = response.json + assert response.status_code == 200 + assert "access_token" in data + assert "refresh_token" in data + +def test_refresh(client): + # get refresh token + response = client.post('/api/v1/chemspectra/login') + data = response.json + refresh_token = data.get('refresh_token') + + refresh_response = client.post('/api/v1/chemspectra/refresh', headers={'Authorization': f'Bearer {refresh_token}'}) + data = refresh_response.json + assert "access_token" in data + assert refresh_response.status_code == 200 + +def test_refresh_without_refresh_token(client): + response = client.post('/api/v1/chemspectra/refresh') + assert response.status_code == 401 \ No newline at end of file diff --git a/tests/controller/test_spectra_layout_api.py b/tests/controller/test_spectra_layout_api.py new file mode 100644 index 00000000..972e17f0 --- /dev/null +++ b/tests/controller/test_spectra_layout_api.py @@ -0,0 +1,117 @@ +import os +import json +from unittest.mock import patch + +test_json_path = './tests/fixtures/test_data_types.json' +orig_json_path = 'chem_spectra.controller.spectra_layout_api.data_type_json_path' + +def fetch_access_token(client): + response = client.post('/api/v1/chemspectra/login') + data = response.json + access_token = data.get('access_token') + return access_token + +def test_get_spectra_layouts_with_data(client): + access_token = fetch_access_token(client) + with patch(orig_json_path, new=test_json_path): + response = client.get('/api/v1/chemspectra/spectra_layouts', + headers={'Authorization': f'Bearer {access_token}'}) + response_data = response.json + assert response.status_code == 200 + assert response_data == { + "INFRARED": ["INFRARED SPECTRUM"], + "MS": ["MASS SPECTRUM"], + "NMR": ["NMR SPECTRUM", "NMRSPECTRUM"], + "RAMAN": ["RAMAN"] + } + +def test_create_data_type(client): + access_token = fetch_access_token(client) + new_data_type = { + "new_data_type": { + "MS": "MASS SPEC" + } + } + + with patch(orig_json_path, test_json_path): + response = client.put('/api/v1/chemspectra/spectra_layouts', json=new_data_type, + headers={'Authorization': f'Bearer {access_token}'}) + + assert response.status_code == 200 + + response_data = response.json + assert "message" in response_data + response_data["message"] == "Data type created successfully" + + delete_data_type = { + "data_type": { + "MS": "MASS SPEC" + } + } + response = client.delete('/api/v1/chemspectra/spectra_layouts', json=delete_data_type, + headers={'Authorization': f'Bearer {access_token}'}) + +def test_create_data_type_unchanged(client): + access_token = fetch_access_token(client) + # data type already exists in JSON + new_data_type = { + "new_data_type": { + "INFRARED": "INFRARED SPECTRUM" + } + } + + with patch(orig_json_path, test_json_path): + response = client.put('/api/v1/chemspectra/spectra_layouts', json=new_data_type, + headers={'Authorization': f'Bearer {access_token}'}) + assert response.status_code == 400 + + response_data = response.json + + assert "message" in response_data + assert response_data["message"] == "Data type 'INFRARED SPECTRUM' already exists" + +def test_create_data_type_layout_does_not_exist(client): + access_token = fetch_access_token(client) + new_data_type = { + "new_data_type": { + "UNKNOWN": "NA" + } + } + + with patch(orig_json_path, test_json_path): + response = client.put('/api/v1/chemspectra/spectra_layouts', json=new_data_type, + headers={'Authorization': f'Bearer {access_token}'}) + assert response.status_code == 400 + + response_data = response.json + + assert "message" in response_data + assert response_data["message"] == "Layout 'UNKNOWN' does not exist" + +def test_delete_data_type(client): + access_token = fetch_access_token(client) + # create a new data type + new_data_type = { + "new_data_type": { + "INFRARED": "IR" + } + } + with patch(orig_json_path, test_json_path): + response = client.put('/api/v1/chemspectra/spectra_layouts', json=new_data_type, + headers={'Authorization': f'Bearer {access_token}'}) + assert response.status_code == 200 + + # delete the new data type + delete_data_type = { + "data_type": { + "INFRARED": "IR" + } + } + + response = client.delete('/api/v1/chemspectra/spectra_layouts', json=delete_data_type, + headers={'Authorization': f'Bearer {access_token}'}) + assert response.status_code == 200 + response_data = response.json + + assert "message" in response_data + assert response_data["message"] == "Data type 'IR' deleted successfully" diff --git a/tests/fixtures/test_data_types.json b/tests/fixtures/test_data_types.json new file mode 100644 index 00000000..79d6efd7 --- /dev/null +++ b/tests/fixtures/test_data_types.json @@ -0,0 +1,17 @@ +{ + "datatypes": { + "NMR": [ + "NMR SPECTRUM", + "NMRSPECTRUM" + ], + "INFRARED": [ + "INFRARED SPECTRUM" + ], + "RAMAN": [ + "RAMAN" + ], + "MS": [ + "MASS SPECTRUM" + ] + } +} \ No newline at end of file