From f18ced580f450f731290422c050e298c4544b41d Mon Sep 17 00:00:00 2001 From: plocket <52798256+plocket@users.noreply.github.com> Date: Wed, 31 Aug 2022 10:45:01 -0400 Subject: [PATCH] Close #600. Allow devs to test list of interviews on their server. --- CHANGELOG.md | 4 +- lib/docassemble/setup.js | 5 -- lib/scope.js | 59 +++++++++++++++++++---- lib/steps.js | 21 ++++---- tests/features/establishing_steps.feature | 25 ++++++++++ 5 files changed, 87 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9b36bc4..40c06823 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,9 @@ Format: ### Security - --> - +## [Unreleased] +### Changed +- Allow devs to test list of interviews on their server. See https://github.com/SuffolkLITLab/ALKiln/issues/600. ## [4.8.0] - 2022-08-30 ### Changed diff --git a/lib/docassemble/setup.js b/lib/docassemble/setup.js index 8e53283f..ca20f5d2 100755 --- a/lib/docassemble/setup.js +++ b/lib/docassemble/setup.js @@ -31,11 +31,6 @@ const setup = async () => { await da_i.wait_for_server_to_restart( task_id ); } - // Make the folder to store all the files for this run of the tests - const artifacts_path_name = files.make_artifacts_folder(); - // Save its name in a file. `session_vars` can get it back later. - session_vars.save_artifacts_path_name( artifacts_path_name ); - // Finish log.info({ type: `setup`, pre: `Success! Test setup has finished successfully.` }); }; // Ends setup(); diff --git a/lib/scope.js b/lib/scope.js index 9016748c..d8110fb7 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -752,10 +752,27 @@ module.exports = { /* Try to load the page. Should we also pass a `timeout` arg or just * use scope.timeout? */ - if ( !file_name.includes('.yml') ) { file_name = `${ file_name }.yml` } - let base_url = await get_base_interview_url(); - let interview_url = `${ base_url }${ file_name }`; - if ( session_vars.get_debug() ) { console.log( interview_url ); } + let interview_url = null; + // If the file is already a full url, just use that arbitrary url + if ( file_name.includes( `http` ) ) { + interview_url = file_name; + + // If the filename is not a full url + } else { + // If the filename is just the name of the interview without `.yml`, add `.yml` to the end + if ( !file_name.includes('.yml') ) { file_name = `${ file_name }.yml` } + // Otherwise, the filename might have url args, so leave it alone + + // Add the server address to the filename + let base_url = await get_base_interview_url(); + interview_url = `${ base_url }${ file_name }`; + } + if ( session_vars.get_debug() ) { console.log( `interview_url:`, interview_url ); } + + await scope.addToReport(scope,{ + type: `row`, + value: `Trying to load the interview question page at ${ interview_url }` + }); if ( !scope.page ) { scope.page = await scope.browser.newPage(); } @@ -766,11 +783,13 @@ module.exports = { } catch ( error ) { + // If the page didn't load because it took to long to load if ( error.name === `TimeoutError` ) { let non_reload_report_msg = `Timeout error occurred when ALKiln tried to go to the interview url "${ interview_url }".`; await scope.handle_page_timeout_error( scope, { non_reload_report_msg, error }); + // If the page didn't load because of any other reason } else { // Throw any non-timeout error @@ -794,35 +813,55 @@ module.exports = { }, // Ends scope.load() getLoadData: async function ( scope ) { - /* Return one of two elements that could load on the page - #daMainQuestion - * or #da-retry. If there's a system error on the page, return its main text. + /* Return elements that could load on the page, like #daMainQuestion + * and #da-retry. If there's a system error on the page, return its main text. * * If server isn't loaded yet, it should get the browser timeout error, - * which won't match either of those and this will timeout and, I assume, error.*/ + * which won't match those selectors and this will timeout and error. */ let result = { error: ``, elem: null }; + // Wait for at least one of these to appear let winner = await Promise.race([ // Signature page scope.page.waitForSelector( `#dasigpage`, { timeout: scope.timeout }), // Any other valid page scope.page.waitForSelector( `#daMainQuestion`, { timeout: scope.timeout }), scope.page.waitForSelector( `#da-retry`, { timeout: scope.timeout }), - ]); + ]).catch( function ( error ) { + // With any error in here, stop execution of the test + + // If none of them appear before this times out + if ( error.name.includes(`TimeoutError`) ) { + + result.error = `ALKiln could not find any interview question page at that url.`; + return result; + + // or if they cause some other kind of error + } else { + throw error; + } // ends if error.name.includes(`TimeoutError`) + }); // ends Promise.race() result.elem = winner; + // If a page was loaded, but there's a specific type of error on the page + // throw an error let error_id_elem = await scope.page.$( `#da-retry` ); if ( error_id_elem ) { + + // If it's a specific type of error, we can show the developer its text let error_elem = await scope.page.$( `blockquote` ); if (error_elem !== null) { let error_handle = await error_elem.getProperty( `textContent` ); let system_error_text = await error_handle.jsonValue(); result.error = system_error_text; + + // Error types we haven't accounted for } else { result.error = "Docassemble ran into an error on the page, but ALKiln does not know what the error is. If a screenshot was taken, check the screenshot"; - } - } + } // ends if error_elem !== null + } // ends if error_id_elem return result; }, // Ends scope.getLoadData() diff --git a/lib/steps.js b/lib/steps.js index 993e3e17..8a6e3275 100644 --- a/lib/steps.js +++ b/lib/steps.js @@ -85,18 +85,17 @@ BeforeAll(async () => { // Store path names for files and docs created for the tests scope.paths = {}; - // Test setup should have created this filepath. Run setup if there's a problem with this. - scope.paths.artifacts = session_vars.get_artifacts_path_name(); - // For GitHub tests, use the artifacts folder that was created during setup - // For local tests, make a new folder for each time scenarios start - if ( !session_vars.is_dev_env() ) { - // Make a new folder to store all the files for this run of the tests - scope.paths.artifacts = files.make_artifacts_folder(); - // Save its name in a file. `session_vars` can get it back later. - session_vars.save_artifacts_path_name( scope.paths.artifacts ); - } - scope.paths.report = `${ scope.paths.artifacts }/report.txt`; + // TODO: figure out how to test file and folder creation stuff, + // especially when setup is excluded from the flow. + + // Make the folder to store all the files for this run of the tests + scope.paths.artifacts = files.make_artifacts_folder(); + // Save its name in a file. `session_vars` can get it back later. + // This is used by at least clean_reports.js. + session_vars.save_artifacts_path_name( scope.paths.artifacts ); + + scope.paths.report = `${ scope.paths.artifacts }/report.txt`; scope.paths.debug_log = `${ scope.paths.artifacts }/${ log.debug_log_file }`; fs.writeFileSync( scope.paths.debug_log, "" ); }); diff --git a/tests/features/establishing_steps.feature b/tests/features/establishing_steps.feature index 42d23d95..97e14109 100644 --- a/tests/features/establishing_steps.feature +++ b/tests/features/establishing_steps.feature @@ -35,3 +35,28 @@ Scenario: Interview name includes url args with a wait Scenario: I sign in   Given I sign in with the email "USER1_EMAIL" and the password "USER1_PASSWORD" And I start the interview at "all_tests" + +@fast @e7 @arbitraryurl +Scenario: I want to go to a full arbitrary url + Given the max seconds for each step in this scenario is 5 + And the Scenario report should include: + """ + Trying to load the interview question page at + """ +  Given I start the interview at "https://apps-test.suffolklitlab.org/start/demo/questions" +  Then I should see the phrase "What language do you speak?" + +# WARNING: This Scenario may fail if the file moves or changes too much +@fast @failing @e8 @rfe8 @arbitraryurl +Scenario: Fail with no interview at arbitrary url + Given the final Scenario status should be "failed" + And the Scenario report should include: + """ + Trying to load the interview question page at + """ + And the Scenario report should include: + """ + ALKiln could not find any interview question page at that url + """ + And the max seconds for each step in this scenario is 5 + Then I start the interview at "https://apps-test.suffolklitlab.org/list"