Tests are failing after Angular 2 RC5 - testing

I had used the following format for my tests:
export function main() {
describe('Angular2 component test', function() {
it('should initialize component',
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
var template = '<specific-component-tag>';
return tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
expect(fixture.componentInstance.viewChild).toBeDefined();
fixture.detectChanges();
expect(fixture.componentInstance.viewChild.items.length).toBe(1);
// .... etc.
}).catch (reason => {
console.log(reason);
return Promise.reject(reason);
});
})));
});
}
This work fine in RC4. But RC5 came suddenly and now this code have not worked.
It throws me the following errors:
Module ".... #angular/core/testing" has no exported member 'it'.
Module ".... #angular/core/testing" has no exported member 'describe'.
Module ".... #angular/core/testing" has no exported member 'expect'.
Module ".... #angular/core/testing" has no exported member 'beforeEachProviders'.
Module ".... #angular/compiler/testing" has no exported member 'TestComponentBuilder'.
Module ".... #angular/compiler/testing" has no exported member 'ComponentFixture'.
Please help me to migrate this test to angular2 RC5.
Update:
I have already read RC5 release notes but nothing comes to my mind how to achieve my goal.

The Jasmine imports available through #angular/core/testing are removed. So remove the imports for the following
Before:
import {
beforeEach,
beforeEachProviders,
describe,
expect,
it,
inject,
} from '#angular/core/testing';
after
/// <reference path="../../../typings/main/ambient/jasmine/index.d.ts" />
import {
inject, addProviders
} from '#angular/core/testing';
The reference path should be the first line in the file and it should point to jasmine type definition file. (Update the relative up. i.e the ../../ to whatever)To get jasmine type defitions, add the following line to ambientDevDependencies. Mine looks something like this
{
"ambientDevDependencies": {
"angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459",
"jasmine": "registry:dt/jasmine#2.2.0+20160412134438",
"selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654"
},
"ambientDependencies": {
"es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654"
}
}
Also change
beforeEachProviders(() => [InMemoryDataService]);
to
import { TestBed } from '#angular/core/testing';
...
describe('...', () => {
TestBed.configureTestingModule({
providers: [ InMemoryDataService ]
});
it(...);
});

Take a look at changelog:
https://github.com/angular/angular/blob/master/CHANGELOG.md
It looks like API, which you are using is deprecated - path and names has changed. :)
For example:
TestComponentBuilder and ComponentFixture is now in #angular/core/testing,
beforeEachProviders:
code:
beforeEachProviders(() => [MyService]);
changed to:
beforeEach(() => {
addProviders([MyService]);
});

If you already read their release note. It's a lot of change in testing API package.
https://github.com/angular/angular/blob/master/CHANGELOG.md#breaking-changes
So, I didn't try to migrate test to RC5 yet. But I found link about change to new testing API.
https://ng2-info.github.io/2016/08/angular-2-rc-5/#テスティングapiに関する変更
Hope this help.

Related

#casl/vue: What should by ability.js file look like?

I'm trying to integrate #casl/vue with Vue 3, and I'm afraid I'm having problems.
Per the instructions, I've added the following to my /main.js:
import { abilitiesPlugin } from '#casl/vue';
import ability from './services/ability';
app.use(abilitiesPlugin, ability, {
useGlobalProperties: true
})
So far, so good. However, it's unclear what I should put in /services/ability.js.
I tried the following (based on this), and it works:
import { defineAbility } from '#casl/ability';
export default defineAbility((can, cannot) => {
can('manage', 'all');
cannot('delete', 'User');
});
But, of course, this doesn't allow me to use different permissions for different users.
So I tried the following instead (based on this):
import { defineAbility } from '#casl/ability';
export default (user) => defineAbility((can) => {
can('read', 'Article');
if (user.isLoggedIn) {
can('update', 'Article', { authorId: user.id });
can('create', 'Comment');
can('update', 'Comment', { authorId: user.id });
}
});
...and that doesn't work. In the console, I see:
plugin.ts:12 Uncaught Error: Please provide an Ability instance to abilitiesPlugin plugin
at l (plugin.ts:12:11)
at Object.use (runtime-core.esm-bundler.js:3812:21)
at main.js?t=1651580949947:29:5
Got any hints? I'm finding the documentation to be pretty unclear. A practical example would really help me!
Thanks!
It means you must pass plugins as an instance of Ability
const ability = new Ability()
.use(abilitiesPlugin, ability, {
....
})

