Jest not handling errors from expect() in subscribe() of RxJS observable - rxjs

I've been trying to get Jest working with RxJS and am having trouble with Jest not propagating errors from inside the subscribe callback.
Here is a sample test I've tried that is not working:
import {of} from 'rxjs';
test('should fail', () => {
of(false).subscribe(val => {
expect(val).toBe(true);
});
});
The above test should fail, but it passes. I've googled around and found the following solution:
Failing expect() inside subscribe() does not mark test as invalid
This suggests using the "done" syntax in jest to solve the issue. While using the "done" callback does get the above test to fail, there are a number of issues with this approach:
Undescriptive errors
The test fails because the 'expect' call in subcribe() throws an error, resulting in 'done()' never getting called. The test then times out, waiting for done. So instead of propagating the 'expect' error, it is causing a timeout error, which means every test that fails in the expect clause will show a timeout error instead of the actual error message of the failed 'expect' call.
Tests take longer to fail
Because all tests are failing due to a timeout error, that means it takes 5 seconds for each test to fail (async tests timeout after 5 seconds). This can dramatically increase the amount of time for tests to run
Poor use of done
The done callback is meant to support asynchronous use cases for testing. But rxjs is not necessarily asynchronous. The code I inlined above actually runs synchronously. For example, the following test will pass:
import {of} from 'rxjs';
test('should pass', () => {
let didRunSynchronously = false;
of(true).subscribe(() => {
didRunSynchronously = true;
});
expect(didRunSynchronously).toBe(true);
});
It seems strange to have to use asynchronous semantics to solve a problem for a synchronous test.
Wondering if anyone has come up with a good solution for testing in rxjs that will result in the expect calls to properly get handled by the testing library.
Thanks in advance!
Relevant dependencies in package.json:
"dependencies": {
"#babel/polyfill": "^7.0.0",
"classnames": "^2.2.6",
"history": "^4.7.2",
"json-stringify-pretty-compact": "^1.2.0",
"minimist": "^1.2.0",
"normalize.css": "^8.0.0",
"nullthrows": "^1.1.0",
"react": "^16.5.2",
"react-dom": "^16.5.2",
"react-router-dom": "^4.3.1",
"rxjs": "^6.3.3",
},
"devDependencies": {
"#babel/core": "^7.2.2",
"#babel/plugin-proposal-class-properties": "^7.1.0",
"#babel/plugin-proposal-object-rest-spread": "^7.0.0",
"#babel/preset-env": "^7.1.0",
"#babel/preset-flow": "^7.0.0",
"#babel/preset-react": "^7.0.0",
"babel-core": "^7.0.0-bridge.0",
"babel-env": "^2.4.1",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"babel-loader": "^8.0.4",
"copy-webpack-plugin": "^4.5.3",
"css-loader": "^1.0.0",
"eslint": "^5.9.0",
"eslint-plugin-flowtype": "^3.2.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-react": "^7.11.1",
"eslint-watch": "^4.0.2",
"flow-bin": "^0.83.0",
"html-webpack-plugin": "^3.2.0",
"jest": "^23.6.0",
"prettier": "^1.15.3",
"style-loader": "^0.23.1",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.9"
}
.babelrc file
{
"plugins": [
"module:#babel/plugin-proposal-class-properties",
"module:#babel/plugin-proposal-object-rest-spread"
],
"presets": [
["module:#babel/preset-env", { "targets": { "node": "6.10" } }],
"module:#babel/preset-flow"
]
}

Even if i am some years later on this topic, this might help others that are new to testing async code.
Please refer for example to https://jestjs.io/docs/asynchronous and use a done() callback at the end of your subscription.
If this callback is not executed, because of the error before, the test will fail as expected.
it('should fetch the right data', done => {
fetchData().subscribe(data => {
expect(data).toBe('expected data');
done();
});
});

Figured out the problem! Leaving this here for anyone who runs into a similar issue. RxJS and Jest were working properly and propagating the errors correctly. The problem was that I added a "jest.useFakeTimers" call to the testing script. For some reason, this was causing the errors not to propagating properly in the test. I needed to add "jest.runAllTimers" to get the errors to throw. Here is the full test script, implemented correctly:
import {of} from 'rxjs';
jest.useFakeTimers();
test('should fail', () => {
of(false).subscribe(val => {
expect(val).toBe(true);
});
jest.runAllTimers();
});
If you don't need mock timers, then no need to add them. I thought it was a bit strange that fake timers were an issue even though I could verify the code was getting called synchronously. If someone has more insight on the implementation details of why this is the case, I'd appreciate some explanation.

