Skip to content

Commit

Permalink
feat(form): Add extension for forms with test cases.
Browse files Browse the repository at this point in the history
  • Loading branch information
vinci1it2000 committed Dec 12, 2022
1 parent 1f99073 commit 9e949bb
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 5 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jobs:
extra: [ base, io, web, plot, sphinx, parallel, all, dev ]
python-version: [ '3.7', '3.8', '3.9' ]
include:
- os: ubuntu-latest
extra: form
python-version: '3.9'
- os: windows-latest
extra: all
python-version: '3.7'
Expand All @@ -26,6 +29,7 @@ jobs:
extra: all
python-version: '3.9'
env:
ACTION: "true"
EXTRAS: ${{ matrix.extra }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
Expand All @@ -45,6 +49,18 @@ jobs:
- if: matrix.extra != 'base'
name: Install Dependencies
run: pip install -e .[${{ matrix.extra }}]

- if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-latest' && (matrix.extra == 'all' || matrix.extra == 'form')
name: Removing previous chrome instances on runner
run: sudo apt purge google-chrome-stable
- if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-latest' && (matrix.extra == 'all' || matrix.extra == 'form')
name: Installing all necessary packages for selenium
run: pip install chromedriver-autoinstaller selenium pyvirtualdisplay

- if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-latest' && (matrix.extra == 'all' || matrix.extra == 'form')
name: Install xvfb
run: sudo apt-get install xvfb

- name: Run Test
run: coverage run --source=schedula setup.py nosetests
- if: matrix.python-version == '3.9' && matrix.extra == 'all' && matrix.os == 'ubuntu-latest'
Expand Down
4 changes: 3 additions & 1 deletion examples/length_converter/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,7 @@ def return_results(units_out, values_out):
import os.path as osp

sites = set()
form.register().form(directory=osp.abspath(osp.dirname(__file__)), sites=sites)
form.register().form(
directory=osp.abspath(osp.dirname(__file__)), sites=sites
)
sites
11 changes: 10 additions & 1 deletion examples/length_converter/static/schedula/forms/index-ui.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"transformData": "function(parent, def){let x = parent.props.context.props.formData.return;def.props['props-run'].disabled=!parent.emptyObj(x); return def}",
"props": {
"props-run": {
"disabled": false
"disabled": false,
"id": "run-button"
},
"props-main": {
"sx": {
Expand Down Expand Up @@ -260,6 +261,14 @@
"justifyContent": "flex-end",
"alignItems": "center",
"children": [
{
"domain": "function(parent){return !!parent.props.context.props.formContext.data}",
"transformData": "function(parent, def){def.props.content=parent.props.context.props.formContext.data; return def}",
"props": {
"id": "context-data",
"content": ""
}
}
]
}
}
Expand Down
3 changes: 3 additions & 0 deletions requirements/form.pip
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-r web.pip

itsdangerous
8 changes: 5 additions & 3 deletions schedula/utils/form/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@
"""
It provides functions to build a form flask app from a dispatcher.
"""
import json
import os
import glob
import hmac
import flask
import secrets
import hashlib
import webbrowser
import os.path as osp
from ..web import WebMap
from urllib.parse import urlparse
Expand All @@ -40,7 +39,10 @@


class FormMap(WebMap):
_view = None
@staticmethod
def _view(url, *args, **kwargs):
webbrowser.open(url)

csrf_defaults = {
'CSRF_FIELD_NAME': 'csrf_token',
'CSRF_SECRET_KEY': lambda: current_app.secret_key,
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ def get_long_description(cleanup=True, core=False):
extras = {
'io': ['dill!=0.2.7'],
'web': ['requests', 'regex', 'flask'],
'form': ['requests', 'regex', 'flask', 'itsdangerous'],
'parallel': ['multiprocess'],
'plot': [
'requests', 'graphviz>=0.17', 'regex', 'flask', 'Pygments',
Expand Down
117 changes: 117 additions & 0 deletions tests/utils/test_form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# Copyright 2015-2022, Vincenzo Arcidiacono;
# Licensed under the EUPL (the 'Licence');
# You may not use this work except in compliance with the Licence.
# You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl

import os
import unittest
import os.path as osp

EXTRAS = os.environ.get('EXTRAS', 'all')


@unittest.skipIf(EXTRAS not in ('all', 'form'), 'Not for extra %s.' % EXTRAS)
class TestDispatcherForm(unittest.TestCase):
@classmethod
def setUpClass(cls):
try:
import sys
import time
import chromedriver_autoinstaller
from selenium import webdriver
except ImportError:
return

if os.environ.get('ACTION', '').lower() == 'true':
from pyvirtualdisplay import Display
cls.display = display = Display(visible=False, size=(800, 800))
display.start()

chromedriver_autoinstaller.install()
cls.driver = webdriver.Chrome()
time.sleep(3)
cls.form_dir = form_dir = osp.abspath(osp.join(
osp.dirname(__file__), '..', '..', 'examples',
'length_converter'
))
sys.path.insert(0, form_dir)

def setUp(self):
from examples.length_converter.form import form as dsp
self.dsp = dsp.register()
self.site = None

@classmethod
def tearDownClass(cls):
if hasattr(cls, 'driver'):
cls.driver.close()

def tearDown(self):
if self.site:
self.site.shutdown()

def test_form1(self):
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support import expected_conditions as EC

sites = set()
self.dsp.form(directory=self.form_dir, run=True, sites=sites)
self.site = sites.pop()
driver = self.driver

driver.get('%s/' % self.site.url)
WebDriverWait(driver, 30).until(
EC.visibility_of_element_located((By.ID, "run-button"))
).click()
with self.assertRaises(NoSuchElementException):
driver.find_element(value='context-data')

def test_form2(self):
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

sites = set()
self.dsp.form(
directory=self.form_dir, run=True, sites=sites,
get_context=lambda: {
'data': 'cool'
}, get_data=lambda: {
"input": {"kwargs": {
"inputs": {
"value_in": 1, "unit_in": "m",
"units_out": ["in", "mm", "km"]
},
"select_output_kw": {
"keys": ["results", "value_in", "unit_in"],
"output_type": "all"
}
}},
"return": {
"results": [
{"unit_out": "in", "value_out": 39.37007874015748},
{"unit_out": "mm", "value_out": 1000},
{"unit_out": "km", "value_out": 0.001}
],
"unit_in": "m",
"value_in": 1
},
"hash": "cc051052ae52aa702474df394b5d4f23c19f3232"
}
)
self.site = sites.pop()
driver = self.driver

driver.get('%s/' % self.site.url)
self.assertTrue(WebDriverWait(driver, 30).until(
EC.visibility_of_element_located((By.ID, "run-button"))
).get_attribute('disabled'))
self.assertEqual(
driver.find_element(value='context-data').get_attribute('content'),
'cool'
)

0 comments on commit 9e949bb

Please sign in to comment.