@datacamp/learn-vm-scripts 1.13.7 → 1.13.8

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.
Files changed (2) hide show
  1. package/dist/index.cjs +21 -6
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -285,6 +285,7 @@ var resetChrome = async ({ userDataDir }) => {
285
285
  var USERNAME_SELECTOR = 'input[autocomplete="username"]';
286
286
  var PASSWORD_SELECTOR = 'input[autocomplete="current-password"]';
287
287
  var OTP_SELECTOR = 'input[autocomplete="one-time-code"]';
288
+ var SELECTOR_TIMEOUT = 7500;
288
289
  async function loginToSnowflake({
289
290
  url,
290
291
  username,
@@ -294,7 +295,7 @@ async function loginToSnowflake({
294
295
  }) {
295
296
  logger.log("Navigating to Snowflake login page...");
296
297
  await page.goto(ensureHttps(url));
297
- await page.waitForSelector(USERNAME_SELECTOR);
298
+ await page.waitForSelector(USERNAME_SELECTOR, { timeout: SELECTOR_TIMEOUT });
298
299
  const usernameField = await page.$(USERNAME_SELECTOR);
299
300
  if (!usernameField) {
300
301
  throw new Error("Username field not found");
@@ -302,7 +303,7 @@ async function loginToSnowflake({
302
303
  await usernameField.click({ clickCount: 3 });
303
304
  await page.keyboard.press("Backspace");
304
305
  await page.type(USERNAME_SELECTOR, username);
305
- await page.waitForSelector(PASSWORD_SELECTOR);
306
+ await page.waitForSelector(PASSWORD_SELECTOR, { timeout: SELECTOR_TIMEOUT });
306
307
  const passwordField = await page.$(PASSWORD_SELECTOR);
307
308
  if (!passwordField) {
308
309
  throw new Error("Password field not found");
@@ -310,7 +311,9 @@ async function loginToSnowflake({
310
311
  await passwordField.click({ clickCount: 3 });
311
312
  await page.keyboard.press("Backspace");
312
313
  await page.type(PASSWORD_SELECTOR, password);
313
- await page.waitForSelector("button:not([disabled])");
314
+ await page.waitForSelector("button:not([disabled])", {
315
+ timeout: SELECTOR_TIMEOUT
316
+ });
314
317
  const buttons = await page.$$("button:not([disabled])");
315
318
  let signInButtonHandle;
316
319
  for (const btn of buttons) {
@@ -329,9 +332,21 @@ async function loginToSnowflake({
329
332
  await signInButtonHandle.click();
330
333
  if (otp != null) {
331
334
  logger.log("Handling Snowflake OTP challenge...");
332
- await page.waitForSelector(OTP_SELECTOR, {
333
- timeout: 15e3
334
- });
335
+ const MFA_LOCK_TEXT = "no valid Multi-Factor Authentication (MFA) methods are available";
336
+ const result = await Promise.race([
337
+ page.waitForSelector(OTP_SELECTOR, { timeout: SELECTOR_TIMEOUT }).then(() => "otp"),
338
+ page.waitForFunction(
339
+ `document.body.innerText.includes('${MFA_LOCK_TEXT}')`,
340
+ {
341
+ timeout: SELECTOR_TIMEOUT
342
+ }
343
+ ).then(() => "mfa_locked")
344
+ ]);
345
+ if (result === "mfa_locked") {
346
+ throw new Error(
347
+ "Snowflake account is temporarily locked due to no valid MFA methods available"
348
+ );
349
+ }
335
350
  const otpField = await page.$(OTP_SELECTOR);
336
351
  if (!otpField) {
337
352
  throw new Error("OTP field not found");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datacamp/learn-vm-scripts",
3
- "version": "1.13.7",
3
+ "version": "1.13.8",
4
4
  "repository": "git@github.com:datacamp-engineering/learn-vm-scripts.git",
5
5
  "description": "Scripts used by VMs in learn.",
6
6
  "main": "./dist/index.cjs",