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

NativeScript Support #994

Open
wSedlacek opened this issue Sep 8, 2021 · 15 comments
Open

NativeScript Support #994

wSedlacek opened this issue Sep 8, 2021 · 15 comments
Labels
🚀 Feature Request new suggested feature

Comments

@wSedlacek
Copy link

wSedlacek commented Sep 8, 2021

🚀 Feature Proposal

Support NativeScriptTestingModule.

Motivation

NativeScript is maturing a lot, recently doing a complete overhaul of their Angular support.

Example

From what I can tell from their documentation the only major blocker here is the hard coded browser testing module.

If that could be injected to be arbitrary then every thing else can be handled in the project configuration.

import '@nativescript/core/globals';
import '@nativescript/angular/polyfills';
import '@nativescript/zone-js/dist/pre-zone-polyfills';
import 'zone.js';
import '@nativescript/zone-js';
import 'zone.js/testing';
import { TestBed } from '@angular/core/testing';
import { NativeScriptTestingModule } from '@nativescript/angular/testing';
import { platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';

TestBed.initTestEnvironment(NativeScriptTestingModule, platformBrowserDynamicTesting());
@wSedlacek wSedlacek added the 🚀 Feature Request new suggested feature label Sep 8, 2021
@ahnpnl
Copy link
Collaborator

ahnpnl commented Sep 8, 2021

Look quite similar to the current setup file we currently have https://github.com/thymikee/jest-preset-angular/blob/master/src/config/setup-jest.ts , small differences are the importing of nativescript files.

@wSedlacek
Copy link
Author

When playing around with it I found this error.

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    import { Observable } from '../data/observable';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import '@nativescript/core/globals';
        | ^
      2 | import '@nativescript/angular/polyfills';
      3 | import '@nativescript/zone-js/dist/pre-zone-polyfills';
      4 | import 'jest-preset-angular';

Seems like we need commonjs nativescript modules to work under jest 🤔
Maybe a transformer can solve this without needing nativescript to change their module format.

@ahnpnl
Copy link
Collaborator

ahnpnl commented Sep 8, 2021

that error is because Jest detects that the import { Observable } from '../data/observable'; exists in import '@nativescript/core/globals'; is not CommonJS module.

You can use transformIgnorePatterns to tell Jest to explicitly transform the files you need. It looks to me like '@nativescript/core/globals' is shipped as ESM module.

Another way is using Jest in ESM mode.

@wSedlacek
Copy link
Author

Great! We are making progress.
Got the esm errors out of the way.

Now to figure out the resolutions for .ios.js and .android.js files.

    Cannot find module '../timer' from 'node_modules/@nativescript/core/globals/index.js'

Screen Shot 2021-09-08 at 00 20 53

@ahnpnl
Copy link
Collaborator

ahnpnl commented Sep 8, 2021

that one requires moduleNameMapper to be configured :)

@wSedlacek
Copy link
Author

Looks like this did the trick for that one.

  haste: {
    defaultPlatform: 'ios',
    platforms: ['ios', 'android', 'native'],
  },

Although we may have found the limit of this as we are getting into missing globals.

  ● Test suite failed to run

    ReferenceError: NSObject is not defined

      at Object.<anonymous> (node_modules/@nativescript/core/timer/index.ios.js:55:3)
      at Object.loader (packages/core/globals/index.ts:304:40)
      at loadModule (packages/core/globals/index.ts:244:31)
      at Window.get [as setTimeout] (packages/core/globals/index.ts:21:21)
      at getNodeSystem (../../node_modules/typescript/lib/typescript.js:7432:29)
      at ../../node_modules/typescript/lib/typescript.js:7980:19
      at ../../node_modules/typescript/lib/typescript.js:7987:7
      at Object.<anonymous> (../../node_modules/typescript/lib/typescript.js:7997:3)
      at ../../../../packages/compiler-cli/src/ngtsc/reflection/src/host.ts:9:1
      at ../../node_modules/@angular/compiler-cli/src/ngtsc/reflection/src/host.js:10:17
      at Object.<anonymous> (../../node_modules/@angular/compiler-cli/src/ngtsc/reflection/src/host.js:16:3)
      at ../../../../packages/compiler-cli/src/ngtsc/reflection/index.ts:9:1
      at ../../node_modules/@angular/compiler-cli/src/ngtsc/reflection/index.js:10:17
      at Object.<anonymous> (../../node_modules/@angular/compiler-cli/src/ngtsc/reflection/index.js:16:3)
      at Object.<anonymous> (src/test-setup.ts:4:1)
      at TestScheduler.scheduleTests (../../node_modules/@jest/core/build/TestScheduler.js:333:13)
      at runJest (../../node_modules/@jest/core/build/runJest.js:387:19)
      at _run10000 (../../node_modules/@jest/core/build/cli/index.js:408:7)
      at Object.runCLI (../../node_modules/@jest/core/build/cli/index.js:261:3)