Related

NestJS and Apollo Federation: buildFederatedSchema is deprecated

I am working with NestJS and Apollo Federation for a while and it seems that since last update I get
"(node:19113) DeprecationWarning: 'buildFederatedSchema' is deprecated. Use 'buildSubgraphSchema' instead."
I don't see a place where I could use buildSubgraphSchema and I didn't find anywhere from NestJS docs of Apollo Federation docs a way to remove this deprecated issue.
The full list of dependencies in my package json are
"dependencies": {
"#apollo/federation": "^0.33.3",
"#apollo/subgraph": "^0.1.2",
"#nestjs/common": "^8.0.0",
"#nestjs/config": "^1.0.2",
"#nestjs/core": "^8.0.0",
"#nestjs/graphql": "^9.1.1",
"#nestjs/mongoose": "^9.0.1",
"#nestjs/platform-express": "^8.0.0",
"apollo-server-express": "^3.4.0",
"class-transformer": "^0.4.0",
"class-validator": "^0.13.1",
"graphql": "^15.6.1",
"helmet": "^4.6.0",
"joi": "^17.4.2",
"mongoose": "^6.0.12",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
},
The GraphQL module is defined in a file called graphql.module.ts with the following:
import { Module } from '#nestjs/common';
import { GraphQLFederationModule } from '#nestjs/graphql';
import { ApolloServerPluginInlineTraceDisabled } from 'apollo-server-core';
#Module({
imports: [
GraphQLFederationModule.forRoot({
plugins: [ApolloServerPluginInlineTraceDisabled()],
autoSchemaFile: true,
playground: true,
introspection: true,
buildSchemaOptions: {
dateScalarMode: 'isoDate',
},
context: ({ req }) => ({
jwt: req.headers.authorization,
}),
}),
],
})
export class GraphqlModule {}
Project still runs normally with the deprecated message but I would be keen to understand how to fix it.
Thanks in advance,
SOLUTION: 2020-03-10
Based on Brando J answer, the next update of nestjs/graphql from version 9 to version 10 fix the issue
The cause of this warning comes from #nestjs/graphql v9 which still use "buildFederatedSchema" from #apollo/federation.
You can update to #nestjs/graphql v10 to get rid of that message. Also GraphQLFederationModule has been removed and replaced by GraphQLModule using ApolloFederationDriver.
tl;dr
update #nestjs/graphql to v10
read this docs to adjust your code to new version https://docs.nestjs.com/graphql/migration-guide

Mac running out of space after several UI automation runs

