Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add tests for importing taxonomies #225

Merged
merged 21 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion backend/editor/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,6 @@ async def upload_taxonomy(
"""
Upload taxonomy file to be parsed
"""
# use the file name as the taxonomy name
taxonomy = TaxonomyGraph(branch, taxonomy_name)
if not taxonomy.is_valid_branch_name():
raise HTTPException(status_code=400, detail="branch_name: Enter a valid branch name!")
Expand Down
6 changes: 3 additions & 3 deletions backend/editor/entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from .exceptions import GithubBranchExistsError # Custom exceptions
from .exceptions import (
GithubUploadError,
TaxnonomyImportError,
TaxonomyImportError,
TaxonomyParsingError,
TaxonomyUnparsingError,
)
Expand Down Expand Up @@ -125,7 +125,7 @@ async def import_from_github(self, description):

return status
except Exception as e:
raise TaxnonomyImportError() from e
raise TaxonomyImportError() from e

async def upload_taxonomy(self, filepath, description):
"""
Expand All @@ -137,7 +137,7 @@ async def upload_taxonomy(self, filepath, description):
await self.create_project(description)
return status
except Exception as e:
raise TaxnonomyImportError() from e
raise TaxonomyImportError() from e

def dump_taxonomy(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion backend/editor/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self):
return super().__init__(exception_message)


class TaxnonomyImportError(RuntimeError):
class TaxonomyImportError(RuntimeError):
"""
Raised when attempting to fetch a taxonomy from GitHub
"""
Expand Down
4 changes: 3 additions & 1 deletion backend/requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pytest==7.1.2
pytest==7.1.2
pytest-mock==3.12.0
httpx==0.23.3
2 changes: 0 additions & 2 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,4 @@ watchfiles==0.18.1
websockets==10.3
PyGithub==1.56
python-multipart==0.0.5
httpx==0.23.3
pytest==7.1.2
-e ../parser/
66 changes: 66 additions & 0 deletions backend/sample/dump.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
"""A script to dump a Neo4J database to a JSON file."""
import argparse
import json

from neo4j import GraphDatabase


DEFAULT_URL = "bolt://localhost:7687"


def get_session(uri=DEFAULT_URL):
"""Get a session object for the Neo4J database."""
return GraphDatabase.driver(uri).session()


def dump_nodes(session, file):
"""Dump all nodes from the database to a JSON file."""
node_count = session.run("MATCH (n) RETURN count(n)").single()[0]
for i, node in enumerate(session.run("MATCH (n) RETURN n")):
node_dict = dict(node['n'])
print(node_dict)
labels_list = list(node['n'].labels)
node_dict['labels'] = labels_list
if i < node_count - 1:
f.write(json.dumps(node_dict, ensure_ascii=False) + ',')
else:
f.write(json.dumps(node_dict, ensure_ascii=False))


def dump_relations(session, file):
"""Dump all relationships from the database to a JSON file."""
rels_count = session.run("MATCH (n)-[r]->(m) RETURN count(r)").single()[0]
for i, rel in enumerate(session.run("MATCH (n)-[r]->(m) RETURN r")):
start_node_id = rel['r'].nodes[0].id
end_node_id = rel['r'].nodes[1].id
start_node = session.run(
"MATCH (n) WHERE id(n) = $id RETURN n", {"id": start_node_id}
).single()["n"]["id"]
end_node = session.run(
"MATCH (n) WHERE id(n) = $id RETURN n", {"id": end_node_id}
).single()["n"]["id"]
rel_dict = {rel['r'].type: [start_node, end_node]}
if i < rels_count - 1:
f.write(json.dumps(rel_dict, ensure_ascii=False) + ',')
else:
f.write(json.dumps(rel_dict, ensure_ascii=False))


def get_options(args=None):
"""Parse command line arguments."""
parser = argparse.ArgumentParser(description='Dump Neo4J database to JSON file')
parser.add_argument('--url', default=DEFAULT_URL, help='Neo4J database bolt URL')
parser.add_argument('file', help='JSON file name to dump')
return parser.parse_args(args)


if __name__ == "__main__":
options = get_options()
session = get_session(options.url)
with open(options.file, 'w') as f:
f.write('{"nodes": [')
dump_nodes(session, f)
f.write('], "relations": [')
dump_relations(session, f)
f.write(']}')
24 changes: 12 additions & 12 deletions backend/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ def client():


@pytest.fixture
def neo4j():
def neo4j(scope="session"):
"""waiting for neo4j to be ready"""
uri = os.environ.get("NEO4J_URI", "bolt://localhost:7687")
driver = GraphDatabase.driver(uri)
session = driver.session()
connected = False
while not connected:
try:
session.run("MATCH () return 1 limit 1")
except ServiceUnavailable:
time.sleep(1)
else:
connected = True
return driver
with GraphDatabase.driver(uri) as driver:
with driver.session() as session:
connected = False
while not connected:
try:
session.run("MATCH () return 1 limit 1")
except ServiceUnavailable:
time.sleep(1)
else:
connected = True
yield driver
126 changes: 126 additions & 0 deletions backend/tests/data/test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# test taxonomy
perierc marked this conversation as resolved.
Show resolved Hide resolved

stopwords:fr: aux,au,de,le,du,la,a,et

synonyms:en:passion fruit, passionfruit

synonyms:fr:fruit de la passion, fruits de la passion, maracuja, passion

en:yogurts, yoghurts
fr:yaourts, yoghourts, yogourts
nl:yoghurts
description:en: a yogurts of whatever type
description:fr: un yaourt de n'importe quel type
color:en: white
flavour:en: undef

<en:yogurts
en:banana yogurts
fr:yaourts à la banane
nl:bananenyoghurt
description:en: a banana yogurt
description:fr: un yaourt à la banane
color:en: yellow
flavour:en: banana

<en:yogurts
en:Passion fruit yogurts
fr:yaourts au fruit de la passion
nl:yoghurts met passievrucht
color:en: undef
flavour:en: passion fruit

<en:yogurts
fr:yaourts allégés

<fr:yoghourts
en:lemon yogurts
fr:yaourts au citron
nl:yoghurts met citroen
description:en: a yogurts with lemon inside
description:fr: un yaourt avec du citron
color:en: yellow
flavour:en: lemon

<fr:yaourts fruit de la passion
<fr:yaourts allégés
fr:yaourts au fruit de la passion allégés
nl:magere yoghurts met passievrucht


<fr:yaourts au citron
<fr:yaourts allégés
fr:yaourts au citron allégés
nl:magere citroenyoghurt
description:en: for light yogurts with lemon

<fr:yaourt
fr:yaourts à la myrtille
nl:bosbessenyoghurt
flavour:en: blueberry
flavour:fr: myrtille

en:meat
vegan:en:no
carbon_footprint_fr_foodges_value:fr:10

<en:meat
en:beef
carbon_footprint_fr_foodges_value:fr:15

<en:beef
en:roast-beef

<en:meat
en:fake-meat
vegan:en:yes
# undef will stop parents from transmitting a value
carbon_footprint_fr_foodges_value:fr:undef

en:fake-stuff

<en:fake-stuff
<en:fake-meat
en:fake-duck-meat

en:vegetable
vegan:en:yes

# the soup yogourt synonym is used to test suggestions matching xx: synonyms
en:soup
xx:something that means soup in every language, something else that means soup in every language
vegan:en:maybe

<en:soup
en:vegan-soup
vegan:en:yes

<en:soup
en:fish-soup
vegan:en:no

de:Spätzle

en:Kale
de:Grünkohl

en:Kefir 2.5 %
de:Kefir 2.5 %
fr:Kéfir 2,5 %
ru:Кефир 2.5 %, Кефир 2.5%

fr:French entry
de:Special value for German

fr:French entry with default value
xx:French entry with default value
de:Special value for German 2

xx:Language-less entry
de:Special value for German 3

# xx: entry with accents, need to match unaccented version
sv:Ä-märket
xx:Ä-märket

en:Entry with (parentheses) and some *!#{}@$ characters, synonym with *%@$(]% chars
Loading