Testcafe data driven testing - how to drive tests with data fetched from API

I'm having trouble figuring out how to drive tests with data fetched from a request. I've read the documentation here: https://testcafe.io/documentation/402804/recipes/best-practices/create-data-driven-tests, and all examples use static json file data available at compile time.
I can't fetch the data in fixture.before hook, because it will only be available inside of the test context, but I need to access the data outside of the test context for iteration, such that the test is inside of a for loop.
I've tried this solution: https://github.com/DevExpress/testcafe/issues/1948, however this fails with testcafe ERROR No tests found in the specified source files. Ensure the sources contain the 'fixture' and 'test' directives., even when I use the flag disable-test-syntax-validation and .run({ disableTestSyntaxValidation: true }); option.
I am looking for suggestions and workarounds so that I can await some data, then run my tests. Even if Testcafe doesn't explicitly support something like this, I figure there must be some workaround... Thanks in advance.
Edit:
file-a.ts
export function tSteps(...args) {
// some setup
const testcase = args[args.length - 1];
const testCtx = test(name, async t => {
...
});
return testCtx;
}
----
file-b.ts
export const parameterizedTest = <T>(..., testcase: (scenario: T) => TestFn) => {
// some setup...
// I have also tried awaiting rows data here, which does not work
// because tests are not discoverable at compile time
...
const scenarios: T[] = rows.map(row => {
...
});
scenarios.forEach((scenario, idx) => {
return testcase(scenario).meta({
some metadata
});
});
};
----
tests.ts
fixture(...).before(async () => {
// can't get the data i need here because it needs to be available outside of the fixture context
})
parameterizedTest<MyInterface>(some params, (scenario: MyInterface) => {
return tSteps('my test',
async f => {
// some setup
// test code goes here which uses scenario.attributex, scenario.attributey, etc.
}
).meta(...);
}
);
In v1.0.0 and later, TestCafe does not validate test syntax. Please specify the TestCafe version that you use when you see the validation error.
Unfortunately, we cannot use pseudo-code to reproduce the issue you encountered. Please share some code that we could run to see the problematic behavior.
Generally speaking, TestCafe allows you to fetch data asynchronously and then spawn tests based on the received values. For instance, the following code works fine for me with TestCafe 1.18.3:
import { fixture, test } from 'testcafe';
import fetch from './node-fetch-mock';
(async () => {
const testData = await fetch();
testData
.map(n => () => {
fixture `Fixture ${n}`
.page `https://google.com`;
test(`Test ${n}`, async t => {
await t.expect(true).ok();
});
})
.map(async test => { await test(); });
})();
node-fetch-mock.js
export default async function fetch() {
return [1, 2, 3, 4, 5];
}
The only caveat is that I have to import fixture and test explicitly because I call them from callbacks.
Could you please provide us with any test code snippet that demonstrates the problem? We need to correctly understand the cause of the problem and reproduce it on our side.

Cypress How to store global constants in a file that can be used across all spec files?