I am running UI automation locally using selenium webdriver, chromedriver, and jest, on MacOS. After several runs I run out of local storage. You can watch storage decrease by about 50 gb every run. When I restart my computer, the storage cleans up and I have space again. I am wondering if I am not cleaning up my tests correctly.
Here are my dependencies:
},
"devDependencies": {
"#babel/core": "^7.14.6",
"#babel/runtime": "^7.14.6",
"#types/jest": "^26.0.23",
"#types/node": "^14.14.31",
"#types/selenium-webdriver": "^4.0.14",
"#typescript-eslint/eslint-plugin": "^4.28.1",
"#typescript-eslint/parser": "^4.28.1",
"babel-jest": "^27.0.6",
"babel-plugin-add-react-displayname": "^0.0.5",
"chromedriver": "^91.0.1",
"eslint": "^7.30.0",
"eslint-plugin-react": "^7.24.0",
"fsevents": "^2.3.2",
"geckodriver": "^2.0.1",
"jasmine": "^3.8.0",
"jest": "^27.0.6",
"metro-react-native-babel-preset": "^0.66.0",
"prettier": "^2.3.2",
"react-native-dotenv": "^3.0.0",
"run-node": "^2.0.0",
"selenium-webdriver": "^4.0.0-beta.4",
"ts-jest": "^27.0.3",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.4.0-dev.20210609",
"weak-napi": "^2.0.2",
"webdriver": "^7.7.4",
"webdriver-manager": "^12.1.8",
"webdriverio": "^7.7.4"
}
Here is my cleanup method:
/** Cleans up all drivers created by this process */
export async function cleanupDrivers(): Promise<void> {
await Promise.all(driversToCleanUp.map((driver) => driver.quit()));
}
My driver creation method:
const driversToCleanUp: WebDriver[] = [];
/** Configures a new WebDriver for e2e testing */
export async function buildDriver(): Promise<WebDriver> {
const driver = await new Builder()
.forBrowser("chrome")
.setChromeOptions(setChromeOptions(new chrome.Options()))
.setFirefoxOptions(setFirefoxOptions(new firefox.Options()))
.build();
driversToCleanUp.push(driver);
return driver;
}
/** Configures a new WebDriver for download testing */
export async function buildDownloadDriver(): Promise<WebDriver> {
const driver = await new Builder()
.forBrowser("chrome") // do not change this
.setChromeOptions(setChromeDownloadOptions(new chrome.Options()))
.build();
driversToCleanUp.push(driver);
return driver;
}
/** Sets chrome options for WebDriver */
function setChromeOptions<T extends chrome.Options>(options: T): T {
options.windowSize({ width: 1920, height: 1080 });
options.addArguments("--incognito");
options.addArguments("--disable-extensions");
options.addArguments("--disable-popup-blocking");
options.addArguments("--disable-notifications");
options.headless();
return options;
}
Not sure if this is enough information, but I am happy to provide more. Thanks for any help!
I have been able to temporarily resolve this by adding a bash script:
# navigates to folder to clean chrome driver files
cd && cd ../../private/var/folders/fg/{yourIDhere}/T
# deletes chromedriver leftover files
rm -rf .com.google.Chrome.*
The {yourIDhere} is unique to your computer.
When the space fills up, I can execute this script to clean up my issue. When I find a more permanent solution, I will post again.

vue laravel | GTM Integration

Well I have a Laravel Vue setup.
Package.json
{
"devDependencies": {
"axios": "^0.15.3",
"babel-preset-es2015": "^6.24.1",
"bootstrap": "4.0.0-beta",
"cross-env": "^3.2.3",
"jquery": "^3.1.1",
"laravel-mix": "1.2.0",
"lodash": "^4.17.4",
"vue": "^2.4.2"
},
"dependencies": {
"favico.js": "^0.3.10",
"intersection-observer": "^0.5.0",
"laravel-echo": "^1.3.2",
"moment-timezone": "^0.5.14",
"popper.js": "^1.12.2",
"pusher-js": "^4.2.1",
"sweetalert2": "^6.6.8",
"vue-image-crop-upload": "^1.3.15",
"vue-moment": "^2.0.2",
"vue-multiselect": "2.0.2",
"vue-observe-visibility": "^0.3.1",
"vue-switches": "^1.1.7",
"vue-template-compiler": "^2.4.2"
}
}
I am trying to integrate GTM. I could have used vue-gtm but since I am not using vue-router Its really hard to configure. I am using Laravel routes.
Any solutions to integrate it?
If anyone know how to integrate spatie/laravel-googletagmanager with vue .. Please help me out.
vue-gtm does not require the router. it just automates it and makes it easier, it doesn't mean you have to do this.
import VueGtm from 'vue-gtm';
import VueRouter from 'vue-router';
const router = new VueRouter({ routes, mode, linkActiveClass });
Vue.use(VueGtm, {
id: 'GTM-xxxxxxx', // Your GTM ID
enabled: true, // defaults to true. Plugin can be disabled by setting this to false for Ex: enabled: !!GDPR_Cookie (optional)
debug: true, // Whether or not display console logs debugs (optional)
vueRouter: router, // Pass the router instance to automatically sync with router (optional)
ignoredViews: ['homepage'] // If router, you can exclude some routes name (case insensitive) (optional)
});
You can completely disregard adding the vueRouter and ignoredViews parameters above.
Then in your components that need to dispatch events:
this.$gtm.trackEvent({
event: null, // Event type [default = 'interaction'] (Optional)
category: 'Calculator',
action: 'click',
label: 'Home page SIP calculator',
value: 5000,
noninteraction: false // Optional
});
You can figure that function on any action. Page load, click, form submission, etc. Just change the properties to meet your needs.

