chore(test): migrate Dart tests to package:test

Instead of running with karma and the karma-dart shim, run dart
tests directly using the new package:test runner. This migrates
away from package:unittest.

Fixes a couple tests, mostly associated with depending on absolute
URLs or editing the test providers after an injector had already
been created.

Remove karma-dart and associated files. Change gupfiles to run tests
via `pub run test` instead.
This commit is contained in:
Julie Ralph 2016-02-10 16:54:32 -08:00
parent 7455b907d1
commit 5a59e44765
39 changed files with 532 additions and 511 deletions

View File

@ -467,7 +467,7 @@ gulp.task('test.js', function(done) {
gulp.task('test.dart', function(done) { gulp.task('test.dart', function(done) {
runSequence('versions.dart', 'test.transpiler.unittest', 'test.unit.dart/ci', runSequence('versions.dart', 'test.transpiler.unittest', 'test.unit.dart/ci',
'test.dart.angular2_testing/ci', sequenceComplete(done)); sequenceComplete(done));
}); });
gulp.task('versions.dart', function() { dartSdk.logVersion(DART_SDK); }); gulp.task('versions.dart', function() { dartSdk.logVersion(DART_SDK); });
@ -635,8 +635,7 @@ gulp.task('buildRouter.dev', function() {
gulp.task('test.unit.dart', function(done) { gulp.task('test.unit.dart', function(done) {
printModulesWarning(); printModulesWarning();
runSequence('build/tree.dart', 'build/pure-packages.dart', '!build/pubget.angular2.dart', runSequence('build/tree.dart', 'build/pure-packages.dart', '!build/pubget.angular2.dart',
'!build/change_detect.dart', '!build/remove-pub-symlinks', 'build.dart.material.css', '!build/change_detect.dart', '!build/remove-pub-symlinks', function(error) {
'!test.unit.dart/karma-server', '!test.unit.dart/karma-run', function(error) {
var watch = require('./tools/build/watch'); var watch = require('./tools/build/watch');
// if initial build failed (likely due to build or formatting step) then exit // if initial build failed (likely due to build or formatting step) then exit
@ -645,9 +644,10 @@ gulp.task('test.unit.dart', function(done) {
done(error); done(error);
return; return;
} }
// treatTestErrorsAsFatal = false;
watch(['modules/angular2/**'], {ignoreInitial: true}, watch(['modules/angular2/**'],
['!build/tree.dart', '!test.unit.dart/karma-run']); ['!build/tree.dart', '!test.unit.dart/run/angular2']);
}); });
}); });
@ -789,20 +789,6 @@ gulp.task('watch.dart.dev', function(done) {
}); });
}); });
gulp.task('!test.unit.dart/karma-run', function(done) {
// run the run command in a new process to avoid duplicate logging by both server and runner from
// a single process
runKarma('karma-dart.conf.js', done);
});
gulp.task('!test.unit.dart/karma-server', function() {
var karma = require('karma');
new karma.Server({configFile: __dirname + '/karma-dart.conf.js', reporters: 'dots'}).start();
});
gulp.task('test.unit.router/ci', function(done) { gulp.task('test.unit.router/ci', function(done) {
var karma = require('karma'); var karma = require('karma');
@ -850,20 +836,56 @@ gulp.task('test.unit.js.browserstack/ci', function(done) {
}); });
gulp.task('test.unit.dart/ci', function(done) { gulp.task('test.unit.dart/ci', function(done) {
var karma = require('karma'); runSequence('test.dart.dartium_symlink', '!test.unit.dart/run/angular2',
'!test.unit.dart/run/angular2_testing', '!test.unit.dart/run/benchpress',
var browserConf = getBrowsersFromCLI(null, true); sequenceComplete(done));
new karma.Server(
{
configFile: __dirname + '/karma-dart.conf.js',
singleRun: true,
reporters: ['dots'],
browsers: browserConf.browsersToRun
},
done)
.start();
}); });
// At the moment, dart test requires dartium to be an executable on the path.
// Make a temporary directory and symlink dartium from there (just for this command)
// so that it can run.
// TODO(juliemr): this won't work with windows - remove the hack and make this platform agnostic.
var dartiumTmpdir = path.join(os.tmpdir(), 'dartium' + new Date().getTime().toString());
var dartiumPathPrefix = 'PATH=$PATH:' + dartiumTmpdir + ' ';
gulp.task(
'test.dart.dartium_symlink',
shell.task(['mkdir ' + dartiumTmpdir, 'ln -s $DARTIUM_BIN ' + dartiumTmpdir + '/dartium']));
gulp.task('!test.unit.dart/run/angular2', function() {
var pubtest = require('./tools/build/pubtest');
return pubtest({
dir: path.join(CONFIG.dest.dart, 'angular2'),
dartiumTmpdir: dartiumTmpdir,
command: DART_SDK.PUB,
files: '**/*_spec.dart',
bunchFiles: true,
useExclusiveTests: true
});
});
gulp.task('!test.unit.dart/run/angular2_testing', function() {
var pubtest = require('./tools/build/pubtest');
return pubtest({
dir: path.join(CONFIG.dest.dart, 'angular2_testing'),
dartiumTmpdir: dartiumTmpdir,
command: DART_SDK.PUB,
files: '**/*_test.dart',
useExclusiveTests: true
});
});
gulp.task('!test.unit.dart/run/benchpress', function() {
var pubtest = require('./tools/build/pubtest');
return pubtest({
dir: path.join(CONFIG.dest.dart, 'benchpress'),
dartiumTmpdir: dartiumTmpdir,
command: DART_SDK.PUB,
files: '**/*_spec.dart',
useExclusiveTests: true
});
});
gulp.task('test.unit.cjs/ci', function(done) { gulp.task('test.unit.cjs/ci', function(done) {
runJasmineTests(['dist/js/cjs/{angular2,benchpress}/test/**/*_spec.js'], done); runJasmineTests(['dist/js/cjs/{angular2,benchpress}/test/**/*_spec.js'], done);
@ -930,24 +952,6 @@ gulp.task('test.server.dart', runServerDartTests(gulp, gulpPlugins, {dest: 'dist
gulp.task('test.transpiler.unittest', gulp.task('test.transpiler.unittest',
function(done) { runJasmineTests(['tools/transpiler/unittest/**/*.js'], done); }); function(done) { runJasmineTests(['tools/transpiler/unittest/**/*.js'], done); });
// At the moment, dart test requires dartium to be an executable on the path.
// Make a temporary directory and symlink dartium from there (just for this command)
// so that it can run.
var dartiumTmpdir = path.join(os.tmpdir(), 'dartium' + new Date().getTime().toString());
gulp.task('test.dart.angular2_testing/ci', ['build/pubspec.dart'], function(done) {
runSequence('test.dart.angular2_testing_symlink', 'test.dart.angular2_testing',
sequenceComplete(done));
});
gulp.task(
'test.dart.angular2_testing_symlink',
shell.task(['mkdir ' + dartiumTmpdir, 'ln -s $DARTIUM_BIN ' + dartiumTmpdir + '/dartium']));
gulp.task('test.dart.angular2_testing',
shell.task(['PATH=$PATH:' + dartiumTmpdir + ' pub run test -p dartium'],
{'cwd': 'dist/dart/angular2_testing'}));
// ----------------- // -----------------
// Pre-test checks // Pre-test checks
@ -1017,6 +1021,7 @@ gulp.task('build/pure-packages.dart/standalone', function() {
'modules_dart/**/*', 'modules_dart/**/*',
'!modules_dart/**/*.proto', '!modules_dart/**/*.proto',
'!modules_dart/**/packages{,/**}', '!modules_dart/**/packages{,/**}',
'!modules_dart/**/.packages',
'!modules_dart/payload{,/**}', '!modules_dart/payload{,/**}',
'!modules_dart/transform{,/**}', '!modules_dart/transform{,/**}',
]) ])

View File

@ -1,86 +0,0 @@
// This module provides a customFileHandler for karma
// that serves files with urls like /packages_<timestamp>/...
// with maximum cache.
// We are using these urls when we spawn isolates
// so that the isolates don't reload files every time.
var common = require('karma/lib/middleware/common');
var fs = require('fs');
var DART_EVAL_PATH_RE = /.*\/packages_\d+\/(.*)$/;
module.exports = createFactory;
function createFactory(proxyPaths) {
return {
'framework:dart-evalcache': ['factory', dartEvalCacheFactory]
};
function dartEvalCacheFactory(emitter, logger, customFileHandlers) {
var filesPromise = new common.PromiseContainer();
emitter.on('file_list_modified', function(files) {
filesPromise.set(Promise.resolve(files));
});
var serveFile = common.createServeFile(fs);
var log = logger.create('dart-evalcache');
customFileHandlers.push({
urlRegex: DART_EVAL_PATH_RE,
handler: handler
});
// See source_files handler
function handler(request, response, fa, fb, basePath) {
return filesPromise.then(function(files) {
try {
var requestedFilePath = mapUrlToFile(request.url, proxyPaths, basePath, log);
// TODO(vojta): change served to be a map rather then an array
var file = findByPath(files.served, requestedFilePath);
if (file) {
serveFile(file.contentPath || file.path, response, function() {
common.setHeavyCacheHeaders(response);
}, file.content);
} else {
response.writeHead(404);
response.end('Not found');
}
} catch (e) {
log.error(e.stack);
response.writeHead(500);
response.end('Error', e.stack);
}
});
}
};
}
function mapUrlToFile(url, proxyPaths, basePath, log) {
var originalUrl = url;
url = url.indexOf('?') > -1 ? url.substring(0, url.indexOf('?')) : url;
var match = DART_EVAL_PATH_RE.exec(url);
var packagePath = match[1];
var result = null;
var lastProxyFromLength = 0;
Object.keys(proxyPaths).forEach(function(proxyFrom) {
if (startsWith(packagePath, proxyFrom) && proxyFrom.length > lastProxyFromLength) {
lastProxyFromLength = proxyFrom.length;
result = proxyPaths[proxyFrom] + packagePath.substring(proxyFrom.length);
}
});
return basePath + '/' + result;
}
function startsWith(string, subString) {
return string.length >= subString.length && string.slice(0, subString.length) === subString;
}
function findByPath(files, path) {
for (var i = 0; i < files.length; i++) {
if (files[i].path === path) {
return files[i];
}
}
return null;
}

View File

@ -1,82 +0,0 @@
var browserProvidersConf = require('./browser-providers.conf.js');
var packageSources = {
// Dependencies installed with `pub install`.
'unittest': 'packages/unittest',
'guinness': 'packages/guinness',
'matcher': 'packages/matcher',
'stack_trace': 'packages/stack_trace',
'collection': 'packages/collection',
'path': 'packages/path',
'observe': 'packages/observe',
'quiver': 'packages/quiver',
'intl': 'packages/intl',
'smoke': 'packages/smoke',
'logging': 'packages/logging',
'utf': 'packages/utf',
// Local dependencies, transpiled from the source.
'angular2': 'dist/dart/angular2/lib',
'angular2/test/': 'dist/dart/angular2/test/',
'http': 'dist/dart/http/lib',
'angular2_material': 'dist/dart/angular2_material/lib',
'benchpress': 'dist/dart/benchpress/lib',
'examples': 'dist/dart/examples/lib'
};
var proxyPaths = {};
Object.keys(packageSources).map(function(packageName) {
var filePath = packageSources[packageName];
proxyPaths['/packages/'+packageName] = '/base/'+filePath;
});
// Karma configuration
// Generated on Thu Sep 25 2014 11:52:02 GMT-0700 (PDT)
module.exports = function(config) {
config.set({
frameworks: ['dart-unittest', 'dart-evalcache'],
files: [
// Init and configure guiness.
{pattern: 'test-init.dart', included: true},
// Unit test files needs to be included.
{pattern: 'dist/dart/**/*_spec.dart', included: true, watched: false},
// Karma-dart via the dart-unittest framework generates
// `__adapter_unittest.dart` that imports these files.
{pattern: 'dist/dart/**', included: false, watched: false},
// Dependencies, installed with `pub install`.
{pattern: 'packages/**/*.dart', included: false, watched: false},
// Init and configure guiness.
{pattern: 'test-main.dart', included: true},
{pattern: 'modules/**/test/**/static_assets/**', included: false, watched: false},
],
exclude: [
'dist/dart/**/packages/**',
'modules/angular1_router/**'
],
karmaDartImports: {
guinness: 'package:guinness/guinness_html.dart'
},
// Map packages to the correct urls where Karma serves them.
proxies: proxyPaths,
customLaunchers: browserProvidersConf.customLaunchers,
browsers: ['DartiumWithWebPlatform'],
port: 9877,
plugins: [
require('karma-dart'),
require('karma-chrome-launcher'),
require('karma-sauce-launcher'),
require('./karma-dart-evalcache')(packageSources)
]
});
};

View File

@ -23,6 +23,7 @@ dependencies:
dev_dependencies: dev_dependencies:
transformer_test: '^0.2.0' transformer_test: '^0.2.0'
guinness: '^0.1.18' guinness: '^0.1.18'
guinness2: '0.0.5'
quiver: '^0.21.4' quiver: '^0.21.4'
test: '^0.12.6' test: '^0.12.6'
transformers: transformers:

View File

@ -2,7 +2,7 @@ library testing.matchers;
import 'dart:async'; import 'dart:async';
import 'package:guinness/guinness.dart' as gns; import 'package:guinness2/guinness2.dart' as gns;
import 'package:angular2/src/platform/dom/dom_adapter.dart' show DOM; import 'package:angular2/src/platform/dom/dom_adapter.dart' show DOM;

View File

@ -1,92 +1,30 @@
library angular2.src.testing.testing_internal; library angular2.src.testing.testing_internal;
import 'dart:async'; import 'testing_internal_core.dart' as core;
export 'testing_internal_core.dart'
import 'package:guinness/guinness.dart' as gns;
export 'package:guinness/guinness.dart'
hide hide
Expect, beforeEachProviders,
expect, beforeEachBindings,
NotExpect,
beforeEach, beforeEach,
it, it,
iit, iit,
xit, xit,
SpyObject, testSetup,
SpyFunction; describe,
ddescribe,
xdescribe;
export 'matchers.dart' show expect, Expect, NotExpect; import 'package:angular2/platform/testing/browser.dart';
import 'package:angular2/src/core/reflection/reflection.dart';
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
import 'package:angular2/src/core/di/provider.dart' show bind;
import 'package:angular2/src/facade/collection.dart' show StringMapWrapper;
import 'test_injector.dart';
export 'test_injector.dart' show inject; export 'test_injector.dart' show inject;
TestInjector _testInjector = getTestInjector();
bool _isCurrentTestAsync;
Future _currentTestFuture;
bool _inIt = false;
class AsyncTestCompleter {
final _completer = new Completer();
AsyncTestCompleter() {
_currentTestFuture = this.future;
}
void done() {
_completer.complete();
}
Future get future => _completer.future;
}
void testSetup() { void testSetup() {
reflector.reflectionCapabilities = new ReflectionCapabilities(); core.setDartBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS, TEST_BROWSER_APPLICATION_PROVIDERS);
// beforeEach configuration:
// - Priority 3: clear the bindings before each test,
// - Priority 2: collect the bindings before each test, see beforeEachProviders(),
// - Priority 1: create the test injector to be used in beforeEach() and it()
gns.beforeEach(() {
_testInjector.reset();
_currentTestFuture = null;
}, priority: 3);
var completerProvider = bind(AsyncTestCompleter).toFactory(() {
// Mark the test as async when an AsyncTestCompleter is injected in an it(),
if (!_inIt) throw 'AsyncTestCompleter can only be injected in an "it()"';
_isCurrentTestAsync = true;
return new AsyncTestCompleter();
});
gns.beforeEach(() {
_isCurrentTestAsync = false;
_testInjector.addProviders([completerProvider]);
}, priority: 1);
} }
/**
* Allows overriding default providers defined in test_injector.js.
*
* The given function must return a list of DI providers.
*
* Example:
*
* beforeEachProviders(() => [
* bind(Compiler).toClass(MockCompiler),
* bind(SomeToken).toValue(myValue),
* ]);
*/
void beforeEachProviders(Function fn) { void beforeEachProviders(Function fn) {
gns.beforeEach(() { testSetup();
var providers = fn(); core.beforeEachProviders(fn);
if (providers != null) _testInjector.addProviders(providers);
}, priority: 2);
} }
@Deprecated('using beforeEachProviders instead') @Deprecated('using beforeEachProviders instead')
@ -95,72 +33,33 @@ void beforeEachBindings(Function fn) {
} }
void beforeEach(fn) { void beforeEach(fn) {
if (fn is! FunctionWithParamTokens) fn = testSetup();
new FunctionWithParamTokens([], fn, false); core.beforeEach(fn);
gns.beforeEach(() {
_testInjector.execute(fn);
});
}
void _it(gnsFn, name, fn) {
if (fn is! FunctionWithParamTokens) fn =
new FunctionWithParamTokens([], fn, false);
gnsFn(name, () {
_inIt = true;
_testInjector.execute(fn);
_inIt = false;
if (_isCurrentTestAsync) return _currentTestFuture;
});
} }
void it(name, fn, [timeOut = null]) { void it(name, fn, [timeOut = null]) {
_it(gns.it, name, fn); core.it(name, fn, timeOut);
} }
void iit(name, fn, [timeOut = null]) { void iit(name, fn, [timeOut = null]) {
_it(gns.iit, name, fn); core.iit(name, fn, timeOut);
} }
void xit(name, fn, [timeOut = null]) { void xit(name, fn, [timeOut = null]) {
_it(gns.xit, name, fn); core.xit(name, fn, timeOut);
} }
class SpyFunction extends gns.SpyFunction { void describe(name, fn) {
SpyFunction(String name) : super(name); testSetup();
core.describe(name, fn);
// TODO: vsavkin move to guinness
andReturn(value) {
return andCallFake(([a0, a1, a2, a3, a4, a5]) => value);
}
} }
class SpyObject extends gns.SpyObject { void ddescribe(name, fn) {
final Map<String, SpyFunction> _spyFuncs = {}; testSetup();
core.ddescribe(name, fn);
SpyObject([arg]) {}
SpyFunction spy(String funcName) =>
_spyFuncs.putIfAbsent(funcName, () => new SpyFunction(funcName));
void prop(String funcName, value) {
_spyFuncs
.putIfAbsent("get:${funcName}", () => new SpyFunction(funcName))
.andReturn(value);
} }
static stub([object = null, config = null, overrides = null]) { void xdescribe(name, fn) {
if (object is! SpyObject) { testSetup();
overrides = config; core.xdescribe(name, fn);
config = object;
object = new SpyObject();
} }
var m = StringMapWrapper.merge(config, overrides);
StringMapWrapper.forEach(m, (value, key) {
object.spy(key).andReturn(value);
});
return object;
}
}
bool isInInnerZone() => Zone.current['_innerZone'] == true;

View File

@ -0,0 +1,200 @@
library angular2.src.testing.testing_internal_core;
import 'dart:async';
import 'package:guinness2/guinness2.dart' as gns;
export 'package:guinness2/guinness2.dart'
hide
Expect,
expect,
NotExpect,
beforeEach,
it,
iit,
xit,
describe,
ddescribe,
xdescribe,
SpyObject,
SpyFunction;
export 'matchers.dart' show expect, Expect, NotExpect;
import 'package:angular2/src/core/reflection/reflection.dart';
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
import 'package:angular2/src/core/di/provider.dart' show bind;
import 'package:angular2/src/facade/collection.dart' show StringMapWrapper;
import 'test_injector.dart';
export 'test_injector.dart' show inject;
TestInjector _testInjector = getTestInjector();
bool _isCurrentTestAsync;
Future _currentTestFuture;
bool _inIt = false;
bool _initialized = false;
List<dynamic> _platformProviders = [];
List<dynamic> _applicationProviders = [];
class AsyncTestCompleter {
final _completer = new Completer();
AsyncTestCompleter() {
_currentTestFuture = this.future;
}
void done() {
_completer.complete();
}
Future get future => _completer.future;
}
void setDartBaseTestProviders(List<dynamic> platform, List<dynamic> application) {
_platformProviders = platform;
_applicationProviders = application;
}
void testSetup() {
if (_initialized) {
return;
}
_initialized = true;
reflector.reflectionCapabilities = new ReflectionCapabilities();
setBaseTestProviders(_platformProviders, _applicationProviders);
// beforeEach configuration:
// - clear the bindings before each test,
// - collect the bindings before each test, see beforeEachProviders(),
// - create the test injector to be used in beforeEach() and it()
gns.beforeEach(() {
_testInjector.reset();
_currentTestFuture = null;
});
var completerProvider = bind(AsyncTestCompleter).toFactory(() {
// Mark the test as async when an AsyncTestCompleter is injected in an it(),
if (!_inIt) throw 'AsyncTestCompleter can only be injected in an "it()"';
_isCurrentTestAsync = true;
return new AsyncTestCompleter();
});
gns.beforeEach(() {
_isCurrentTestAsync = false;
_testInjector.addProviders([completerProvider]);
});
}
/**
* Allows overriding default providers defined in test_injector.js.
*
* The given function must return a list of DI providers.
*
* Example:
*
* beforeEachProviders(() => [
* bind(Compiler).toClass(MockCompiler),
* bind(SomeToken).toValue(myValue),
* ]);
*/
void beforeEachProviders(Function fn) {
testSetup();
gns.beforeEach(() {
var providers = fn();
if (providers != null) _testInjector.addProviders(providers);
});
}
@Deprecated('using beforeEachProviders instead')
void beforeEachBindings(Function fn) {
beforeEachProviders(fn);
}
void beforeEach(fn) {
testSetup();
if (fn is! FunctionWithParamTokens) fn =
new FunctionWithParamTokens([], fn, false);
gns.beforeEach(() {
_testInjector.execute(fn);
});
}
void _it(gnsFn, name, fn) {
testSetup();
if (fn is! FunctionWithParamTokens) fn =
new FunctionWithParamTokens([], fn, false);
gnsFn(name, () {
_inIt = true;
_testInjector.execute(fn);
_inIt = false;
if (_isCurrentTestAsync) return _currentTestFuture;
});
}
void it(name, fn, [timeOut = null]) {
_it(gns.it, name, fn);
}
void iit(name, fn, [timeOut = null]) {
_it(gns.iit, name, fn);
}
void xit(name, fn, [timeOut = null]) {
_it(gns.xit, name, fn);
}
void describe(name, fn) {
testSetup();
gns.describe(name, fn);
}
void ddescribe(name, fn) {
testSetup();
gns.ddescribe(name, fn);
}
void xdescribe(name, fn) {
testSetup();
gns.xdescribe(name, fn);
}
class SpyFunction extends gns.SpyFunction {
SpyFunction(String name) : super(name);
// TODO: vsavkin move to guinness
andReturn(value) {
return andCallFake(([a0, a1, a2, a3, a4, a5]) => value);
}
}
class SpyObject extends gns.SpyObject {
final Map<String, SpyFunction> _spyFuncs = {};
SpyObject([arg]) {}
SpyFunction spy(String funcName) =>
_spyFuncs.putIfAbsent(funcName, () => new SpyFunction(funcName));
void prop(String funcName, value) {
_spyFuncs
.putIfAbsent("get:${funcName}", () => new SpyFunction(funcName))
.andReturn(value);
}
static stub([object = null, config = null, overrides = null]) {
if (object is! SpyObject) {
overrides = config;
config = object;
object = new SpyObject();
}
var m = StringMapWrapper.merge(config, overrides);
StringMapWrapper.forEach(m, (value, key) {
object.spy(key).andReturn(value);
});
return object;
}
}
bool isInInnerZone() => Zone.current['_innerZone'] == true;

View File

@ -13,6 +13,7 @@ import {
import {DecimalPipe, PercentPipe, CurrencyPipe} from 'angular2/common'; import {DecimalPipe, PercentPipe, CurrencyPipe} from 'angular2/common';
export function main() { export function main() {
describe('Number pipes', () => {
// TODO(mlaval): enable tests when Intl API is no longer used, see // TODO(mlaval): enable tests when Intl API is no longer used, see
// https://github.com/angular/angular/issues/3333 // https://github.com/angular/angular/issues/3333
if (browserDetection.supportsIntlApi) { if (browserDetection.supportsIntlApi) {
@ -69,4 +70,5 @@ export function main() {
}); });
}); });
} }
});
} }

