Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protractor oracledb connection failing with NoSuchSessionError #1002

Closed
bhoppeadoy opened this issue Nov 1, 2018 · 11 comments
Closed

Protractor oracledb connection failing with NoSuchSessionError #1002

bhoppeadoy opened this issue Nov 1, 2018 · 11 comments
Labels

Comments

@bhoppeadoy
Copy link

bhoppeadoy commented Nov 1, 2018

Node v8.9.4
node-oracledb v3.0.0
protractor v5.4.0

I'm trying to run a data-driven protractor test. First thing is run a query against oracle table to return a set of data. Then loop over that data calling other specs. The oracle connection is failing without an error. So I run in debug mode I get this uncaught exception:

NoSuchSessionError: This driver instance does not have a valid session ID (did you call WebDriver.quit()?) and may no longer be used.
    at session_.flow_.promise (C:\Users\me\repos\wbhtml5\designer-e2e\node_modules\selenium-webdriver\lib\webdriver.js:847:16)
    at new Promise (<anonymous>)
    at SimpleScheduler.promise (C:\Users\me\repos\wbhtml5\designer-e2e\node_modules\selenium-webdriver\lib\promise.js:2242:12)
    at promise.finally (C:\Users\me\repos\wbhtml5\designer-e2e\node_modules\selenium-webdriver\lib\webdriver.js:846:34)
    at promise.then.error (C:\Users\me\repos\wbhtml5\designer-e2e\node_modules\selenium-webdriver\lib\promise.js:1684:12)
I can't figure out why I'm getting Promise errors or session errors. I'm not using the browser/webdriver yet I just want to connect to oracle.

Here's my test spec that protractor is running that's setting up the connection:

test.js

import ProductFolderSpec from '../../specs/product-folder.e2e-spec';
import dbms = require('../../database');

// Connect to oracle and get list of parts
dbms.getProductFolderPartsCallback(dbms.PFPartKind.Switcher, dbms.PFPartStatus.Production, runProductFolderCallback);

// Callback function to loop over list of parts
function runProductFolderCallback(err, result) {
  const partsToTest = JSON.parse(result);
  partsToTest.forEach(part => {
     ProductFolderSpec.OpenProductFolder(part);
  });
}

This is database.js

import Common from './common';
import credentials = require('./credentials');
import oracledb = require('oracledb');

export function getProductFolderPartsCallback(partType: PFPartKind, partStatus: PFPartStatus, callback) {
  const dbms = oracledb;
  dbms.fetchAsString = [ oracledb.CLOB ];

  const cred = credentials.getCredential(credentials.TestCredentialKind.SomeDB);

  dbms.getConnection({
    user: cred.Userid,
    password: cred.Password,
    connectString: cred.ConnectionString
  },
    function (connErr, conn) {
      if (connErr) {
        Common.error(`getProductFolderParts: connection error: ${connErr}.`, true);
        return callback(connErr);
      }

      const sqlCmd = 'SELECT PART_JSON FROM WEBENCHDB.ODT_PRODUCT_FOLDER_PARTS';

      conn.execute(sqlCmd, function (queryErr, result) {
        if (queryErr) {
          Common.error(`getProductFolderParts: query error: ${queryErr}`, true);
          closeConnection(conn);
          return callback(queryErr);
        }

        let resultJSON = '';

        (result.rows as any[]).forEach(row => {
          if (resultJSON.length === 0) {
            resultJSON = `[ ${row[0]}`;
          } else {
            resultJSON = resultJSON + `, ${row}`;
          }
        });

        resultJSON = resultJSON + ']';

        closeConnection(conn);

        return callback(null, resultJSON);
      }
      );
    });
}

function closeConnection(conn) {
  conn.close(function (err) {
    if (err) {
      Common.error(`getProductFolderParts: connection close error: ${err}`, true);
    } else {
      Common.info(`getProductFolderParts: connection closed`, true);
    }
  });
}

Is there another way that I'm supposed to set this up?

@dmcghan
Copy link

dmcghan commented Nov 1, 2018

@bhoppeadoy Can you show us verify-design.e2e-spec?

Also, is this needed/correct?

        let resultJSON = '';

        (result.rows as any[]).forEach(row => {
          if (resultJSON.length === 0) {
            resultJSON = `[ ${row[0]}`;
          } else {
            resultJSON = resultJSON + `, ${row}`;
          }
        });

        resultJSON = resultJSON + ']';

Maybe this is better?

resultJSON  = JSON.stringify(result.rows);

@bhoppeadoy
Copy link
Author

bhoppeadoy commented Nov 1, 2018

@dmcghan Good point on the JSON.stringify(), not sure why the developer did it that way.

I've updated the example to call ProductFolderSpec.OpenProductFolder(). Basically what I need the test to do is get a list of parts and their associated properties from an oracle database. Then for each part run the below spec.

product-folder.e2e-spec.ts

import 'mocha';
import { expect } from 'chai';
import ProductFolderPage from '../pages/product-folder.po';
import Common from '../common';
const globals: any = global;

