@suffolklitlab/alkiln 4.0.0-pre-api.6 → 4.0.0-pre-api.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,69 +16,22 @@ require('dotenv').config();
16
16
  * much easier to test.
17
17
  */
18
18
 
19
- const session_vars = {
20
- PLAYGROUND_ID: process.env.PLAYGROUND_ID, // Need to get rid of this in favor of API
21
- };
19
+ const session_vars = {};
22
20
 
23
21
  module.exports = session_vars;
24
22
 
25
- /**
26
- * Ensure all required environment variables exist. Add each missing variable
27
- * to an error that will be thrown at the end.
28
- *
29
- * @throws ReferenceError with a message for all missing variables.
30
- */
31
- session_vars.validateEnvironment = function() {
32
-
33
- // We are checking for BASE_URL, but we are referring it as SERVER_URL as that
34
- // is the name used in GitHub secrets, which is what most devs will be using.
35
-
36
- let errorMessage = '';
37
-
38
- // Since this code will most often be run in GitHub, I'm going to build a single error message that outlines all missing variables. Otherwise, a developer
39
- // will have to run their pipeline an incredible number of times to discover all the missing variables.
40
- if (!process.env.DOCASSEMBLE_DEVELOPER_API_KEY)
41
- {
42
- errorMessage += `\nThe DOCASSEMBLE_DEVELOPER_API_KEY GitHub secret must be defined. The DOCASSEMBLE_DEVELOPER_API_KEY is a docassemble API key you created for your server's testing account. It should have developer permissions.`
43
- }
44
- if (!process.env.PLAYGROUND_ID)
45
- {
46
- errorMessage += '\nThe PLAYGROUND_ID GitHub secret must be defined. The PLAYGROUND_ID is the ID of the Docassemble suite to run.'
47
- }
48
- if (!process.env.SERVER_URL && !process.env.BASE_URL)
49
- {
50
- errorMessage += `\nThe SERVER_URL GitHub secret must be defined. The SERVER_URL is the URL of the Docassemble Server where the tests should be run.`;
51
- }
52
- if (!process.env.REPO_URL)
53
- {
54
- errorMessage += `\nThe REPO_URL GitHub secret must be defined. The REPO_URL is the URL to the Git repo whose Actions are being run.`;
55
- }
56
- if (!process.env.BRANCH_PATH && !process.env.BRANCH_NAME)
57
- {
58
- errorMessage += `\nThe BRANCH_NAME environment variable must be defined. The BRANCH_NAME is the name of the repository branch that should be pulled into the docassemble project.`;
59
- }
60
-
61
- errorMessage = errorMessage.trim();
62
-
63
- if (errorMessage !== '') {
64
- throw new ReferenceError(errorMessage);
65
- }
66
- };
67
-
68
- session_vars.validateEnvironment();
23
+ session_vars.get_debug = function () { return process.env.DEBUG || null; };
24
+ session_vars.get_dev_api_key = function () { return process.env.DOCASSEMBLE_DEVELOPER_API_KEY || null; };
25
+ session_vars.get_repo_url = function () { return process.env.REPO_URL || null; };
69
26
 
70
- session_vars.get_dev_api_key = function () { return process.env.DOCASSEMBLE_DEVELOPER_API_KEY; };
71
27
  session_vars.get_da_server_url = function () {
72
- let url = process.env.SERVER_URL || process.env.BASE_URL;
73
- return url.replace(/\/$/g, ''); // Remove any trailing slash for safety
28
+ try {
29
+ let url = process.env.SERVER_URL || process.env.BASE_URL;
30
+ return url.replace(/\/$/g, ''); // Remove any trailing slash for safety
31
+ } catch ( error ) {
32
+ return null;
33
+ }
74
34
  };
75
- session_vars.get_debug = function () { return process.env.DEBUG; };
76
- session_vars.get_repo_url = function () { return process.env.REPO_URL; };
77
- // missing/moving functionality:
78
- // getBaseInterviewURL
79
- // Project name setting/getting
80
- // Playground id functionality needs to be transfered to api requests
81
-
82
35
 
83
36
  session_vars.get_branch_name = function () {
84
37
  /* Get the name of the repository's branch that is being tested */
@@ -102,29 +55,6 @@ session_vars.get_project_base_name = function () {
102
55
  return sanitized_name;
103
56
  };
104
57
 
105
- // // Notes: We were using `new_session=1` in the url args, but it wasn't
106
- // // always working. The idea was to save each session so we could look
107
- // // back on it if needed. Aside from the fact that you usually need to log in
108
- // // to make the sessions retrievable (though if you're using `interview_list()`
109
- // // you can get them anyway), it also has inconsistent behavior when
110
- // // `sessions are unique`` or `temporary session` or use `interview_list()`
111
- // // and/or respond immediately with a `command()`. Three ways to avoid this:
112
- // // 1. x Start a new browser instead of just a new page each time. Lengthens the tests.
113
- // // 1. √ Visit `/user/sign-out` (needed even if the user is not logged in)
114
- // // 1. x (seems to be causing a 'Unable to locate interview session' error
115
- // // instead) Use `reset=2` instead , which will not save the previous session at all. It
116
- // // Will not just restart any existing interview sessions, it will also
117
- // // clear out the browser session's memory of what other interviews the user has
118
- // // visited in the same browser session_vars.
119
- // session_vars.getBaseInterviewURL = function () {
120
- // /* Return the part of the interview URL that comes before the filename.
121
- // * Depends on the project name, which may have been changed. */
122
- // let new_session = `/interview?new_session=1&i=docassemble.playground`;
123
- // return `${ session_vars.BASE_URL }${ new_session }${ session_vars.PLAYGROUND_ID }${ session_vars.getProjectName() }%3A`;
124
- // };
125
- // // session_vars.BASE_INTERVIEW_URL = session_vars.getBaseInterviewURL();
126
-
127
-
128
58
  session_vars.get_languages = function () {
129
59
  /* Returns an array of strings, names of languages that should be tested. */
130
60
 
@@ -186,3 +116,47 @@ session_vars.delete_project_name = function () {
186
116
  return false;
187
117
  }
188
118
  };
119
+
120
+ /**
121
+ * Ensure all required environment variables exist. Add each missing variable
122
+ * to an error that will be thrown at the end.
123
+ *
124
+ * @throws ReferenceError with a message for all missing variables.
125
+ */
126
+ session_vars.validateEnvironment = function() {
127
+ /** Throw a useful error for the developer if any of the required env vars
128
+ * are missing. For most devs, these will be GitHub secrets. */
129
+
130
+ // Note: We are checking for BASE_URL, but we are referring it as SERVER_URL as that
131
+ // is the name used in GitHub secrets, which is what most devs will be using.
132
+
133
+ let errorMessage = '';
134
+
135
+ // Since this code will most often be run in GitHub, I'm going to build a single error message that outlines all missing variables. Otherwise, a developer
136
+ // will have to run their pipeline an incredible number of times to discover all the missing variables.
137
+ if ( !session_vars.get_dev_api_key() )
138
+ {
139
+ errorMessage += `\nThe DOCASSEMBLE_DEVELOPER_API_KEY GitHub secret must be defined. The DOCASSEMBLE_DEVELOPER_API_KEY is a docassemble API key you created for your server's testing account. It should have developer permissions.`
140
+ }
141
+ if ( !session_vars.get_da_server_url() )
142
+ {
143
+ errorMessage += `\nThe SERVER_URL GitHub secret must be defined. The SERVER_URL is the URL of the Docassemble Server where the tests should be run.`;
144
+ }
145
+ if ( !session_vars.get_repo_url() )
146
+ {
147
+ errorMessage += `\nThe REPO_URL GitHub secret must be defined. The REPO_URL is the URL to the Git repo whose Actions are being run.`;
148
+ }
149
+ // The branch name is always automatically defined in Github, it'll be missing only if you're running locally and missing an env var.
150
+ if ( !session_vars.get_branch_name() )
151
+ {
152
+ errorMessage += `\nThe BRANCH_NAME environment variable must be defined. The BRANCH_NAME is the name of the repository branch that should be pulled into the docassemble project.`;
153
+ }
154
+
155
+ errorMessage = errorMessage.trim();
156
+
157
+ if (errorMessage !== '') {
158
+ throw new ReferenceError(errorMessage);
159
+ }
160
+ };
161
+
162
+ session_vars.validateEnvironment();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suffolklitlab/alkiln",
3
- "version": "4.0.0-pre-api.6",
3
+ "version": "4.0.0-pre-api.9",
4
4
  "description": "Integrated automated end-to-end testing with docassemble, puppeteer, and cucumber.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",
20
- "url": "git+https://github.com/SuffolkLITLab/alkiln.git"
20
+ "url": "git+https://github.com/SuffolkLITLab/ALKiln.git"
21
21
  },
22
22
  "keywords": [
23
23
  "docassemble",
@@ -30,7 +30,7 @@
30
30
  "author": "",
31
31
  "license": "MIT",
32
32
  "bugs": {
33
- "url": "https://github.com/SuffolkLITLab/alkiln/issues"
33
+ "url": "https://github.com/SuffolkLITLab/ALKiln/issues"
34
34
  },
35
35
  "homepage": "https://suffolklitlab.github.io/docassemble-AssemblyLine-documentation/docs/automated_integrated_testing",
36
36
  "dependencies": {
@@ -48,7 +48,6 @@
48
48
  "bin": {
49
49
  "alkiln-setup": "./lib/docassemble/setup.js",
50
50
  "alkiln-takedown": "./lib/docassemble/takedown.js",
51
- "alkiln-cucumber": "./lib/index.js",
52
51
  "alkiln-langs": "./lib/utils/langs.js"
53
52
  }
54
53
  }
@@ -4,13 +4,13 @@ Feature: Establishing steps
4
4
  Steps that establish things about the state of the test
5
5
  # In tag names, 'e' is for 'establishing'
6
6
 
7
- @slow @e1
7
+ @slow @e1 @wait
8
8
  Scenario: I am able to set a custom wait time that allows steps to run longer than the half minute default
9
9
  Given I start the interview at "all_tests"
10
10
  And the max seconds for each step in this scenario is 40
11
11
  And I wait 35 seconds
12
12
 
13
- @slow @e2
13
+ @slow @e2 @wait
14
14
  Scenario: I am able to set a custom wait time before an interview has been loaded
15
15
  Given the max seconds for each step in this scenario is 40
16
16
  And I start the interview at "all_tests"
@@ -96,7 +96,7 @@ Scenario: Test "Then I don’t continue" with an apostrophe
96
96
  Then I don’t continue
97
97
  And I will be told an answer is invalid
98
98
 
99
- @fast @o9
99
+ @fast @o9 @table
100
100
  Scenario: I can match JSON page var to str
101
101
  Given I start the interview at "all_tests.yml"
102
102
    And I get to "showifs" with this data:
@@ -138,7 +138,7 @@ Scenario: Fail with missing link with url
138
138
  And I start the interview at "all_tests"
139
139
  Then I should see the link to "http://missing-url.com"
140
140
 
141
- @slow @rf13 @error
141
+ @slow @rf13 @error @table
142
142
  Scenario: Fail with link with given text does not lead to correct url
143
143
  Given the final Scenario status should be "failed"
144
144
  Given the Scenario report should include:
@@ -166,7 +166,7 @@ Scenario: Fail with link with given text does not lead to correct url
166
166
  And I should see the link to "http://ecosia.org/"
167
167
  Then the "Link to external page" link leads to "http://wrong-url.com"
168
168
 
169
- @slow @rf14 @error
169
+ @slow @rf14 @error @table
170
170
  Scenario: Fail with link unexpectedly opens in same window
171
171
  Given the final Scenario status should be "failed"
172
172
  Given the Scenario report should include:
@@ -194,7 +194,7 @@ Scenario: Fail with link unexpectedly opens in same window
194
194
  And I should see the link to "http://ecosia.org/"
195
195
  Then the "Link to external page" link opens in the same window
196
196
 
197
- @fast @rf15 @error
197
+ @fast @rf15 @error @table
198
198
  Scenario: Fail with link unexpectedly opens in a new window
199
199
  Given the final Scenario status should be "failed"
200
200
  Given the Scenario report should include:
@@ -223,7 +223,7 @@ Scenario: Fail with link unexpectedly opens in a new window
223
223
  Then the "Link: reload the page" link opens in a new window
224
224
 
225
225
  ## Don't currently have a broken link to test and this Step is not officially supported
226
- #@fast @rf16 @error
226
+ #@fast @rf16 @error @table
227
227
  #Scenario: Fail with link leads to a broken page
228
228
  # Given the final Scenario status should be "failed"
229
229
  # Given the Scenario report should include:
@@ -321,7 +321,7 @@ Scenario: Fail with system error after Step using wrong file name as trigger
321
321
  # """
322
322
  # And I start the interview at "wrong_yaml_filename"
323
323
 
324
- @fast @rf22
324
+ @fast @rf22 @table
325
325
  Scenario: I can't match JSON page var to str
326
326
  Given the final Scenario status should be "failed"
327
327
  Given the Scenario report should include:
@@ -448,70 +448,27 @@ Scenario: Report still shows page id when I tap to continue without setting any
448
448
  # Next page (showifs ID SHOULD BE SHOWN IN REPORT)
449
449
  Then the question id should be "buttons yesnomaybe"
450
450
 
451
- @slow @rp2
451
+ @slow @rp2 @table
452
452
  Scenario: Report lists unused table rows
453
453
  Given the final Scenario status should be "passed"
454
454
  Given the Scenario report should include:
455
455
  """
456
-
457
- ---------------
458
- Scenario: Report lists unused table rows
459
- Tags: @reports @slow @rp2
460
- ---------------
461
- screen id: upload-files
462
- screen id: group-of-complex-fields
463
- | single_quote_dict['single_quote_key']['sq_two'] | true | |
464
- | double_quote_dict[\"double_quote_key\"]['dq_two'] | true | |
465
-
466
- Rows that got set:
467
- And I get to the question id "direct standard fields" with this data:
468
- | var | value | trigger |
469
- | double_quote_dict[\"double_quote_key\"]['dq_two'] | true | |
470
- | single_quote_dict['single_quote_key']['sq_two'] | true | |
471
456
  Unused rows:
472
457
  | extra_2 | extra 2 | |
473
458
  | extra_out_of_alphabetical_order | extra 1 | |
474
-
475
- screen id: direct-standard-fields
476
- | checkboxes_other['checkbox_other_opt_1'] | true | |
477
- | radio_yesno | False | false |
478
- | radio_other | radio_other_opt_3 | |
479
- | text_input | Regular text input field value | |
480
- | textarea | Multiline text\narea value | |
481
- | dropdown_test | dropdown_opt_2 | |
482
-
483
- Rows that got set:
484
- And I get to the question id "showifs" with this data:
485
- | var | value | trigger |
486
- | checkboxes_other['checkbox_other_opt_1'] | true | |
487
- | dropdown_test | dropdown_opt_2 | |
488
- | radio_other | radio_other_opt_3 | |
489
- | radio_yesno | False | false |
490
- | text_input | Regular text input field value | |
491
- | textarea | Multiline text\narea value | |
459
+ """
460
+ Given the Scenario report should include:
461
+ """
492
462
  Unused rows:
493
463
  | extra_3 | extra 3 | |
494
464
  | extra_4 | extra 4 | |
495
465
  | extra_5 | extra 5 | |
496
-
497
- screen id: showifs
498
- screen id: buttons-yesnomaybe
499
- | buttons_yesnomaybe | True | |
500
- screen id: buttons-other
501
- | buttons_other | button_2 | |
502
- screen id: button-continue
503
- | button_continue | True | |
504
-
505
- Rows that got set:
506
- And I get to the question id "screen features" with this data:
507
- | var | value | trigger |
508
- | button_continue | True | |
509
- | buttons_other | button_2 | |
510
- | buttons_yesnomaybe | True | |
466
+ """
467
+ Given the Scenario report should include:
468
+ """
511
469
  Unused rows:
512
470
  | extra_6 | extra 6 | |
513
471
  | extra_7 | extra 7 | |
514
-
515
472
  """
516
473
  And I start the interview at "all_tests"
517
474
    And I get to "direct standard fields" with this data:
@@ -1,4 +1,4 @@
1
- @story_tables_formats
1
+ @story_tables_formats @table
2
2
  Feature: Supported story table formats
3
3
 
4
4
  NOTE:
@@ -1,4 +1,4 @@
1
- @story_tables
1
+ @story_tables @table
2
2
  Feature: Story tables
3
3
 
4
4
  NOTE:
@@ -7,6 +7,8 @@ const fields = require('./fields.fixtures.js');
7
7
  const matches = require('./matches.fixtures.js');
8
8
  const scope = require('../../lib/scope.js');
9
9
  const getMatchingRows = scope.getMatchingRows;
10
+ // Match state var instantiated in steps.js. TODO: Add tests for such rows.
11
+ scope.row_needs_trigger_flag = `ALKiln: no trigger variable needed`;
10
12
 
11
13
  // TODO: Add tests for reports
12
14
 
@@ -188,6 +190,32 @@ describe(`For mulitple rows with the same proxies`, async function() {
188
190
  }
189
191
  });
190
192
 
193
+ // Missing table row for loop
194
+ describe(`For a second proxy loop page,`, async function() {
195
+ for ( let test_i = 0; test_i < fields.proxies_multi.length; test_i++ ) {
196
+ let field = fields.proxies_multi[ test_i ];
197
+ let curr_matches = matches.proxies_missing_loop[ test_i ];
198
+ let name = getSafeName( field );
199
+ it( `does not find any matches when table row for second loop page is missing`, async function() {
200
+ let result = await getMatchingRows( scope, { field, var_data: tables.proxies_missing_loop });
201
+ expect( result ).to.deep.equal( curr_matches );
202
+ });
203
+ }
204
+ });
205
+
206
+ // Missing trigger matches second loop
207
+ describe(`For a second proxy loop page,`, async function() {
208
+ for ( let test_i = 0; test_i < fields.proxies_multi.length; test_i++ ) {
209
+ let field = fields.proxies_multi[ test_i ];
210
+ let curr_matches = matches.proxies_missing_trigger[ test_i ];
211
+ let name = getSafeName( field );
212
+ it( `matches with a missing trigger row with the correct variable name`, async function() {
213
+ let result = await getMatchingRows( scope, { field, var_data: tables.proxies_missing_trigger });
214
+ expect( result ).to.deep.equal( curr_matches );
215
+ });
216
+ }
217
+ });
218
+
191
219
 
192
220
  // ============================
193
221
  // Signature
@@ -15,7 +15,7 @@ matches.standard = [
15
15
  [],
16
16
  [ { var: 'radio_other', value: 'radio_other_opt_2' } ],
17
17
  [],
18
- [ { var: 'text_input', value: 'Some one-line text' }, { var: 'text_input', value: 'Some conflicting text' } ],
18
+ [ { var: 'text_input', value: 'Some one-line text', "original": { var: 'text_input', value: 'Some one-line text' } }, { var: 'text_input', value: 'Some conflicting text', "original": { var: 'text_input', value: 'Some conflicting text' } } ],
19
19
  [ { var: 'textarea', value: 'Some\nmulti-line\ntext' } ],
20
20
  [ { 'var': 'date_input','value':'today-1' } ],
21
21
  [ { var: 'dropdown_test', value: 'dropdown_opt_2' } ],
@@ -111,6 +111,18 @@ matches.proxies_multi = [
111
111
  []
112
112
  ];
113
113
 
114
+ // Missing table row for second loop
115
+ matches.proxies_missing_loop = [
116
+ [],
117
+ []
118
+ ];
119
+
120
+ // Missing trigger matches second loop
121
+ matches.proxies_missing_trigger = [
122
+ [{ "trigger": "", "var": "x[i].name.first", "value": "Firstname", "original": { "trigger": "", "var": "x[i].name.first", "value": "Firstname" }}],
123
+ []
124
+ ];
125
+
114
126
 
115
127
  // ============================
116
128
  // Signature
@@ -0,0 +1,46 @@
1
+ const chai = require('chai');
2
+ const expect = chai.expect;
3
+
4
+ const session_vars = require("../../lib/utils/session_vars.js");
5
+ const validateEnvironment = session_vars.validateEnvironment;
6
+
7
+ describe('When the `session_vars` object uses', function () {
8
+ describe('validateEnvironment, it', function() {
9
+
10
+ /**
11
+ * All required variables should be defined in .env. For reference, those variables are the following:
12
+ *
13
+ * DOCASSEMBLE_DEVELOPER_API_KEY
14
+ * BASE_URL
15
+ * REPO_URL
16
+ */
17
+ it("successfully completes when all required env vars exist", function() {
18
+ session_vars.validateEnvironment();
19
+ });
20
+
21
+ /**
22
+ * This test has an ordering dependency with the test below. I'm not certain if I am getting lucky or if I need to explicitly declare the order.
23
+ */
24
+ it("throws a reference error when any var is missing", function() {
25
+ delete process.env.DOCASSEMBLE_DEVELOPER_API_KEY;
26
+
27
+ expect(session_vars.validateEnvironment).to.throw(ReferenceError, /DOCASSEMBLE_DEVELOPER_API_KEY/);
28
+ });
29
+
30
+ /**
31
+ * Delete all environment variables before validating the variables.
32
+ */
33
+ it("names all missing variables in the error, not just one", function() {
34
+ delete process.env.DOCASSEMBLE_DEVELOPER_API_KEY;
35
+ delete process.env.BASE_URL;
36
+ delete process.env.SERVER_URL;
37
+ delete process.env.REPO_URL;
38
+
39
+ // This test just tests that the variable names show up in a fixed order.
40
+ expect(session_vars.validateEnvironment).to.throw(
41
+ ReferenceError,
42
+ /DOCASSEMBLE_DEVELOPER_API_KEY.*\n.*SERVER_URL.*\n.*REPO_URL/
43
+ );
44
+ });
45
+ });
46
+ });
@@ -21,8 +21,8 @@ tables.standard = [
21
21
  { "var": "date_input","value":"today-1" },
22
22
  { "var": "radio_yesno", "value": "False" },
23
23
  { "var": "radio_other", "value": "radio_other_opt_2" },
24
- { "var": "text_input", "value": "Some one-line text" },
25
- { "var": "text_input","value":"Some conflicting text" },
24
+ { "var": "text_input", "value": "Some one-line text", "original": { "var": "text_input", "value": "Some one-line text" } },
25
+ { "var": "text_input","value":"Some conflicting text", "original": { "var": "text_input","value":"Some conflicting text" } },
26
26
  { "var": "textarea", "value": "Some\nmulti-line\ntext" },
27
27
  { "var": "dropdown_test", "value": "dropdown_opt_2" }, // May want to change `checked`
28
28
  ];
@@ -373,6 +373,16 @@ tables.proxies_multi = [
373
373
  { "trigger": "proxy_list[2].name.first", "var": "x[i].name.first", "value": "Firstname", },
374
374
  ];
375
375
 
376
+ // Missing table row for second loop
377
+ tables.proxies_missing_loop = [
378
+ { "trigger": "proxy_list[0].name.first", "var": "x[i].name.first", "value": "Firstname", "original": { "trigger": "proxy_list[0].name.first", "var": "x[i].name.first", "value": "Firstname" } },
379
+ ];
380
+
381
+ // Missing trigger matches second loop
382
+ tables.proxies_missing_trigger = [
383
+ { "trigger": "", "var": "x[i].name.first", "value": "Firstname", "original": { "trigger": "", "var": "x[i].name.first", "value": "Firstname" }},
384
+ ];
385
+
376
386
 
377
387
  // ============================
378
388
  // Signature