Node.js adds " " to the expected as it is a String. Is there anyway I can remove the " "

Viewed 82

I have written a unit test using 2 different logics but both lead to the same issue.

Logic 1:

describe('aresFileCopier', () => {
  test('log error', async () => {
    await registerDB('ares-test', {
      client: 'mssql',
      connection: {
        host: 'test-mssql',
        database: 'master',
        user: 'BAD_USER',
        password: 'BAD_Password',
        port: 1433,
      },
    });
    //eslint-disable-next-line jest/valid-expect
    expect(
      exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO')
    ).rejects.toBe('[Error: Login failed for user \'BAD_USER\'.]');

    await shutdown();
  });

And the output 1 is as follows:

    expect(received).rejects.toBe(expected) // Object.is equality

    Expected: "[Error: Login failed for user 'BAD_USER'.]"
    Received: [Error: Login failed for user 'BAD_USER'.]

Logic 2:

describe('aresFileCopier', () => {
  test('log error', async () => {
    await registerDB('ares-test', {
      client: 'mssql',
      connection: {
        host: 'test-mssql',
        database: 'master',
        user: 'BAD_USER',
        password: 'BAD_Password',
        port: 1433,
      },
    });
      try{
      await exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO');
    }catch(err){
       console.log(err);
      // eslint-disable-next-line jest/no-conditional-expect
      expect(err).toBe('[Error: Login failed for user \'BAD_USER\'.]');
    }
  });

The output 2 is:

   Expected: "[Error: Login failed for user 'BAD_USER'.]"
   Received: [Error: Login failed for user 'BAD_USER'.]

The console.log(err) gives:

 console.log
    ConnectionError: Login failed for user 'BAD_USER'.
        at Login7TokenHandler.onErrorMessage (/home/rjohar/narada/node_modules/tedious/src/token/handler.ts:268:19)
        at Readable.<anonymous> (/home/rjohar/narada/node_modules/tedious/src/token/token-stream-parser.ts:23:7)
        at Readable.emit (node:events:527:28)
        at addChunk (node:internal/streams/readable:315:12)
        at readableAddChunk (node:internal/streams/readable:289:9)
        at Readable.push (node:internal/streams/readable:228:10)
        at next (node:internal/streams/from:98:31)
        at processTicksAndRejections (node:internal/process/task_queues:96:5) {
      code: 'ELOGIN',
      isTransient: undefined

Node.js adds " " to the expected as it is a String but the received is an error, therefore it does not have any " ".

I have tried using err.toString() and err.message but they both lead to a run time error Object is of type unknown on line 26 which is the expect(err.toString()).toBe('Error: Login failed for user \'BAD_USER\'.')

The exec function looks like

export function exec(name: string, stmt: string) {
  log(DEBUG, `Raw SQL ${name}${stmt}}`);
  return connection[name].raw(stmt);
}

Is there any way I can remove the quotation marks?

How can I overcome this error?

PS: I have tried .toThrow but I get an error the function does not throw. I believe it is due to the fact it rejects registerDB.

2 Answers

err.toString() lead to an error Object is of type unknown, therefore trying this worked for me.

describe('aresFileCopier', () => {
  test('log error', async () => {
    await registerDB('ares-test', {
      client: 'mssql',
      connection: {
        host: 'test-mssql',
        database: 'master',
        user: 'BAD_USER',
        password: 'BAD_Password',
        port: 1433,
      },
    });
    try {
      await exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO');
    } catch (err:any) {
      expect(err.toString).toMatch(/Login failed for user 'BAD_USER'/);
    }
  });
});

I think you can try this. You want the error.message string:

describe('aresFileCopier', () => {
  test('log error', async () => {
    await registerDB('ares-test', {
      client: 'mssql',
      connection: {
        host: 'test-mssql',
        database: 'master',
        user: 'BAD_USER',
        password: 'BAD_Password',
        port: 1433,
      },
    });
    try {
      await exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO');
    } catch (err) {
      expect(err.message).toEqual('Login failed for user \'BAD_USER\'.');
    }
  });
});

I did not test this, but I use this approach in all my tests and it works just fine.

EDIT

Maybe it is because the way the child process outputs to STDERR. I just tested with some other commands, and they are a mess. Sometimes they come in multiple lines and with weird spaces. So when this happens, I usually do a regex pattern match.

like:

expect(e.message.replace(/\n/g, '')).toMatch(/.*login.*failed.*BAD_USER/i)

And make sure you are promisifying the exec function like this:

const util = require('node:util');
const exec = util.promisify(require('node:child_process').exec);

async function lsExample() {
  try {
    await exec('commandthatdoesnotexist');
  } catch (e) {
    console.log(e.message.replace(/\n/g, ''));
  }
}

Otherwise, you have to pass a callback to exec to access the error.

Related