first commit
This commit is contained in:
0
test/integration/__init__.py
Normal file
0
test/integration/__init__.py
Normal file
121
test/integration/array_summary_dynamic_test.py
Normal file
121
test/integration/array_summary_dynamic_test.py
Normal file
@@ -0,0 +1,121 @@
|
||||
from flask.ext.testing import LiveServerTestCase
|
||||
import mockredis
|
||||
from splinter import Browser
|
||||
from helix import main
|
||||
from helix.constants import sql_constant
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants import redis_constant
|
||||
from test.test_helpers import *
|
||||
|
||||
|
||||
class ArraySummaryDynamicTest(LiveServerTestCase):
|
||||
def create_app(self):
|
||||
redis_constant.redis_store = mockredis.mock_redis_client()
|
||||
sql_constant.sql_session_maker = lambda: SQLManager.get_sql_session_maker('postgres://pivotal:@localhost/test')
|
||||
|
||||
app = main.app
|
||||
app.config['TESTING'] = True
|
||||
app.config['LIVESERVER_PORT'] = 8943
|
||||
return app
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.test_db_session = test_db_session()
|
||||
cls.browser = Browser('phantomjs')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.test_db_session.close_all()
|
||||
cls.browser.quit()
|
||||
|
||||
def setUp(self):
|
||||
self.browser.visit('/array_summary/')
|
||||
|
||||
def tearDown(self):
|
||||
reset_db_session(self.test_db_session)
|
||||
self.browser.cookies.delete()
|
||||
|
||||
def fill_in_site_characterization_data(self,
|
||||
system_type=SystemType.singleTilt,
|
||||
module_type=ModuleType.Cell96):
|
||||
self.browser.visit(self.get_server_url() + '/site_characterization/')
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '200')
|
||||
self.browser.fill('building_height', '30')
|
||||
self.browser.fill('building_length', '75.5')
|
||||
self.browser.fill('wind_speed', '125')
|
||||
self.browser.fill('ballast_block_weight', '13')
|
||||
self.browser.fill('building_parapet_height', '0')
|
||||
self.browser.fill('max_system_pressure', '10')
|
||||
self.browser.select('system_type', system_type.value)
|
||||
self.browser.select('anchor_type', AnchorType.EcoFasten.value)
|
||||
self.browser.select('module_type', module_type.value)
|
||||
self.browser.fill('design_spectral_response', '1.02')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
self.browser.visit(self.get_server_url() + '/array_summary/')
|
||||
|
||||
def upload_cad_block_file(self, file):
|
||||
self.browser.attach_file('file_upload', file)
|
||||
|
||||
def upload_dxf_file(self, file='test/fixtures/dxf/input_single_tilt_96_cell.dxf'):
|
||||
self.browser.attach_file('dxf_upload', file)
|
||||
|
||||
def test_shows_subarray_summary_table_if_user_has_uploaded_data(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_cad_block_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
|
||||
assert len(self.browser.find_by_css("#seismic_anchor_table")) > 0
|
||||
eq_(len(self.browser.find_by_css("#seismic_anchor_table tr")), 4)
|
||||
eq_(len(self.browser.find_by_css("#seismic_anchor_table tr:nth-child(2) td")), 13)
|
||||
|
||||
def test_shows_errors_if_user_tries_to_upload_select_invalid_data(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_cad_block_file('test/fixtures/invalid_wind_zone.csv')
|
||||
assert len(self.browser.find_by_id('error_message_txt')) > 0
|
||||
assert len(self.browser.find_by_css("#seismic_anchor_table")) == 0
|
||||
|
||||
# def test_shows_subarray_summary_table_after_user_uploads_dxf(self):
|
||||
# self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
# self.upload_dxf_file('test/fixtures/dxf/input_dual_tilt_96_cell.dxf')
|
||||
# assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
|
||||
# assert len(self.browser.find_by_css("#seismic_anchor_table")) > 0
|
||||
# eq_(len(self.browser.find_by_css("#seismic_anchor_table tr")), 4)
|
||||
# eq_(len(self.browser.find_by_css("#seismic_anchor_table tr:nth-child(2) td")), 8)
|
||||
|
||||
def test_indicates_that_user_has_already_uploaded_a_csv_file_after_uploading(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_cad_block_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
|
||||
assert 'input_single_tilt_csv_for_bom.csv' in self.browser.html
|
||||
|
||||
def test_adding_seismic_anchor_updates_subarray_summary(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_cad_block_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
assert self.browser.is_element_visible_by_css('#arrayCanvas')
|
||||
self.browser.execute_script('arrayVisualization.selectPanel(1631);')
|
||||
|
||||
self.browser.find_by_css('#add_seismic').click()
|
||||
assert self.browser.find_by_css('#current_anchors td:nth-child(14)').text == '1'
|
||||
|
||||
self.browser.find_by_css('#add_seismic').click()
|
||||
assert self.browser.find_by_css('#current_anchors td:nth-child(14)').text == '2'
|
||||
|
||||
def test_removig_seismic_anchor_updates_subarray_summary(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_cad_block_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
assert self.browser.is_element_visible_by_css('#arrayCanvas')
|
||||
self.browser.execute_script('arrayVisualization.selectPanel(1631);')
|
||||
|
||||
self.browser.find_by_css('#add_seismic').click()
|
||||
assert self.browser.find_by_css('#current_anchors td:nth-child(14)').text == '1'
|
||||
|
||||
self.browser.find_by_css('#remove_seismic').click()
|
||||
assert self.browser.find_by_css('#current_anchors td:nth-child(14)').text == '0'
|
||||
|
||||
# def test_indicate_that_user_has_uploaded_a_dxf_file_after_uploading_dxf(self):
|
||||
# self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
# self.upload_dxf_file('test/fixtures/dxf/input_dual_tilt_96_cell.dxf')
|
||||
# assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
|
||||
# assert 'input_dual_tilt_96_cell.dxf' in self.browser.html
|
||||
417
test/integration/array_summary_test.py
Normal file
417
test/integration/array_summary_test.py
Normal file
@@ -0,0 +1,417 @@
|
||||
import json
|
||||
import unittest
|
||||
|
||||
import flask
|
||||
import mockredis
|
||||
from numpy.testing import assert_array_equal
|
||||
from splinter import Browser
|
||||
|
||||
from helix import main
|
||||
from helix.constants import redis_constant
|
||||
from helix.constants import sql_constant
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.dxf_validation import INVALID_DUAL_TILT_DESIGN
|
||||
from helix.constants.file_validation_error import FileValidationMessage
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.seismic_anchor_validation_error import SeismicAnchorValidationError
|
||||
from helix.constants.subarray import SUBARRAY_SIZE_BIG
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.session_manager import SessionManager
|
||||
from test.integration.integration_test_helpers import assert_step_is_active, assert_step_is_completed
|
||||
from test.test_helpers import *
|
||||
|
||||
|
||||
class ArraySummaryTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.test_db_session = test_db_session()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.test_db_session.close_all()
|
||||
|
||||
def setUp(self):
|
||||
redis_constant.redis_store = mockredis.mock_redis_client()
|
||||
sql_constant.sql_session_maker = lambda: self.test_db_session
|
||||
self.app = main.app.test_client()
|
||||
self.browser = Browser('flask', app=main.app)
|
||||
self.browser.visit('/array_summary/')
|
||||
|
||||
def tearDown(self):
|
||||
reset_db_session(self.test_db_session)
|
||||
|
||||
def fill_in_site_characterization_data(self,
|
||||
system_type=SystemType.singleTilt,
|
||||
module_type=ModuleType.Cell96):
|
||||
self.browser.visit('/site_characterization/')
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '200')
|
||||
self.browser.fill('building_height', '30')
|
||||
self.browser.fill('building_length', '75.5')
|
||||
self.browser.fill('wind_speed', '125')
|
||||
self.browser.fill('exposure_category', 'C')
|
||||
self.browser.fill('ballast_block_weight', '13')
|
||||
self.browser.fill('building_parapet_height', '0')
|
||||
self.browser.fill('max_system_pressure', '10')
|
||||
self.browser.fill('system_type', system_type.value)
|
||||
self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
|
||||
self.browser.fill('module_type', module_type.value)
|
||||
self.browser.fill('design_spectral_response', '1.02')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
self.browser.visit('/array_summary/')
|
||||
|
||||
def upload_csv_file(self, file='test/fixtures/input_single_tilt.csv'):
|
||||
self.browser.visit('/array_summary/')
|
||||
self.browser.attach_file('file_upload', file)
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
def upload_dxf_file(self, file='test/fixtures/dxf/input_dual_tilt_96_cell.dxf'):
|
||||
self.browser.visit('/array_summary/')
|
||||
self.browser.attach_file('dxf_upload', file)
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
def assert_summary_values_column_data(self, column, label, value):
|
||||
eq_(self.browser.find_by_css('.array_summary .summary_item:nth-child(%d) .item_title' % column).first.html,
|
||||
label)
|
||||
eq_(self.browser.find_by_css('.array_summary .summary_item:nth-child(%d) .item_body' % column).first.text,
|
||||
value)
|
||||
|
||||
def test_does_not_show_tables_if_user_has_not_uploaded_site_data(self):
|
||||
assert len(self.browser.find_by_css("#seismic_anchor_table")) == 0
|
||||
assert len(self.browser.find_by_css("#summary_values_table")) == 0
|
||||
|
||||
def test_does_not_show_next_button(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
next_button = self.browser.find_by_value('Next')
|
||||
assert next_button.first._control.attrib['style'] == 'display: none;'
|
||||
|
||||
def test_without_csv_or_dxf_form_submission_requires_csv_attachment(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
assert self.browser.is_text_present("Please provide a .txt file!")
|
||||
|
||||
def test_with_invalid_csv_file(self):
|
||||
self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
self.browser.attach_file('file_upload', 'test/fixtures/input_single_tilt.csv')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
eq_(self.browser.find_by_id('error_message_txt').first.value, 'Invalid wind zone for Dual Tilt System on line 1')
|
||||
|
||||
def test_shows_subarray_summary_table_if_user_has_uploaded_data(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_csv_file(file='test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
|
||||
assert len(self.browser.find_by_css("#seismic_anchor_table")) > 0
|
||||
eq_(len(self.browser.find_by_css("#seismic_anchor_table tr")), 4)
|
||||
eq_(len(self.browser.find_by_css("#seismic_anchor_table tr:nth-child(2) td")), 13)
|
||||
|
||||
def test_indicate_that_user_has_already_uploaded_a_csv_file_after_uploading_csv(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_csv_file(file='test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
|
||||
assert 'test/fixtures/input_single_tilt_csv_for_bom.csv' in self.browser.html
|
||||
|
||||
# def test_dxf_as_cad_file_if_dxf_file_uploaded(self):
|
||||
# self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
# self.upload_dxf_file()
|
||||
# assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
|
||||
# assert len(self.browser.find_by_css("#seismic_anchor_table")) > 0
|
||||
# eq_(len(self.browser.find_by_css("#seismic_anchor_table tr")), 4)
|
||||
# eq_(len(self.browser.find_by_css("#seismic_anchor_table tr:nth-child(2) td")), 8)
|
||||
|
||||
def test_indicate_that_user_has_uploaded_a_dxf_file_after_uploading_dxf(self):
|
||||
self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
self.upload_dxf_file()
|
||||
assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
|
||||
assert 'test/fixtures/dxf/input_dual_tilt_96_cell.dxf' in self.browser.html
|
||||
|
||||
def test_shows_errors_if_dxf_fails_validation(self):
|
||||
self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
self.upload_dxf_file(file="test/fixtures/dxf/invalid_dual_tilt_96_cell_has_unpairable_modules.dxf")
|
||||
assert len(self.browser.find_by_id('error_message_dxf')) == 1
|
||||
msg = INVALID_DUAL_TILT_DESIGN
|
||||
eq_(self.browser.find_by_id('error_message_dxf').first.value, msg)
|
||||
|
||||
def test_shows_errors_if_dxf_has_big_subarrays(self):
|
||||
self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
self.upload_dxf_file(file="test/fixtures/dxf/invalid_dual_tilt_96_cell_subarrays_too_large.dxf")
|
||||
assert len(self.browser.find_by_id('error_message_dxf')) == 1
|
||||
msg = SUBARRAY_SIZE_BIG
|
||||
eq_(self.browser.find_by_id('error_message_dxf').first.value, msg)
|
||||
|
||||
def test_viewing_summary_table_after_uploading_data_updates_navigation_header(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_csv_file(file='test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
assert_step_is_active(self.browser, 3)
|
||||
assert_step_is_completed(self.browser, 3)
|
||||
self.browser.click_link_by_partial_text("Back")
|
||||
assert_step_is_active(self.browser, 3, False)
|
||||
assert_step_is_completed(self.browser, 3)
|
||||
|
||||
def test_viewing_summary_table_before_uploading_data_does_not_update_navigation_header(self):
|
||||
assert_step_is_active(self.browser, 3)
|
||||
assert_step_is_completed(self.browser, 3, False)
|
||||
self.browser.click_link_by_partial_text("Back")
|
||||
assert_step_is_active(self.browser, 3, False)
|
||||
assert_step_is_completed(self.browser, 3, False)
|
||||
|
||||
def test_next_is_not_available_before_uploading_data(self):
|
||||
eq_(len(self.browser.find_by_value('Next')), 0)
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_csv_file()
|
||||
eq_(len(self.browser.find_by_value('Next')), 1)
|
||||
|
||||
def test_clicking_next_after_uploading_data_goes_to_power_station_configuration(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_csv_file()
|
||||
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
assert_step_is_active(self.browser, 4)
|
||||
assert_step_is_active(self.browser, 3, False)
|
||||
|
||||
def test_shows_summary_values(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.upload_csv_file(file='test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
self.assert_summary_values_column_data(1, 'Total System Weight (lbs)', '216,074')
|
||||
self.assert_summary_values_column_data(2, 'Max PSF', '9.11')
|
||||
self.assert_summary_values_column_data(3, 'Avg PSF', '5.05')
|
||||
self.assert_summary_values_column_data(4, 'Total Anchors', '421')
|
||||
self.assert_summary_values_column_data(5, 'Total Ballast', '10,150')
|
||||
|
||||
def test_shows_seismic_placement_interval(self):
|
||||
self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
self.upload_csv_file(file='test/fixtures/input_small_dual_tilt.csv')
|
||||
self.assert_summary_values_column_data(8, 'Seismic Anchor Max. Spacing', '14')
|
||||
|
||||
def test_clicking_back_goes_to_site_summary(self):
|
||||
self.browser.click_link_by_partial_text('Back')
|
||||
|
||||
assert_step_is_active(self.browser, 2)
|
||||
|
||||
def test_getting_panel_data(self):
|
||||
redis = redis_constant.redis_store
|
||||
with self.app.session_transaction() as session:
|
||||
session_manager = SessionManager(session, redis, self.test_db_session)
|
||||
session_manager.save_form_submission({
|
||||
'project_name': 'Test',
|
||||
'building_width': 64,
|
||||
'building_height': 24,
|
||||
'building_length': 86,
|
||||
'wind_speed': 110,
|
||||
'exposure_category': 'B',
|
||||
'ballast_block_weight': 14,
|
||||
'building_parapet_height': 1,
|
||||
'max_system_pressure': 10,
|
||||
'system_type': SystemType.dualTilt.value,
|
||||
'module_type': ModuleType.Cell96.value,
|
||||
'anchor_type': AnchorType.EcoFasten.value,
|
||||
'design_spectral_response': 1,
|
||||
})
|
||||
with open('test/fixtures/input_dual_subarray.txt', 'r', newline='') as csv_file:
|
||||
session_manager.save_uploaded_file(csv_file.read())
|
||||
response = self.app.get('/api/panel_data')
|
||||
eq_(response.content_type, "application/json")
|
||||
data = json.loads(response.data.decode())
|
||||
expected = [
|
||||
{'data': {'ballast': 7, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 1, 'panel_type': 2, 'psf': 4.94, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 2, 'panel_type': 2, 'psf': 3.12, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 3, 'panel_type': 1, 'psf': 6.47, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 4, 'panel_type': 1, 'psf': 6.47, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 5, 'panel_type': 1, 'psf': 4.57, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 6, 'panel_type': 2, 'psf': 3.12, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 7, 'panel_type': 4, 'psf': 2.26, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 8, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 9, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 10, 'panel_type': 4, 'psf': 2.26, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 11, 'panel_type': 2, 'psf': 3.12, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 12, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 13, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 14, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 15, 'panel_type': 1, 'psf': 4.57, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 16, 'panel_type': 1, 'psf': 4.57, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 17, 'panel_type': 1, 'psf': 4.57, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 18, 'panel_type': 1, 'psf': 6.47, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 19, 'panel_type': 3, 'psf': 4.48, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
|
||||
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 20, 'panel_type': 1, 'psf': 6.47, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5}
|
||||
]
|
||||
|
||||
# Removing these keys as they get calculated differently in CircleCI
|
||||
entries_to_remove = ('x', 'y')
|
||||
for k in entries_to_remove:
|
||||
for entry in data['panel_data']:
|
||||
entry.pop(k, None)
|
||||
assert_array_equal(data['panel_data'], expected)
|
||||
|
||||
def test_posting_user_seismic_anchors(self):
|
||||
redis = redis_constant.redis_store
|
||||
with self.app.session_transaction() as session:
|
||||
session_manager = SessionManager(session, redis, self.test_db_session)
|
||||
session_manager.save_form_submission({
|
||||
'project_name': 'Test',
|
||||
'building_width': 200,
|
||||
'building_height': 30,
|
||||
'building_length': 75.5,
|
||||
'wind_speed': 125,
|
||||
'exposure_category': 'C',
|
||||
'ballast_block_weight': 13,
|
||||
'building_parapet_height': 0,
|
||||
'max_system_pressure': 0,
|
||||
'system_type': SystemType.singleTilt.value,
|
||||
'anchor_type': AnchorType.EcoFasten.value,
|
||||
'design_spectral_response': 1.02,
|
||||
})
|
||||
with open('test/fixtures/input_single_tilt.csv', 'r', newline='') as csv_file:
|
||||
session_manager.save_uploaded_file(csv_file.read())
|
||||
result = self.app.post("/api/update_panel_data", content_type='application/json', data=json.dumps([
|
||||
{"panel_id": 1, "seismic_anchors": 2},
|
||||
{"panel_id": 2, "seismic_anchors": 0},
|
||||
{"panel_id": 3, "seismic_anchors": 0},
|
||||
{"panel_id": 4, "seismic_anchors": 0},
|
||||
{"panel_id": 5, "seismic_anchors": 0},
|
||||
{"panel_id": 6, "seismic_anchors": 0},
|
||||
{"panel_id": 7, "seismic_anchors": 0},
|
||||
{"panel_id": 8, "seismic_anchors": 0},
|
||||
{"panel_id": 9, "seismic_anchors": 0},
|
||||
{"panel_id": 10, "seismic_anchors": 0},
|
||||
{"panel_id": 11, "seismic_anchors": 0},
|
||||
{"panel_id": 12, "seismic_anchors": 0},
|
||||
{"panel_id": 13, "seismic_anchors": 0},
|
||||
{"panel_id": 14, "seismic_anchors": 0},
|
||||
{"panel_id": 15, "seismic_anchors": 0},
|
||||
{"panel_id": 16, "seismic_anchors": 0},
|
||||
{"panel_id": 17, "seismic_anchors": 0},
|
||||
{"panel_id": 18, "seismic_anchors": 0},
|
||||
{"panel_id": 19, "seismic_anchors": 0},
|
||||
]))
|
||||
with self.app.session_transaction() as session:
|
||||
session_manager = SessionManager(session, redis, self.test_db_session)
|
||||
eq_(session_manager.user_values().user_override_seismic_anchors(), True)
|
||||
|
||||
expected_result = {
|
||||
"status": "success",
|
||||
"error": None,
|
||||
"panel_data": [
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.08, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 1, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 2, 'panel_id': 1}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.04, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 3, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 2, 'seismic_anchors': 0, 'panel_id': 2}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.08, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 1, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 3}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.08, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 1, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 4}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.04, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 3, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 2, 'seismic_anchors': 0, 'panel_id': 5}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.04, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 3, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 2, 'seismic_anchors': 0, 'panel_id': 6}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.04, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 3, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 2, 'seismic_anchors': 0, 'panel_id': 7}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.08, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 1, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 8}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 9}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 10}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'I', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 11}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 12}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 13}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 14}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 15}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 16}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 17}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 18}},
|
||||
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'I', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 19}},
|
||||
],
|
||||
"subarray_data": [
|
||||
{"subarray": 8, "weight": 972, "required_seismic_anchors": 0},
|
||||
],
|
||||
}
|
||||
received_result = flask.json.loads(result.data)
|
||||
eq_(received_result, expected_result)
|
||||
eq_(result.content_type, "application/json")
|
||||
|
||||
def test_posting_user_seismic_anchors_with_required_ones(self):
|
||||
redis = redis_constant.redis_store
|
||||
with self.app.session_transaction() as session:
|
||||
session_manager = SessionManager(session, redis, self.test_db_session)
|
||||
session_manager.save_form_submission({
|
||||
'project_name': 'Test',
|
||||
'building_width': 64,
|
||||
'building_height': 24,
|
||||
'building_length': 86,
|
||||
'wind_speed': 110,
|
||||
'exposure_category': 'B',
|
||||
'ballast_block_weight': 14,
|
||||
'building_parapet_height': 1,
|
||||
'max_system_pressure': 10,
|
||||
'system_type': SystemType.dualTilt.value,
|
||||
'module_type': ModuleType.Cell96.value,
|
||||
'anchor_type': AnchorType.EcoFasten.value,
|
||||
'design_spectral_response': 1,
|
||||
})
|
||||
with open('test/fixtures/input_dual_subarray.txt', 'r', newline='') as csv_file:
|
||||
session_manager.save_uploaded_file(csv_file.read())
|
||||
result = self.app.post("/api/update_panel_data", content_type='application/json', data=json.dumps([
|
||||
{"panel_id": 1, "seismic_anchors": 2},
|
||||
{"panel_id": 2, "seismic_anchors": 0},
|
||||
{"panel_id": 3, "seismic_anchors": 0},
|
||||
{"panel_id": 4, "seismic_anchors": 2},
|
||||
{"panel_id": 5, "seismic_anchors": 0},
|
||||
{"panel_id": 6, "seismic_anchors": 0},
|
||||
{"panel_id": 7, "seismic_anchors": 0},
|
||||
{"panel_id": 8, "seismic_anchors": 0},
|
||||
{"panel_id": 9, "seismic_anchors": 0},
|
||||
{"panel_id": 10, "seismic_anchors": 0},
|
||||
{"panel_id": 11, "seismic_anchors": 0},
|
||||
{"panel_id": 12, "seismic_anchors": 0},
|
||||
{"panel_id": 13, "seismic_anchors": 0},
|
||||
{"panel_id": 14, "seismic_anchors": 0},
|
||||
{"panel_id": 15, "seismic_anchors": 0},
|
||||
{"panel_id": 16, "seismic_anchors": 0},
|
||||
{"panel_id": 17, "seismic_anchors": 0},
|
||||
{"panel_id": 18, "seismic_anchors": 0},
|
||||
{"panel_id": 19, "seismic_anchors": 0},
|
||||
{"panel_id": 20, "seismic_anchors": 0},
|
||||
]))
|
||||
with self.app.session_transaction() as session:
|
||||
session_manager = SessionManager(session, redis, self.test_db_session)
|
||||
eq_(session_manager.user_values().user_override_seismic_anchors(), True)
|
||||
|
||||
expected_result = [
|
||||
{"subarray": 7, "weight": 2253, "required_seismic_anchors": 4},
|
||||
{"subarray": 8, "weight": 673, "required_seismic_anchors": 0},
|
||||
]
|
||||
received_result = flask.json.loads(result.data)
|
||||
eq_(received_result['subarray_data'], expected_result)
|
||||
eq_(result.content_type, "application/json")
|
||||
|
||||
def test_posting_user_seismic_anchors_below_amount(self):
|
||||
redis = redis_constant.redis_store
|
||||
with self.app.session_transaction() as session:
|
||||
session_manager = SessionManager(session, redis, self.test_db_session)
|
||||
session_manager.save_form_submission({
|
||||
'project_name': 'Test',
|
||||
'building_width': 200,
|
||||
'building_height': 300,
|
||||
'building_length': 755,
|
||||
'wind_speed': 200,
|
||||
'exposure_category': 'B',
|
||||
'ballast_block_weight': 20,
|
||||
'building_parapet_height': 0,
|
||||
'max_system_pressure': 100,
|
||||
'system_type': SystemType.dualTilt.value,
|
||||
'anchor_type': AnchorType.EcoFasten.value,
|
||||
'design_spectral_response': 5.0,
|
||||
})
|
||||
with open('test/fixtures/input_dual_tilt.csv', 'r', newline='') as csv_file:
|
||||
session_manager.save_uploaded_file(csv_file.read())
|
||||
result = self.app.post("/api/update_panel_data", content_type='application/json', data=json.dumps([
|
||||
{"panel_id": 1, "seismic_anchors": 0},
|
||||
{"panel_id": 2, "seismic_anchors": 0},
|
||||
{"panel_id": 3, "seismic_anchors": 0},
|
||||
{"panel_id": 4, "seismic_anchors": 0},
|
||||
{"panel_id": 5, "seismic_anchors": 0},
|
||||
{"panel_id": 6, "seismic_anchors": 0},
|
||||
{"panel_id": 7, "seismic_anchors": 0},
|
||||
]))
|
||||
with self.app.session_transaction() as session:
|
||||
session_manager = SessionManager(session, redis, self.test_db_session)
|
||||
eq_(session_manager.user_values().user_override_seismic_anchors(), False)
|
||||
expected_result = {
|
||||
"status": "error",
|
||||
"error": SeismicAnchorValidationError.TooFewAnchors.value,
|
||||
"panel_data": None,
|
||||
"subarray_data": [
|
||||
{"subarray": 1, "weight": 2739, "required_seismic_anchors": 6},
|
||||
],
|
||||
}
|
||||
eq_(flask.json.loads(result.data), expected_result)
|
||||
eq_(result.content_type, "application/json")
|
||||
299
test/integration/bom_integration_test.py
Normal file
299
test/integration/bom_integration_test.py
Normal file
@@ -0,0 +1,299 @@
|
||||
import unittest
|
||||
import mockredis
|
||||
from numpy.testing import assert_array_equal
|
||||
from helix.calculators.calculator import Calculator
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.exposure_category import ExposureCategory
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.models.sql.sites import Site
|
||||
from helix.store import Store
|
||||
from helix.user_values import UserValues
|
||||
|
||||
|
||||
class BomIntegrationTest(unittest.TestCase):
|
||||
def test_lwoods_2381(self): # name of the site
|
||||
self.store = mockredis.mock_redis_client()
|
||||
self.site = Site()
|
||||
self.values = UserValues(self.store, self.site)
|
||||
self.site.building_height = 40
|
||||
self.site.building_width = 87
|
||||
self.site.building_length = 195
|
||||
self.site.parapet_height = 0.3
|
||||
self.site.wind_speed = 130
|
||||
self.site.exposure_category = ExposureCategory.B.value
|
||||
self.site.ballast_block_weight = 14
|
||||
self.site.max_psf= 10
|
||||
self.site.anchor_type = AnchorType.OMG_PowerGrip_Plus.value
|
||||
self.site.spectral_response = 1
|
||||
|
||||
self.site.system_type = SystemType(SystemType.dualTilt.value)
|
||||
self.site.module_type = ModuleType(ModuleType.Cell96.value)
|
||||
with open('test/fixtures/input_dual_tilt_96_cell_lw_2381.tsv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.site.cad_file = csv_content
|
||||
self.subject = Calculator(self.values)
|
||||
|
||||
expected = [
|
||||
["512200", "CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2", "510"],
|
||||
["513833", "TRAY, LINK, HELIX ROOF", "78"], # TODO: should be 74 for part perfect bom
|
||||
["513841", "DEFLECTOR, LH, HELIX ROOF", "30"],
|
||||
["513842", "DEFLECTOR, RH, HELIX ROOF", "30"],
|
||||
["513843", "PLATE, ANCHOR, HELIX ROOF", "86"],
|
||||
["513844", "TRAY, OPTIONAL BALLAST, HELIX ROOF", "35"],
|
||||
["514056", "BASE, CHASSIS, DUAL TILT, HELIX ROOF", "147"],
|
||||
["514057", "PLATFORM, CHASSIS, DUAL TILT, HELIX ROOF", "147"],
|
||||
["514265", "FOOT, RECYCLED RUBBER, HELIX ROOF", "26"],
|
||||
["515063", "SCREW, CAP, SH, M6 X 1 X 12, 18-8 SS (DIN 912)", "600"],
|
||||
["515928", "FRONT SKIRT, HELIX ROOF", "126"],
|
||||
["517871", "TRAY, LEADING, HELIX ROOF, RIVETED VERSION", "67"],
|
||||
["518477", "WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS", "100"],
|
||||
["Contractor Supplied", "Ballast Blocks", "608"],
|
||||
["TBD", "Anchors", "86"],
|
||||
["TBD", "Modules", "252"]
|
||||
]
|
||||
|
||||
bom = self.subject.compute_bom()
|
||||
assert_array_equal(bom, expected)
|
||||
|
||||
def test_lw_2394(self):
|
||||
self.store = Store(mockredis.mock_redis_client(), "foo")
|
||||
self.site = Site()
|
||||
self.values = UserValues(self.store, self.site)
|
||||
self.site.building_height = 40
|
||||
self.site.building_width = 88.25
|
||||
self.site.building_length = 195.25
|
||||
self.site.parapet_height = 0.3333
|
||||
self.site.wind_speed = 130
|
||||
self.site.exposure_category = ExposureCategory.B_C.value
|
||||
self.site.exposure_transition_distance = 1212
|
||||
self.site.ballast_block_weight = 14
|
||||
self.site.max_psf= 10
|
||||
self.site.anchor_type = AnchorType.OMG_PowerGrip_Plus.value
|
||||
self.site.spectral_response = 0.993
|
||||
|
||||
self.site.system_type = SystemType(SystemType.dualTilt.value)
|
||||
self.site.module_type = ModuleType(ModuleType.Cell96.value)
|
||||
with open('test/fixtures/input_dual_tilt_96_cell_lw_2394.tsv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.site.cad_file= csv_content
|
||||
self.subject = Calculator(self.values)
|
||||
|
||||
expected = [
|
||||
['512200', 'CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2', '540'],
|
||||
['513833', 'TRAY, LINK, HELIX ROOF', '75'], # TODO: should be 73 for part perfect bom
|
||||
['513841', 'DEFLECTOR, LH, HELIX ROOF', '20'],
|
||||
['513842', 'DEFLECTOR, RH, HELIX ROOF', '20'],
|
||||
['513843', 'PLATE, ANCHOR, HELIX ROOF', '114'],
|
||||
['513844', 'TRAY, OPTIONAL BALLAST, HELIX ROOF', '17'],
|
||||
['514056', 'BASE, CHASSIS, DUAL TILT, HELIX ROOF', '148'],
|
||||
['514057', 'PLATFORM, CHASSIS, DUAL TILT, HELIX ROOF', '148'],
|
||||
['514265', 'FOOT, RECYCLED RUBBER, HELIX ROOF', '27'],
|
||||
['515063', 'SCREW, CAP, SH, M6 X 1 X 12, 18-8 SS (DIN 912)', '600'],
|
||||
['515928', 'FRONT SKIRT, HELIX ROOF', '130'],
|
||||
['517871', 'TRAY, LEADING, HELIX ROOF, RIVETED VERSION', '69'],
|
||||
['518477', 'WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS', '125'],
|
||||
['Contractor Supplied', 'Ballast Blocks', '358'],
|
||||
['TBD', 'Anchors', '114'],
|
||||
['TBD', 'Modules', '264']
|
||||
]
|
||||
|
||||
bom = self.subject.compute_bom()
|
||||
assert_array_equal(bom, expected)
|
||||
|
||||
def test_lw_5510(self):
|
||||
self.store = Store(mockredis.mock_redis_client(), "foo")
|
||||
self.site = Site()
|
||||
self.values = UserValues(self.store, self.site)
|
||||
self.site.building_height = 40
|
||||
self.site.building_width = 86.75
|
||||
self.site.building_length = 210.33
|
||||
self.site.parapet_height = 1
|
||||
self.site.wind_speed = 130
|
||||
self.site.exposure_category = ExposureCategory.B.value
|
||||
self.site.ballast_block_weight = 14
|
||||
self.site.max_psf= 10
|
||||
self.site.anchor_type = AnchorType.OMG_PowerGrip_Plus.value
|
||||
self.site.spectral_response = 1.009
|
||||
|
||||
self.site.system_type = SystemType(SystemType.dualTilt.value)
|
||||
self.site.module_type = ModuleType(ModuleType.Cell96.value)
|
||||
with open('test/fixtures/input_dual_tilt_96_cell_lw_5510.tsv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.site.cad_file = csv_content
|
||||
self.subject = Calculator(self.values)
|
||||
|
||||
expected = [
|
||||
['512200', 'CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2', '330'],
|
||||
['513833', 'TRAY, LINK, HELIX ROOF', '45'], # 45 is perfect value for this bom
|
||||
['513841', 'DEFLECTOR, LH, HELIX ROOF', '36'],
|
||||
['513842', 'DEFLECTOR, RH, HELIX ROOF', '36'],
|
||||
['513843', 'PLATE, ANCHOR, HELIX ROOF', '67'],
|
||||
['513844', 'TRAY, OPTIONAL BALLAST, HELIX ROOF', '13'],
|
||||
['514056', 'BASE, CHASSIS, DUAL TILT, HELIX ROOF', '102'],
|
||||
['514057', 'PLATFORM, CHASSIS, DUAL TILT, HELIX ROOF', '102'],
|
||||
['514265', 'FOOT, RECYCLED RUBBER, HELIX ROOF', '16'],
|
||||
['515063', 'SCREW, CAP, SH, M6 X 1 X 12, 18-8 SS (DIN 912)', '450'],
|
||||
['515928', 'FRONT SKIRT, HELIX ROOF', '88'],
|
||||
['517871', 'TRAY, LEADING, HELIX ROOF, RIVETED VERSION', '53'],
|
||||
['518477', 'WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS', '75'],
|
||||
['Contractor Supplied', 'Ballast Blocks', '286'],
|
||||
['TBD', 'Anchors', '67'],
|
||||
['TBD', 'Modules', '160'],
|
||||
]
|
||||
|
||||
bom = self.subject.compute_bom()
|
||||
assert_array_equal(bom, expected)
|
||||
|
||||
def test_al_2400(self):
|
||||
self.store = Store(mockredis.mock_redis_client(), "foo")
|
||||
self.site = Site()
|
||||
self.values = UserValues(self.store, self.site)
|
||||
self.site.building_height = 40
|
||||
self.site.building_width = 189
|
||||
self.site.building_length = 81
|
||||
self.site.parapet_height = 0
|
||||
self.site.wind_speed = 130
|
||||
self.site.exposure_category = ExposureCategory.B_C.value
|
||||
self.site.exposure_transition_distance = 1500
|
||||
self.site.module_type = ModuleType.Cell96.value
|
||||
self.site.ballast_block_weight = 14
|
||||
self.site.max_psf = 10
|
||||
self.site.anchor_type = AnchorType.OMG_PowerGrip_Plus.value
|
||||
self.site.spectral_response = 0.994
|
||||
|
||||
self.site.system_type = SystemType.dualTilt.value
|
||||
with open('test/fixtures/input_dual_tilt_96_cell_al_2400.tsv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.site.cad_file = csv_content
|
||||
self.subject = Calculator(self.values)
|
||||
|
||||
expected = [
|
||||
['512200', 'CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2', '510'],
|
||||
['513833', 'TRAY, LINK, HELIX ROOF', '73'], # TODO: should be 70 for part perfect bom
|
||||
['513841', 'DEFLECTOR, LH, HELIX ROOF', '24'],
|
||||
['513842', 'DEFLECTOR, RH, HELIX ROOF', '24'],
|
||||
['513843', 'PLATE, ANCHOR, HELIX ROOF', '94'],
|
||||
['513844', 'TRAY, OPTIONAL BALLAST, HELIX ROOF', '28'],
|
||||
['514056', 'BASE, CHASSIS, DUAL TILT, HELIX ROOF', '140'],
|
||||
['514057', 'PLATFORM, CHASSIS, DUAL TILT, HELIX ROOF', '140'],
|
||||
['514265', 'FOOT, RECYCLED RUBBER, HELIX ROOF', '25'],
|
||||
['515063', 'SCREW, CAP, SH, M6 X 1 X 12, 18-8 SS (DIN 912)', '600'],
|
||||
['515928', 'FRONT SKIRT, HELIX ROOF', '120'],
|
||||
['517871', 'TRAY, LEADING, HELIX ROOF, RIVETED VERSION', '64'],
|
||||
['518477', 'WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS', '100'],
|
||||
['Contractor Supplied', 'Ballast Blocks', '560'],
|
||||
['TBD', 'Anchors', '94'],
|
||||
['TBD', 'Modules', '244'],
|
||||
]
|
||||
|
||||
bom = self.subject.compute_bom()
|
||||
assert_array_equal(bom, expected)
|
||||
|
||||
def test_array2(self):
|
||||
"""
|
||||
Pivotal: 1544689
|
||||
"""
|
||||
self.store = Store(mockredis.mock_redis_client(), "foo")
|
||||
self.site = Site()
|
||||
self.values = UserValues(self.store, self.site)
|
||||
self.site.building_height = 45
|
||||
self.site.building_width = 383
|
||||
self.site.building_length = 430
|
||||
self.site.parapet_height = 0.3
|
||||
self.site.wind_speed = 110
|
||||
self.site.exposure_category = ExposureCategory.C.value
|
||||
self.site.exposure_transition_distance = 1500
|
||||
self.site.module_type = ModuleType.Cell96.value
|
||||
self.site.ballast_block_weight = 14
|
||||
self.site.max_psf = 6
|
||||
self.site.anchor_type = AnchorType.OMG_PowerGrip_Plus.value
|
||||
self.site.spectral_response = 1.03
|
||||
|
||||
self.site.system_type = SystemType.dualTilt.value
|
||||
with open('test/fixtures/input_dual_tilt_96_cell_array_2.tsv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.site.cad_file = csv_content
|
||||
self.subject = Calculator(self.values)
|
||||
|
||||
expected_link = [
|
||||
['513833', 'TRAY, LINK, HELIX ROOF', '50'],
|
||||
]
|
||||
expected_link_num = expected_link[0][2]
|
||||
|
||||
bom = self.subject.compute_bom()
|
||||
links_in_bom = [elem[2] for elem in bom if elem[0] == '513833'][0]
|
||||
|
||||
self.assertEqual(expected_link_num, links_in_bom)
|
||||
|
||||
def test_array1(self):
|
||||
"""
|
||||
Pivotal: 1544689
|
||||
"""
|
||||
self.store = Store(mockredis.mock_redis_client(), "foo")
|
||||
self.site = Site()
|
||||
self.values = UserValues(self.store, self.site)
|
||||
self.site.building_height = 45
|
||||
self.site.building_width = 383
|
||||
self.site.building_length = 430
|
||||
self.site.parapet_height = 0.3
|
||||
self.site.wind_speed = 110
|
||||
self.site.exposure_category = ExposureCategory.C.value
|
||||
self.site.exposure_transition_distance = 1500
|
||||
self.site.module_type = ModuleType.Cell96.value
|
||||
self.site.ballast_block_weight = 14
|
||||
self.site.max_psf = 10
|
||||
self.site.anchor_type = AnchorType.OMG_PowerGrip_Plus.value
|
||||
self.site.spectral_response = 1.03
|
||||
|
||||
self.site.system_type = SystemType.dualTilt.value
|
||||
with open('test/fixtures/input_dual_tilt_96_cell_array_1.tsv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.site.cad_file = csv_content
|
||||
self.subject = Calculator(self.values)
|
||||
|
||||
expected_link = [
|
||||
['513833', 'TRAY, LINK, HELIX ROOF', '37'],
|
||||
]
|
||||
expected_link_num = expected_link[0][2]
|
||||
|
||||
bom = self.subject.compute_bom()
|
||||
links_in_bom = [elem[2] for elem in bom if elem[0] == '513833'][0]
|
||||
|
||||
self.assertEqual(expected_link_num, links_in_bom)
|
||||
|
||||
def test_array7(self):
|
||||
"""
|
||||
Pivotal: 1544689
|
||||
"""
|
||||
self.store = Store(mockredis.mock_redis_client(), "foo")
|
||||
self.site = Site()
|
||||
self.values = UserValues(self.store, self.site)
|
||||
self.site.building_height = 45
|
||||
self.site.building_width = 383
|
||||
self.site.building_length = 430
|
||||
self.site.parapet_height = 0.3
|
||||
self.site.wind_speed = 110
|
||||
self.site.exposure_category = ExposureCategory.C.value
|
||||
self.site.exposure_transition_distance = 1500
|
||||
self.site.module_type = ModuleType.Cell96.value
|
||||
self.site.ballast_block_weight = 14
|
||||
self.site.max_psf = 10
|
||||
self.site.anchor_type = AnchorType.OMG_PowerGrip_Plus.value
|
||||
self.site.spectral_response = 1.03
|
||||
|
||||
self.site.system_type = SystemType.dualTilt.value
|
||||
with open('test/fixtures/input_dual_tilt_96_cell_array_7.tsv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.site.cad_file = csv_content
|
||||
self.subject = Calculator(self.values)
|
||||
|
||||
expected_link = [
|
||||
['513833', 'TRAY, LINK, HELIX ROOF', '30'],
|
||||
]
|
||||
expected_link_num = expected_link[0][2]
|
||||
|
||||
bom = self.subject.compute_bom()
|
||||
links_in_bom = [elem[2] for elem in bom if elem[0] == '513833'][0]
|
||||
|
||||
self.assertEqual(expected_link_num, links_in_bom)
|
||||
265
test/integration/full_user_flow_test.py
Normal file
265
test/integration/full_user_flow_test.py
Normal file
@@ -0,0 +1,265 @@
|
||||
import os
|
||||
import unittest
|
||||
|
||||
import mockredis
|
||||
from splinter import Browser
|
||||
|
||||
from helix import main
|
||||
from helix.constants import redis_constant
|
||||
from helix.constants import sql_constant
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.inverter_type import InverterType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.constants.version import version
|
||||
from helix.models.sql.power_stations import PowerStation
|
||||
from test.integration.integration_test_helpers import *
|
||||
from test.test_helpers import test_db_session, reset_db_session
|
||||
|
||||
|
||||
class FullUserFlowTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.test_db_session = test_db_session()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.test_db_session.close_all()
|
||||
|
||||
def setUp(self):
|
||||
redis_constant.redis_store = mockredis.mock_redis_client()
|
||||
sql_constant.sql_session_maker = lambda: self.test_db_session
|
||||
|
||||
self.app = main.app.test_client()
|
||||
self.browser = Browser('flask', app=main.app)
|
||||
self.browser.visit('/site_characterization/')
|
||||
|
||||
def tearDown(self):
|
||||
reset_db_session(self.test_db_session)
|
||||
|
||||
def fill_in_site_characterization_data(self):
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '200')
|
||||
self.browser.fill('building_height', '30')
|
||||
self.browser.fill('building_length', '75.5')
|
||||
self.browser.fill('wind_speed', '125')
|
||||
self.browser.fill('exposure_category', 'C')
|
||||
self.browser.fill('ballast_block_weight', '13')
|
||||
self.browser.fill('building_parapet_height', '0')
|
||||
self.browser.fill('max_system_pressure', '10')
|
||||
self.browser.fill('system_type', SystemType.singleTilt.value)
|
||||
self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
|
||||
self.browser.fill('design_spectral_response', '1')
|
||||
|
||||
def attach_file(self, file):
|
||||
self.browser.visit('/array_summary/')
|
||||
self.browser.attach_file('file_upload', file)
|
||||
|
||||
def attach_dxf(self, dxf_file):
|
||||
self.browser.visit('/array_summary/')
|
||||
self.browser.attach_file('dxf_upload', dxf_file)
|
||||
|
||||
def advance_n_times(self, advance_count):
|
||||
for _ in range(advance_count):
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
def test_uploading_and_downloading_dual_tilt_csv(self):
|
||||
"""
|
||||
This is using data from an old-style file but works because
|
||||
the old spacing is within the new spacing's variance tolerance
|
||||
"""
|
||||
|
||||
with open('test/fixtures/expected_dual_tilt.csv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '1000')
|
||||
self.browser.fill('building_height', '100')
|
||||
self.browser.fill('building_length', '1500')
|
||||
self.browser.fill('wind_speed', '110')
|
||||
self.browser.fill('exposure_category', 'D')
|
||||
self.browser.fill('ballast_block_weight', '20')
|
||||
self.browser.fill('building_parapet_height', '0')
|
||||
self.browser.fill('max_system_pressure', '17')
|
||||
self.browser.fill('system_type', SystemType.dualTilt.value)
|
||||
self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
|
||||
self.browser.fill('design_spectral_response', '1')
|
||||
|
||||
self.advance_n_times(1)
|
||||
self.attach_file('test/fixtures/input_dual_tilt.csv')
|
||||
|
||||
self.advance_n_times(3)
|
||||
self.browser.click_link_by_partial_text('Download AutoCAD import file')
|
||||
eq_(self.browser.html, csv_content)
|
||||
eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')
|
||||
|
||||
def test_clicking_back_at_download_goes_to_power_station_configuration(self):
|
||||
self.browser.visit('/download/')
|
||||
|
||||
assert not self.browser.is_text_present('Next')
|
||||
assert self.browser.is_text_present('Back')
|
||||
|
||||
self.browser.click_link_by_partial_text('Back')
|
||||
assert_step_is_active(self.browser, 4)
|
||||
|
||||
def test_uploading_and_downloading_single_tilt_csv(self):
|
||||
with open('test/fixtures/expected_single_tilt.csv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '1000')
|
||||
self.browser.fill('building_height', '100')
|
||||
self.browser.fill('building_length', '1500')
|
||||
self.browser.fill('wind_speed', '110')
|
||||
self.browser.fill('exposure_category', 'D')
|
||||
self.browser.fill('ballast_block_weight', '20')
|
||||
self.browser.fill('building_parapet_height', '0')
|
||||
self.browser.fill('max_system_pressure', '17')
|
||||
self.browser.fill('system_type', SystemType.singleTilt.value)
|
||||
self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
|
||||
self.browser.fill('design_spectral_response', '1')
|
||||
|
||||
self.advance_n_times(1)
|
||||
self.attach_file('test/fixtures/input_single_tilt.csv')
|
||||
|
||||
self.advance_n_times(3)
|
||||
self.browser.click_link_by_partial_text('Download AutoCAD import file')
|
||||
eq_(self.browser.html, csv_content)
|
||||
eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')
|
||||
|
||||
def test_downloading_coordinates_csv(self):
|
||||
with open('test/fixtures/expected_dual_tilt_coordinates.csv', 'r', newline='') as csv_file:
|
||||
csv_content = csv_file.read()
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '450')
|
||||
self.browser.fill('building_height', '35')
|
||||
self.browser.fill('building_length', '500')
|
||||
self.browser.fill('wind_speed', '110')
|
||||
self.browser.fill('exposure_category', 'B')
|
||||
self.browser.fill('ballast_block_weight', '14')
|
||||
self.browser.fill('building_parapet_height', '5')
|
||||
self.browser.fill('max_system_pressure', '10')
|
||||
self.browser.fill('system_type', SystemType.dualTilt.value)
|
||||
self.browser.fill('anchor_type', AnchorType.OMG_PowerGrip_Plus.value)
|
||||
self.browser.fill('design_spectral_response', '1.5')
|
||||
|
||||
self.advance_n_times(1)
|
||||
self.attach_file('test/fixtures/input_dual_tilt_coordinates.csv')
|
||||
|
||||
self.advance_n_times(1)
|
||||
self.browser.visit('/download/')
|
||||
self.browser.click_link_by_partial_text('Download AutoCAD import file')
|
||||
eq_(self.browser.html, csv_content)
|
||||
eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')
|
||||
|
||||
# def test_uploading_dxf_and_downloading_csv(self):
|
||||
# self.browser.fill('project_name', 'Test Project Name')
|
||||
# self.browser.fill('building_width', '100')
|
||||
# self.browser.fill('building_height', '30')
|
||||
# self.browser.fill('building_length', '100')
|
||||
# self.browser.fill('building_parapet_height', '5')
|
||||
# self.browser.fill('wind_speed', '130')
|
||||
# self.browser.fill('exposure_category', 'C')
|
||||
# self.browser.fill('ballast_block_weight', '14')
|
||||
# self.browser.fill('max_system_pressure', '12')
|
||||
# self.browser.fill('system_type', SystemType.dualTilt.value)
|
||||
# self.browser.fill('anchor_type', AnchorType.OMG_PowerGrip_Plus.value)
|
||||
# self.browser.fill('design_spectral_response', '0.5')
|
||||
#
|
||||
# self.advance_n_times(1)
|
||||
# self.attach_dxf('test/fixtures/dxf/input_dual_tilt_96_cell.dxf')
|
||||
#
|
||||
# self.advance_n_times(1)
|
||||
# self.browser.visit('/download/')
|
||||
# self.browser.click_link_by_partial_text('Download AutoCAD import file')
|
||||
# assert self.browser.html != ''
|
||||
# eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')
|
||||
|
||||
def test_downloading_documentation(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
|
||||
self.advance_n_times(1)
|
||||
self.attach_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
self.advance_n_times(3)
|
||||
os.environ['SP_DOCGEN_API_KEY'] = 'DC97-20AF-567E'
|
||||
self.browser.click_link_by_partial_text('Download Project Report')
|
||||
os.environ['SP_DOCGEN_API_KEY'] = ''
|
||||
|
||||
# with open('test/fixtures/expected_single_tilt_documentation.pdf', 'r', newline='') as pdf_file:
|
||||
# expected_doc = pdf_file.read()
|
||||
#
|
||||
# eq_(self.browser.html, expected_doc)
|
||||
eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_documentation.pdf')
|
||||
|
||||
def test_downloading_BOM_dual_tilt(self):
|
||||
assert len(self.browser.find_by_text('Download BOM')) == 0
|
||||
self.fill_in_site_characterization_data()
|
||||
self.browser.fill('system_type', SystemType.dualTilt.value)
|
||||
|
||||
self.advance_n_times(1)
|
||||
self.attach_file('test/fixtures/input_dual_tilt_csv_for_bom.csv')
|
||||
self.advance_n_times(3)
|
||||
|
||||
self.browser.click_link_by_partial_text('Download BOM')
|
||||
|
||||
with open('test/fixtures/expected_dual_tilt_bom.csv', 'r', newline='') as csv_file:
|
||||
expected_bom = csv_file.read()
|
||||
|
||||
eq_(self.browser.html, expected_bom)
|
||||
eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_bom.txt')
|
||||
|
||||
def test_downloading_BOM_single_tilt(self):
|
||||
assert len(self.browser.find_by_text('Download BOM')) == 0
|
||||
self.fill_in_site_characterization_data()
|
||||
self.advance_n_times(1)
|
||||
self.attach_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
|
||||
self.advance_n_times(2)
|
||||
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name', count=1, inverter_count=3,
|
||||
inverters=[
|
||||
{
|
||||
'model': InverterType.SMA.MODEL_15KW,
|
||||
'strings': 3,
|
||||
'sunshade': True,
|
||||
'dc_switch': True
|
||||
},
|
||||
{
|
||||
'model': InverterType.SMA.MODEL_12KW,
|
||||
'sunshade': True,
|
||||
'dc_switch': True,
|
||||
'strings': 4
|
||||
},
|
||||
{
|
||||
'model': InverterType.SMA.MODEL_24KW,
|
||||
'sunshade': True,
|
||||
'dc_switch': True,
|
||||
'strings': 7
|
||||
}
|
||||
])
|
||||
submit_power_station_form(self.browser)
|
||||
first_power_station_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
|
||||
fill_in_power_station(self.browser, count=5, inverter_count=2,
|
||||
inverters=[
|
||||
{
|
||||
'model': InverterType.SMA.MODEL_24KW,
|
||||
'strings': 8,
|
||||
},
|
||||
{
|
||||
'model': InverterType.SMA.MODEL_12KW,
|
||||
'strings': 2
|
||||
}
|
||||
])
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
fill_in_standalone_inverter(self.browser, model=InverterType.SMA.MODEL_15KW, sunshade=True, dc_switch=True, strings=3)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser, model=InverterType.SMA.MODEL_15KW, sunshade=True, dc_switch=True, strings=3)
|
||||
self.browser.fill('attachment_point', first_power_station_id)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
self.advance_n_times(1)
|
||||
self.browser.click_link_by_partial_text('Download BOM')
|
||||
|
||||
with open('test/fixtures/expected_single_tilt_bom.csv', 'r', newline='') as csv_file:
|
||||
expected_bom = csv_file.read()
|
||||
|
||||
eq_(self.browser.html, expected_bom)
|
||||
eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_bom.txt')
|
||||
170
test/integration/integration_test_helpers.py
Normal file
170
test/integration/integration_test_helpers.py
Normal file
@@ -0,0 +1,170 @@
|
||||
from nose.tools import eq_
|
||||
|
||||
from helix.constants.inverter_brand import InverterBrand
|
||||
from helix.constants.inverter_type import InverterType
|
||||
|
||||
|
||||
def assert_step_is_active(browser, step_number, is_active=True):
|
||||
eq_(browser.find_by_css('.navigation_header #step_%d' % step_number).has_class('active'), is_active)
|
||||
|
||||
|
||||
def assert_step_is_completed(browser, step_number, is_completed=True):
|
||||
eq_(browser.find_by_css('.navigation_header #step_%d' % step_number).has_class('completed'), is_completed)
|
||||
|
||||
|
||||
def select_inverter_brand(browser, brand=None):
|
||||
if brand not in InverterBrand.all():
|
||||
raise ValueError('Brand must be a valid InverterBrand')
|
||||
browser.select('inverter_brand_id', str(brand))
|
||||
|
||||
|
||||
def submit_inverter_brand_form(browser):
|
||||
browser.find_by_css('#inverter_brand_form input[type=submit]').first.click()
|
||||
|
||||
|
||||
def fill_in_power_station(browser, name=None, count=None, run_length=None, inverter_count=None, inverters=()):
|
||||
if name is not None:
|
||||
browser.fill('power_station_description', str(name))
|
||||
if count is not None:
|
||||
browser.fill('power_station_quantity', str(count))
|
||||
if run_length is not None:
|
||||
browser.fill('ac_run_length', str(run_length))
|
||||
if inverter_count:
|
||||
browser.select('inverter_quantity', str(inverter_count))
|
||||
|
||||
for index, inverter in enumerate(inverters):
|
||||
prefix = 'inverter_%d-' % (index + 1)
|
||||
if inverter.get('model'):
|
||||
browser.select(prefix + 'model', str(inverter['model'].value))
|
||||
if inverter.get('strings'):
|
||||
browser.select(prefix + 'strings_per_inverter', str(inverter['strings']))
|
||||
if inverter.get('sunshade'):
|
||||
browser.check(prefix + 'sunshade')
|
||||
if inverter.get('dc_switch'):
|
||||
browser.check(prefix + 'dc_switch')
|
||||
|
||||
|
||||
def submit_power_station_form(browser):
|
||||
browser.find_by_value('Add').first.click()
|
||||
|
||||
|
||||
def show_power_station_form(browser):
|
||||
browser.find_by_css('#add_new_power_station').first.click()
|
||||
|
||||
|
||||
def assert_power_station_table_row(browser, row_number, name=None, models=None, strings=None, quantity=None):
|
||||
row = browser.find_by_css('.power_station_table tr:nth-child(%d)' % (row_number + 1)).first
|
||||
if name:
|
||||
eq_(row.find_by_css('td:nth-child(1)').first.text.strip(), name)
|
||||
|
||||
if models and strings:
|
||||
eq_(len(row.find_by_css('td:nth-child(2)').find_by_tag('p')), len(models))
|
||||
eq_(len(row.find_by_css('td:nth-child(3)').find_by_tag('p')), len(strings))
|
||||
for i in range(len(models)):
|
||||
eq_(row.find_by_css('td:nth-child(2)').find_by_tag('p')[i].text, models[i])
|
||||
eq_(row.find_by_css('td:nth-child(3)').find_by_tag('p')[i].text, strings[i])
|
||||
|
||||
if quantity:
|
||||
eq_(row.find_by_css('td:nth-child(4)').first.text, str(quantity))
|
||||
|
||||
|
||||
def edit_power_station(browser, row_number):
|
||||
browser.find_by_css('.power_station_table tr:nth-child(%d) i.icon-pencil' % (row_number + 1)).first.click()
|
||||
|
||||
|
||||
def assert_number_of_power_station_table_rows(browser, number_of_rows):
|
||||
eq_(len(browser.find_by_css('.power_station_table tr')), number_of_rows + 1)
|
||||
|
||||
|
||||
# Standalone Inverters
|
||||
|
||||
|
||||
def show_standalone_inverter_form(browser):
|
||||
browser.find_by_css('#add_standalone_inverter').first.click()
|
||||
|
||||
|
||||
def fill_in_standalone_inverter(browser, quantity=None, model=None, strings=None,
|
||||
sunshade=None, dc_switch=None, ac_run_length=None, splice_box=None):
|
||||
if quantity:
|
||||
browser.select('inverter-quantity', str(quantity))
|
||||
if model:
|
||||
browser.select('inverter-model', str(model.value))
|
||||
if strings:
|
||||
browser.select('inverter-strings_per_inverter', str(strings))
|
||||
if sunshade:
|
||||
browser.check('inverter-sunshade')
|
||||
if dc_switch:
|
||||
browser.check('inverter-dc_switch')
|
||||
if ac_run_length:
|
||||
browser.fill('standalone_ac_run_length', str(ac_run_length))
|
||||
if splice_box:
|
||||
browser.check('inverter-splice_box')
|
||||
|
||||
|
||||
def submit_standalone_inverter_form(browser):
|
||||
browser.find_by_css('#standalone_inverter_form input[type=submit]').first.click()
|
||||
|
||||
|
||||
def edit_standalone_inverter(browser, row_number):
|
||||
browser.find_by_css('.standalone_inverter_table tr:nth-child(%d) i.icon-pencil' % (row_number + 1)).first.click()
|
||||
|
||||
|
||||
def assert_number_of_standalone_inverter_table_rows(browser, number_of_rows):
|
||||
eq_(len(browser.find_by_css('.standalone_inverter_table tr')), number_of_rows + 1)
|
||||
|
||||
|
||||
def assert_standalone_inverter_row(browser, row_number, model=None, interconnect=None, strings=None, sunshade=None,
|
||||
dc_switch=None, splice_box=None):
|
||||
first_table_row = browser.find_by_css('.standalone_inverter_table tr:nth-child(%d)' % (row_number + 1)).first
|
||||
if model is not None:
|
||||
eq_(first_table_row.find_by_css('td:nth-child(1)').first.text, model.label)
|
||||
if interconnect is not None:
|
||||
eq_(first_table_row.find_by_css('td:nth-child(2)').first.text, interconnect)
|
||||
if strings is not None:
|
||||
eq_(first_table_row.find_by_css('td:nth-child(3)').first.text, str(strings))
|
||||
|
||||
if sunshade is not None:
|
||||
eq_(first_table_row.find_by_css('td:nth-child(5) i').has_class('hidden'), not sunshade)
|
||||
if dc_switch is not None:
|
||||
eq_(first_table_row.find_by_css('td:nth-child(4) i').has_class('hidden'), not dc_switch)
|
||||
if splice_box is not None:
|
||||
eq_(first_table_row.find_by_css('td:nth-child(3) i').has_class('hidden'), not splice_box)
|
||||
|
||||
|
||||
def assert_standalone_inverter_string_options(browser, expected_list):
|
||||
inverter_strings_field_options = browser.find_by_css('#inverter-strings_per_inverter option')
|
||||
inverter_strings_field_options_list = list(map(lambda x: x.html, inverter_strings_field_options))
|
||||
eq_(len(inverter_strings_field_options_list), len(expected_list))
|
||||
eq_(inverter_strings_field_options_list, expected_list)
|
||||
|
||||
|
||||
def show_supervisor_monitor_form(browser):
|
||||
browser.find_by_css("#add_supervisor_monitor").first.click()
|
||||
|
||||
|
||||
# PV Supervisor Monitoring
|
||||
|
||||
|
||||
def show_monitoring_form(browser):
|
||||
browser.find_by_css('#add_supervisor_monitor').first.click()
|
||||
|
||||
|
||||
def fill_in_monitoring_form(browser, power_source):
|
||||
browser.fill('power_source', power_source)
|
||||
|
||||
|
||||
def submit_monitoring_form(browser):
|
||||
browser.find_by_css('#supervisor_monitor_form input[type=submit]').first.click()
|
||||
|
||||
|
||||
def edit_supervisor_monitor(browser, row_number):
|
||||
browser.find_by_css('.supervisor_monitor_table tr:nth-child(%d) i.icon-pencil' % (row_number + 1)).first.click()
|
||||
|
||||
|
||||
def assert_number_of_supervisor_monitor_table_rows(browser, number_of_rows):
|
||||
eq_(len(browser.find_by_css('.supervisor_monitor_table tr')), number_of_rows + 1)
|
||||
|
||||
|
||||
def assert_supervisor_monitor_row(browser, row_number, power_source):
|
||||
table_row = browser.find_by_css('.supervisor_monitor_table tr:nth-child(%d)' % (row_number + 1)).first
|
||||
eq_(table_row.find_by_css('td:nth-child(1)').first.text, power_source)
|
||||
@@ -0,0 +1,503 @@
|
||||
from flask.ext.testing import LiveServerTestCase
|
||||
import mockredis
|
||||
from splinter import Browser
|
||||
|
||||
from helix import main
|
||||
from helix.constants import redis_constant
|
||||
from helix.constants import sql_constant
|
||||
from helix.constants.inverter_type import InverterType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.db.sql_manager import SQLManager
|
||||
from helix.models.sql.power_monitors import PowerMonitor
|
||||
from helix.models.sql.power_stations import PowerStation
|
||||
from helix.models.sql.standalone_inverters import StandaloneInverter
|
||||
from test.integration.integration_test_helpers import *
|
||||
from test.test_helpers import test_db_session, reset_db_session
|
||||
|
||||
|
||||
class PowerStationConfigurationDynamicFormTestCase(LiveServerTestCase):
|
||||
def create_app(self):
|
||||
redis_constant.redis_store = mockredis.mock_redis_client()
|
||||
sql_constant.sql_session_maker = lambda: SQLManager.get_sql_session_maker('postgres://pivotal:@localhost/test')
|
||||
|
||||
app = main.app
|
||||
app.config['TESTING'] = True
|
||||
app.config['LIVESERVER_PORT'] = 8943
|
||||
return app
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.test_db_session = test_db_session()
|
||||
cls.browser = Browser('phantomjs')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.test_db_session.close_all()
|
||||
cls.browser.quit()
|
||||
|
||||
def setUp(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.browser.visit(self.get_server_url() + '/power_station_configuration/')
|
||||
|
||||
def tearDown(self):
|
||||
reset_db_session(self.test_db_session)
|
||||
self.browser.cookies.delete()
|
||||
|
||||
def fill_in_site_characterization_data(self, system_type=SystemType.singleTilt):
|
||||
self.browser.visit(self.get_server_url() + '/site_characterization/')
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '200')
|
||||
self.browser.fill('building_height', '30')
|
||||
self.browser.fill('building_length', '75.5')
|
||||
self.browser.fill('wind_speed', '125')
|
||||
self.browser.fill('ballast_block_weight', '13')
|
||||
self.browser.fill('building_parapet_height', '0')
|
||||
self.browser.fill('max_system_pressure', '10')
|
||||
self.browser.fill('design_spectral_response', '1.02')
|
||||
self.browser.select('system_type', system_type.value)
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
def expect_power_station_input_field(self, name='Test Power Station Name', uuid=None, count=2, run_length=None,
|
||||
inverter_count=3):
|
||||
eq_(self.browser.find_by_name('power_station_description').first.value, name)
|
||||
if uuid:
|
||||
eq_(self.browser.find_by_name('power_station_id').first.value, uuid)
|
||||
eq_(self.browser.find_by_name('power_station_quantity').first.value, str(count))
|
||||
if run_length:
|
||||
eq_(self.browser.find_by_name('ac_run_length').first.value, str(run_length))
|
||||
|
||||
eq_(self.browser.find_by_name('inverter_quantity').first.value, str(inverter_count))
|
||||
|
||||
eq_(self.browser.find_by_name('inverter_1-model').first.value, str(InverterType.SMA.MODEL_15KW.value))
|
||||
eq_(self.browser.find_by_name('inverter_1-strings_per_inverter').first.value, '3')
|
||||
eq_(self.browser.find_by_name('inverter_1-sunshade').first.checked, False)
|
||||
eq_(self.browser.find_by_name('inverter_1-dc_switch').first.checked, False)
|
||||
|
||||
def test_switching_inverter_brand_removes_power_station_section(self):
|
||||
select_inverter_brand(self.browser, brand=InverterBrand.DELTA.value)
|
||||
assert self.browser.is_element_not_present_by_css('#add_new_power_station')
|
||||
assert self.browser.is_element_not_present_by_css('form[name=power_station_form]')
|
||||
|
||||
def test_switching_inverter_brand_shows_different_inverter_models(self):
|
||||
show_standalone_inverter_form(self.browser)
|
||||
eq_(len(self.browser.find_by_css('#inverter-model option')), 4)
|
||||
eq_(self.browser.find_by_name('inverter-model').first.value, str(InverterType.SMA.default_value()))
|
||||
|
||||
select_inverter_brand(self.browser, brand=InverterBrand.DELTA.value)
|
||||
|
||||
show_standalone_inverter_form(self.browser)
|
||||
eq_(len(self.browser.find_by_css('#inverter-model option')), 3)
|
||||
eq_(self.browser.find_by_name('inverter-model').first.value, str(InverterType.DELTA.default_value()))
|
||||
|
||||
def test_switching_inverter_brand_hides_attachment_point(self):
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name', count=1, inverter_count=3)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
attachment_point_options = self.browser.find_by_css('#attachment_point option')
|
||||
eq_(len(attachment_point_options), 2)
|
||||
attachment_options_as_list = list(map(lambda x: x.html, attachment_point_options))
|
||||
eq_(attachment_options_as_list, ['Switch Gear', 'Test Power Station Name'])
|
||||
|
||||
select_inverter_brand(self.browser, brand=InverterBrand.DELTA.value)
|
||||
|
||||
show_standalone_inverter_form(self.browser)
|
||||
|
||||
assert self.browser.is_element_not_present_by_css('#attachment_point')
|
||||
|
||||
def test_inverters_without_string_range_hides_string_select(self):
|
||||
show_standalone_inverter_form(self.browser)
|
||||
assert self.browser.is_element_visible_by_css('#inverter-strings_per_inverter_row')
|
||||
|
||||
select_inverter_brand(self.browser, brand=InverterBrand.DELTA.value)
|
||||
|
||||
show_standalone_inverter_form(self.browser)
|
||||
assert not self.browser.is_element_visible_by_css('#inverter-strings_per_inverter_row')
|
||||
|
||||
def test_inverter_input_is_based_on_number_selected(self):
|
||||
show_power_station_form(self.browser)
|
||||
|
||||
assert self.browser.is_text_present('Inverter 1')
|
||||
assert self.browser.is_text_present('Inverter 2')
|
||||
assert self.browser.is_text_present('Inverter 3')
|
||||
assert self.browser.is_text_present('Inverter 4')
|
||||
|
||||
self.browser.select('inverter_quantity', '2')
|
||||
assert self.browser.is_text_present('Inverter 1')
|
||||
assert self.browser.is_text_present('Inverter 2')
|
||||
assert not self.browser.is_text_present('Inverter 3')
|
||||
assert not self.browser.is_text_present('Inverter 4')
|
||||
|
||||
self.browser.select('inverter_quantity', '3')
|
||||
assert self.browser.is_text_present('Inverter 1')
|
||||
assert self.browser.is_text_present('Inverter 2')
|
||||
assert self.browser.is_text_present('Inverter 3')
|
||||
assert not self.browser.is_text_present('Inverter 4')
|
||||
|
||||
def test_data_deleted_when_switching_brand(self):
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name', count=1, inverter_count=3)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
show_standalone_inverter_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser, model=InverterType.SMA.MODEL_20KW)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
show_standalone_inverter_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser, model=InverterType.SMA.MODEL_15KW)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
show_monitoring_form(self.browser)
|
||||
submit_monitoring_form(self.browser)
|
||||
|
||||
select_inverter_brand(self.browser, brand=InverterBrand.DELTA.value)
|
||||
|
||||
assert_number_of_power_station_table_rows(self.browser, -1)
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, -1)
|
||||
assert_number_of_supervisor_monitor_table_rows(self.browser, -1)
|
||||
|
||||
def test_inverter_strings_options_same_for_all_inverter_capacity_options_single_tilt(self):
|
||||
show_power_station_form(self.browser)
|
||||
|
||||
inverter_strings_field = self.browser.find_by_name('inverter_1-strings_per_inverter').first
|
||||
inverter_strings_options = inverter_strings_field.find_by_css('option:enabled')
|
||||
|
||||
eq_(list(map(lambda x: x.value, inverter_strings_options)), ['2', '3', '4', '5', '6', '7', '8'])
|
||||
eq_(inverter_strings_field.value, '8')
|
||||
|
||||
string_counts = [4, 5, 6, 8]
|
||||
for idx, inverter_type in enumerate(InverterType.SMA.all()):
|
||||
self.browser.select('inverter_1-model', inverter_type.value)
|
||||
|
||||
inverter_strings_field = self.browser.find_by_name('inverter_1-strings_per_inverter').first
|
||||
eq_(inverter_strings_field.value, str(string_counts[idx]))
|
||||
|
||||
inverter_strings_options = inverter_strings_field.find_by_css('option:enabled')
|
||||
eq_(list(map(lambda x: x.value, inverter_strings_options)), ['2', '3', '4', '5', '6', '7', '8'])
|
||||
|
||||
def test_inverter_strings_options_same_for_all_inverter_capacity_options_dual_tilt(self):
|
||||
self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
self.browser.visit(self.get_server_url() + '/power_station_configuration/')
|
||||
show_power_station_form(self.browser)
|
||||
|
||||
inverter_strings_field = self.browser.find_by_name('inverter_1-strings_per_inverter').first
|
||||
inverter_strings_options = inverter_strings_field.find_by_css('option:enabled')
|
||||
|
||||
eq_(list(map(lambda x: x.value, inverter_strings_options)), ['2', '4', '6', '8'])
|
||||
eq_(inverter_strings_field.value, '8')
|
||||
|
||||
string_counts = [4, 4, 6, 8]
|
||||
for idx, inverter_type in enumerate(InverterType.SMA.all()):
|
||||
self.browser.select('inverter_1-model', inverter_type.value)
|
||||
|
||||
inverter_strings_field = self.browser.find_by_name('inverter_1-strings_per_inverter').first
|
||||
eq_(inverter_strings_field.value, str(string_counts[idx]))
|
||||
|
||||
inverter_strings_options = inverter_strings_field.find_by_css('option:enabled')
|
||||
eq_(list(map(lambda x: x.value, inverter_strings_options)), ['2', '4', '6', '8'])
|
||||
|
||||
def test_add_power_station_button_shows_power_station_input_form(self):
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name', count=2)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
assert not self.browser.find_by_css('#power_station_form').first.visible
|
||||
assert not self.browser.find_by_css('#add_new_power_station').first.has_class('disabled')
|
||||
show_power_station_form(self.browser)
|
||||
assert self.browser.find_by_css('#power_station_form').first.visible
|
||||
assert self.browser.find_by_css('#add_new_power_station').first.has_class('disabled')
|
||||
|
||||
def test_editing_power_stations(self):
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser,
|
||||
name='Test Power Station Name',
|
||||
count=2,
|
||||
run_length=102,
|
||||
inverter_count=3,
|
||||
inverters=[
|
||||
{
|
||||
'model': InverterType.SMA.MODEL_15KW,
|
||||
'strings': 3,
|
||||
}
|
||||
])
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
saved_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser,
|
||||
count=3,
|
||||
inverter_count=2,
|
||||
inverters=[{'model': InverterType.SMA.MODEL_20KW}])
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
edit_power_station(self.browser, 1)
|
||||
|
||||
assert self.browser.find_by_css('#power_station_form').first.visible
|
||||
eq_(self.browser.find_by_name('power_station_description').first.value, 'Test Power Station Name')
|
||||
eq_(self.browser.find_by_name('power_station_id').first.value, saved_id)
|
||||
eq_(self.browser.find_by_name('power_station_quantity').first.value, '2')
|
||||
eq_(self.browser.find_by_name('ac_run_length').first.value, '102')
|
||||
eq_(self.browser.find_by_name('inverter_quantity').first.value, '3')
|
||||
assert self.browser.is_text_present('Inverter 3')
|
||||
eq_(self.browser.find_by_name('inverter_1-model').first.value, str(InverterType.SMA.MODEL_15KW.value))
|
||||
eq_(self.browser.find_by_name('inverter_1-strings_per_inverter').first.value, '3')
|
||||
eq_(self.browser.find_by_name('inverter_1-sunshade').first.checked, False)
|
||||
eq_(self.browser.find_by_name('inverter_1-dc_switch').first.checked, False)
|
||||
|
||||
fill_in_power_station(self.browser, name='Extra Special Power Station', inverter_count=4,
|
||||
inverters=[{'model': InverterType.SMA.MODEL_12KW}])
|
||||
self.browser.find_by_value('Save').first.click()
|
||||
|
||||
assert_number_of_power_station_table_rows(self.browser, 2)
|
||||
|
||||
models = ['12kW SMA Tripower - 514686', '24kW SMA Tripower - 514685', '24kW SMA Tripower - 514685', '24kW SMA Tripower - 514685']
|
||||
strings = ['4', '8', '8', '8']
|
||||
assert_power_station_table_row(self.browser, 1,
|
||||
name='Extra Special Power Station',
|
||||
models=models,
|
||||
strings=strings,
|
||||
quantity=2)
|
||||
|
||||
def test_editing_power_station_styles_current_row_as_selected(self):
|
||||
show_power_station_form(self.browser)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
show_power_station_form(self.browser)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
edit_power_station(self.browser, 1)
|
||||
assert self.browser.find_by_css('.power_station_table tr:nth-child(2)').has_class('selected')
|
||||
assert not self.browser.find_by_css('.power_station_table tr:nth-child(3)').has_class('selected')
|
||||
|
||||
edit_power_station(self.browser, 2)
|
||||
assert not self.browser.find_by_css('.power_station_table tr:nth-child(2)').has_class('selected')
|
||||
assert self.browser.find_by_css('.power_station_table tr:nth-child(3)').has_class('selected')
|
||||
|
||||
def test_cancelling_editing_power_stations(self):
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name')
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
saved_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
|
||||
edit_power_station(self.browser, 1)
|
||||
|
||||
fill_in_power_station(self.browser, name='Extra Special Power Station')
|
||||
self.browser.click_link_by_text('Cancel')
|
||||
|
||||
assert not self.browser.find_by_css('#power_station_form').first.visible
|
||||
assert not self.browser.find_by_name('power_station_id').first.value == saved_id
|
||||
eq_(self.browser.find_by_name('power_station_description').first.value, 'Power Station 2')
|
||||
|
||||
assert_number_of_power_station_table_rows(self.browser, 1)
|
||||
assert_power_station_table_row(self.browser, 1, name='Test Power Station Name')
|
||||
|
||||
def test_deleting_power_station_from_edit_position(self):
|
||||
show_power_station_form(self.browser)
|
||||
assert not self.browser.is_text_present('Delete')
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
errors = self.browser.find_by_css('.error_message')
|
||||
assert len(errors) == 0, "expected no errors, got %s errors" % str([error.value for error in errors])
|
||||
assert_number_of_power_station_table_rows(self.browser, 1)
|
||||
|
||||
edit_power_station(self.browser, 1)
|
||||
|
||||
assert self.browser.is_text_present('Delete')
|
||||
self.browser.click_link_by_text('Delete')
|
||||
|
||||
eq_(len(self.browser.find_by_css('.power_station_table')), 0)
|
||||
|
||||
def test_able_to_toggle_between_adding_standalone_inverter_and_power_station_and_monitoring(self):
|
||||
assert not self.browser.find_by_css('#add_standalone_inverter').first.has_class('disabled')
|
||||
show_standalone_inverter_form(self.browser)
|
||||
assert self.browser.find_by_css('#add_standalone_inverter').first.has_class('disabled')
|
||||
assert not self.browser.find_by_css('#add_new_power_station').first.has_class('disabled')
|
||||
assert not self.browser.find_by_css('#add_supervisor_monitor').first.has_class('disabled')
|
||||
assert not self.browser.is_text_present('Power Station Description')
|
||||
assert not self.browser.is_text_present('Power Source')
|
||||
assert self.browser.is_text_present('Attachment Point')
|
||||
|
||||
show_power_station_form(self.browser)
|
||||
assert not self.browser.find_by_css('#add_standalone_inverter').first.has_class('disabled')
|
||||
assert not self.browser.find_by_css('#add_supervisor_monitor').first.has_class('disabled')
|
||||
assert self.browser.find_by_css('#add_new_power_station').first.has_class('disabled')
|
||||
assert self.browser.is_text_present('Power Station Description')
|
||||
assert not self.browser.is_text_present('Power Source')
|
||||
assert not self.browser.is_text_present('Attachment Point')
|
||||
|
||||
show_monitoring_form(self.browser)
|
||||
assert self.browser.find_by_css('#add_supervisor_monitor').first.has_class('disabled')
|
||||
assert not self.browser.find_by_css('#add_standalone_inverter').first.has_class('disabled')
|
||||
assert not self.browser.find_by_css('#add_standalone_inverter').first.has_class('disabled')
|
||||
assert not self.browser.is_text_present('Power Station Description')
|
||||
assert not self.browser.is_text_present('Attachment Point')
|
||||
assert self.browser.is_text_present('Power Source')
|
||||
|
||||
def test_adding_stand_alone_inverter(self):
|
||||
show_standalone_inverter_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser, model=InverterType.SMA.MODEL_20KW)
|
||||
eq_(self.browser.find_by_name('inverter-strings_per_inverter').first.value, '6')
|
||||
attachment_point_field = self.browser.find_by_name('attachment_point').first
|
||||
attachment_point_options = attachment_point_field.find_by_css('option')
|
||||
eq_(len(attachment_point_options), 1)
|
||||
|
||||
def test_adding_stand_alone_inverter_shows_quantity(self):
|
||||
show_standalone_inverter_form(self.browser)
|
||||
assert self.browser.is_element_visible_by_css('#inverter-quantity')
|
||||
|
||||
def test_editing_stand_alone_inverter_hides_quantity(self):
|
||||
show_standalone_inverter_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
edit_standalone_inverter(self.browser, 1)
|
||||
assert self.browser.is_element_not_visible_by_css('#inverter-quantity')
|
||||
|
||||
def test_adding_stand_alone_inverter_allows_previously_added_power_stations_as_attachment_points(self):
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name', count=1, inverter_count=4)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name 2', count=1, inverter_count=3)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
show_standalone_inverter_form(self.browser)
|
||||
attachment_point_field = self.browser.find_by_name('attachment_point').first
|
||||
attachment_point_options = attachment_point_field.find_by_css('option')
|
||||
eq_(len(attachment_point_options), 2)
|
||||
eq_(attachment_point_options.first.text, 'Switch Gear')
|
||||
eq_(attachment_point_options.last.text, 'Test Power Station Name 2')
|
||||
|
||||
def test_editing_sma_standalone_inverters(self):
|
||||
show_standalone_inverter_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser, model=InverterType.SMA.MODEL_12KW, strings=3, dc_switch=True, ac_run_length=453)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 1)
|
||||
saved_id = str(self.test_db_session.query(StandaloneInverter).first().id)
|
||||
|
||||
show_standalone_inverter_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser, sunshade=True)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 2)
|
||||
|
||||
edit_standalone_inverter(self.browser, 1)
|
||||
assert self.browser.find_by_css('#standalone_inverter_form').first.visible
|
||||
eq_(self.browser.find_by_name('standalone_inverter_id').first.value, saved_id)
|
||||
eq_(self.browser.find_by_name('standalone_ac_run_length').first.value, '453')
|
||||
eq_(self.browser.find_by_name('inverter-model').first.value, str(InverterType.SMA.MODEL_12KW.value))
|
||||
eq_(self.browser.find_by_name('inverter-strings_per_inverter').first.value, '3')
|
||||
eq_(self.browser.find_by_name('inverter-sunshade').first.checked, False)
|
||||
eq_(self.browser.find_by_name('inverter-dc_switch').first.checked, True)
|
||||
|
||||
self.browser.check('inverter-sunshade')
|
||||
self.browser.select('inverter-model', InverterType.SMA.MODEL_15KW.value)
|
||||
self.browser.find_by_value('Save').first.click()
|
||||
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 2)
|
||||
assert_standalone_inverter_row(self.browser, 1,
|
||||
model=InverterType.SMA.MODEL_15KW,
|
||||
interconnect='Switch Gear',
|
||||
strings=5,
|
||||
sunshade=True,
|
||||
dc_switch=True)
|
||||
|
||||
def test_editing_delta_standalone_inverters(self):
|
||||
select_inverter_brand(self.browser, brand=InverterBrand.DELTA.value)
|
||||
|
||||
show_standalone_inverter_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser, model=InverterType.DELTA.MODEL_36KW, ac_run_length=453)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
assert_standalone_inverter_row(self.browser, 1,
|
||||
model=InverterType.DELTA.MODEL_36KW,
|
||||
interconnect='Switch Gear',
|
||||
splice_box=True)
|
||||
|
||||
saved_id = str(self.test_db_session.query(StandaloneInverter).first().id)
|
||||
|
||||
show_standalone_inverter_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser, model=InverterType.DELTA.MODEL_60KW, splice_box=False)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 2)
|
||||
|
||||
edit_standalone_inverter(self.browser, 1)
|
||||
assert self.browser.find_by_css('#standalone_inverter_form').first.visible
|
||||
eq_(self.browser.find_by_name('standalone_inverter_id').first.value, saved_id)
|
||||
eq_(self.browser.find_by_name('standalone_ac_run_length').first.value, '453')
|
||||
eq_(self.browser.find_by_name('inverter-model').first.value, str(InverterType.DELTA.MODEL_36KW.value))
|
||||
eq_(self.browser.find_by_name('inverter-splice_box').first.checked, True)
|
||||
|
||||
self.browser.uncheck('inverter-splice_box')
|
||||
self.browser.find_by_value('Save').first.click()
|
||||
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 2)
|
||||
assert_standalone_inverter_row(self.browser, 1,
|
||||
model=InverterType.DELTA.MODEL_36KW,
|
||||
interconnect='Switch Gear',
|
||||
splice_box=False)
|
||||
|
||||
def test_delta_standalone_inverters_defaults_with_splice_box(self):
|
||||
pass
|
||||
|
||||
def test_deleting_standalone_inverters_from_edit(self):
|
||||
show_standalone_inverter_form(self.browser)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
edit_standalone_inverter(self.browser, 1)
|
||||
self.browser.is_text_present('Delete')
|
||||
self.browser.click_link_by_partial_href('delete_standalone_inverter')
|
||||
|
||||
eq_(len(self.browser.find_by_css('.standalone_inverter_table')), 0)
|
||||
|
||||
def test_editing_power_monitors(self):
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name', count=1, inverter_count=4)
|
||||
submit_power_station_form(self.browser)
|
||||
power_station_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
|
||||
show_monitoring_form(self.browser)
|
||||
self.browser.select('power_source', power_station_id)
|
||||
submit_monitoring_form(self.browser)
|
||||
saved_id = str(self.test_db_session.query(PowerMonitor).first().id)
|
||||
|
||||
show_monitoring_form(self.browser)
|
||||
submit_monitoring_form(self.browser)
|
||||
|
||||
assert_supervisor_monitor_row(self.browser, 1, 'Test Power Station Name')
|
||||
edit_supervisor_monitor(self.browser, 1)
|
||||
assert self.browser.find_by_css('#supervisor_monitor_form').first.visible
|
||||
eq_(self.browser.find_by_name('power_source').first.value, power_station_id)
|
||||
eq_(self.browser.find_by_css('#supervisor_monitor_form #monitor_id').first.value, saved_id)
|
||||
self.browser.find_by_value('Save').first.click()
|
||||
|
||||
assert_number_of_supervisor_monitor_table_rows(self.browser, 2)
|
||||
assert_supervisor_monitor_row(self.browser, 1, 'Test Power Station Name')
|
||||
|
||||
def test_editing_power_station_after_assigning_supervisor_monitor(self):
|
||||
show_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name', count=1, inverter_count=4)
|
||||
submit_power_station_form(self.browser)
|
||||
power_station_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
|
||||
show_monitoring_form(self.browser)
|
||||
self.browser.select('power_source', power_station_id)
|
||||
submit_monitoring_form(self.browser)
|
||||
|
||||
edit_power_station(self.browser, 1)
|
||||
self.browser.find_by_value('Save').first.click()
|
||||
|
||||
row = self.browser.find_by_css('.power_station_table tr:nth-child(2) td:nth-child(1)').first
|
||||
assert "Monitoring" in row.text
|
||||
|
||||
def test_deleting_power_monitors_from_edit(self):
|
||||
show_monitoring_form(self.browser)
|
||||
submit_monitoring_form(self.browser)
|
||||
|
||||
edit_supervisor_monitor(self.browser, 1)
|
||||
self.browser.is_text_present('Delete')
|
||||
self.browser.click_link_by_partial_href('delete_supervisor_monitor')
|
||||
|
||||
eq_(len(self.browser.find_by_css('.supervisor_monitor_table')), 0)
|
||||
313
test/integration/power_station_configuration_test.py
Normal file
313
test/integration/power_station_configuration_test.py
Normal file
@@ -0,0 +1,313 @@
|
||||
import unittest
|
||||
|
||||
import mockredis
|
||||
from splinter import Browser
|
||||
|
||||
from helix import main
|
||||
from helix.constants import redis_constant
|
||||
from helix.constants import sql_constant
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.inverter_type import InverterType
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.models.sql.power_stations import PowerStation
|
||||
from test.integration.integration_test_helpers import *
|
||||
from test.test_helpers import assert_error, test_db_session, assert_no_error, \
|
||||
reset_db_session
|
||||
|
||||
|
||||
class PowerStationConfigurationTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.test_db_session = test_db_session()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.test_db_session.close_all()
|
||||
|
||||
def setUp(self):
|
||||
redis_constant.redis_store = mockredis.mock_redis_client()
|
||||
sql_constant.sql_session_maker = lambda: self.test_db_session
|
||||
|
||||
self.app = main.app.test_client()
|
||||
self.browser = Browser('flask', app=main.app)
|
||||
self.fill_in_site_characterization_data()
|
||||
self.browser.visit('/power_station_configuration/')
|
||||
|
||||
def tearDown(self):
|
||||
reset_db_session(self.test_db_session)
|
||||
|
||||
def fill_in_site_characterization_data(self,
|
||||
system_type=SystemType.singleTilt,
|
||||
module_type=ModuleType.Cell96):
|
||||
self.browser.visit('/site_characterization/')
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '200')
|
||||
self.browser.fill('building_height', '30')
|
||||
self.browser.fill('building_length', '75.5')
|
||||
self.browser.fill('wind_speed', '125')
|
||||
self.browser.fill('exposure_category', 'C')
|
||||
self.browser.fill('ballast_block_weight', '13')
|
||||
self.browser.fill('building_parapet_height', '0')
|
||||
self.browser.fill('max_system_pressure', '10')
|
||||
self.browser.fill('system_type', system_type.value)
|
||||
self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
|
||||
self.browser.fill('module_type', module_type.value)
|
||||
self.browser.fill('design_spectral_response', '1.02')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
self.browser.visit('/power_station_configuration/')
|
||||
|
||||
def test_entering_power_station_data_shows_entered_values_in_table(self):
|
||||
fill_in_power_station(self.browser, name='Test Power Station Name', inverter_count=3, inverters=[
|
||||
{
|
||||
'model': InverterType.SMA.MODEL_15KW,
|
||||
'strings': '3',
|
||||
},
|
||||
{
|
||||
'model': InverterType.SMA.MODEL_12KW,
|
||||
'strings': '4',
|
||||
},
|
||||
{
|
||||
'model': InverterType.SMA.MODEL_24KW,
|
||||
'strings': '7',
|
||||
}
|
||||
])
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
assert_number_of_power_station_table_rows(self.browser, 1)
|
||||
models = ['15kW SMA Tripower - 514687', '12kW SMA Tripower - 514686', '24kW SMA Tripower - 514685']
|
||||
strings = ['3', '4', '7']
|
||||
assert_power_station_table_row(self.browser, 1, name='Test Power Station Name', models=models, strings=strings,
|
||||
quantity=1)
|
||||
|
||||
eq_(self.browser.find_by_name('power_station_description').first.value, 'Power Station 2')
|
||||
|
||||
def test_clicking_back_goes_to_summary_table(self):
|
||||
self.browser.click_link_by_partial_text('Back')
|
||||
assert_step_is_active(self.browser, 3)
|
||||
|
||||
def test_all_power_station_values_are_required(self):
|
||||
fill_in_power_station(self.browser, name='', count='', run_length='')
|
||||
submit_power_station_form(self.browser)
|
||||
assert_error(self.browser, 'power_station_description', 'Power Station Description is required.')
|
||||
assert_error(self.browser, 'power_station_quantity', 'Not a valid integer value')
|
||||
assert_error(self.browser, 'ac_run_length', 'Not a valid integer value')
|
||||
eq_(len(self.browser.find_by_css('#power_station_form.hidden')), 0)
|
||||
|
||||
def test_ac_run_length_must_be_non_negative(self):
|
||||
fill_in_power_station(self.browser, run_length=-5)
|
||||
submit_power_station_form(self.browser)
|
||||
assert_error(self.browser, 'ac_run_length', 'Number must be at least 0.')
|
||||
eq_(len(self.browser.find_by_css('#power_station_form.hidden')), 0)
|
||||
|
||||
def test_ac_run_length_defaults_to_zero(self):
|
||||
eq_(self.browser.find_by_name('ac_run_length').first.value, '0')
|
||||
|
||||
def test_power_station_quantity_must_be_non_negative(self):
|
||||
fill_in_power_station(self.browser, count=-2)
|
||||
submit_power_station_form(self.browser)
|
||||
assert_error(self.browser, 'power_station_quantity', 'Number must be at least 0.')
|
||||
eq_(len(self.browser.find_by_css('#power_station_form.hidden')), 0)
|
||||
|
||||
def test_power_station_description_defaults_to_power_station_1(self):
|
||||
eq_(self.browser.find_by_name('power_station_description').first.value, 'Power Station 1')
|
||||
|
||||
def test_default_inverter_type_is_24kW(self):
|
||||
eq_(self.browser.find_by_name('inverter_1-model').first.value, str(InverterType.SMA.MODEL_24KW.value))
|
||||
eq_(self.browser.find_by_name('inverter_2-model').first.value, str(InverterType.SMA.MODEL_24KW.value))
|
||||
eq_(self.browser.find_by_name('inverter_3-model').first.value, str(InverterType.SMA.MODEL_24KW.value))
|
||||
eq_(self.browser.find_by_name('inverter_4-model').first.value, str(InverterType.SMA.MODEL_24KW.value))
|
||||
|
||||
def test_clicking_trash_can_deletes_power_station(self):
|
||||
fill_in_power_station(self.browser, name='Fake PS ONE')
|
||||
submit_power_station_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Fake PS TWO')
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
assert_number_of_power_station_table_rows(self.browser, 2)
|
||||
|
||||
self.browser.click_link_by_partial_href('delete_power_station')
|
||||
|
||||
assert_number_of_power_station_table_rows(self.browser, 1)
|
||||
|
||||
assert not self.browser.is_text_present('Fake PS ONE')
|
||||
assert self.browser.is_text_present('Fake PS TWO')
|
||||
|
||||
self.browser.click_link_by_partial_href('delete_power_station')
|
||||
eq_(len(self.browser.find_by_css('.power_station_table')), 0)
|
||||
|
||||
def test_standalone_inverter_form_does_not_show_power_stations_with_more_than_one_in_group(self):
|
||||
fill_in_power_station(self.browser, name='Fake PS ONE', inverter_count=3, count=1)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Fake PS TWO', inverter_count=3, count=2)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
attachment_point_options = self.browser.find_by_css('#attachment_point option')
|
||||
eq_(len(attachment_point_options), 2)
|
||||
attachment_options_as_list = list(map(lambda x: x.text, attachment_point_options))
|
||||
eq_(attachment_options_as_list, ['Switch Gear', 'Fake PS ONE'])
|
||||
|
||||
def test_standalone_inverter_form_only_shows_power_stations_with_open_spots(self):
|
||||
fill_in_power_station(self.browser, name='Fake PS ONE', inverter_count=2, count=1)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
fill_in_power_station(self.browser, name='Fake PS TWO', inverter_count=4, count=1)
|
||||
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
attachment_point_options = self.browser.find_by_css('#attachment_point option')
|
||||
eq_(len(attachment_point_options), 2)
|
||||
attachment_options_as_list = list(map(lambda x: x.text, attachment_point_options))
|
||||
eq_(attachment_options_as_list, ['Switch Gear', 'Fake PS ONE'])
|
||||
|
||||
power_station_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
self.browser.fill('attachment_point', power_station_id)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
attachment_point_options = self.browser.find_by_css('#attachment_point option')
|
||||
eq_(len(attachment_point_options), 2)
|
||||
attachment_options_as_list = list(map(lambda x: x.text, attachment_point_options))
|
||||
eq_(attachment_options_as_list, ['Switch Gear', 'Fake PS ONE'])
|
||||
|
||||
self.browser.fill('attachment_point', power_station_id)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
attachment_point_options = self.browser.find_by_css('#attachment_point option')
|
||||
eq_(len(attachment_point_options), 1)
|
||||
attachment_options_as_list = list(map(lambda x: x.text, attachment_point_options))
|
||||
eq_(attachment_options_as_list, ['Switch Gear'])
|
||||
|
||||
def test_standalone_inverter_quantity_creates_multiple_inverters(self):
|
||||
fill_in_standalone_inverter(self.browser, quantity=5, model=InverterType.SMA.MODEL_15KW, strings=3, sunshade=True, dc_switch=True)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 5)
|
||||
|
||||
assert_standalone_inverter_row(self.browser, 1, model=InverterType.SMA.MODEL_15KW, strings=3, sunshade=True, dc_switch=True)
|
||||
assert_standalone_inverter_row(self.browser, 2, model=InverterType.SMA.MODEL_15KW, strings=3, sunshade=True, dc_switch=True)
|
||||
assert_standalone_inverter_row(self.browser, 3, model=InverterType.SMA.MODEL_15KW, strings=3, sunshade=True, dc_switch=True)
|
||||
assert_standalone_inverter_row(self.browser, 4, model=InverterType.SMA.MODEL_15KW, strings=3, sunshade=True, dc_switch=True)
|
||||
assert_standalone_inverter_row(self.browser, 5, model=InverterType.SMA.MODEL_15KW, strings=3, sunshade=True, dc_switch=True)
|
||||
|
||||
def test_entering_standalone_inverter_data_shows_entered_values_in_table_and_hides_form(self):
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
fill_in_power_station(self.browser, name='Fake PS ONE', inverter_count=3)
|
||||
submit_power_station_form(self.browser)
|
||||
fill_in_standalone_inverter(self.browser, model=InverterType.SMA.MODEL_15KW, strings=3, sunshade=True, dc_switch=True)
|
||||
power_station_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
self.browser.fill('attachment_point', power_station_id)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 2)
|
||||
assert_standalone_inverter_row(self.browser, 1,
|
||||
model=InverterType.SMA.MODEL_24KW,
|
||||
interconnect='Switch Gear',
|
||||
strings=8,
|
||||
dc_switch=False,
|
||||
sunshade=False)
|
||||
|
||||
assert_standalone_inverter_row(self.browser, 2,
|
||||
model=InverterType.SMA.MODEL_15KW,
|
||||
interconnect='Fake PS ONE',
|
||||
strings=3,
|
||||
dc_switch=True,
|
||||
sunshade=True)
|
||||
|
||||
assert len(self.browser.find_by_css('#standalone_inverter_form.hidden')) == 1
|
||||
|
||||
def test_standalone_inverter_ac_run_length_must_be_non_negative(self):
|
||||
fill_in_standalone_inverter(self.browser, ac_run_length=-5)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
assert_error(self.browser, 'standalone_ac_run_length', 'Number must be at least 0.')
|
||||
eq_(len(self.browser.find_by_css('#standalone_inverter_form.hidden')), 0)
|
||||
|
||||
def test_standalone_inverter_ac_run_length_defaults_to_zero(self):
|
||||
eq_(self.browser.find_by_name('standalone_ac_run_length').first.value, '0')
|
||||
|
||||
def test_clicking_trash_can_deletes_standalone_inverter(self):
|
||||
eq_(len(self.browser.find_by_css('.standalone_inverter_table')), 0)
|
||||
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
assert_no_error(self.browser, 'attachment_point')
|
||||
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 1)
|
||||
|
||||
fill_in_power_station(self.browser, name='Fake PS ONE', count=1, inverter_count=3)
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
power_station_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
|
||||
self.browser.fill('attachment_point', power_station_id)
|
||||
submit_standalone_inverter_form(self.browser)
|
||||
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 2)
|
||||
|
||||
self.browser.click_link_by_partial_href('delete_standalone_inverter')
|
||||
|
||||
assert_number_of_standalone_inverter_table_rows(self.browser, 1)
|
||||
|
||||
assert_standalone_inverter_row(self.browser, 1, interconnect='Fake PS ONE')
|
||||
|
||||
self.browser.click_link_by_partial_href('delete_standalone_inverter')
|
||||
eq_(len(self.browser.find_by_css('.standalone_inverter_table')), 0)
|
||||
|
||||
def test_supervisor_monitoring_form_does_not_show_power_stations_that_already_have_monitoring(self):
|
||||
fill_in_power_station(self.browser, name='Fake PS One')
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
power_source_options = self.browser.find_by_css('#power_source option')
|
||||
eq_(len(power_source_options), 2)
|
||||
power_source_options_as_list = list(map(lambda x: x.text, power_source_options))
|
||||
eq_(power_source_options_as_list, ['Switch Gear/External', 'Fake PS One'])
|
||||
|
||||
power_station_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
fill_in_monitoring_form(self.browser, power_station_id)
|
||||
submit_monitoring_form(self.browser)
|
||||
|
||||
power_source_options = self.browser.find_by_css('#power_source option')
|
||||
eq_(len(power_source_options), 1)
|
||||
power_source_options_as_list = list(map(lambda x: x.text, power_source_options))
|
||||
eq_(power_source_options_as_list, ['Switch Gear/External'])
|
||||
|
||||
def test_adding_supervisor_monitoring_to_power_station_shows_monitoring_label_on_power_station_table(self):
|
||||
fill_in_power_station(self.browser, name='Fake PS One')
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
power_station_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
|
||||
fill_in_monitoring_form(self.browser, power_station_id)
|
||||
submit_monitoring_form(self.browser)
|
||||
|
||||
row = self.browser.find_by_css('.power_station_table tr:nth-child(2) td:nth-child(1)').first
|
||||
assert "Monitoring" in row.text, "Expected \n'%s'\n to contain 'Monitoring'" % row.text
|
||||
|
||||
def test_entering_supervisor_monitoring_data_shows_entered_values_in_table_and_hides_form(self):
|
||||
fill_in_monitoring_form(self.browser, 'switch_gear')
|
||||
submit_monitoring_form(self.browser)
|
||||
assert_number_of_supervisor_monitor_table_rows(self.browser, 1)
|
||||
assert_supervisor_monitor_row(self.browser, 1, 'Switch Gear/External')
|
||||
eq_(len(self.browser.find_by_css('#supervisor_monitor_form.hidden')), 1)
|
||||
|
||||
def test_clicking_trash_can_deletes_supervisor_monitor(self):
|
||||
fill_in_monitoring_form(self.browser, 'switch_gear')
|
||||
submit_monitoring_form(self.browser)
|
||||
|
||||
fill_in_power_station(self.browser, name='Fake PS ONE')
|
||||
submit_power_station_form(self.browser)
|
||||
|
||||
power_station_id = str(self.test_db_session.query(PowerStation).first().id)
|
||||
fill_in_monitoring_form(self.browser, power_station_id)
|
||||
submit_monitoring_form(self.browser)
|
||||
|
||||
assert_number_of_supervisor_monitor_table_rows(self.browser, 2)
|
||||
self.browser.click_link_by_partial_href('delete_supervisor_monitor')
|
||||
|
||||
assert_number_of_supervisor_monitor_table_rows(self.browser, 1)
|
||||
|
||||
assert_supervisor_monitor_row(self.browser, 1, 'Fake PS ONE')
|
||||
|
||||
self.browser.click_link_by_partial_href('delete_supervisor_monitor')
|
||||
eq_(len(self.browser.find_by_css('.supervisor_monitor_table')), 0)
|
||||
58
test/integration/site_characterization_dynamic_form_test.py
Normal file
58
test/integration/site_characterization_dynamic_form_test.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from flask.ext.testing import LiveServerTestCase
|
||||
import mockredis
|
||||
from splinter import Browser
|
||||
|
||||
from helix import main
|
||||
from helix.constants import redis_constant
|
||||
from helix.constants import sql_constant
|
||||
from helix.db.sql_manager import SQLManager
|
||||
from test.test_helpers import test_db_session, reset_db_session
|
||||
|
||||
|
||||
class SiteCharacterizationDynamicFormTestCase(LiveServerTestCase):
|
||||
def create_app(self):
|
||||
redis_constant.redis_store = mockredis.mock_redis_client()
|
||||
sql_constant.sql_session_maker = lambda: SQLManager.get_sql_session_maker('postgres://pivotal:@localhost/test')
|
||||
|
||||
app = main.app
|
||||
app.config['TESTING'] = True
|
||||
app.config['LIVESERVER_PORT'] = 8943
|
||||
return app
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.test_db_session = test_db_session()
|
||||
cls.browser = Browser('phantomjs')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.test_db_session.close_all()
|
||||
cls.browser.quit()
|
||||
|
||||
def setUp(self):
|
||||
self.browser.visit(self.get_server_url() + '/site_characterization/')
|
||||
|
||||
def tearDown(self):
|
||||
reset_db_session(self.test_db_session)
|
||||
self.browser.cookies.delete()
|
||||
|
||||
def test_selecting_exposure_B_to_C_shows_transition_distance(self):
|
||||
assert not self.browser.is_text_present("Exposure Transition Distance")
|
||||
self.browser.select('exposure_category', 'B to C')
|
||||
assert self.browser.is_text_present("Exposure Transition Distance")
|
||||
self.browser.select('exposure_category', 'D')
|
||||
assert not self.browser.is_text_present("Exposure Transition Distance")
|
||||
|
||||
def test_showing_and_hiding_tooltip_for_anchor_type(self):
|
||||
assert not self.browser.is_text_present('OMG anchors are compatible with TPO and PVC roof membranes.')
|
||||
self.browser.find_by_css('#anchor_type_row i.icon-info-circled').first.click()
|
||||
assert self.browser.is_text_present('OMG anchors are compatible with TPO and PVC roof membranes.')
|
||||
self.browser.find_by_css('body').first.click()
|
||||
assert not self.browser.is_text_present('OMG anchors are compatible with TPO and PVC roof membranes.')
|
||||
|
||||
def test_showing_and_hiding_tooltip_for_importance_factor(self):
|
||||
assert not self.browser.is_text_present('Use 1.5 for essential facilities such as: Hospitals, Police, Fire & Rescue stations & Designated emergency shelters. All other structures should use 1.0.')
|
||||
self.browser.find_by_css('#importance_factor_row i.icon-info-circled').first.click()
|
||||
assert self.browser.is_text_present('Use 1.5 for essential facilities such as: Hospitals, Police, Fire & Rescue stations & Designated emergency shelters. All other structures should use 1.0.')
|
||||
self.browser.find_by_css('body').first.click()
|
||||
assert not self.browser.is_text_present('Use 1.5 for essential facilities such as: Hospitals, Police, Fire & Rescue stations & Designated emergency shelters. All other structures should use 1.0.')
|
||||
229
test/integration/site_characterization_test.py
Normal file
229
test/integration/site_characterization_test.py
Normal file
@@ -0,0 +1,229 @@
|
||||
import unittest
|
||||
import mockredis
|
||||
from nose.tools import eq_
|
||||
from splinter import Browser
|
||||
from helix import main
|
||||
from helix.constants import redis_constant
|
||||
from helix.constants import sql_constant
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.models.sql.inverters import Inverter
|
||||
from helix.models.sql.power_monitors import PowerMonitor
|
||||
from helix.models.sql.power_stations import PowerStation
|
||||
from helix.models.sql.sites import Site
|
||||
from helix.models.sql.standalone_inverters import StandaloneInverter
|
||||
from helix.models.sql.users import User
|
||||
from test.test_helpers import assert_error, assert_no_error, test_db_session, reset_db_session
|
||||
|
||||
|
||||
class SiteCharacterizationTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.test_db_session = test_db_session()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.test_db_session.close_all()
|
||||
|
||||
def setUp(self):
|
||||
redis_constant.redis_store = mockredis.mock_redis_client()
|
||||
sql_constant.sql_session_maker = lambda: self.test_db_session
|
||||
self.app = main.app.test_client()
|
||||
self.browser = Browser('flask', app=main.app)
|
||||
self.browser.visit('/site_characterization')
|
||||
|
||||
def tearDown(self):
|
||||
self.test_db_session.rollback()
|
||||
reset_db_session(self.test_db_session)
|
||||
|
||||
def fill_in_site_characterization_data(self, module_type=ModuleType.Cell96):
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '200')
|
||||
self.browser.fill('building_height', '30')
|
||||
self.browser.fill('building_length', '75.5')
|
||||
self.browser.fill('wind_speed', '125')
|
||||
self.browser.fill('exposure_category', 'C')
|
||||
self.browser.fill('ballast_block_weight', '13')
|
||||
self.browser.fill('building_parapet_height', '0')
|
||||
self.browser.fill('max_system_pressure', '10')
|
||||
self.browser.fill('module_type', module_type.value)
|
||||
self.browser.fill('system_type', SystemType.singleTilt.value)
|
||||
self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
|
||||
self.browser.fill('importance_factor', '1.5')
|
||||
self.browser.fill('design_spectral_response', '1')
|
||||
|
||||
def test_page_displays_welcome_text(self):
|
||||
assert self.browser.is_text_present("Helix Calculator")
|
||||
|
||||
def test_navigation_header_shows_user_on_first_step(self):
|
||||
assert self.browser.find_by_css('.navigation_header #step_1').has_class('active')
|
||||
assert not self.browser.find_by_css('.navigation_header #step_1').has_class('completed')
|
||||
|
||||
def test_completing_site_characterization_step_updates_navigation_header(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
assert self.browser.find_by_css('.navigation_header #step_2').has_class('active')
|
||||
assert not self.browser.find_by_css('.navigation_header #step_1').has_class('active')
|
||||
assert self.browser.find_by_css('.navigation_header #step_1').has_class('completed')
|
||||
self.browser.click_link_by_partial_text("Back")
|
||||
assert not self.browser.find_by_css('.navigation_header #step_2').has_class('active')
|
||||
assert self.browser.find_by_css('.navigation_header #step_1').has_class('active')
|
||||
assert self.browser.find_by_css('.navigation_header #step_1').has_class('completed')
|
||||
|
||||
def test_entering_site_characterization_data_saves_entered_values(self):
|
||||
self.fill_in_site_characterization_data() # TODO: Fill in to change to 128
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
self.browser.click_link_by_partial_text("Back")
|
||||
eq_(self.browser.find_by_name('project_name').first.value, 'Test Project Name')
|
||||
eq_(self.browser.find_by_name('building_width').first.value, '200.0')
|
||||
eq_(self.browser.find_by_name('building_height').first.value, '30.0')
|
||||
eq_(self.browser.find_by_name('building_length').first.value, '75.5')
|
||||
eq_(self.browser.find_by_name('wind_speed').first.value, '125')
|
||||
eq_(self.browser.find_by_name('exposure_category').first.value, 'C')
|
||||
eq_(self.browser.find_by_name('ballast_block_weight').first.value, '13.0')
|
||||
eq_(self.browser.find_by_name('building_parapet_height').first.value, '0.0')
|
||||
eq_(self.browser.find_by_name('max_system_pressure').first.value, '10.0')
|
||||
eq_(self.browser.find_by_name('module_type').first.value, ModuleType.Cell96.value)
|
||||
eq_(self.browser.find_by_name('system_type').first.value, SystemType.singleTilt.value)
|
||||
eq_(self.browser.find_by_name('anchor_type').first.value, AnchorType.EcoFasten.value)
|
||||
eq_(self.browser.find_by_name('importance_factor').first.value, '1.5')
|
||||
eq_(self.browser.find_by_name('design_spectral_response').first.value, '1.0')
|
||||
|
||||
def test_form_shows_wind_speed_link(self):
|
||||
info_link = self.browser.find_by_css('#wind_speed_row a').first
|
||||
eq_(info_link.text, 'Look up')
|
||||
eq_(info_link['href'], 'http://windspeed.atcouncil.org/')
|
||||
|
||||
def test_form_shows_seismic_link(self):
|
||||
info_link = self.browser.find_by_css('#design_spectral_response_row a').first
|
||||
eq_(info_link.text, 'Look up')
|
||||
eq_(info_link['href'], 'http://earthquake.usgs.gov/designmaps/us/application.php')
|
||||
|
||||
def test_form_shows_exposure_category_link(self):
|
||||
info_link = self.browser.find_by_css('#exposure_category_row a').first
|
||||
eq_(info_link.text, 'More info')
|
||||
info_link.click()
|
||||
assert self.browser.is_text_present("Urban and suburban areas, wooded areas")
|
||||
|
||||
def test_all_site_charactarization_values_are_required(self):
|
||||
self.browser.fill('ballast_block_weight', '')
|
||||
self.browser.fill('max_system_pressure', '')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
assert_error(self.browser, 'project_name', 'Project Name is required.')
|
||||
assert_error(self.browser, 'building_height', 'Not a valid decimal value')
|
||||
assert_error(self.browser, 'building_width', 'Not a valid decimal value')
|
||||
assert_error(self.browser, 'building_length', 'Not a valid decimal value')
|
||||
assert_error(self.browser, 'wind_speed', 'Not a valid integer value')
|
||||
assert_error(self.browser, 'ballast_block_weight', 'Not a valid decimal value')
|
||||
assert_error(self.browser, 'building_parapet_height', 'Not a valid decimal value')
|
||||
assert_error(self.browser, 'max_system_pressure', 'Not a valid decimal value')
|
||||
assert_error(self.browser, 'design_spectral_response', 'Not a valid decimal value')
|
||||
|
||||
def test_characterization_values_not_overwritten_when_Nextting_invalid_request(self):
|
||||
self.browser.fill('project_name', '')
|
||||
self.browser.fill('building_width', '-1')
|
||||
self.browser.fill('building_height', '-10')
|
||||
self.browser.fill('building_length', 'hi')
|
||||
self.browser.fill('wind_speed', '400')
|
||||
self.browser.fill('exposure_category', 'D')
|
||||
self.browser.fill('ballast_block_weight', '40')
|
||||
self.browser.fill('building_parapet_height', '-1')
|
||||
self.browser.fill('max_system_pressure', '0')
|
||||
self.browser.fill('system_type', SystemType.dualTilt.value)
|
||||
self.browser.fill('module_type', ModuleType.Cell128.value)
|
||||
self.browser.fill('anchor_type', AnchorType.OMG_PowerGrip.value)
|
||||
self.browser.fill('design_spectral_response', '-2')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
eq_(self.browser.find_by_name('project_name').first.value, '')
|
||||
eq_(self.browser.find_by_name('building_width').first.value, '-1')
|
||||
eq_(self.browser.find_by_name('building_height').first.value, '-10')
|
||||
eq_(self.browser.find_by_name('building_length').first.value, 'hi')
|
||||
eq_(self.browser.find_by_name('wind_speed').first.value, '400')
|
||||
eq_(self.browser.find_by_name('exposure_category').first.value, 'D')
|
||||
eq_(self.browser.find_by_name('ballast_block_weight').first.value, '40')
|
||||
eq_(self.browser.find_by_name('building_parapet_height').first.value, '-1')
|
||||
eq_(self.browser.find_by_name('max_system_pressure').first.value, '0')
|
||||
eq_(self.browser.find_by_name('system_type').first.value, SystemType.dualTilt.value)
|
||||
eq_(self.browser.find_by_name('module_type').first.value, ModuleType.Cell128.value)
|
||||
eq_(self.browser.find_by_name('anchor_type').first.value, AnchorType.OMG_PowerGrip.value)
|
||||
eq_(self.browser.find_by_name('design_spectral_response').first.value, '-2')
|
||||
|
||||
|
||||
def test_wind_speed_value_must_be_in_range(self):
|
||||
self.browser.fill('wind_speed', '90')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
assert_error(self.browser, 'wind_speed', 'Number must be between 100 and 200.')
|
||||
|
||||
def test_ballast_block_weight_value_must_be_in_range(self):
|
||||
self.browser.fill('ballast_block_weight', '90')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
assert_error(self.browser, 'ballast_block_weight', 'Number must be between 12 and 20.')
|
||||
|
||||
def test_building_dimensions_must_be_non_negative(self):
|
||||
self.browser.fill('building_width', '-4')
|
||||
self.browser.fill('building_height', '-10')
|
||||
self.browser.fill('building_length', '-1')
|
||||
self.browser.fill('building_parapet_height', '-3')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
assert_error(self.browser, 'building_height', 'Number must be at least 0.')
|
||||
assert_error(self.browser, 'building_width', 'Number must be at least 0.')
|
||||
assert_error(self.browser, 'building_length', 'Number must be at least 0.')
|
||||
assert_error(self.browser, 'building_parapet_height', 'Number must be at least 0.')
|
||||
|
||||
def test_transition_distance_must_be_filled_out_for_interpolating_exposure_categories(self):
|
||||
self.browser.fill('exposure_category', 'B to C')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
assert_error(self.browser, 'exposure_category_transition_distance', 'Number must be at least 1.')
|
||||
|
||||
def test_transition_distance_must_be_greater_than_0_for_interpolating_exposure_categories(self):
|
||||
self.browser.fill('exposure_category', 'B to C')
|
||||
self.browser.fill('exposure_category_transition_distance', '-10')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
assert_error(self.browser, 'exposure_category_transition_distance', 'Number must be at least 1.')
|
||||
|
||||
def test_transition_distance_standard_categories_does_not_need_to_be_filled_out(self):
|
||||
self.browser.fill('exposure_category', 'B')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
assert_no_error(self.browser, 'exposure_category_transition_distance')
|
||||
|
||||
def test_max_system_pressure_must_be_non_negative(self):
|
||||
self.browser.fill('max_system_pressure', '-2')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
assert_error(self.browser, 'max_system_pressure', 'Number must be at least 0.')
|
||||
|
||||
def test_design_spectral_response_must_be_in_range(self):
|
||||
self.browser.fill('design_spectral_response', '-1')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
assert_error(self.browser, 'design_spectral_response', 'Number must be between 0 and 5.')
|
||||
|
||||
def test_building_dimensions_allow_zero(self):
|
||||
self.browser.fill('building_width', '0')
|
||||
self.browser.fill('building_height', '0')
|
||||
self.browser.fill('building_length', '0')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
|
||||
assert_no_error(self.browser, 'building_width')
|
||||
assert_no_error(self.browser, 'building_height')
|
||||
assert_no_error(self.browser, 'building_length')
|
||||
|
||||
def test_ballast_block_weight_defaults_to_14(self):
|
||||
eq_(self.browser.find_by_name('ballast_block_weight').first.value, '14.0')
|
||||
|
||||
def test_max_system_pressure_defaults_to_10(self):
|
||||
eq_(self.browser.find_by_name('max_system_pressure').first.value, '12.0')
|
||||
|
||||
def test_system_type_defaults_to_dual_tilt(self):
|
||||
eq_(self.browser.find_by_name('system_type').first.value, SystemType.dualTilt.value)
|
||||
|
||||
def test_module_type_defaults_to_96_cell(self):
|
||||
eq_(self.browser.find_by_name('module_type').first.value, ModuleType.Cell96.value)
|
||||
|
||||
def test_exposure_transition_distance_defaults_to_zero(self):
|
||||
eq_(self.browser.find_by_name('exposure_category_transition_distance').first.value, '0')
|
||||
127
test/integration/site_summary_test.py
Normal file
127
test/integration/site_summary_test.py
Normal file
@@ -0,0 +1,127 @@
|
||||
import unittest
|
||||
from helix.constants.module_type import ModuleType
|
||||
import mockredis
|
||||
from splinter import Browser
|
||||
from helix import main
|
||||
from helix.constants import redis_constant, sql_constant
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.models.panel import PanelWarnings
|
||||
from test.integration.integration_test_helpers import assert_step_is_active, assert_step_is_completed
|
||||
from test.test_helpers import *
|
||||
|
||||
|
||||
class SiteSummaryTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.test_db_session = test_db_session()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.test_db_session.close_all()
|
||||
|
||||
def setUp(self):
|
||||
redis_constant.redis_store = mockredis.mock_redis_client()
|
||||
sql_constant.sql_session_maker = lambda: self.test_db_session
|
||||
self.app = main.app.test_client()
|
||||
self.browser = Browser('flask', app=main.app)
|
||||
self.browser.visit('/summary/')
|
||||
|
||||
def tearDown(self):
|
||||
reset_db_session(self.test_db_session)
|
||||
|
||||
def fill_in_site_characterization_data(self, system_type=SystemType.singleTilt, module_type=ModuleType.Cell96, ul_warning=False):
|
||||
self.browser.visit('/site_characterization/')
|
||||
self.browser.fill('project_name', 'Test Project Name')
|
||||
self.browser.fill('building_width', '200')
|
||||
self.browser.fill('building_height', '30.254')
|
||||
self.browser.fill('building_length', '75.5')
|
||||
self.browser.fill('wind_speed', '125' if not ul_warning else '160')
|
||||
self.browser.fill('exposure_category', 'C')
|
||||
self.browser.fill('ballast_block_weight', '13')
|
||||
self.browser.fill('building_parapet_height', '0')
|
||||
self.browser.fill('max_system_pressure', '10')
|
||||
self.browser.fill('system_type', system_type.value)
|
||||
self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
|
||||
self.browser.fill('module_type', module_type.value)
|
||||
self.browser.fill('design_spectral_response', '1.02')
|
||||
self.browser.find_by_value('Next').first.click()
|
||||
self.browser.visit('/summary/')
|
||||
|
||||
def assert_summary_values_column_data(self, column, label, value):
|
||||
eq_(self.browser.find_by_css('#summary_values_table tr:nth-child(1) th:nth-child(%d)' % column).first.html,
|
||||
label)
|
||||
eq_(self.browser.find_by_css('#summary_values_table tr:nth-child(2) td:nth-child(%d)' % column).first.text,
|
||||
value)
|
||||
|
||||
def test_shows_summary_table_if_user_has_uploaded_data(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
assert len(self.browser.find_by_css("#summary_table")) > 0
|
||||
eq_(len(self.browser.find_by_css("#summary_table tr.alternating_row_color")), 13)
|
||||
|
||||
def test_does_not_show_tables_if_user_has_not_uploaded_site_data(self):
|
||||
assert len(self.browser.find_by_css("#summary_table")) == 0
|
||||
|
||||
def test_viewing_summary_table_without_site_characteristics_marks_as_incomplete(self):
|
||||
assert_step_is_active(self.browser, 2, True)
|
||||
assert_step_is_completed(self.browser, 2, False)
|
||||
self.fill_in_site_characterization_data()
|
||||
assert_step_is_active(self.browser, 2, True)
|
||||
assert_step_is_completed(self.browser, 2, True)
|
||||
|
||||
def test_clicking_next_goes_to_array_summary(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
|
||||
self.browser.click_link_by_partial_text('Next')
|
||||
assert_step_is_active(self.browser, 3)
|
||||
assert_step_is_active(self.browser, 2, False)
|
||||
|
||||
def test_shows_summary_values(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
self.assert_summary_values_column_data(1, 'L<sub>B</sub> - Building Scaling Factor (feet)', '30.25')
|
||||
self.assert_summary_values_column_data(2, 'K<sub>Z</sub> - Site Wind Pressure Factor', '0.98')
|
||||
self.assert_summary_values_column_data(3, 'q<sub>z</sub> - Site Wind Pressure (psf)', '33.46')
|
||||
|
||||
def test_clicking_back_goes_to_site_characterization(self):
|
||||
self.browser.click_link_by_partial_text('Back')
|
||||
|
||||
assert_step_is_active(self.browser, 1)
|
||||
|
||||
def test_shows_minimum_array_size_single_tilt(self):
|
||||
self.fill_in_site_characterization_data()
|
||||
eq_(len(self.browser.find_by_css("#summary_table tr:last_child td")), 12)
|
||||
eq_(self.browser.find_by_css("#summary_table tr:last_child td:first_child").first.text,
|
||||
"Minimum Array Size by Zone")
|
||||
|
||||
def test_shows_minimum_array_size_dual_tilt(self):
|
||||
self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
eq_(len(self.browser.find_by_css("#summary_table tr:last_child td")), 6)
|
||||
eq_(self.browser.find_by_css("#summary_table tr:last_child td:first_child").first.text,
|
||||
"Minimum Array Size by Zone (Tents)")
|
||||
|
||||
def test_shows_dual_tilt_images_for_dual_tilt_system(self):
|
||||
self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
|
||||
eq_(len(self.browser.find_by_css('.image_container a')), 2)
|
||||
assert 'panel_types_dual_tilt' in self.browser.find_by_css('.image_container a:nth-child(1)').first['data-featherlight']
|
||||
assert 'wind_zones_dual_tilt' in self.browser.find_by_css('.image_container a:nth-child(2)').first['data-featherlight']
|
||||
|
||||
def test_shows_single_tilt_images_for_single_tilt_system(self):
|
||||
self.fill_in_site_characterization_data(system_type=SystemType.singleTilt)
|
||||
eq_(len(self.browser.find_by_css('.image_container a')), 3)
|
||||
assert 'panel_types_single_tilt' in self.browser.find_by_css('.image_container a:nth-child(1)').first['data-featherlight']
|
||||
assert 'wind_zones_single_tilt_north' in self.browser.find_by_css('.image_container a:nth-child(2)').first['data-featherlight']
|
||||
assert 'wind_zones_single_tilt_south' in self.browser.find_by_css('.image_container a:nth-child(3)').first['data-featherlight']
|
||||
|
||||
def test_shows_warning_message(self):
|
||||
self.fill_in_site_characterization_data(ul_warning=True)
|
||||
summary_warning_selector = self.browser.find_by_css('.summary_warning')
|
||||
eq_(len(summary_warning_selector), 1)
|
||||
summary_warning_message = summary_warning_selector.first.text
|
||||
eq_(summary_warning_message, PanelWarnings.MaxPsf.value)
|
||||
|
||||
def test_shows_cells_with_warning_with_different_style(self):
|
||||
self.fill_in_site_characterization_data(ul_warning=True)
|
||||
eq_(len(self.browser.find_by_css('.table_horizontal_borders.warning')), 3)
|
||||
assert 'warning' in self.browser.find_by_css('#summary_table tr:nth-child(3) td:nth-child(3)').first['class']
|
||||
assert 'warning' in self.browser.find_by_css('#summary_table tr:nth-child(4) td:nth-child(2)').first['class']
|
||||
assert 'warning' in self.browser.find_by_css('#summary_table tr:nth-child(5) td:nth-child(2)').first['class']
|
||||
Reference in New Issue
Block a user