@suffolklitlab/alkiln 4.10.3-feat-debug-cache → 4.10.4-cli-playground-1

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.
package/CHANGELOG.md CHANGED
@@ -39,10 +39,26 @@ Format:
39
39
  -
40
40
  -->
41
41
  ## [Unreleased]
42
- ## Added
43
- - Contribution docs.
44
- - Story table can take screenshots after each visited page.
45
- - Projects created in da each have a unique name. We assume for now this will not build up test packages in the server.
42
+
43
+ ### Added
44
+ - A new script: `alkiln-run`, which acts like `npm run cucumber`, but can
45
+ be run in any directory, not just in an npm package.
46
+ - Ability to run ALKiln from an interview by a logged-in user
47
+
48
+ ### Changed
49
+ - upgraded cucumber v8.6.0
50
+ - using cucumber's JS API to run tests. For more details on how it works,
51
+ see [the cucumber-js docs](https://github.com/cucumber/cucumber-js/blob/main/docs/javascript_api.md).
52
+ - the github action no longer runs `npm run XYZ`; it directly calls scripts,
53
+ e.g. `alkiln-setup`, `alkiln-run`, `alkiln-takedown`
54
+ - don't print the ["publish this cucumber report" message](https://github.com/cucumber/cucumber-js/blob/main/docs/configuration.md#options)
55
+
56
+ ## [4.10.4] - 2023-02-15
57
+ ### Added
58
+ - Contribution docs
59
+
60
+ ### Fixed
61
+ - #511, couldn't take screenshots of signature pages https://github.com/SuffolkLITLab/ALKiln/issues/511
46
62
 
47
63
  ## [4.10.3] - 2023-01-11
48
64
  ### Removed
@@ -565,4 +581,4 @@ Format:
565
581
  - `example.feature` - an example test to get a project started
566
582
  - `github/workflows/run_form_tests.yml` - Automated github workflow to run tests when code is pushed and a manual trigger for testing without needing to push
567
583
  - `.gitignore` - ignores files that are generated by the tests and shouldn't be added to the repo
568
- - `package.json` - keep up-to-date version of this test repository and hold scripts that the automated tests run
584
+ - `package.json` - keep up-to-date version of this test repository and hold scripts that the automated tests run
package/action.yml CHANGED
@@ -5,15 +5,6 @@ inputs:
5
5
  SERVER_URL:
6
6
  description: 'The url of your docassemble server. This should be in your GitHub SECRETS or the SECRETS of your org.'
7
7
  required: true
8
- PLAYGROUND_EMAIL:
9
- description: 'The email of your docassemble testing account. This should be in your GitHub SECRETS or the SECRETS of your org.'
10
- required: true
11
- PLAYGROUND_PASSWORD:
12
- description: 'The password of your docassemble testing account. This should be in your GitHub SECRETS or the SECRETS of your org.'
13
- required: true
14
- PLAYGROUND_ID:
15
- description: 'The id of your docassemble testing account. This should be in your GitHub SECRETS or the SECRETS of your org.'
16
- required: true
17
8
  DOCASSEMBLE_DEVELOPER_API_KEY:
18
9
  description: 'API key of the testing account with developer permissions on your docassemble server.'
19
10
  required: true
@@ -33,6 +24,16 @@ inputs:
33
24
  required: false
34
25
  default: '120'
35
26
 
27
+ ## Testing by hand on the server. Should only be created by interview code.
28
+ #_USER_ID:
29
+ # description: 'AVOID SETTING THIS YOURSELF. The id of your docassemble playground account. This is created and used by ALKiln when testing manually on your server.'
30
+ # required: false
31
+ #_PROJECT_NAME:
32
+ # description: 'AVOID SETTING THIS YOURSELF. The name of the Playground Project to test manually on your server. ALKiln will ask you for this information.'
33
+ # required: false
34
+ #_ORIGIN:
35
+ # description: 'AVOID SETTING THIS YOURSELF. The origin that's triggering this round of tests.'
36
+
36
37
  runs:
37
38
  using: "composite"
38
39
  steps:
@@ -55,12 +56,12 @@ runs:
55
56
  echo "REPO_URL=${{ github.server_url }}/${{ github.repository }}" >> $GITHUB_ENV
56
57
  echo "BRANCH_PATH=${{ github.ref }}" >> $GITHUB_ENV
57
58
  echo "BASE_URL=${{ inputs.SERVER_URL }}" >> $GITHUB_ENV
58
- echo "PLAYGROUND_EMAIL=${{ inputs.PLAYGROUND_EMAIL }}" >> $GITHUB_ENV
59
- echo "PLAYGROUND_PASSWORD=${{ inputs.PLAYGROUND_PASSWORD }}" >> $GITHUB_ENV
60
- echo "PLAYGROUND_ID=${{ inputs.PLAYGROUND_ID }}" >> $GITHUB_ENV
61
59
  echo "DOCASSEMBLE_DEVELOPER_API_KEY=${{ inputs.DOCASSEMBLE_DEVELOPER_API_KEY }}" >> $GITHUB_ENV
62
60
  echo "ALKILN_VERSION=${{ inputs.ALKILN_VERSION }}" >> $GITHUB_ENV
63
61
  echo "MAX_SECONDS_FOR_SETUP=${{ inputs.MAX_SECONDS_FOR_SETUP }}" >> $GITHUB_ENV
62
+
63
+ # echo "_USER_ID=${{ inputs._USER_ID }}" >> $GITHUB_ENV
64
+ # echo "_PROJECT_NAME=${{ inputs._PROJECT_NAME }}" >> $GITHUB_ENV
64
65
  shell: bash
65
66
  - name: "ALKiln: confirm info"
66
67
  run: |
@@ -68,58 +69,31 @@ runs:
68
69
  echo -e "\nALKiln version is $ALKILN_VERSION\nRepo is $REPO_URL\nBranch ref is $BRANCH_PATH\nMAX_SECONDS_FOR_SETUP is $MAX_SECONDS_FOR_SETUP\nManually added languages are $EXTRA_LANGUAGES\n"
69
70
  shell: bash
70
71
 
71
- # This doesn't use an already established package-lock.json and that
72
- # comes with some types of test breaking risks. Same problem as before.
73
- - name: Temporarily overwrite or create package.json
74
- run: |
75
- cat << EOF > "package.json"
76
- {
77
- "scripts": {
78
- "test": "npm run langs_setup && npm run cucumber -- $@",
79
- "cucumber_base": "./node_modules/.bin/cucumber-js --require ./node_modules/@suffolklitlab/alkiln/lib/index.js",
80
- "cucumber": "run_cucumber(){ npm run cucumber_base -- \"$@\" docassemble/*/data/sources/*.feature --retry 1; }; run_cucumber",
81
- "langs": "npm run langs_setup && ./node_modules/.bin/cucumber-js --require ./node_modules/.bin/alkiln-cucumber docassemble/*/data/sources/*_lang*.feature",
82
- "langs_setup": "node_modules/.bin/alkiln-langs 'docassemble/*/data/sources/*.feature'",
83
- "setup": "node_modules/.bin/alkiln-setup",
84
- "takedown": "node_modules/.bin/alkiln-takedown"
85
- },
86
- "dependencies": {
87
- "colors": "1.4.0",
88
- "@cucumber/cucumber": "7.3.2",
89
- "@suffolklitlab/alkiln": "$ALKILN_VERSION"
90
- }
91
- }
92
- EOF
93
- # Keep in sync with the cucumber.js in root
94
- cat << EOF > "cucumber.js"
95
- module.exports = {
96
- default: "--require ./lib/index.js --format progress --format summary:cucumber-report.txt"
97
- }
98
- EOF
99
- shell: bash
100
-
101
72
  # Install node
102
73
  - name: "ALKiln: Install node packages"
103
74
  uses: actions/setup-node@v1
104
75
  with:
105
76
  node-version: "17"
106
- - run: npm install
77
+ # npm install -g "@suffolklitlab/alkiln@$ALKILN_VERSION"
78
+ - name: Install ALKiln directly from npm
79
+ run: |
80
+ npm install -g github:SuffolkLITLab/ALKiln#lighter_package_json
107
81
  shell: bash
108
82
 
109
83
  # Run tests
110
84
  - name: "ALKiln: Create a Project and pull the package from GitHub"
111
- run: npm run setup
85
+ run: alkiln-setup
112
86
  shell: bash
113
87
  - name: "ALKiln: Run tests"
114
88
  if: ${{ success() }}
115
- run: npm run test -- ${{ github.event.inputs.tags && format('"--tags" "{0}"', github.event.inputs.tags) }}
89
+ run: alkiln-run ${{ github.event.inputs.tags && format('"{0}"', github.event.inputs.tags) }}
116
90
  shell: bash
117
91
  - run: echo -e "\n\n====ALKiln could not create a project on your server's testing account or pull your package into it. Check the messages above this line.\n\n"
118
92
  if: ${{ failure() }}
119
93
  shell: bash
120
94
  - name: "ALKiln: Delete project from docassemble test account"
121
95
  if: ${{ always() }}
122
- run: npm run takedown
96
+ run: alkiln-takedown
123
97
  shell: bash
124
98
 
125
99
  # Upload artifacts that subscribers can download on the Actions summary page
package/cucumber.js CHANGED
@@ -1,3 +1,3 @@
1
1
  module.exports = {
2
- default: "--require ./lib/index.js --format progress --format summary:cucumber-report.txt"
2
+ default: "--publish-quiet --require ./lib/index.js --format progress --format summary:cucumber-report.txt"
3
3
  }
@@ -204,16 +204,16 @@ da_i.loop_to_create_project = async function( creation_options ) {
204
204
  let wait_seconds = creation_options.wait_seconds || 5;
205
205
 
206
206
  let project_name = null;
207
- let num_tries = 0;
207
+ let name_incrementor = 0;
208
208
 
209
209
  // Try to create a project. If the project name is already taken, increment and loop again.
210
- while ( num_tries <= max_tries ) {
211
- num_tries++;
210
+ while ( name_incrementor <= max_tries ) {
211
+ name_incrementor++;
212
212
  try {
213
213
 
214
- // Try adding a new timestamp to the name. Must remove all non-valid characters
214
+ // Try next name that could be unique. Must remove all non-valid characters
215
215
  // TODO: This sanitization is already done in session_vars, so remove it from here
216
- project_name = session_vars.get_project_base_name().replace(/[^A-Za-z0-9]/g, '') + `${Date.now()}`;
216
+ project_name = session_vars.get_project_base_name().replace(/[^A-Za-z0-9]/g, '') + name_incrementor;
217
217
  log.info({ pre: `Trying to create a docassemble Project with the name ${ project_name }` });
218
218
  let response = await _da_REST.create_project( project_name, timeout );
219
219
  log.info({ pre: `The docassemble server is ready. Created a Project named ${ project_name }` });
@@ -226,7 +226,7 @@ da_i.loop_to_create_project = async function( creation_options ) {
226
226
 
227
227
  if ( response && response.data ) {
228
228
  if ( response.data.includes( `Invalid project` ) ) {
229
- if ( num_tries < max_tries ) {
229
+ if ( name_incrementor < max_tries ) {
230
230
  // A non-unique project name. Try the next project name.
231
231
  continue;
232
232
 
@@ -256,11 +256,11 @@ da_i.loop_to_create_project = async function( creation_options ) {
256
256
 
257
257
  // If it's a timeout error, server is busy. Try again after waiting.
258
258
  // Why are we using `max_tries` for timeout error as well?
259
- if ( is_timeout_error( error ) && num_tries < max_tries ) {
259
+ if ( is_timeout_error( error ) && name_incrementor < max_tries ) {
260
260
  log.info({ pre: `The docassemble server was busy when we tried to `
261
- + `create the Project. Attempt ${ num_tries } of `
261
+ + `create the Project. Attempt ${ name_incrementor } of `
262
262
  + `${ max_tries }. Will try again in ${ wait_seconds } seconds.` });
263
- num_tries--; // Try this name again next time
263
+ name_incrementor--; // Try this name again next time
264
264
  await time.waitForTimeout( wait_seconds * 1000 );
265
265
  continue;
266
266
 
@@ -272,8 +272,6 @@ da_i.loop_to_create_project = async function( creation_options ) {
272
272
  } // ends type of non-response error
273
273
  } // ends type of response error
274
274
  } // ends try
275
-
276
- // TODO: Add a message that we're done trying to create a project, successful or not
277
275
  } // ends while
278
276
  }; // Ends da_i.loop_to_create_project()
279
277
 
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const log = require('./utils/log');
5
+ const session_vars = require('./utils/session_vars');
6
+
7
+ // import {loadConfiguration, loadSupport, runCucumber } from '@cucumber/cucumber/api';
8
+ const cucumber_api = require('@cucumber/cucumber/api');
9
+
10
+ (async function main() {
11
+ let argv = process.argv;
12
+
13
+ let just_args = argv.slice(2);
14
+
15
+ const environment = { cwd: process.cwd() };
16
+ const provided_config = {
17
+ "publishQuiet": true,
18
+ "require": "./lib/index.js",
19
+ "format": ["progress", "summary:cucumber-report.txt"],
20
+ "paths": ["docassemble/*/data/sources/*.feature"],
21
+ "retry": 1,
22
+ }
23
+
24
+ // If they're running it from an interview on their server instead of from GitHub
25
+ if ( session_vars.get_origin() === `interview` ) {
26
+ provided_config.paths.append(`/usr/share/docassemble/files/playgroundsources/${session_vars.get_user_id()}/${session_vars.get_user_project_name()}/*.feature`);
27
+ }
28
+
29
+ let tag_vals = just_args;
30
+ if ( session_vars.get_origin() === `interview` ) {
31
+ // Should tags be given as a string or a list? String would give option to
32
+ // give a boolean expression. TODO: offer a dropdown with available tags.
33
+ tag_vals = session_vars.get_tags().split(` `);
34
+ }
35
+
36
+ if (tag_vals.length > 0) {
37
+ // Cucumber expects tags in boolean expressions, like (@a0 or @a1) and @random.
38
+ // If we get a list of only tags, then "or" them all together
39
+ if (tag_vals.every((val) => val.startsWith(`@`))) {
40
+ provided_config.tags = tag_vals.join(` or `);
41
+ }
42
+ // If we get a list of seemingly no tags, assume they meant to use tags
43
+ else if (tag_vals.every((val) => !val.startsWith(`@`))) {
44
+ provided_config.tags = tag_vals.map((val) => `@${ val }`).join(` or `);
45
+ }
46
+ // If it's a mix of tags and no tags, it's probably a boolean expression!
47
+ else {
48
+ provided_config.tags = tag_vals.join(` `);
49
+ }
50
+ }
51
+
52
+
53
+ const { runConfiguration } = await cucumber_api.loadConfiguration({
54
+ provided: provided_config
55
+ }, environment);
56
+ var path = require('path');
57
+ var codeDir = path.dirname(require.main.filename);
58
+ const support = await cucumber_api.loadSupport({ support: {
59
+ requireModules: [`${ codeDir }/index.js`],
60
+ requirePaths: [ `${ codeDir }/index.js`],
61
+ importPaths: [],
62
+ }, sources: {paths: []}}, environment);
63
+
64
+ // TODO: Maybe only log these for debug?
65
+ console.log(`ALKiln run_cucumber.js configuration:`);
66
+ console.log(`%o`, runConfiguration);
67
+
68
+ const { success } = await cucumber_api.runCucumber({...runConfiguration, support});
69
+ console.log(`ALKiln run_cucumber.js succeeded:`);
70
+ console.log(`%o`, success);
71
+ const exitCode = success ? 0 : 1;
72
+ process.exitCode = exitCode;
73
+
74
+ // This is hardcoded information from `cucumber.js`. Now we on cucumber 8, we should
75
+ // change that the cucumber.json and actually parse the info from it.
76
+ // This code isn't used for anything other than detecting and removing color codes
77
+ let summary_file_name = 'cucumber-report.txt';
78
+ fs.readFile(summary_file_name, 'utf8', (err, data) => {
79
+ if (err) {
80
+ console.error(err);
81
+ return;
82
+ }
83
+
84
+ // Replace terminal color codes, if present
85
+ // https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#colors--graphics-mode
86
+ data = data.replace(/\x1b\[[0-9][0-9]?[0-9]?m/g, '');
87
+
88
+ // Put it in the correct file in the correct folder
89
+ let artifacts_path = session_vars.get_artifacts_path_name();
90
+ fs.appendFileSync( `${ artifacts_path}/${ log.debug_log_file }`, data);
91
+ });
92
+ })();
package/lib/scope.js CHANGED
@@ -2002,13 +2002,6 @@ module.exports = {
2002
2002
  if ( row_used.source ) { row_used.source.times_used += 1 }
2003
2003
  row_used.times_used += 1;
2004
2004
 
2005
- let { id } = scope.examinePageID( scope );
2006
- await scope.page.screenshot({
2007
- path: `./${ scope.paths.scenario }/pic-${Date.now()}-${ id }.jpg`,
2008
- type: 'jpeg',
2009
- fullPage: true
2010
- });
2011
-
2012
2005
  // TODO: special continue/navigation button function that handles url and all?
2013
2006
 
2014
2007
  // Have to catch errors right now or may get stuck in an infinite loop?
@@ -2022,7 +2015,6 @@ module.exports = {
2022
2015
  // Discuss moving this out of here. Having to pass in `id` just for
2023
2016
  // these messages smells bad. Con: Already a lot of code out there.
2024
2017
  error = await scope.waitUntilContinued( scope, { url: page_url, id });
2025
-
2026
2018
  // if ( error.was_found ) {
2027
2019
  // await scope.throwPageError( scope, { id: id });
2028
2020
  // }
@@ -2061,14 +2053,6 @@ module.exports = {
2061
2053
  if ( !did_navigate && ensure_navigation ) {
2062
2054
  // All fields on this page should be taken care of
2063
2055
  let page_url = await scope.page.url();
2064
-
2065
- let { id } = scope.examinePageID( scope );
2066
- await scope.page.screenshot({
2067
- path: `./${ scope.paths.scenario }/pic-${Date.now()}-${ id }.jpg`,
2068
- type: 'jpeg',
2069
- fullPage: true
2070
- });
2071
-
2072
2056
  await scope.continue( scope );
2073
2057
  // Have to catch errors right now or may get stuck in an infinite loop?
2074
2058
  // TODO: Don't catch errors - maybe the developer expected/wanted an error
@@ -2295,6 +2279,23 @@ module.exports = {
2295
2279
  return scope;
2296
2280
  }, // Ends scope.throwPageError()
2297
2281
 
2282
+ take_a_screenshot: async ( scope,{ path }) => {
2283
+ /* Takes a jpeg screenshot. Avoids destroying signatures. */
2284
+
2285
+ let fullPage = true;
2286
+ let signature_elem = await scope.page.$(scope.signature_selector);
2287
+ if ( signature_elem !== null ) {
2288
+ fullPage = false;
2289
+ }
2290
+
2291
+ await scope.page.screenshot({
2292
+ path: path,
2293
+ type: 'jpeg',
2294
+ fullPage: fullPage,
2295
+ });
2296
+
2297
+ }, // Ends scope.take_a_screenshot()
2298
+
2298
2299
 
2299
2300
  //#####################################
2300
2301
  //#####################################
@@ -2317,11 +2318,7 @@ module.exports = {
2317
2318
  name = `screenshot_on-${ id }-${ date }`;
2318
2319
  }
2319
2320
 
2320
- await scope.page.screenshot({
2321
- path: `./${ scope.paths.scenario }/${ name }.jpg`,
2322
- type: 'jpeg',
2323
- fullPage: true
2324
- });
2321
+ await scope.take_a_screenshot( scope, { path: `./${ scope.paths.scenario }/${ name }.jpg` });
2325
2322
 
2326
2323
  await scope.afterStep( scope );
2327
2324
  }, // Ends scope.steps.screenshot()
package/lib/steps.js CHANGED
@@ -92,7 +92,7 @@ BeforeAll(async () => {
92
92
  // Make the folder to store all the files for this run of the tests
93
93
  scope.paths.artifacts = files.make_artifacts_folder();
94
94
  // Save its name in a file. `session_vars` can get it back later.
95
- // This is used by at least clean_reports.js.
95
+ // This is used by at least run_cucumber.js.
96
96
  session_vars.save_artifacts_path_name( scope.paths.artifacts );
97
97
 
98
98
  scope.paths.report = `${ scope.paths.artifacts }/report.txt`;
@@ -103,7 +103,7 @@ BeforeAll(async () => {
103
103
  Before(async (scenario) => {
104
104
  // Create browser, which can't be created in BeforeAll() where .driver doesn't exist for some reason
105
105
  if (!scope.browser) {
106
- scope.browser = await scope.driver.launch({ headless: !session_vars.get_debug(), devtools: session_vars.get_debug() });
106
+ scope.browser = await scope.driver.launch({ args: ['--no-sandbox'], headless: !session_vars.get_debug(), devtools: session_vars.get_debug() });
107
107
  }
108
108
  // Clean up all previously existing pages
109
109
  for (const page of await scope.browser.pages()) {
@@ -386,12 +386,6 @@ When(/^(?:the user gets)?(?:I get)? to ?(?:the)?(?: ?question)?(?: id)? "([^"]+)
386
386
  if( row1.report_str > row2.report_str ) { return 1; }
387
387
  return 0;
388
388
  });
389
-
390
- await scope.page.screenshot({
391
- path: `./${ scope.paths.scenario }/pic-${Date.now()}-${ id }.jpg`,
392
- type: 'jpeg',
393
- fullPage: true
394
- });
395
389
 
396
390
  // Add full used table to report so it can be copied if needed.
397
391
  // TODO: Should we/How do we get this in the final scenario report instead of here?
@@ -852,11 +846,8 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
852
846
  let buttons = await scope.steps.set_random_page_vars( scope );
853
847
 
854
848
  // Take a screenshot of the page before continuing or ending
855
- await scope.page.screenshot({
856
- path: `${ scope.paths.random_screenshots }/random-${ Date.now() }.jpg`,
857
- type: `jpeg`,
858
- fullPage: true
859
- });
849
+ let path = `${ scope.paths.random_screenshots }/random-${ Date.now() }.jpg`;
850
+ await scope.take_a_screenshot( scope, { path: path });
860
851
 
861
852
  // Prep for the next loop to possibly stop. Signature page buttons
862
853
  // don't count as buttons in the way our field detects them
@@ -1125,27 +1116,23 @@ After(async function(scenario) {
1125
1116
  if ( !!scope.disable_error_screenshot ) {
1126
1117
  scope.addToReport(scope, {
1127
1118
  type: `row`,
1128
- value: `For security, ALKiln will not create a screenshot for this error. It's possible a secret is being used on this screen.`
1119
+ value: `For security, ALKiln will avoid creating a screenshot for this error. It's possible a secret is being used on this screen.`
1129
1120
  });
1130
1121
  } else {
1131
1122
 
1132
1123
  // Save/download a picture of the screen that's showing during the unexpected status
1133
1124
  // Save one copy in the outer-most artifact folder
1134
1125
  let scenario_filename = await scope.getSafeScenarioFilename( scope, { prefix: `error_on` });
1135
- await scope.page.screenshot({
1136
- path: `${ scope.paths.artifacts }/${ scenario_filename }.jpg`,
1137
- type: `jpeg`,
1138
- fullPage: true
1139
- });
1126
+ let path_outer = `${ scope.paths.artifacts }/${ scenario_filename }.jpg`;
1127
+ await scope.take_a_screenshot( scope, { path: path_outer });
1128
+
1140
1129
  // Save another copy in the artifact's Scenario folder
1141
1130
  let screenshot_name = `error_on`;
1142
1131
  let { id } = await scope.examinePageID( scope, 'none to match' );
1143
1132
  screenshot_name += `-${ id }`;
1144
- await scope.page.screenshot({
1145
- path: `${ scope.paths.scenario }/${ screenshot_name }.jpg`,
1146
- type: `jpeg`,
1147
- fullPage: true
1148
- });
1133
+ let path_scenario = `${ scope.paths.scenario }/${ screenshot_name }.jpg`;
1134
+ await scope.take_a_screenshot( scope, { path: path_scenario });
1135
+
1149
1136
  } // ends if scope.disable_error_screenshot
1150
1137
  } // ends if scope.page exists
1151
1138
 
package/lib/utils/log.js CHANGED
@@ -52,7 +52,8 @@ log.debug = function ({ type='', pre='', data='', post='' }) {
52
52
  };
53
53
 
54
54
  log.add_to_debug_log = function(value) {
55
- fs.appendFileSync(log.debug_log_file, value);
55
+ let artifacts_path = session_vars.get_artifacts_path_name();
56
+ fs.appendFileSync(`${ artifacts_path }/${ log.debug_log_file}`, value);
56
57
  };
57
58
 
58
59
  log.debug_log_file = 'debug_log.txt'
@@ -23,9 +23,19 @@ module.exports = session_vars;
23
23
  // These default to null
24
24
  // TODO: How to isolate debug elsewhere so this file can use the logger?
25
25
  session_vars.get_debug = function () { return process.env.DEBUG || null; };
26
+ session_vars.is_dev_env = function () { return process.env.DEV || null; }
27
+
26
28
  session_vars.get_dev_api_key = function () { return process.env.DOCASSEMBLE_DEVELOPER_API_KEY || null; };
27
29
  session_vars.get_repo_url = function () { return process.env.REPO_URL || null; };
28
- session_vars.is_dev_env = function () { return process.env.DEV || null; }
30
+
31
+ // Created by interview code when tests through an interview manually on the server
32
+ session_vars.get_origin = function () {
33
+ /** Possible values: 'interview', 'github'. In future, maybe 'playground' or 'dashboard'. */
34
+ return process.env._ORIGIN || null;
35
+ };
36
+ session_vars.get_user_project_name = function () { return process.env._PROJECT_NAME || null; };
37
+ session_vars.get_user_id = function () { return process.env._USER_ID || null; };
38
+ session_vars.get_tags = function () { return process.env._TAGS || null; };
29
39
 
30
40
  // More complex logic
31
41
  session_vars.get_server_reload_timeout = function () {
@@ -129,8 +139,12 @@ session_vars.save_project_name = function ( project_name ) {
129
139
  return file;
130
140
  }; // Ends save_project_name()
131
141
 
142
+ // TODO next: Add use of env var in here in case not through GitHub cli_playground
132
143
  session_vars.get_project_name = function () {
133
- /* Get the name of the current docassemble Project */
144
+ /* Get the name of the current docassemble Project */
145
+ if ( session_vars.get_origin() === 'interview' ) {
146
+ return session_vars.get_user_project_name();
147
+ }
134
148
  let json = JSON.parse( fs.readFileSync( runtime_config_path ));
135
149
  let project_name = json[ project_name_key ] || null;
136
150
  if ( session_vars.get_debug() ) { console.log( `ALKiln debug: Project name from file is "${ project_name }".` ); }
@@ -174,7 +188,7 @@ session_vars.save_artifacts_path_name = function ( path_name ) {
174
188
  console.log( `ALKiln debug: Stored name of artifacts directory "${ path_name }" locally.` );
175
189
  }
176
190
  return file;
177
- }; // Ends get_project_name()
191
+ }; // Ends save_artifacts_path_name()
178
192
 
179
193
  session_vars.get_artifacts_path_name = function () {
180
194
  /* Get the name of the current artifacts path. */
@@ -187,7 +201,7 @@ session_vars.get_artifacts_path_name = function () {
187
201
  } catch ( error ) {
188
202
  return null;
189
203
  }
190
- }; // Ends get_project_name()
204
+ }; // Ends get_artifacts_path_name()
191
205
 
192
206
  /**
193
207
  * Ensure all required environment variables exist. Add each missing variable
package/package.json CHANGED
@@ -1,14 +1,12 @@
1
1
  {
2
2
  "name": "@suffolklitlab/alkiln",
3
- "version": "4.10.3-feat-debug-cache",
3
+ "version": "4.10.4-cli-playground-1",
4
4
  "description": "Integrated automated end-to-end testing with docassemble, puppeteer, and cucumber.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
7
7
  "test": "npm run unit && npm run langs_setup && npm run cucumber -- $@",
8
- "cucumber_base": "run_cucumber(){ ./node_modules/.bin/cucumber-js \"$@\"; status=$?; ./lib/utils/clean_reports.js; return $status; }; run_cucumber",
9
- "cucumber": "run_base(){ npm run cucumber_base -- \"$@\" docassemble/*/data/sources/*.feature --retry 1; }; run_base",
10
- "cucumber_external": "run_cucumber(){ tmp_path=`pwd`; ( new_path=\"$1\"; shift; cd \"$new_path\"; npm run --prefix \"${tmp_path}\" cucumber_base -- \"$@\" \"$new_path\"/docassemble/*/data/sources/*.feature;) }; run_cucumber",
11
- "langs": "npm run langs_setup && ./node_modules/.bin/cucumber-js --require ./lib/index.js docassemble/*/data/sources/*_lang*.feature",
8
+ "cucumber": "./lib/run_cucumber.js",
9
+ "langs": "npm run langs_setup && npm run cucumber",
12
10
  "langs_setup": "./lib/utils/langs.js 'docassemble/*/data/sources/*.feature'",
13
11
  "langs_local": "npm run langs_setup && npm run local",
14
12
  "local": "npm run setup && npm run cucumber; npm run takedown",
@@ -36,13 +34,13 @@
36
34
  "homepage": "https://suffolklitlab.org/docassemble-AssemblyLine-documentation/docs/automated_integrated_testing/",
37
35
  "dependencies": {
38
36
  "@axe-core/puppeteer": "4.4.2",
39
- "@cucumber/cucumber": "7.3.2",
37
+ "@cucumber/cucumber": "8.6.0",
40
38
  "@faker-js/faker": "^7.3.0",
41
39
  "axios": "0.24.0",
42
40
  "chai": "4.2.0",
43
41
  "cheerio": "1.0.0-rc.10",
44
- "dotenv": "8.2.0",
45
42
  "deep-equal-in-any-order": "^2.0.0",
43
+ "dotenv": "8.2.0",
46
44
  "mocha": "9.2.0",
47
45
  "puppeteer": "13.1.3",
48
46
  "qs": "6.10.2",
@@ -52,6 +50,7 @@
52
50
  "bin": {
53
51
  "alkiln-setup": "./lib/docassemble/setup.js",
54
52
  "alkiln-takedown": "./lib/docassemble/takedown.js",
55
- "alkiln-langs": "./lib/utils/langs.js"
53
+ "alkiln-langs": "./lib/utils/langs.js",
54
+ "alkiln-run": "./lib/run_cucumber.js"
56
55
  }
57
56
  }
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const fs = require('fs');
4
- const log = require('./log');
5
- const session_vars = require('./session_vars');
6
-
7
- // This is hardcoded information from `cucumber.js`. Once we move to cucumber 8, we should
8
- // change that the cucumber.json and actually parse the info from it.
9
- // The file won't be used for anything other than detecting and removing color codes
10
- let summary_file_name = 'cucumber-report.txt';
11
- fs.readFile(summary_file_name, 'utf8', (err, data) => {
12
- if (err) {
13
- console.error(err);
14
- return;
15
- }
16
-
17
- // Replace terminal color codes, if present
18
- // https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#colors--graphics-mode
19
- data = data.replace(/\x1b\[[0-9][0-9]?[0-9]?m/g, '');
20
-
21
- // Put it in the correct file in the correct folder
22
- let artifacts_path = session_vars.get_artifacts_path_name();
23
- fs.appendFile( `${ artifacts_path }/${ log.debug_log_file }`, data, err => {
24
- if (err) {
25
- console.error(err);
26
- return;
27
- }
28
- }); // Ends appendFileSync
29
- });