export default class ProductFolderSpec {
  static OpenProductFolder(part) {
    describe('Product Folder Page : ', function() {
      let pfFailure = false;

      before(function() {
        globals.currentSpec = this;
        Common.info('[BEGIN DESCRIBE] ' + this.test.parent.title);
        // Reset global error
        globals.fatalError = false;
      });

      beforeEach(function() {
        globals.currentSpec = this;
        Common.info('[BEGIN SPEC] ' + this.currentTest.title);
        if (pfFailure) {
          Common.warn(' - This test skipped due to previous error.');
          this.currentTest.fn = function() { this.skip(); };
        }
      });

      afterEach(async function() {
        if (this.currentTest.state === 'failed') {
          pfFailure = true;
          await Common.createScreenshot();
        }
        Common.info('[END SPEC] ' + this.currentTest.title + ' - ' + this.currentTest.state);
      });

      after(function() {
        if (pfFailure) {
          globals.fatalError = true;
        }
        Common.info('[END DESCRIBE] ' + this.test.parent.title);
      });

      it('Should open Product Folder page.', async function() {
        this.timeout(60000);
        await ProductFolderPage.navigateTo(part.properties.ProductFolderLink);
      });

      if (part.properties.production === 'Y') { // Production Part
        it('Should verify product folder page exists', async function() {
          const isValid = await ProductFolderPage.isPageValid();
          expect(isValid).to.be.equal(true, 'Product Folder page does not exist.');
        });

        it('Part should not be NRND', async function() {
          const isNRND = await ProductFolderPage.isPartNRND();
          expect(isNRND).to.be.equal(false, 'Part is Not Recommended for New Designs.');
        });

        it('Should have panel', async function() {
          const isPresent = await ProductFolderPage.isPanelPresent();
          expect(isPresent).to.be.equal(true, 'Panel does not exist.');
        });
      } else { // Development Part
        it('Should not have panel for development part', async function() {
          const validPage = await ProductFolderPage.isPageValid();
          if (validPage) {
            const isPresent = await ProductFolderPage.isPanelPresent();
            expect(isPresent).to.be.equal(false, 'Panel exists for development part.');
          }
        });
      }
    });
  }

@cjbj
Copy link
Member

cjbj commented Nov 1, 2018

Just checking: you're using node-oracledb in the mid-tier right, not in Angular? See #957 (comment)

@cjbj cjbj added the question label Nov 1, 2018
@dmcghan
Copy link

dmcghan commented Nov 1, 2018

@bhoppeadoy Try commenting out this line in product-folder.e2e-spec.ts.

await Common.createScreenshot();

@bhoppeadoy
Copy link
Author

Just checking: you're using node-oracledb in the mid-tier right, not in Angular? See #957 (comment)

No, this is not in an Angular project. This is in a Protractor/Selenium End-to-End test.

@bhoppeadoy
Copy link
Author

@bhoppeadoy Try commenting out this line in product-folder.e2e-spec.ts.

await Common.createScreenshot();

@dmcghan it never reaches that code. The exception is thrown in dbms.getConnection(). For simplification, you can remove product-folder.e2e-spec.ts from the call and just have this:

// Connect to oracle and get list of parts
dbms.getProductFolderPartsCallback(dbms.PFPartKind.Switcher, dbms.PFPartStatus.Production, runProductFolderCallback);

// Callback function to loop over list of parts
function runProductFolderCallback(err, result) {
  const partsToTest = JSON.parse(result);
}

@dmcghan
Copy link

dmcghan commented Nov 2, 2018

@bhoppeadoy How do you know where the exception is thrown. I don't see any line numbers in the error stack you showed. Maybe we're missing the output you're seeing?

Earlier you said:

The oracle connection is failing without an error.

What makes you believe this is true?

@bhoppeadoy
Copy link
Author

bhoppeadoy commented Nov 2, 2018

I'm not getting any type of error printed to the console when this is ran, so I'm not sure what exactly is failing. When I run in debug mode, I put a breakpoint in database.js at

  dbms.getConnection({

and one at

    function (connErr, conn) {

After continuing from the first breakpoint I get the uncaught exception thrown. It never reaches the second breakpoint. The exception is thrown from webdriver.js

@dmcghan
Copy link

dmcghan commented Nov 2, 2018

@bhoppeadoy I still don't see how that the Oracle connection is failing without an error. As you say, the error is from webdriver.js, not node-oracledb.

Could you please show us common.js? I'm guessing that even if you never get to the point of executing createScreenshot, there's some initialization code that's causing the problem.

@bhoppeadoy
Copy link
Author

bhoppeadoy commented Nov 2, 2018

@dmcghan I even removed common.js to see if that was doing it but same issue. I agree that someting is being initialized as part of the test that is causing it. Probably something inherent with how Protractor/Selenium/Webdriver works that is causing it.

I moved the call to getProductFolderParts() in the onPrepare() function of the protractor.conf.js file. This way the oracle connection is called before any other Protractor setup has happened. From there, it works and I get back the data that I'm wanting.

This should solve my issue now. Thanks for working through this with me.

@dmcghan
Copy link

dmcghan commented Nov 3, 2018

@bhoppeadoy I'm glad you got it working!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants