NativeScript / nativescript-cli

Command-line interface for building NativeScript apps
https://www.npmjs.com/package/nativescript
Apache License 2.0
1.04k stars 195 forks source link

Unit tests run with --bundle does not bundle 3rd party libraries #4477

Closed cowboyd closed 5 years ago

cowboyd commented 5 years ago

Environment ✔ Getting NativeScript components versions information... ✔ Component nativescript has 5.4.0-2019-03-21-13075 version and is up to date. ✔ Component tns-core-modules has 5.3.0 version and is up to date. ✔ Component tns-android has 5.3.0 version and is up to date. ✔ Component tns-ios has 5.3.0 version and is up to date.

Describe the bug Webpack test bundle does not include 3rd party libraries. We're trying to unit test some of our library code that uses the @microstates/union. This works when the app is built, but when we try to run the unit tests, they fail with the error:

TypeError: undefined is not an object (evaluating 'modules[moduleId].call')

Which indicates that the microstate library is not bundled at all. Manually inspecting the built vendor.js, and bundle.js confirms that this is the case.

To Reproduce

  1. import a 3rd party library from within a unit test case. You don't even have to try and use it, just log it to the console.
  2. run yarn test ios --bundle

Expected behavior

  1. it resolves the module and dependencies from the node_modules directory and includes it in your application's vendor.js bundle.
  2. in this case, it should have the microstates and @microstates/union modules since they are being imported by our bluetooth library.

Sample project

Fatme commented 5 years ago

@cowboyd,

Yes, it doesn't work :(

I've just checked it and found that the problem is here https://github.com/NativeScript/nativescript-dev-webpack/blob/master/unit-testing-config-loader.js#L5. Actually nativescript-dev-webpack collects the dependencies only from tests/**/.js files. As your test is .ts file, it is not required so its dependencies are not collected. This is the reason why @microstates is not included in vendor.js.

I tried to manually change the above mentioned code from nativescript-dev-webpack:

`const testFilesRegExp = /tests\/.*\.ts/;`

After that I ran tns test ios --bundle and received the following output:

CONSOLE LOG Bluetooth =  [object Module]
CONSOLE LOG file:///app/vendor.js:2797:24: NSUTR: beginning test run
NativeScript / 10.3.1 (10.3.1; iPhone): Executed 0 of 1 SUCCESS (0 secs / 0 secs)
NativeScript / 10.3.1 (10.3.1; iPhone) Bluetooth Service starts out as being off FAILED
    undefined is not an object (evaluating 'bluetooth.isOff')

As you can see the bluetooth object is populated now - CONSOLE LOG Bluetooth = [object Module] but the test still doesn't pass. I assume this is expected as bluetooth.isOff is not exported from bluetooth.ts file. (correct me if I'm mistaken here)

I've played a little bit more with the code and was able to successfully run the tests with the following modifications:

bluetooth.test.ts

import * as bluetooth from '../bluetooth';

console.log('Bluetooth = ', bluetooth);

describe('Bluetooth Service', function () {
  it('starts out as being off', () => {
    const powerOn = bluetooth.ble.onPowerOn();
    expect(powerOn).to.equal(10);
  })
});

bluetooth.ts

import { Store, create } from 'microstates';
import State from "./bluetooth/bluetooth";

class BLE {
  onPowerOn() {
    return 10;
  }

  onPowerOff() {

  }
}

export const ble = new BLE();

export function Bluetooth(fn: (State) => any) {
  return Store(create(State), fn);
}
cowboyd commented 5 years ago

That's seems to fix it.

Don't worry so much about the imports, we were just fooling around with them to see if there was something that we had to change, I changed them back to the way they were, and we can now use the module as expected. In the meantime, we can try to fix it or vendor it.