Shoutem/React-Native Error: 'jest-haste-map: #providesModule naming collision'

I am using Shoutem and have tried running 'react-native run-ios' and running the xcode workspace file directly. Using both gives this error (I realize Restaurants is misspelled):
Loading dependency graph...(node:22499) UnhandledPromiseRejectionWarning: Error: jest-haste-map: #providesModule naming collision:
Duplicate module name: user.resturants
Paths: /Users/USERNAME/Resturaunts/user.resturants/server/package.json collides with /Users/USERNAME/Resturaunts/user.resturants/app/package.json
This error is caused by a #providesModule declaration with the same name across two different files.
at setModule (/Users/USERNAME/Resturaunts/node_modules/jest-haste-map/build/index.js:446:17)
at workerReply (/Users/USERNAME/Resturaunts/node_modules/jest-haste-map/build/index.js:496:9)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:19894) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:19894) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
error: bundling failed: Error: jest-haste-map: #providesModule naming collision:
Duplicate module name: user.resturants
Paths: /Users/USERNAME/Resturaunts/user.resturants/server/package.json collides with /Users/USERNAME/Resturaunts/user.resturants/app/package.json
This error is caused by a #providesModule declaration with the same name across two different files.
at setModule (/Users/USERNAME/Resturaunts/node_modules/jest-haste-map/build/index.js:446:17)
at workerReply (/Users/USERNAME/Resturaunts/node_modules/jest-haste-map/build/index.js:496:9)
at process._tickCallback (internal/process/next_tick.js:68:7)
BUNDLE [ios, dev] ../../index.js ░░░░░░░░░░░░░░░░ 0.0% (0/1), failed.
I have tried following the steps shown here and I still run into the same problem.
Using 'react-native run-ios' also shows this error in the terminal. I am unsure if this is related.
The following commands produced analyzer issues:
Analyze /Users/USERNAME/Resturaunts/node_modules/react-native/React/Base/RCTModuleMethod.mm normal x86_64
Analyze /Users/USERNAME/Resturaunts/node_modules/react-native/React/Base/RCTUtils.m normal x86_64
(2 commands with analyzer issues)
Installing build/Build/Products/Debug-iphonesimulator/Resturaunts.app
An error was encountered processing the command (domain=com.apple.CoreSimulator.SimError, code=164):
Unable to lookup in current state: Shutdown
Launching com.shoutem.ShoutemApp
An error was encountered processing the command (domain=com.apple.CoreSimulator.SimError, code=164):
Unable to lookup in current state: Shutdown
The build does succeed but the simulator shows nothing. I have also tried this solution here. I don't have enough experience to know what is going on. I have been trying to get this thing to work for a while now. This is the closest I have ever gotten to a working build.
Here is my package.json:
{
"name": "#shoutem/platform",
"version": "1.7.1-rc.0",
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"setup": "cd scripts && yarn install",
"lint": "eslint .",
"configure": "node scripts/configure",
"bundle": "node scripts/bundle",
"build": "node scripts/build"
},
"dependencies": {
"#shoutem/animation": "~0.12.2",
"#shoutem/core": "0.2.5",
"#shoutem/redux-composers": "0.1.4",
"#shoutem/redux-io": "3.0.1-beta.3",
"#shoutem/theme": "~0.11.2",
"#shoutem/ui": "0.23.6",
"#shoutem/ui-addons": "0.0.29",
"babel-preset-es2015": "~6.24.1",
"es6-symbol": "3.1.1",
"lodash": "~4.17.4",
"moment": "2.22.2",
"prop-types": "15.6.0",
"react": "16.4.1",
"react-native": "0.56.0",
"react-redux": "~5.0.2",
"redux": "~3.6.0",
"redux-action-buffer": "~1.0.1",
"redux-api-middleware": "2.0.1",
"redux-logger": "2.6.1",
"redux-persist": "4.1.0",
"redux-thunk": "~2.0.0",
"whatwg-fetch": "1.0.0",
"user.resturants": "https://extensions.static.shoutem.com/user/resturants/0.0.1/app.tgz?timestamp=1540222210009",
"shoutem.about": "https://extensions.static.shoutem.com/shoutem/about/1.7.1/app.tgz?timestamp=1532019904679",
"shoutem.analytics": "https://extensions.static.shoutem.com/shoutem/analytics/1.7.0/app.tgz?timestamp=1531924714589",
"shoutem.application": "https://extensions.static.shoutem.com/shoutem/application/1.7.0/app.tgz?timestamp=1531924719204",
"shoutem.auth": "https://extensions.static.shoutem.com/shoutem/auth/1.7.1/app.tgz?timestamp=1533647965562",
"shoutem.books": "https://extensions.static.shoutem.com/shoutem/books/1.7.0/app.tgz?timestamp=1531924805228",
"shoutem.camera": "https://extensions.static.shoutem.com/shoutem/camera/1.7.1/app.tgz?timestamp=1532513463813",
"shoutem.cms": "https://extensions.static.shoutem.com/shoutem/cms/1.7.0/app.tgz?timestamp=1531924864035",
"shoutem.code-push": "https://extensions.static.shoutem.com/shoutem/code-push/1.7.0/app.tgz?timestamp=1531924869983",
"shoutem.deals": "https://extensions.static.shoutem.com/shoutem/deals/1.7.2/app.tgz?timestamp=1531930828925",
"shoutem.events": "https://extensions.static.shoutem.com/shoutem/events/1.7.1/app.tgz?timestamp=1532513603690",
"shoutem.favorites": "https://extensions.static.shoutem.com/shoutem/favorites/1.7.1/app.tgz?timestamp=1531924890654",
"shoutem.flurry-analytics": "https://extensions.static.shoutem.com/shoutem/flurry-analytics/1.7.0/app.tgz?timestamp=1531925003203",
"shoutem.google-analytics": "https://extensions.static.shoutem.com/shoutem/google-analytics/1.7.0/app.tgz?timestamp=1531925048071",
"shoutem.i18n": "https://extensions.static.shoutem.com/shoutem/i18n/1.7.0/app.tgz?timestamp=1531926118452",
"shoutem.ical-events": "https://extensions.static.shoutem.com/shoutem/ical-events/1.7.1/app.tgz?timestamp=1532513791098",
"shoutem.layouts": "https://extensions.static.shoutem.com/shoutem/layouts/1.7.0/app.tgz?timestamp=1531925159116",
"shoutem.loyalty": "https://extensions.static.shoutem.com/shoutem/loyalty/1.7.7/app.tgz?timestamp=1534422589121",
"shoutem.menu": "https://extensions.static.shoutem.com/shoutem/menu/1.7.0/app.tgz?timestamp=1531925240759",
"shoutem.navigation": "https://extensions.static.shoutem.com/shoutem/navigation/1.7.1/app.tgz?timestamp=1534422615806",
"shoutem.news": "https://extensions.static.shoutem.com/shoutem/news/1.7.0/app.tgz?timestamp=1531925281565",
"shoutem.notification-center": "https://extensions.static.shoutem.com/shoutem/notification-center/1.7.0/app.tgz?timestamp=1531925287012",
"shoutem.page": "https://extensions.static.shoutem.com/shoutem/page/1.7.0/app.tgz?timestamp=1531925310994",
"shoutem.people": "https://extensions.static.shoutem.com/shoutem/people/1.7.0/app.tgz?timestamp=1531925316211",
"shoutem.persist": "https://extensions.static.shoutem.com/shoutem/persist/1.7.0/app.tgz?timestamp=1531925320758",
"shoutem.photos": "https://extensions.static.shoutem.com/shoutem/photos/1.7.0/app.tgz?timestamp=1531925325437",
"shoutem.places": "https://extensions.static.shoutem.com/shoutem/places/1.7.0/app.tgz?timestamp=1531925330220",
"shoutem.platform-analytics": "https://extensions.static.shoutem.com/shoutem/platform-analytics/1.7.0/app.tgz?timestamp=1531925334766",
"shoutem.preview": "https://extensions.static.shoutem.com/shoutem/preview/1.7.0/app.tgz?timestamp=1531925340045",
"shoutem.products": "https://extensions.static.shoutem.com/shoutem/products/1.7.0/app.tgz?timestamp=1531925346246",
"shoutem.push-notifications": "https://extensions.static.shoutem.com/shoutem/push-notifications/1.7.0/app.tgz?timestamp=1531925350876",
"shoutem.rss": "https://extensions.static.shoutem.com/shoutem/rss/1.7.0/app.tgz?timestamp=1531925392345",
"shoutem.rss-news": "https://extensions.static.shoutem.com/shoutem/rss-news/1.7.0/app.tgz?timestamp=1531925397913",
"shoutem.rss-photos": "https://extensions.static.shoutem.com/shoutem/rss-photos/1.7.0/app.tgz?timestamp=1531925402877",
"shoutem.rss-videos": "https://extensions.static.shoutem.com/shoutem/rss-videos/1.7.0/app.tgz?timestamp=1531925407618",
"shoutem.rubicon-theme": "https://extensions.static.shoutem.com/shoutem/rubicon-theme/1.7.2/app.tgz?timestamp=1534422920061",
"shoutem.shopify": "https://extensions.static.shoutem.com/shoutem/shopify/1.7.0/app.tgz?timestamp=1531925522991",
"shoutem.social": "https://extensions.static.shoutem.com/shoutem/social/1.7.0/app.tgz?timestamp=1531925590399",
"shoutem.sub-navigation": "https://extensions.static.shoutem.com/shoutem/sub-navigation/1.7.1/app.tgz?timestamp=1534423025262",
"shoutem.theme": "https://extensions.static.shoutem.com/shoutem/theme/1.7.0/app.tgz?timestamp=1531925600521",
"shoutem.video": "https://extensions.static.shoutem.com/shoutem/video/1.7.0/app.tgz?timestamp=1531925610624",
"shoutem.vimeo": "https://extensions.static.shoutem.com/shoutem/vimeo/1.7.0/app.tgz?timestamp=1531925661052",
"shoutem.web-view": "https://extensions.static.shoutem.com/shoutem/web-view/1.7.2/app.tgz?timestamp=1531925714059",
"shoutem.wordpress": "https://extensions.static.shoutem.com/shoutem/wordpress/1.7.0/app.tgz?timestamp=1531925779176",
"shoutem.youtube": "https://extensions.static.shoutem.com/shoutem/youtube/1.7.0/app.tgz?timestamp=1531925850488"
},
"devDependencies": {
"#shoutem/build-tools": "file:scripts/helpers",
"babel": "~6.3.26",
"babel-eslint": "~6.0.4",
"babel-jest": "23.2.0",
"babel-plugin-transform-decorators-legacy": "~1.3.4",
"babel-preset-react-native": "^5.0.1",
"eslint": "~2.9.0",
"eslint-config-airbnb": "~8.0.0",
"eslint-plugin-import": "~1.6.1",
"eslint-plugin-jsx-a11y": "~1.0.4",
"eslint-plugin-react": "~5.0.1",
"eslint-plugin-react-native": "~1.0.2",
"jest": "23.1.0",
"react-test-renderer": "16.4.1"
},
"jest": {
"preset": "react-native",
"transformIgnorePatterns": [
"node_modules/(?!react-native|#shoutem/theme|#shoutem/animation|#shoutem/ui)"
]
}
}
You are able to reproduce this by following the shoutem tutorial . I stopped at the linked part (setting local environment). I also got an error when running 'react-native run-ios' but solved it by following this