I'm looking for a way to store global constants in a file that could be used across all my spec files. Can anyone help?
Use the cypress.json file that is in your project root like this:
{
"env": {
"your_var": "your_value"
}
}
https://docs.cypress.io/guides/references/configuration.html
Once you set some env variables, you can reference them from your specs like this: Cypress.env('your_var');
The following link might help with an easy way to set and get from env variables.
https://docs.cypress.io/api/cypress-api/env.html#Syntax
describe('My First Test', function() {
it('it set value to global variable', function() {
Cypress.env('some_variable', "hello")
})
it('it get value to global variable', function() {
expect(Cypress.env('some_variable')).to.equal('hello')
})
})
I like to create a constants file such as constants.js as an exportable constants object:
export const NAME = {
FIRST: 'John',
LAST: 'Smith',
};
and in my spec files import them: test.spec.js
import { NAME } from '../../support/constants';
describe('Landing page', () => {
beforeEach(() => cy.login());
cy.get(NAME.FIRST).assertion('verify the name');
});
Global variables - sounds like fixtures.
See writefile - JSON - Write response data to a fixture file
cy.request('https://jsonplaceholder.typicode.com/users').then((response) => {
cy.writeFile('cypress/fixtures/users.json', response.body)
})
// our fixture file is now generated and can be used
cy.fixture('users').then((users) => {
expect(users[0].name).to.exist
})
Care to share why you want to do so?
Sounds like it may be interesting.
since cypress is js, it is possible to define const in on js file (my-const.js) as
export const ARE_YOU_SURE='Are you sure';
and use them in another file as
import * as constants from "../[proper path]/my-conste.js";
...
var s = constants.ARE_YOU_SURE + ' about this?'
You can use environment variables stored in either cypress.json or cypress.env.json.
cypress.json
{
"env": {
"myVar": "value..."
}
}
cypress.env.json
{
"myVar": "value..."
}
You can use your environment variable using Cypress.env('myVar').
const myVar = Cypress.env('myVar')
You can review your environment variables in the Settings tab of the cypress runner.

How to create unit test cases with Vue, Karma, browserify

I am trying to build some unit test cases to my existing Vue project.
I found some documents there but not useful especially for testing on functions such as Watch, Promise and Then.
Is there any specific and detailed guide line on unit testing with Vue and these plugins?
The target vue has defined a function named test.
const vm = new Vue(target).$mount();
vm.test("message");
But the error message is vm.test is not a function
I do not know why I could not use the function defined in the target.vue.
Meanwhile once I use the test function to change some data, the target vue will update the data automatically.
But it seems that Vue.nextTick does not work on this situation.
Could someone help me on this point?
Thank you very much for your help.
Hellocomponent
export default {
name: 'hello',
data () {
return {
msg: 'Welcome to Your Vue.js App',
test: 'Testing'
}
}
}
Hello.spec.js //for testing Hello.vue
describe('Hello', () => {
it('set correct default data', () => {
expect(typeof Hello.data).to.equal('function')
assert.typeOf(Hello.data, 'function')
const defaultdata = Hello.data()
expect(defaultdata.test).to.be.a('string')
expect(defaultdata.test).to.equal('Testing')
})
})
This is test case of Hello component of vue.js which is created automatically when new template is created. This is using Karma+Mocha+Chai.

How to dynamically mock ES6 modules with SystemJS?

I have a single-page application written in ES6. The code in transpiled server-side into classic javascript by babelJs, then loaded by SystemJs.
Javascript present in my html file:
System.config({
baseURL: '/js',
meta: {
'/js/*': { format: 'cjs' }
}});
System.defaultJSExtensions = true;
System.import("index.js")
.catch(function (error) {
console.error(error)
});
index.js:
import f1 from 'file1';
import f2 from 'file2';
// code here ...
Everything works fine. index.js is loaded, and all import statements are correctly executed.
Now, I want to create some pages with mocked ES6 modules, for testing purpose. My goal is to display pages by replacing model classes (contained in ES6 modules) with other static test classes.
Let's say I have 3 files: real_model.js, fake_model.js and component.js. component.js import the real model (import Model from 'real_model';).
How can I replace the real model by the fake one (in the component) dynamically ?
It's been a while since this question was posted, but maybe this solution might still be of help to anyone else.
With SystemJS it is possible to create a module on-the-fly using System.newModule. Then you can use System.set to overwrite existing modules with the new one. In our tests we use the following helper function to mock existing modules:
function mockModule(name, value) {
const normalizedName = System.normalizeSync(name);
System.delete(normalizedName);
System.set(normalizedName, System.newModule(Object.assign({ default: value }, value)));
}
Then, e.g. inside the beforeEach callback, we assign the mock and then import the module to be tested using System.import:
let [component, fake_model] = [];
beforeEach(() => {
// define mock
fake_model = { foo: 'bar' };
// overwrite module with mock
mockModule('real_model', fake_model);
// delete and reimport module
System.delete(System.normalizeSync('component'));
return System.import('src/testing').then((m) => {
component = m.default;
}).catch(err => console.error(err));
});
// test your component here ...
A big advantage of this approach is that you don't need an additional mocking library and it works solely with SystemJS.