View File

@ -72,8 +72,7 @@ export function main() {
inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => { inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => {
var value: string = var value: string =
resolver.getDirectiveMetadata(ComponentWithoutModuleId).type.moduleUrl; resolver.getDirectiveMetadata(ComponentWithoutModuleId).type.moduleUrl;
var expectedEndValue = var expectedEndValue = IS_DART ? 'test/compiler/runtime_metadata_spec.dart' : './';
IS_DART ? 'base/dist/dart/angular2/test/compiler/runtime_metadata_spec.dart' : './';
expect(value.endsWith(expectedEndValue)).toBe(true); expect(value.endsWith(expectedEndValue)).toBe(true);
})); }));
}); });

View File

@ -50,50 +50,58 @@ import {Unparser} from '../core/change_detection/parser/unparser';
var expressionUnparser = new Unparser(); var expressionUnparser = new Unparser();
var MOCK_SCHEMA_REGISTRY = [
provide(
ElementSchemaRegistry,
{useValue: new MockSchemaRegistry({'invalidProp': false}, {'mappedAttr': 'mappedProp'})})
];
export function main() { export function main() {
describe('TemplateParser', () => {
beforeEachProviders(() => [
TEST_PROVIDERS,
provide(ElementSchemaRegistry,
{
useValue: new MockSchemaRegistry({'invalidProp': false},
{'mappedAttr': 'mappedProp'})
})
]);
var parser: TemplateParser;
var ngIf; var ngIf;
var parse;
beforeEach(inject([TemplateParser], (_parser) => { function commonBeforeEach() {
parser = _parser; beforeEach(inject([TemplateParser], (parser) => {
ngIf = CompileDirectiveMetadata.create( ngIf = CompileDirectiveMetadata.create(
{selector: '[ngIf]', type: new CompileTypeMetadata({name: 'NgIf'}), inputs: ['ngIf']}); {selector: '[ngIf]', type: new CompileTypeMetadata({name: 'NgIf'}), inputs: ['ngIf']});
}));
function parse(template: string, directives: CompileDirectiveMetadata[], parse = (template: string, directives: CompileDirectiveMetadata[],
pipes: CompilePipeMetadata[] = null): TemplateAst[] { pipes: CompilePipeMetadata[] = null): TemplateAst[] => {
if (pipes === null) { if (pipes === null) {
pipes = []; pipes = [];
} }
return parser.parse(template, directives, pipes, 'TestComp'); return parser.parse(template, directives, pipes, 'TestComp');
};
}));
} }
describe('template transform', () => { describe('TemplateParser template transform', () => {
beforeEachProviders(() => [TEST_PROVIDERS, MOCK_SCHEMA_REGISTRY]);
beforeEachProviders( beforeEachProviders(
() => [provide(TEMPLATE_TRANSFORMS, {useValue: new FooAstTransformer(), multi: true})]); () => [provide(TEMPLATE_TRANSFORMS, {useValue: new FooAstTransformer(), multi: true})]);
describe('single', () => {
commonBeforeEach();
it('should transform TemplateAST', it('should transform TemplateAST',
() => { expect(humanizeTplAst(parse('<div>', []))).toEqual([[ElementAst, 'foo']]); }); () => { expect(humanizeTplAst(parse('<div>', []))).toEqual([[ElementAst, 'foo']]); });
});
describe('multiple', () => { describe('multiple', () => {
beforeEachProviders( beforeEachProviders(
() => [provide(TEMPLATE_TRANSFORMS, {useValue: new BarAstTransformer(), multi: true})]); () => [provide(TEMPLATE_TRANSFORMS, {useValue: new BarAstTransformer(), multi: true})]);
commonBeforeEach();
it('should compose transformers', it('should compose transformers',
() => { expect(humanizeTplAst(parse('<div>', []))).toEqual([[ElementAst, 'bar']]); }); () => { expect(humanizeTplAst(parse('<div>', []))).toEqual([[ElementAst, 'bar']]); });
}); });
}); });
describe('TemplateParser', () => {
beforeEachProviders(() => [TEST_PROVIDERS, MOCK_SCHEMA_REGISTRY]);
commonBeforeEach();
describe('parse', () => { describe('parse', () => {
describe('nodes without bindings', () => { describe('nodes without bindings', () => {

View File

@ -99,7 +99,7 @@ export function main() {
DOM.removeChild(headEl, baseEl); DOM.removeChild(headEl, baseEl);
DOM.resetBaseElement(); DOM.resetBaseElement();
expect(baseHref).toEqual('/base'); expect(baseHref.endsWith('/base')).toBe(true);
}); });
}); });
} }

View File

@ -1,7 +1,7 @@
library angular2.dom.html5lib_adapter.test; library angular2.dom.html5lib_adapter.test;
import 'package:guinness/guinness.dart'; import 'package:guinness2/guinness2.dart';
import 'package:unittest/unittest.dart' hide expect; import 'package:test/test.dart' hide expect;
import 'package:angular2/src/platform/server/html_adapter.dart'; import 'package:angular2/src/platform/server/html_adapter.dart';
// A smoke-test of the adapter. It is primarily tested by the compiler. // A smoke-test of the adapter. It is primarily tested by the compiler.

View File

@ -263,7 +263,7 @@ export function main() {
describe("importUri", () => { describe("importUri", () => {
it("should return the importUri for a type", () => { it("should return the importUri for a type", () => {
expect(reflector.importUri(TestObjWith00Args) expect(reflector.importUri(TestObjWith00Args)
.endsWith('base/dist/dart/angular2/test/core/reflection/reflector_spec.dart')) .endsWith('test/core/reflection/reflector_spec.dart'))
.toBe(true); .toBe(true);
}); });
}); });

View File

@ -12,12 +12,21 @@ import {
import {XHRImpl} from 'angular2/src/platform/browser/xhr_impl'; import {XHRImpl} from 'angular2/src/platform/browser/xhr_impl';
import {PromiseWrapper} from 'angular2/src/facade/async'; import {PromiseWrapper} from 'angular2/src/facade/async';
import {IS_DART} from 'angular2/src/facade/lang';
export function main() { export function main() {
describe('XHRImpl', () => { describe('XHRImpl', () => {
var xhr: XHRImpl; var xhr: XHRImpl;
var url200 = '/base/modules/angular2/test/platform/browser/static_assets/200.html';
var url404 = '/base/modules/angular2/test/platform/browser/static_assets/404.html'; // TODO(juliemr): This file currently won't work with dart unit tests run using
// exclusive it or describe (iit or ddescribe). This is because when
// pub run test is executed against this specific file the relative paths
// will be relative to here, so url200 should look like
// static_assets/200.html.
// We currently have no way of detecting this.
var urlBase = IS_DART ? '' : '/base/modules/angular2/';
var url200 = urlBase + 'test/platform/browser/static_assets/200.html';
var url404 = '/bad/path/404.html';
beforeEach(() => { xhr = new XHRImpl(); }); beforeEach(() => { xhr = new XHRImpl(); });

View File

@ -18,10 +18,10 @@ import {DOM} from 'angular2/src/platform/dom/dom_adapter';
export function main() { export function main() {
var domEventPlugin; var domEventPlugin;
beforeEach(() => { domEventPlugin = new DomEventsPlugin(); });
describe('EventManager', () => { describe('EventManager', () => {
beforeEach(() => { domEventPlugin = new DomEventsPlugin(); });
it('should delegate event bindings to plugins that are passed in from the most generic one to the most specific one', it('should delegate event bindings to plugins that are passed in from the most generic one to the most specific one',
() => { () => {
var element = el('<div></div>'); var element = el('<div></div>');

View File

@ -4,12 +4,19 @@ import {
describeWith, describeWith,
describeWithout, describeWithout,
describeWithAndWithout, describeWithAndWithout,
itShouldRoute itShouldRoute,
TEST_ROUTER_PROVIDERS
} from './util'; } from './util';
import {beforeEachProviders, describe} from 'angular2/testing_internal';
import {registerSpecs} from './impl/async_route_spec_impl'; import {registerSpecs} from './impl/async_route_spec_impl';
export function main() { export function main() {
describe('async route spec', () => {
beforeEachProviders(() => TEST_ROUTER_PROVIDERS);
registerSpecs(); registerSpecs();
describeRouter('async routes', () => { describeRouter('async routes', () => {
@ -22,7 +29,9 @@ export function main() {
() => { describeWithAndWithout('default routes', itShouldRoute); }); () => { describeWithAndWithout('default routes', itShouldRoute); });
describeWith('async children', () => { describeWith('async children', () => {
describeWithAndWithout('params', () => { describeWithout('default routes', itShouldRoute); }); describeWithAndWithout('params',
() => { describeWithout('default routes', itShouldRoute); });
});
}); });
}); });
} }

View File

@ -4,16 +4,27 @@ import {
describeWith, describeWith,
describeWithout, describeWithout,
describeWithAndWithout, describeWithAndWithout,
itShouldRoute itShouldRoute,
TEST_ROUTER_PROVIDERS
} from './util'; } from './util';
import {
beforeEachProviders,
describe,
} from 'angular2/testing_internal';
import {registerSpecs} from './impl/aux_route_spec_impl'; import {registerSpecs} from './impl/aux_route_spec_impl';
export function main() { export function main() {
describe('auxiliary route spec', () => {
beforeEachProviders(() => TEST_ROUTER_PROVIDERS);
registerSpecs(); registerSpecs();
describeRouter('aux routes', () => { describeRouter('aux routes', () => {
itShouldRoute(); itShouldRoute();
describeWith('a primary route', itShouldRoute); describeWith('a primary route', itShouldRoute);
}); });
});
} }

View File

@ -238,7 +238,9 @@ export function main() {
async.done(); async.done();
}); });
router.navigateByUrl('/rainbow(pony)'); // TODO(juliemr): This isn't necessary for the test to pass - figure
// out what's going on.
// router.navigateByUrl('/rainbow(pony)');
}); });
})); }));
}); });

View File

@ -26,7 +26,7 @@ import {
Redirect Redirect
} from 'angular2/src/router/route_config/route_config_decorator'; } from 'angular2/src/router/route_config/route_config_decorator';
import {specs, compile, TEST_ROUTER_PROVIDERS, clickOnElement, getHref} from '../util'; import {specs, compile, clickOnElement, getHref} from '../util';
import {BaseException} from 'angular2/src/facade/exceptions'; import {BaseException} from 'angular2/src/facade/exceptions';
function getLinkElement(rtc: ComponentFixture, linkIndex: number = 0) { function getLinkElement(rtc: ComponentFixture, linkIndex: number = 0) {
@ -38,8 +38,6 @@ function auxRoutes() {
var fixture: ComponentFixture; var fixture: ComponentFixture;
var rtr; var rtr;
beforeEachProviders(() => TEST_ROUTER_PROVIDERS);
beforeEach(inject([TestComponentBuilder, Router], (tcBuilder, router) => { beforeEach(inject([TestComponentBuilder, Router], (tcBuilder, router) => {
tcb = tcBuilder; tcb = tcBuilder;
rtr = router; rtr = router;
@ -143,8 +141,6 @@ function auxRoutesWithAPrimaryRoute() {
var fixture: ComponentFixture; var fixture: ComponentFixture;
var rtr; var rtr;
beforeEachProviders(() => TEST_ROUTER_PROVIDERS);
beforeEach(inject([TestComponentBuilder, Router], (tcBuilder, router) => { beforeEach(inject([TestComponentBuilder, Router], (tcBuilder, router) => {
tcb = tcBuilder; tcb = tcBuilder;
rtr = router; rtr = router;

View File

@ -4,23 +4,33 @@ import {
describeWith, describeWith,
describeWithout, describeWithout,
describeWithAndWithout, describeWithAndWithout,
itShouldRoute itShouldRoute,
TEST_ROUTER_PROVIDERS
} from './util'; } from './util';
import {beforeEachProviders, describe, ddescribe} from 'angular2/testing_internal';
import {registerSpecs} from './impl/sync_route_spec_impl'; import {registerSpecs} from './impl/sync_route_spec_impl';
export function main() { export function main() {
describe('sync route spec', () => {
beforeEachProviders(() => TEST_ROUTER_PROVIDERS);
registerSpecs(); registerSpecs();
describeRouter('sync routes', () => { describeRouter('sync routes', () => {
describeWithout('children', () => { describeWithAndWithout('params', itShouldRoute); }); describeWithout('children', () => { describeWithAndWithout('params', itShouldRoute); });
describeWith('sync children', () => { describeWith('sync children', () => {
describeWithout('default routes', () => { describeWithAndWithout('params', itShouldRoute); }); describeWithout('default routes',
() => { describeWithAndWithout('params', itShouldRoute); });
describeWith('default routes', () => { describeWithout('params', itShouldRoute); }); describeWith('default routes', () => { describeWithout('params', itShouldRoute); });
}); });
describeWith('dynamic components', itShouldRoute); describeWith('dynamic components', itShouldRoute);
}); });
});
} }

View File

@ -1,7 +1,7 @@
library angular2.test.web_workers.debug_tools.bootstrap; library angular2.test.web_workers.debug_tools.bootstrap;
import 'package:angular2/src/platform/server/html_adapter.dart'; import 'package:angular2/src/platform/server/html_adapter.dart';
import "package:angular2/testing_internal.dart"; import "package:angular2/src/testing/testing_internal_core.dart";
import "package:angular2/src/core/reflection/reflection_capabilities.dart"; import "package:angular2/src/core/reflection/reflection_capabilities.dart";
import "package:angular2/src/core/reflection/reflection.dart"; import "package:angular2/src/core/reflection/reflection.dart";
import "package:angular2/src/platform/worker_app_common.dart" import "package:angular2/src/platform/worker_app_common.dart"

View File

@ -2,7 +2,7 @@ library angular2.test.web_workers.debug_tools.message_bus_common;
import "dart:convert" show JSON; import "dart:convert" show JSON;
import "package:angular2/src/web_workers/shared/message_bus.dart"; import "package:angular2/src/web_workers/shared/message_bus.dart";
import "package:angular2/testing_internal.dart" import "package:angular2/src/testing/testing_internal_core.dart"
show AsyncTestCompleter, expect, SpyObject; show AsyncTestCompleter, expect, SpyObject;
var MESSAGE = const {'test': 10}; var MESSAGE = const {'test': 10};

View File

@ -2,7 +2,7 @@ library angular2.test.web_workers.debug_tools.multi_client_server_message_bus;
import "dart:io"; import "dart:io";
import "dart:async"; import "dart:async";
import "package:angular2/testing_internal.dart" import "package:angular2/src/testing/testing_internal_core.dart"
show show
AsyncTestCompleter, AsyncTestCompleter,
SpyObject, SpyObject,

View File

@ -2,7 +2,7 @@ library angular2.test.web_workers.debug_tools.single_client_server_message_bus;
import "dart:io"; import "dart:io";
import "dart:async"; import "dart:async";
import "package:angular2/testing_internal.dart" import "package:angular2/src/testing/testing_internal_core.dart"
show show
AsyncTestCompleter, AsyncTestCompleter,
SpyObject, SpyObject,

View File

@ -3,7 +3,7 @@
*/ */
library angular2.test.web_workers.debug_tools.server_message_bus_common; library angular2.test.web_workers.debug_tools.server_message_bus_common;
import "package:angular2/testing_internal.dart"; import "package:angular2/src/testing/testing_internal_core.dart";
import "dart:io"; import "dart:io";
@proxy @proxy

View File

@ -3,7 +3,7 @@ import {PromiseWrapper} from 'angular2/src/facade/async';
import {UiArguments} from 'angular2/src/web_workers/shared/client_message_broker'; import {UiArguments} from 'angular2/src/web_workers/shared/client_message_broker';
import {Type, isPresent} from 'angular2/src/facade/lang'; import {Type, isPresent} from 'angular2/src/facade/lang';
import {SpyMessageBroker} from '../worker/spies'; import {SpyMessageBroker} from '../worker/spies';
import {expect} from 'angular2/testing_internal'; import {expect} from 'angular2/src/testing/matchers';
import { import {
MessageBusSink, MessageBusSink,
MessageBusSource, MessageBusSource,

View File

@ -102,6 +102,7 @@ export function main() {
var domRootRenderer = uiInjector.get(DomRootRenderer); var domRootRenderer = uiInjector.get(DomRootRenderer);
workerRenderStore = new RenderStore(); workerRenderStore = new RenderStore();
return [ return [
Serializer,
provide(ChangeDetectorGenConfig, provide(ChangeDetectorGenConfig,
{useValue: new ChangeDetectorGenConfig(true, true, false)}), {useValue: new ChangeDetectorGenConfig(true, true, false)}),
provide(RenderStore, {useValue: workerRenderStore}), provide(RenderStore, {useValue: workerRenderStore}),

View File

@ -1,7 +1,7 @@
library web_workers.spies; library web_workers.spies;
import 'package:angular2/src/web_workers/shared/client_message_broker.dart'; import 'package:angular2/src/web_workers/shared/client_message_broker.dart';
import 'package:angular2/testing_internal.dart'; import 'package:angular2/src/testing/testing_internal_core.dart';
@proxy @proxy
class SpyMessageBroker extends SpyObject implements ClientMessageBroker {} class SpyMessageBroker extends SpyObject implements ClientMessageBroker {}

View File

@ -15,6 +15,6 @@ dependency_overrides:
angular2: angular2:
path: ../angular2 path: ../angular2
dev_dependencies: dev_dependencies:
guinness: '^0.1.17' guinness2: '0.0.4'
transformers: transformers:
- angular2 - angular2

View File

@ -13,7 +13,10 @@ dependencies:
stack_trace: '^1.1.1' stack_trace: '^1.1.1'
webdriver: '^0.9.0' webdriver: '^0.9.0'
dev_dependencies: dev_dependencies:
guinness: '^0.1.17' guinness2: '0.0.4'
quiver: '^0.21.4'
test: '^0.12.10'
dependency_overrides: dependency_overrides:
angular2: angular2:
path: ../angular2 path: ../angular2
matcher: '0.12.0+1'

View File

@ -7,7 +7,7 @@ dependencies:
angular2_material: '^<%= packageJson.version %>' angular2_material: '^<%= packageJson.version %>'
browser: '^0.10.0' browser: '^0.10.0'
dev_dependencies: dev_dependencies:
guinness: '^0.1.17' guinness2: '0.0.5'
benchpress: benchpress:
path: ../benchpress path: ../benchpress
dependency_overrides: dependency_overrides:
@ -15,6 +15,7 @@ dependency_overrides:
path: ../angular2 path: ../angular2
angular2_material: angular2_material:
path: ../angular2_material path: ../angular2_material
matcher: '0.12.0+1'
transformers: transformers:
- angular2: - angular2:
platform_directives: 'package:angular2/src/common/directives.dart#CORE_DIRECTIVES' platform_directives: 'package:angular2/src/common/directives.dart#CORE_DIRECTIVES'

View File

@ -1,6 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:io' show Platform; import 'dart:io' show Platform;
import 'package:guinness/guinness.dart'; import 'package:guinness2/guinness2.dart';
import 'package:benchpress/benchpress.dart'; import 'package:benchpress/benchpress.dart';
import 'package:webdriver/webdriver.dart' import 'package:webdriver/webdriver.dart'
show WebDriver, Capabilities, LogType, LogLevel, By; show WebDriver, Capabilities, LogType, LogLevel, By;

View File

@ -82,7 +82,6 @@
"karma": "^0.13.17", "karma": "^0.13.17",
"karma-browserstack-launcher": "^0.1.9", "karma-browserstack-launcher": "^0.1.9",
"karma-chrome-launcher": "^0.2.0", "karma-chrome-launcher": "^0.2.0",
"karma-dart": "^0.3.0",
"karma-jasmine": "^0.3.6", "karma-jasmine": "^0.3.6",
"karma-sauce-launcher": "^0.3.0", "karma-sauce-launcher": "^0.3.0",
"karma-sourcemap-loader": "^0.3.6", "karma-sourcemap-loader": "^0.3.6",

View File

@ -4,7 +4,7 @@ environment:
dependencies: dependencies:
observe: '^0.13.1' observe: '^0.13.1'
dev_dependencies: dev_dependencies:
guinness: '^0.1.18' guinness2: '0.0.5'
intl: '^0.12.4' intl: '^0.12.4'
unittest: '^0.11.5+4' unittest: '^0.11.5+4'
quiver: '^0.21.4' quiver: '^0.21.4'

View File

@ -1,9 +0,0 @@
import 'package:angular2/testing.dart';
import 'package:angular2/platform/testing/browser.dart';
import 'package:angular2/src/core/reflection/reflection.dart';
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS, TEST_BROWSER_APPLICATION_PROVIDERS);
}

View File

@ -1,29 +0,0 @@
import 'package:guinness/guinness.dart';
import 'package:unittest/unittest.dart' as unit;
import 'package:angular2/src/testing/testing_internal.dart' show testSetup;
main() {
unit.filterStacks = true;
unit.formatStacks = false;
unit.unittestConfiguration.timeout = new Duration(milliseconds: 2000);
_printWarnings();
guinness.autoInit = false;
guinness.initSpecs();
testSetup();
}
_printWarnings () {
final info = guinness.suiteInfo();
if (info.activeIts.any((it) => it.exclusive)) {
print("WARN: iit caused some tests to be excluded");
}
if (info.exclusiveDescribes.isNotEmpty) {
print("WARN: ddescribe caused some tests to be excluded");
}
}

View File

@ -0,0 +1,21 @@
var path = require('path');
var fs = require('fs');
module.exports = function(dir, files) {
var filename = 'main_test.dart';
var imports = [
'@TestOn("browser")',
'import "package:guinness2/guinness2.dart";'];
var executes = [];
files.forEach(function(match) {
var varName = match.replace(/[\/.]/g, '_');
imports.push('import "' + match + '" as ' + varName +';');
executes.push(' ' + varName + '.main();');
});
var output = imports.join('\n') + '\n\nmain() {\n' + executes.join('\n') + '\n}';
fs.writeFileSync(path.join(dir, filename), output);
return filename;
};

View File

@ -1,7 +1,7 @@
var util = require('./util'); var util = require('./util');
var spawn = require('child_process').spawn; var spawn = require('child_process').spawn;
module.exports = function(gulp, plugins, config, module) { module.exports = function(gulp, plugins, config) {
return function() { return function() {
config.port = config.port || 8080; config.port = config.port || 8080;
var pubMode = config.mode || 'debug'; var pubMode = config.mode || 'debug';

51
tools/build/pubtest.js Normal file
View File

@ -0,0 +1,51 @@
var util = require('./util');
var spawn = require('child_process').spawn;
var glob = require('glob');
var path = require('path');
var fs = require('fs');
var process = require('process');
var createTestMain = require('./create_dart_test_main.js')
function filterExclusiveTestFiles(files, dir) {
return files.filter(function(file) {
// TODO(juliemr): revisit if readFileSync becomes too slow.
// At the moment, this takes <100ms for all of angular2.
var text = fs.readFileSync(path.join(dir, file));
var iit = text.indexOf('iit(');
var ddescribe = text.indexOf('ddescribe(');
return (iit !== -1 || ddescribe !== -1);
});
}
module.exports = function(config) {
var platform = config.platform || 'dartium';
var pubArgs = ['run', 'test', '-p', platform];
var env = process.env;
var exclusive = false;
if (config.dartiumTmpdir) {
env['PATH'] = env['PATH'] + ':' + config.dartiumTmpdir;
}
testFiles = glob.sync(path.join(config.files), {cwd: config.dir});
if (config.useExclusiveTests) {
var filtered = filterExclusiveTestFiles(testFiles, config.dir);
if (filtered.length) {
exclusive = true;
pubArgs.push('--tags');
pubArgs.push('solo');
testFiles = filtered;
}
}
if (config.bunchFiles && !exclusive) {
var bigFile = createTestMain(config.dir, testFiles);
testFiles = [bigFile];
}
pubArgs = pubArgs.concat(testFiles);
return util.processToPromise(spawn(config.command, pubArgs, {
cwd: config.dir, stdio: 'inherit', env: env
}));
};