"it()" seems to get stuck in jasmine test

I am using karma & jasmine to do unit tests, and I am trying to do my first test. I am using the first example here:
https://jasmine.github.io/1.3/introduction.html#section-Matchers
and it didn't seem to do anything, so I added some logging and tried to make it catch an error:
console.log('a');
describe("A suite", function() {
console.log('b', typeof(it));
it("contains spec with an expectation", function() {
console.log('c');
expect(true).toBe(false);
});
});
And this is what my output comes out with:
Chrome 43.0.2357 (Mac OS X 10.10.3) LOG: 'a'
Chrome 43.0.2357 (Mac OS X 10.10.3) LOG: 'b', 'function'
so it looks like nothing internal to the "it" function gets executed since 'c' is never outputted. Am I missing something?
Update
So this is the grunt task I am running:
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
karma: {
unit: {
configFile: 'karma.conf.js'
}
}
});
grunt.loadNpmTasks('grunt-karma');
grunt.registerTask('default', ['karma']);
};
And this is my package.json with the list of installed npm packages:
{
"name": "abc.com",
"version": "0.0.1",
"private": true,
"dependencies": {
"bcrypt": "^0.8.3",
"body-parser": "^1.0.2",
"bower": "^1.4.1",
"ejs": "^2.3.1",
"email-templates": "^2.0.0-beta.1",
"error-handler": "^0.1.4",
"errorhandler": "^1.3.6",
"express": "~4.1.1",
"express-session": "^1.11.2",
"grunt": "^0.4.5",
"jade": "~0.31.2",
"jasmine": "^2.3.1",
"jasmine-runner": "^0.2.9",
"karma": "^0.12.37",
"karma-chrome-launcher": "^0.2.0",
"karma-jasmine": "^0.3.5",
"karma-junit-reporter": "^0.2.2",
"method-override": "^1.0.0",
"morgan": "^1.0.0",
"mysql": "^2.6.2",
"nodemailer": "^1.3.4",
"protractor": "^1.1.1",
"shelljs": "^0.2.6",
"xoauth2": "^1.0.0"
},
"scripts": {
"prestart": "npm install",
"postinstall": "bower install --allow-root",
"start": "supervisor -n error app.js",
"pretest": "npm install",
"test": "karma start karma.conf.js",
"test-single-run": "karma start karma.conf.js --single-run",
"preupdate-webdriver": "npm install",
"update-webdriver": "webdriver-manager update",
"preprotractor": "npm run update-webdriver",
"protractor": "protractor e2e-tests/protractor.conf.js",
"update-index-async": "node -e \"require('shelljs/global'); sed('-i', /\\/\\/##NG_LOADER_START##[\\s\\S]*\\/\\/##NG_LOADER_END##/, '//##NG_LOADER_START##\\n' + sed(/sourceMappingURL=angular-loader.min.js.map/,'sourceMappingURL=bower_components/angular-loader/angular-loader.min.js.map','app/bower_components/angular-loader/angular-loader.min.js') + '\\n//##NG_LOADER_END##', 'app/index-async.html');\""
},
"configs": {
"client_javascript_paths": [
"public/components/common/helpers.js",
"public/libs/bower_components/html5-boilerplate/js/vendor/modernizr-2.6.2.min.js",
"public/libs/bower_components/jquery/dist/jquery.min.js",
"public/libs/bower_components/angular/angular.js",
"public/libs/bower_components/angular-route/angular-route.js",
"public/libs/bower_components/angular-resource/angular-resource.js",
"public/libs/bower_components/d3/d3.js",
"public/libs/bower_components/c3/c3.js",
"public/libs/bower_components/angular-chart/angular-chart.js",
"public/libs/bower_components/moment/moment.js",
"public/components/common/filters.js",
"public/components/notify/notify.js",
"public/components/static/static.js",
"public/components/account/account.js",
"public/components/auth/auth.js",
"public/components/formatted-table/formatted-table.js",
"public/app.js",
"public/libs/underscore.js"
]
},
"devDependencies": {
"jasmine": "^2.3.1",
"jasmine-core": "^2.3.4",
"karma": "^0.12.37",
"karma-chrome-launcher": "^0.2.0",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.2.0",
"phantomjs": "^1.9.17"
}
}
And finally, this is my karma.conf.js
module.exports = function(config) {
var package = require('./package.json')
console.log(package.configs.client_javascript_paths);
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine', 'requirejs'],
// list of files / patterns to load in the browser
files: package.configs.client_javascript_paths.concat([
'public/components/**/*.tests.js'
]),
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
and I just run
grunt
to start it to get the output at the top of this.
It is happening because of requirejs framework you use with karma. If you don't need it, then you could just remove it from karma.conf.js and test will work just fine. But if you actually need it, then I would suggest to look at this documentation page, explaining how to configure requirejs for karma, it actually requires an extra file.
Using the files you've presented in the question I was able to execute the tests after the following steps:
first create a backup of karma.conf.js
use CLI command karma init to reinitiate creation of karma config
on the step Do you want to use Require.js ? selected Yes
on the step Do you wanna generate a bootstrap file for RequireJS? selected Yes
copied everything from a backup and added a file that was generated by karma init, it should be called test-main.js, to the list of watched files:
module.exports = function(config) {
var package = require('./package.json');
config.set({
// ...
files: package.configs.client_javascript_paths.concat([
'public/components/**/*.tests.js',
'test-main.js', // here it is
])
// ...
});
};

Resources