@ahnpnl
Copy link
Collaborator

ahnpnl commented Sep 8, 2021

NSObject must be defined in some of the scripts which you need to let that script run first to setup global objects before node_modules/@nativescript/core/timer/index.ios.js is loaded

@wSedlacek
Copy link
Author

I think that is intended to be bound to a native implementation via the NativeScript runtime, so not sure we can solve that in a node environment without polly filling it or something.

In any case, it would be nice to configure that testing module maybe an interface like this.

import { configurePreset } from 'jest-preset-angular';
import { NativeScriptTestingModule } from '@nativescript/angular/testing';

import '@nativescript/core/globals';
import '@nativescript/angular/polyfills';
import '@nativescript/zone-js/dist/pre-zone-polyfills';
configurePreset(NativeScriptTestingModule);
import '@nativescript/zone-js';

Not sure this would give the exact execution ordered needed given the import side effects.
Iirc there is some hoisting going on there some where.

@ahnpnl
Copy link
Collaborator

ahnpnl commented Sep 8, 2021

Regarding to global Node objects, you might need to do

import { NSObject } from <somewhere>

global['NSObject']= NSObject;

something like that

I think that is intended to be bound to a native implementation via the NativeScript runtime, so not sure we can solve that in a node environment without polly filling it or something.

In any case, it would be nice to configure that testing module maybe an interface like this.

import { configurePreset } from 'jest-preset-angular';
import { NativeScriptTestingModule } from '@nativescript/angular/testing';

import '@nativescript/core/globals';
import '@nativescript/angular/polyfills';
import '@nativescript/zone-js/dist/pre-zone-polyfills';
configurePreset(NativeScriptTestingModule);
import '@nativescript/zone-js';

Not sure this would give the exact execution ordered needed given the import side effects.
Iirc there is some hoisting going on there some where.

I think for NativeScript, the current setup won't be reusable. It looks to me like NativeScript environment would require different set of imported files.

I was thinking about having 2 separate setup files, one is the existing one, one is for NativeScript. So you would do in your local setup jest file

import 'jest-preset-angular/setup-jest-nativescript'

for example.

Also there would be separate presets for NativeScript which can be created in https://github.com/thymikee/jest-preset-angular/tree/master/presets

@wSedlacek
Copy link
Author

wSedlacek commented Sep 8, 2021

Having a separate entry point would be fine great if you want to go the whole 9 yards in support.

@ahnpnl
Copy link
Collaborator

ahnpnl commented Sep 12, 2021

do you have an example repo of Ns + Angular with some example tests?

@wSedlacek
Copy link
Author

I am still in preliminary investigation of the NativeScript platform myself, however their demo app does have some test built into it.

https://github.com/NativeScript/angular/tree/main/apps/nativescript-demo-ng

@ahnpnl
Copy link
Collaborator

ahnpnl commented Sep 12, 2021

I looked a bit today about the NSObject. It seems like something in C or C++ which isn’t exposed by default as a global script setup.

My guess is during the start up of the dev server, ns command somehow takes care of “transforming” C/C++ script into js which can create that object?

The main problem now when using Jest with jsdom is the potential global objects from C/C++ not available to import.

I also checked a bit about Detox but it seems to work in a different way since it requires to build the app first before running tests.

The positive point is the approach of Detox is also possibly the approach which we want to change also for the existing Angular Jest integration.

Another thing I haven’t tried is: whether or not we can reuse what we are importing for existing Jest Angular integration instead of things from polyfill like you mentioned in the description.

@Fafnur
Copy link

Fafnur commented Aug 23, 2022

@ahnpnl you have a working example with NS and jest?

@ahnpnl
Copy link
Collaborator

ahnpnl commented Aug 23, 2022

Sorry we don’t have at the moment. I did a few attempts to set it up but wasn’t quite successful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🚀 Feature Request new suggested feature
Projects
None yet
Development

No branches or pull requests

4 participants
@Fafnur @wSedlacek @ahnpnl and others