@suffolklitlab/alkiln 5.15.0 → 5.15.1-fix-race-condition
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/.github/workflows/github_server.yml +1 -1
- package/.github/workflows/playground.yml +1 -1
- package/CHANGELOG.md +15 -1
- package/lib/scope.js +58 -18
- package/lib/utils/pdf_reader.js +9 -2
- package/npm-shrinkwrap.json +906 -949
- package/package.json +4 -8
|
@@ -160,7 +160,7 @@ jobs:
|
|
|
160
160
|
#### Developer note: You can probably leave the rest out
|
|
161
161
|
#### To learn more, see https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#optional-inputs
|
|
162
162
|
ALKILN_TAG_EXPRESSION: "${{ env.ALKILN_TAG_EXPRESSION }}"
|
|
163
|
-
|
|
163
|
+
ALKILN_VERSION: "@race"
|
|
164
164
|
|
|
165
165
|
#### Developer note: Example of making an issue when tests fail
|
|
166
166
|
#### that includes the text of the failure output file
|
package/CHANGELOG.md
CHANGED
|
@@ -43,7 +43,21 @@ Format:
|
|
|
43
43
|
-
|
|
44
44
|
-->
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
## [Unreleased]
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- Fixed race condition between navigating and extracting button text.
|
|
51
|
+
|
|
52
|
+
## [5.15.1] - 2025-08-05
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
|
|
56
|
+
- Updated dependencies. See [#1012](https://github.com/SuffolkLITLab/ALKiln/issues/1012).
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
|
|
60
|
+
- Fix pdfjs version mismatch with docassemble's most recent version of node. See ALKilnInThePlayground https://github.com/SuffolkLITLab/docassemble-ALKilnInThePlayground/issues/42.
|
|
47
61
|
|
|
48
62
|
## [5.15.0] - 2025-05-22
|
|
49
63
|
|
package/lib/scope.js
CHANGED
|
@@ -7,6 +7,7 @@ const { AxePuppeteer } = require('@axe-core/puppeteer');
|
|
|
7
7
|
const safe_filename = require("sanitize-filename");
|
|
8
8
|
// "en" is faster to import: https://github.com/faker-js/faker/issues/1114#issuecomment-1169532948
|
|
9
9
|
const faker = require('@faker-js/faker/locale/en').faker;
|
|
10
|
+
const { v4: uuidv4 } = require('uuid');
|
|
10
11
|
|
|
11
12
|
// Ours
|
|
12
13
|
const pdf_reader = require('./utils/pdf_reader');
|
|
@@ -254,23 +255,21 @@ module.exports = {
|
|
|
254
255
|
if ( options.waitForTimeout ) { await time.waitForTimeout( options.waitForTimeout ); }
|
|
255
256
|
}, // Ends afterStep
|
|
256
257
|
|
|
257
|
-
tapElementAndNavigate: async function(scope, { elem, waitForTimeout=
|
|
258
|
-
/** Tap a given element, detect navigation, and do appropriate related things.
|
|
259
|
-
* TODO: not quite sure if we'll be using `waitForTimeout`. */
|
|
258
|
+
tapElementAndNavigate: async function(scope, { elem, waitForTimeout=null }) {
|
|
259
|
+
/** Tap a given element, detect navigation, and do appropriate related things. */
|
|
260
260
|
|
|
261
261
|
let start_url = await scope.page.url(); // so we can later check for navigation
|
|
262
262
|
|
|
263
263
|
await scope.tapElementAndStayOnPage(scope, {
|
|
264
264
|
elem,
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
elem.evaluate( (el) => { return el.click(); })
|
|
268
|
-
]
|
|
265
|
+
promise_returners: [
|
|
266
|
+
() => { return scope.nav_race(scope, {}).result; },
|
|
267
|
+
() => { return elem.evaluate( (el) => { return el.click(); }) },
|
|
268
|
+
]
|
|
269
269
|
});
|
|
270
270
|
|
|
271
|
-
//
|
|
272
|
-
//
|
|
273
|
-
// Maybe url change + trigger var change? Maybe just trigger var?
|
|
271
|
+
// For other ideas for detecting navigation, see
|
|
272
|
+
// https://github.com/SuffolkLITLab/ALKiln/issues/229
|
|
274
273
|
let end_url = await scope.page.url();
|
|
275
274
|
let navigated = start_url !== end_url;
|
|
276
275
|
|
|
@@ -282,36 +281,77 @@ module.exports = {
|
|
|
282
281
|
let { question_has_id, id, id_matches } = await scope.examinePageID( scope, 'none to match' );
|
|
283
282
|
|
|
284
283
|
// If navigation, wait for 200ms to let things finish loading and moving
|
|
285
|
-
await scope.afterStep(scope, {
|
|
284
|
+
await scope.afterStep(scope, {
|
|
285
|
+
waitForTimeout: ( waitForTimeout || 200 ),
|
|
286
|
+
navigated: true
|
|
287
|
+
});
|
|
286
288
|
} else {
|
|
287
|
-
|
|
289
|
+
// Discuss: Fail here or later since the test didn't manage to navigate?
|
|
290
|
+
await scope.afterStep(scope, {
|
|
291
|
+
waitForTimeout: ( waitForTimeout || 0 ),
|
|
292
|
+
navigated: false
|
|
293
|
+
});
|
|
288
294
|
}
|
|
289
295
|
}, // Ends scope.tapElementAndNavigate()
|
|
290
296
|
|
|
291
|
-
|
|
297
|
+
nav_race: function(scope, opts={}) {
|
|
298
|
+
/**
|
|
299
|
+
* Return a Promise for a race that detects which, if any, navigation result
|
|
300
|
+
* a navigation had.
|
|
301
|
+
*
|
|
302
|
+
* Warning: Unable to effectively add event listener for `daPageLoad`. Gets
|
|
303
|
+
* overwritten on every page load.
|
|
304
|
+
*
|
|
305
|
+
* @returns
|
|
306
|
+
* { obj }
|
|
307
|
+
* ok { bool } - True if no unexpected errors
|
|
308
|
+
* messages {[ str ]} - Any error or info messages
|
|
309
|
+
* errors {[ Error ]} - Any Errors that happened
|
|
310
|
+
* result { Promise } with result of { obj } - HTTP response or other data
|
|
311
|
+
* aborters {[ obj ]} - Abort signals for all the Promises involved
|
|
312
|
+
* */
|
|
313
|
+
let ok, messages, errors;
|
|
314
|
+
let aborters = [];
|
|
315
|
+
|
|
316
|
+
let result = Promise.race([
|
|
317
|
+
scope.page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
|
|
318
|
+
]);
|
|
319
|
+
|
|
320
|
+
return { result, aborters, ok, messages, errors, };
|
|
321
|
+
}, // Ends scope.nav_race()
|
|
322
|
+
|
|
323
|
+
tapElementAndStayOnPage: async function(scope, { elem, promise_returners=null }) {
|
|
292
324
|
/** Tap a given element, detect navigation, and do appropriate related things.
|
|
293
|
-
|
|
325
|
+
*
|
|
326
|
+
* @param elem { obj } - element to tap
|
|
327
|
+
* @param promise_returners {[ func -> Promise ]} - list of functions that
|
|
328
|
+
* return promises
|
|
294
329
|
*/
|
|
295
330
|
await scope.guard_against_missing_tap_element(scope, { elem });
|
|
296
331
|
|
|
297
332
|
// Get the text on the button or link for a potential error message later
|
|
298
333
|
let tapperText = await (await elem.getProperty('textContent')).jsonValue();
|
|
299
334
|
|
|
300
|
-
|
|
335
|
+
let click_promises = null;
|
|
336
|
+
if ( promise_returners ) {
|
|
337
|
+
click_promises = Promise.all(promise_returners.map( pr_ret => pr_ret() ));
|
|
338
|
+
} else {
|
|
339
|
+
click_promises = elem.click();
|
|
340
|
+
}
|
|
301
341
|
|
|
302
342
|
// TODO: implement and use scope.handle_possible_timeout()
|
|
303
343
|
try {
|
|
304
|
-
//
|
|
344
|
+
// Server error loads page, so keeping things shorter by not looking
|
|
305
345
|
// for that text too. Also, puppeteer will ensure proper timeout.
|
|
306
346
|
await Promise.race([
|
|
307
|
-
|
|
347
|
+
click_promises,
|
|
308
348
|
// This is meant to detect user-visible alerts/errors,
|
|
309
349
|
// not breaking errors in the testing code.
|
|
350
|
+
// No need for aborters since puppeteer has its own timeout
|
|
310
351
|
scope.page.waitForSelector('.alert-danger', { visible: true }),
|
|
311
352
|
scope.page.waitForSelector('.da-has-error', { visible: true }),
|
|
312
353
|
]);
|
|
313
354
|
} catch ( error ) {
|
|
314
|
-
|
|
315
355
|
if ( error.name === `TimeoutError` ) {
|
|
316
356
|
let non_reload_report_msg = `After ALKiln tapped "${ tapperText }" it took too long to load the next page.`;
|
|
317
357
|
await scope.handle_page_timeout_error( scope, { non_reload_report_data: {
|
package/lib/utils/pdf_reader.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
// All functions dealing with getting information from PDFs
|
|
2
2
|
|
|
3
|
-
const pdfjs_lib = require("pdfjs-dist/legacy/build/pdf.js");
|
|
4
3
|
const diff_lib = require("diff");
|
|
5
4
|
|
|
5
|
+
async function importPdfLib() {
|
|
6
|
+
// pdfjs only supports nodejs in its legacy build
|
|
7
|
+
// https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions/c47467dd05966b686af96f55ce061dab2f96c306
|
|
8
|
+
const pdfjsLib = await import("pdfjs-dist/legacy/build/pdf.mjs");
|
|
9
|
+
return pdfjsLib;
|
|
10
|
+
}
|
|
11
|
+
|
|
6
12
|
let _load_pdf = async function(pdf_path) {
|
|
7
13
|
// Simple wrapper to get the document
|
|
14
|
+
let pdfjs_lib = await importPdfLib();
|
|
8
15
|
return await pdfjs_lib.getDocument({
|
|
9
16
|
url: pdf_path,
|
|
10
17
|
// https://github.com/mozilla/pdf.js/issues/4244#issuecomment-1479534301
|
|
@@ -110,4 +117,4 @@ pdf_reader.compare_pdfs = async function(existing_pdf_path, new_pdf_path) {
|
|
|
110
117
|
return null;
|
|
111
118
|
}; // End compare_pdfs
|
|
112
119
|
|
|
113
|
-
module.exports = pdf_reader;
|
|
120
|
+
module.exports = pdf_reader;
|