Compare commits

...

51 Commits

Author SHA1 Message Date
Jason Aden 0f37ed1060 release: cut the v7.2.3 release 2019-01-30 11:42:59 -08:00
Jeff Cross 5c85b4f1e9 docs: add Jeff Cross to contributors (#28432)
PR Close #28432
2019-01-29 16:41:32 -08:00
jithil-kore 22bc6ef22a docs: fix typo for Browserslist in build guide (#28328)
PR Close #28328
2019-01-29 16:35:27 -08:00
Matti Järvinen bf928d1c9e docs: fix typo for Browserslist in file structure guide (#28312)
PR Close #28312
2019-01-29 16:33:19 -08:00
Nazar Nasirzada d11c2f915b docs: fix typo in lifecycle-hooks.md (#28206)
## PR Checklist
Please check if your PR fulfills the following requirements:
 
* [x]  The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
* [ ]  Tests for the changes have been added (for bug fixes / features)
* [x]  Docs have been added / updated (for bug fixes / features)
 
## PR Type
What kind of change does this PR introduce?

* [ ]  Bugfix
* [ ]  Feature
* [ ]  Code style update (formatting, local variables)
* [ ]  Refactoring (no functional changes, no api changes)
* [ ]  Build related changes
* [ ]  CI related changes
* [x]  Documentation content changes
* [ ]  angular.io application / infrastructure changes
* [ ]  Other... Please describe:

## What is the current behavior?
Issue Number: N/A

## What is the new behavior?
## Does this PR introduce a breaking change?
* [ ]  Yes
* [x]  No

## Other information
PR Close #28206
2019-01-29 16:32:03 -08:00
Janghyun Han 98c99e5073 docs: angular.kr link added (#28113)
PR Close #28113
2019-01-29 16:31:38 -08:00
Erick Xavier 2c63108faa docs(core): add relative path information to component metadata (#27962)
Adds the information that the templateUrl and styleUrls options supports only relative Urls.

Adds more information about relative paths and absolute URLs in project metadata.

PR Close #27962
2019-01-29 16:31:12 -08:00
onlyflix 0ff48a1266 style: change to American English (#27266)
PR Close #27266
2019-01-29 16:30:26 -08:00
Jason Aden ea2a3f8335 Revert "build: switch example e2e tests to bazel (#28402)" (#28438)
This reverts commit ef78e33560.

PR Close #28438
2019-01-29 16:20:27 -08:00
Jason Aden cbed4851a3 Revert "test: disable failing ivy example e2e tests (#28402)" (#28438)
This reverts commit 351610ca8d.

PR Close #28438
2019-01-29 16:20:27 -08:00
jithil-kore 7c157780a9 docs: fix Redundant "See also:" link in ContentChild (#28334)
PR Close #28334
2019-01-29 12:03:26 -08:00
jithil-kore cc1b2a5373 perf: yarn version upgrade (#28360)
PR Close #28360
2019-01-29 11:58:48 -08:00
WilliamKoza 5076185fc8 fix(docs-infra): add hamburger button to CLI COMMANDS section (#28418)
Currently, when we navigate in the `CLI COMMANDS` section, the "hamburger button" isn't present because the class css `folder-cli` is missing.
This PR add this class in order to show this button when we are in this section.

PR Close #28418
2019-01-29 11:48:34 -08:00
Alan Agius 65375f4c21 fix(docs-infra): boolean options default value is incorrect when it's undefined (#27024)
In the CLI when it's undefined it can mean `false`, or sometimes it will be overwritten by a runtime value.

PR Close #27024
2019-01-28 20:43:16 -08:00
Dhananjay Kumar 068a6070dc docs(docs-infra): add ng-India to events list (#28119)
docs: add ng-India to events list
PR Close #28119
2019-01-28 20:18:52 -08:00
Paul Gschwendtner 47e9761a01 build: improve compiler-cli codegen output test (#28191)
* Improves the `compiler-cli/integrationtest` codegen output test slightly by using a more clear test description and by adding an assertion that ensures that decorators are downleveled.

PR Close #28191
2019-01-28 20:07:23 -08:00
Paul Gschwendtner bef52d20b5 build: fix outdated ngtools compiler-cli test logic (#28191)
* Fixes that the test logic for `ngtools` in the offline compiler test is no longer working due to being unmaintained for a long time
* Makes the path comparison logic platform agnostic, so that the tests can be also executed on Windows

PR Close #28191
2019-01-28 20:07:23 -08:00
Paul Gschwendtner fe50710021 build: fix outdated i18n compiler-cli test assertions (#28191)
PR Close #28191
2019-01-28 20:07:23 -08:00
Paul Gschwendtner 71b66fb862 build: run offline_compiler_test using bazel (#28191)
PR Close #28191
2019-01-28 20:07:23 -08:00
Keen Yee Liau 8db05b408e test(bazel): Integration test for Sass support (#28297)
Add .sass files to the integration test for bazel-schematics.

Also addressed Alex's comment in
https://github.com/angular/angular/pull/28167/files#r248149866
about the unit tests being too brittle.

PR Close #28297
2019-01-28 20:01:19 -08:00
Paul Gschwendtner 351610ca8d test: disable failing ivy example e2e tests (#28402)
PR Close #28402
2019-01-28 19:21:10 -08:00
Paul Gschwendtner ef78e33560 build: switch example e2e tests to bazel (#28402)
* No longer builds the example e2e tests using "tsc". The examples are now built with Bazel and can therefore be built with Ivy by using the `--define=compile=aot` switch.
* No longer runs the example e2e tests using the protractor CLI. example e2e tests are executed with the Bazel protractor rule and can therefore run incrementally.

NOTE: Unit tests found within the examples are still running within the legacy jobs.

PR Close #28402
2019-01-28 19:21:10 -08:00
Keen Yee Liau 12b8a6e351 fix(bazel): Builder should invoke local bazel/iblaze (#28303)
Builder for `@angular/bazel` schematics should not expect bazel/ibazel
to be on the PATH. It should instead invoke the local executable
installed by yarn/npm.

PR Close #28303
2019-01-28 12:01:36 -08:00
Keen Yee Liau 260ac20e92 fix(bazel): Bazel-workspace schematics should run in ScopedTree (#28349)
Users should be able to add Bazel workspace to an existing project.
The current approach assumes that the schematics is working on the same
tree as that of ng-new, which includes the top-level directory. Instead,
the schematic should work on the tree rooted at `appRoot` to enable
Bazel files to be added to existing project.

This change uses the newly implemented ScopedTree
https://github.com/angular/angular-cli/commit/a0ac4b0e3dd60c75e1edafd6bb8cced47d10a8d3
to achieve this.

NOTE: The version of `@angular-devkit/schematics` that is installed is
used to run the `@angular/bazel` schematic. Even if a different version
is used in the schematic itself, it has no effect.
Therefore, the *latest* Angular CLI should be used to generate the
files. As of this commit, the latest version is @angular/cli@7.3.0-rc.0

PR Close #28349
2019-01-28 12:00:16 -08:00
Paul Gschwendtner aed48e00d2 build: update sauce connect version (#28378)
PR Close #28378
2019-01-28 11:55:07 -08:00
Keen Yee Liau a9d46e4952 fix(bazel): ng-new should run yarn install (#28381)
yarn install was disabled in ng-new for Bazel schematics because
Bazel manages its own node_modules dependencies and therefore
there is no need to install dependencies twice.

However, the first yarn install is needed for `ng` commands to work,
most notably `ng build`.

This commit restores the original behavior.

PR Close #28381
2019-01-28 11:54:37 -08:00
WilliamKoza 2f19ad9b46 fix(docs-infra): upgrade codelyzer to 4.5.0 (#28389)
PR Close #28389
2019-01-28 11:51:57 -08:00
Greg Magolan 81678e62db build(bazel): update to bazel 0.22.0 and turn on --incompatible_strict_action_env flag (#28404)
PR Close #28404
2019-01-28 11:48:42 -08:00
Alex Eagle cf82fbceba build: set a default module_name for ts_library rules (#28051) (#28241)
PR Close #28051

PR Close #28241
2019-01-25 12:52:27 -08:00
George Kalpakas 1d67cb0ce1 test(docs-infra): increase timeout for redirection tests more (#28290)
Occasionally, external URLs take even longer than the previously set 60s
to load, which causes CI flakes.

PR Close #28290
2019-01-25 12:51:38 -08:00
George Kalpakas 318bd83a6e test(docs-infra): unregister the SW after each test (#28290)
This ensures that the SW is cleaned up, even in cases where
synchronization is disabled (and thus the clean-up inside `goTo()`
happens without waiting for Angular).

PR Close #28290
2019-01-25 12:51:38 -08:00
George Kalpakas f767c22b31 test(docs-infra): unregister the SW after waitForAngular() (#28290)
This increases the chances that the clean-up will take place _after_ the
SW has been registered.

PR Close #28290
2019-01-25 12:51:38 -08:00
George Kalpakas 8346a6dca2 test(docs-infra): properly report errors if page.init() fails/rejects (#28290)
For asynchronous callbacks, this can be done either by calling
`done.fail()` or by returning the promise directly (without requesting a
`done` callback). (Using the latter, because it is shorter.)

PR Close #28290
2019-01-25 12:51:37 -08:00
Keen Yee Liau 6397885e74 test(bazel): Cleanup bazel-schematics integration test (#28351)
PR Close #28351
2019-01-25 12:47:27 -08:00
Greg Magolan 8cee56e8c5 fix(bazel): add @npm//tslib dep to e2e ts_library target in bazel-workspace schematic (#28358)
PR Close #28358
2019-01-25 12:38:35 -08:00
Jason Aden a1b9995731 refactor(router): initalize browserUrlTree to empty tree (#28376)
The value here is unimportant on initialization since it's not looked at until the second navigation. However, sometimes in testing  the `Location` service is mocked out, or the Router constructor manually called. Assuming `Location` exists in the constructor leads to test failures in `google3` therefore we initialize to a value that will not cause errors.

PR Close #28376
2019-01-25 12:37:57 -08:00
Judy Bogart 35f7ff047a docs: add api doc for ngif (#27376) (#28344)
PR Close #27376

PR Close #28344
2019-01-24 15:45:06 -08:00
Judy Bogart 4ad691a33d docs: add api doc for ngfor (#27377) (#28344)
PR Close #27377

PR Close #28344
2019-01-24 15:45:06 -08:00
Judy Bogart c5af3f8617 docs: add api doc to template_ref (#28344)
PR Close #28344
2019-01-24 15:45:06 -08:00
WilliamKoza bc1032866c fix(docs-infra): change the key used to find out the cli section (#28293)
PR Close #28293
2019-01-24 15:41:45 -08:00
Carlos Schneider 63e6d1a896 docs(docs-infra): show top menu at 992px screen width (#26418)
Show top menu at 992px screen width. The JS expression was checking just for screen widths
strictly greater than 992px to show the menu, while the CSS media query was showing the hamburger
icon just for screen widths strictly smaller than 992px, so there was a gap of 1px that the user
could't navigate through the top menu.

closes #24324

PR Close #26418
2019-01-24 10:26:55 -08:00
WilliamKoza cb9fd9b4d7 feat(docs-infra): saves the scroll position before the change of location (#28037)
Issue #27916, #17308

PR Close #28037
2019-01-24 10:24:43 -08:00
George Kalpakas d5dca0764c fix(docs-infra): align property names to the top (#28104)
This looks better when the property descriptions span multiple lines;
especially when scrolling to a specific property (e.g.
[AbstractControl#status][1]).

[1]: https://next.angular.io/api/forms/AbstractControl#status

PR Close #28104
2019-01-24 10:24:04 -08:00
George Kalpakas bcd1a09dec refactor(docs-infra): remove unused CSS style rule (#28104)
The `.properties-table` selector does not match any element and the
styles don't look relevant for the similarly named `.property-table`
class.

PR Close #28104
2019-01-24 10:24:04 -08:00
Dario Braun 898c0134e7 docs: fix typo and add parenthesis to method in HTTP tutorial (#28289)
Merge remote-tracking branch 'origin/TOH' into TOH


PR Close #28289
2019-01-24 10:23:25 -08:00
Felix Lemke 763d2150cc docs(animations): fix group and sequence function usage examples (#28305)
animate functions now contain style functions instead of plain objects
e.g. animate(1s, { background: black }))
to   animate(1s, style({ background: black }))

PR Close #28305
2019-01-24 10:21:35 -08:00
George Kalpakas beacbfcb8e build(docs-infra): upgrade cli command docs sources to 699743282 (#28329)
Updating [angular#7.2.x](https://github.com/angular/angular/tree/7.2.x) from [cli-builds#7.2.x](https://github.com/angular/cli-builds/tree/7.2.x).
Relevant changes in [commit range](https://github.com/angular/cli-builds/compare/02d2ec250...699743282):

**Modified**
- help/generate.json
- help/new.json

PR Close #28329
2019-01-24 10:18:56 -08:00
William Neely f72319cf6e docs(router): removed additional to (#25989)
PR Close #25989
2019-01-23 11:00:20 -08:00
Daniel Ruf 5877b3f702 refactor: remove unused parameter in _main method invocation (#28203)
PR Close #28203
2019-01-23 10:58:39 -08:00
Daniel Ruf cf310ba1fa refactor: fix code style (#28203)
PR Close #28203
2019-01-23 10:58:38 -08:00
Daniel Ruf c2d2953ee4 refactor: remove unused parameters (#28203)
PR Close #28203
2019-01-23 10:58:38 -08:00
128 changed files with 1414 additions and 923 deletions
+10
View File
@@ -42,6 +42,16 @@ build --watchfs
run --nolegacy_external_runfiles
test --nolegacy_external_runfiles
# Turn on --incompatible_strict_action_env which was on by default
# in Bazel 0.21.0 but turned off again in 0.22.0. Follow
# https://github.com/bazelbuild/bazel/issues/7026 for more details.
# This flag is needed to so that the bazel cache is not invalidated
# when running bazel via `yarn bazel`.
# See https://github.com/angular/angular/issues/27514.
build --incompatible_strict_action_env
run --incompatible_strict_action_env
test --incompatible_strict_action_env
###############################
# Release support #
# Turn on these settings with #
+18
View File
@@ -1,3 +1,21 @@
<a name="7.2.3"></a>
## [7.2.3](https://github.com/angular/angular/compare/7.2.2...7.2.3) (2019-01-30)
### Bug Fixes
* **bazel:** add [@npm](https://github.com/npm)//tslib dep to e2e ts_library target in bazel-workspace schematic ([#28358](https://github.com/angular/angular/issues/28358)) ([8cee56e](https://github.com/angular/angular/commit/8cee56e))
* **bazel:** Bazel-workspace schematics should run in ScopedTree ([#28349](https://github.com/angular/angular/issues/28349)) ([260ac20](https://github.com/angular/angular/commit/260ac20))
* **bazel:** Builder should invoke local bazel/iblaze ([#28303](https://github.com/angular/angular/issues/28303)) ([12b8a6e](https://github.com/angular/angular/commit/12b8a6e))
* **bazel:** ng-new should run yarn install ([#28381](https://github.com/angular/angular/issues/28381)) ([a9d46e4](https://github.com/angular/angular/commit/a9d46e4))
### Performance Improvements
* yarn version upgrade ([#28360](https://github.com/angular/angular/issues/28360)) ([cc1b2a5](https://github.com/angular/angular/commit/cc1b2a5))
<a name="7.2.2"></a>
## [7.2.2](https://github.com/angular/angular/compare/7.2.1...7.2.2) (2019-01-22)
+2 -2
View File
@@ -62,8 +62,8 @@ local_repository(
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
# Bazel version must be at least v0.21.0 because:
# - 0.21.0 --experimental_strict_action_env flag turned on by default which fixes cache when
# running `yarn bazel` (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
# - 0.21.0 Using --incompatible_strict_action_env flag fixes cache when running `yarn bazel`
# (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
check_bazel_version("0.21.0", """
You no longer need to install Bazel on your machine.
Angular has a dependency on the @bazel/bazel package which supplies it.
+1 -1
View File
@@ -1508,7 +1508,7 @@ done manually.
When `true`, this option tells the compiler not to check the TypeScript version.
The compiler will skip checking and will not error out when an unsupported version of TypeScript is used.
Setting this option to `true` is not recommended because unsupported versions of TypeScript might have undefined behaviour.
Setting this option to `true` is not recommended because unsupported versions of TypeScript might have undefined behavior.
This option is `false` by default.
+2 -2
View File
@@ -273,8 +273,8 @@ The CLI uses [Autoprefixer](https://github.com/postcss/autoprefixer) to ensure c
You may find it necessary to target specific browsers or exclude certain browser versions from your build.
Internally, Autoprefixer relies on a library called [Browserslist](https://github.com/browserslist/browserslist) to figure out which browsers to support with prefixing.
Browserlist looks for configuration options in a `browserlist` property of the package configuration file, or in a configuration file named `.browserslistrc`.
Autoprefixer looks for the Browserlist configuration when it prefixes your CSS.
Browserlist looks for configuration options in a `browserslist` property of the package configuration file, or in a configuration file named `.browserslistrc`.
Autoprefixer looks for the `browserslist` configuration when it prefixes your CSS.
* You can tell Autoprefixer what browsers to target by adding a browserslist property to the package configuration file, `package.json`:
```
+1 -1
View File
@@ -53,7 +53,7 @@ Workspace-wide `node_modules` dependencies are visible to this project.
| `app/` | Contains the component files in which your app logic and data are defined. See details in [App source folder](#app-src) below. |
| `assets/` | Contains image files and other asset files to be copied as-is when you build your application. |
| `environments/` | Contains build configuration options for particular target environments. By default there is an unnamed standard development environment and a production ("prod") environment. You can define additional target environment configurations. |
| `browserlist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserlist on GitHub](https://github.com/browserslist/browserslist) for more information. |
| `browserslist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserslist on GitHub](https://github.com/browserslist/browserslist) for more information. |
| `favicon.ico` | An icon to use for this app in the bookmark bar. |
| `index.html` | The main HTML page that is served when someone visits your site. The CLI automatically adds all JavaScript and CSS files when building your app, so you typically don't need to add any `<script>` or` <link>` tags here manually. |
| `main.ts` | The main entry point for your app. Compiles the application with the [JIT compiler](https://angular.io/guide/glossary#jit) and bootstraps the application's root module (AppModule) to run in the browser. You can also use the [AOT compiler](https://angular.io/guide/aot-compiler) without changing any code by appending the `--aot` flag to the CLI `build` and `serve` commands. |
+1 -1
View File
@@ -124,7 +124,7 @@ calls the lifecycle hook methods in the following sequence at specific moments:
Respond after Angular checks the component's views and child views / the view that a directive is in.
Called after the `ngAfterViewInit` and every subsequent `ngAfterContentChecked()`.
Called after the `ngAfterViewInit()` and every subsequent `ngAfterContentChecked()`.
</td>
</tr>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 154 KiB

+8
View File
@@ -698,5 +698,13 @@
"website": "https://brianflove.com",
"bio": "Brian is a software engineer and GDE in Angular with a passion for learning, writing, speaking, teaching and mentoring. Brian has been building web applications for over 20 years and has long been a fanboy of JavaScript. When not in front of his Macbook Pro Brian is in the Rocky Mountains skiing or hiking.",
"group": "GDE"
},
"jeffbcross": {
"name": "Jeff Cross",
"picture": "jeff-cross.jpg",
"twitter": "jeffbcross",
"website": "https://nrwl.io/",
"bio": "Jeff is an Angular Consultant at nrwl.io where he helps enterprise teams succeed with Angular. Prior to founding Nrwl, Jeff was one of the earliest members of the Angular Core Team at Google, and contributed to many of the early state management and performance efforts of AngularJS and Angular.",
"group": "GDE"
}
}
+6
View File
@@ -19,6 +19,12 @@
<td>Atlanta, Georgia</td>
<td>January 9 - 12, 2019</td>
</tr>
<!-- ng-India 2019-->
<tr>
<th><a href="https://www.ng-ind.com/" title="ng-India">ng-India</a></th>
<td>Gurgaon, India</td>
<td>February 23, 2019</td>
</tr>
</tbody>
</table>
+4
View File
@@ -753,6 +753,10 @@
{
"title": "日本語版",
"url": "https://angular.jp/"
},
{
"title": "한국어",
"url": "https://angular.kr/"
}
]
}
+1 -1
View File
@@ -112,7 +112,7 @@ Inject `HttpClient` into the constructor in a private property called `http`.
</code-example>
Keep injecting the `MessageService`. You'll call it so frequently that
you'll wrap it in private `log` method.
you'll wrap it in a private `log()` method.
<code-example
path="toh-pt6/src/app/hero.service.ts"
+3 -3
View File
@@ -17,7 +17,7 @@
"build": "yarn ~~build",
"prebuild-local": "yarn setup-local",
"build-local": "yarn ~~build",
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 02d2ec250",
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 699743282",
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",
"test": "yarn check-env && ng test",
"pree2e": "yarn check-env && yarn update-webdriver",
@@ -71,7 +71,7 @@
},
"engines": {
"node": ">=10.9.0 <11.0.0",
"yarn": ">=1.10.1 <1.13.0"
"yarn": ">=1.10.1 <1.14.0"
},
"private": true,
"dependencies": {
@@ -107,7 +107,7 @@
"canonical-path": "1.0.0",
"chalk": "^2.1.0",
"cjson": "^0.5.0",
"codelyzer": "~4.2.1",
"codelyzer": "~4.5.0",
"cross-spawn": "^5.1.0",
"css-selector-parser": "^1.3.0",
"dgeni": "^0.4.11",
+1 -1
View File
@@ -9,7 +9,7 @@ const SRC_DIR = resolve(__dirname, '../src');
const DIST_DIR = resolve(__dirname, '../dist');
// Run
_main(process.argv.slice(2));
_main();
// Functions - Definitions
function _main() {
+19 -17
View File
@@ -169,6 +169,13 @@ describe('AppComponent', () => {
expect(component.tocMaxHeight).toMatch(/^\d+\.\d{2}$/);
});
it('should update `scrollService.updateScrollPositonInHistory()`', () => {
const scrollService = fixture.debugElement.injector.get<ScrollService>(ScrollService);
spyOn(scrollService, 'updateScrollPositionInHistory');
component.onScroll();
expect(scrollService.updateScrollPositionInHistory).toHaveBeenCalled();
});
});
describe('SideNav', () => {
@@ -461,11 +468,15 @@ describe('AppComponent', () => {
let scrollService: ScrollService;
let scrollSpy: jasmine.Spy;
let scrollToTopSpy: jasmine.Spy;
let scrollAfterRenderSpy: jasmine.Spy;
let removeStoredScrollPositionSpy: jasmine.Spy;
beforeEach(() => {
scrollService = fixture.debugElement.injector.get<ScrollService>(ScrollService);
scrollSpy = spyOn(scrollService, 'scroll');
scrollToTopSpy = spyOn(scrollService, 'scrollToTop');
scrollAfterRenderSpy = spyOn(scrollService, 'scrollAfterRender');
removeStoredScrollPositionSpy = spyOn(scrollService, 'removeStoredScrollPosition');
});
it('should not scroll immediately when the docId (path) changes', () => {
@@ -510,33 +521,24 @@ describe('AppComponent', () => {
expect(scrollSpy).toHaveBeenCalledTimes(1);
});
it('should scroll to top when call `onDocRemoved` directly', () => {
scrollToTopSpy.calls.reset();
it('should call `removeStoredScrollPosition` when call `onDocRemoved` directly', () => {
component.onDocRemoved();
expect(scrollToTopSpy).toHaveBeenCalled();
expect(removeStoredScrollPositionSpy).toHaveBeenCalled();
});
it('should scroll after a delay when call `onDocInserted` directly', fakeAsync(() => {
it('should call `scrollAfterRender` when call `onDocInserted` directly', (() => {
component.onDocInserted();
expect(scrollSpy).not.toHaveBeenCalled();
tick(scrollDelay);
expect(scrollSpy).toHaveBeenCalled();
expect(scrollAfterRenderSpy).toHaveBeenCalledWith(scrollDelay);
}));
it('should scroll (via `onDocInserted`) when finish navigating to a new doc', fakeAsync(() => {
expect(scrollToTopSpy).not.toHaveBeenCalled();
it('should call `scrollAfterRender` (via `onDocInserted`) when navigate to a new Doc', fakeAsync(() => {
locationService.go('guide/pipes');
tick(1); // triggers the HTTP response for the document
tick(1); // triggers the HTTP response for the document
fixture.detectChanges(); // triggers the event that calls `onDocInserted`
expect(scrollToTopSpy).toHaveBeenCalled();
expect(scrollSpy).not.toHaveBeenCalled();
expect(scrollAfterRenderSpy).toHaveBeenCalledWith(scrollDelay);
tick(scrollDelay);
expect(scrollSpy).toHaveBeenCalled();
tick(500); // there are other outstanding timers in the AppComponent that are not relevant
}));
});
+8 -14
View File
@@ -127,7 +127,7 @@ export class AppComponent implements OnInit {
}
if (path === this.currentPath) {
// scroll only if on same page (most likely a change to the hash)
this.autoScroll();
this.scrollService.scroll();
} else {
// don't scroll; leave that to `onDocRendered`
this.currentPath = path;
@@ -187,11 +187,6 @@ export class AppComponent implements OnInit {
.subscribe(() => this.updateShell());
}
// Scroll to the anchor in the hash fragment or top of doc.
autoScroll() {
this.scrollService.scroll();
}
onDocReady() {
// About to transition to new view.
this.isTransitioning = true;
@@ -204,9 +199,7 @@ export class AppComponent implements OnInit {
}
onDocRemoved() {
// The previous document has been removed.
// Scroll to top to restore a clean visual state for the new document.
this.scrollService.scrollToTop();
this.scrollService.removeStoredScrollPosition();
}
onDocInserted() {
@@ -216,9 +209,8 @@ export class AppComponent implements OnInit {
// (e.g. sidenav, host classes) needs to happen asynchronously.
setTimeout(() => this.updateShell());
// Scroll 500ms after the new document has been inserted into the doc-viewer.
// The delay is to allow time for async layout to complete.
setTimeout(() => this.autoScroll(), 500);
// Scroll the good position depending on the context
this.scrollService.scrollAfterRender(500);
}
onDocRendered() {
@@ -242,7 +234,7 @@ export class AppComponent implements OnInit {
@HostListener('window:resize', ['$event.target.innerWidth'])
onResize(width: number) {
this.isSideBySide = width > this.sideBySideWidth;
this.isSideBySide = width >= this.sideBySideWidth;
this.showFloatingToc.next(width > this.showFloatingTocWidth);
if (this.isSideBySide && !this.isSideNavDoc) {
@@ -256,7 +248,6 @@ export class AppComponent implements OnInit {
@HostListener('click', ['$event.target', '$event.button', '$event.ctrlKey', '$event.metaKey', '$event.altKey'])
onClick(eventTarget: HTMLElement, button: number, ctrlKey: boolean, metaKey: boolean, altKey: boolean): boolean {
// Hide the search results if we clicked outside both the "search box" and the "search results"
if (!this.searchElements.some(element => element.nativeElement.contains(eventTarget))) {
this.hideSearchResults();
@@ -348,6 +339,9 @@ export class AppComponent implements OnInit {
// Dynamically change height of table of contents container
@HostListener('window:scroll')
onScroll() {
this.scrollService.updateScrollPositionInHistory();
if (!this.tocMaxHeightOffset) {
// Must wait until `mat-toolbar` is measurable.
const el = this.hostElement.nativeElement as Element;
@@ -46,7 +46,7 @@ export interface TabInfo {
export class CodeTabsComponent implements OnInit, AfterViewInit {
tabs: TabInfo[];
@Input('linenums') linenums: string;
@Input() linenums: string;
@ViewChild('content') content;
@@ -15,7 +15,7 @@ import { DocumentContents } from 'app/documents/document.service';
export class DtComponent {
@Input() on = false;
@Input('doc') doc: DocumentContents;
@Input() doc: DocumentContents;
@Output() docChange = new EventEmitter<DocumentContents>();
@ViewChild('dt', { read: ElementRef })
+160 -8
View File
@@ -1,6 +1,8 @@
import { ReflectiveInjector } from '@angular/core';
import { PlatformLocation } from '@angular/common';
import { Location, LocationStrategy, PlatformLocation, ViewportScroller } from '@angular/common';
import { DOCUMENT } from '@angular/common';
import { MockLocationStrategy, SpyLocation } from '@angular/common/testing';
import { fakeAsync, tick } from '@angular/core/testing';
import { ScrollService, topMargin } from './scroll.service';
@@ -8,8 +10,9 @@ describe('ScrollService', () => {
const topOfPageElem = {} as Element;
let injector: ReflectiveInjector;
let document: MockDocument;
let location: MockPlatformLocation;
let platformLocation: MockPlatformLocation;
let scrollService: ScrollService;
let location: SpyLocation;
class MockPlatformLocation {
hash: string;
@@ -27,6 +30,11 @@ describe('ScrollService', () => {
scrollIntoView = jasmine.createSpy('Element scrollIntoView');
}
const viewportScrollerStub = jasmine.createSpyObj(
'viewportScroller',
['getScrollPosition', 'scrollToPosition']);
beforeEach(() => {
spyOn(window, 'scrollBy');
});
@@ -34,12 +42,24 @@ describe('ScrollService', () => {
beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([
ScrollService,
{ provide: Location, useClass: SpyLocation },
{ provide: DOCUMENT, useClass: MockDocument },
{ provide: PlatformLocation, useClass: MockPlatformLocation }
{ provide: PlatformLocation, useClass: MockPlatformLocation },
{ provide: ViewportScroller, useValue: viewportScrollerStub },
{ provide: LocationStrategy, useClass: MockLocationStrategy }
]);
location = injector.get(PlatformLocation);
platformLocation = injector.get(PlatformLocation);
document = injector.get(DOCUMENT);
scrollService = injector.get(ScrollService);
location = injector.get(Location);
});
it('should set `scrollRestoration` to `manual` if supported', () => {
if (scrollService.supportManualScrollRestoration) {
expect(window.history.scrollRestoration).toBe('manual');
} else {
expect(window.history.scrollRestoration).toBeUndefined();
}
});
describe('#topOffset', () => {
@@ -107,7 +127,7 @@ describe('ScrollService', () => {
describe('#scroll', () => {
it('should scroll to the top if there is no hash', () => {
location.hash = '';
platformLocation.hash = '';
const topOfPage = new MockElement();
document.getElementById.and
@@ -118,7 +138,7 @@ describe('ScrollService', () => {
});
it('should not scroll if the hash does not match an element id', () => {
location.hash = 'not-found';
platformLocation.hash = 'not-found';
document.getElementById.and.returnValue(null);
scrollService.scroll();
@@ -128,7 +148,7 @@ describe('ScrollService', () => {
it('should scroll to the element whose id matches the hash', () => {
const element = new MockElement();
location.hash = 'some-id';
platformLocation.hash = 'some-id';
document.getElementById.and.returnValue(element);
scrollService.scroll();
@@ -139,7 +159,7 @@ describe('ScrollService', () => {
it('should scroll to the element whose id matches the hash with encoded characters', () => {
const element = new MockElement();
location.hash = '%F0%9F%91%8D'; // 👍
platformLocation.hash = '%F0%9F%91%8D'; // 👍
document.getElementById.and.returnValue(element);
scrollService.scroll();
@@ -210,4 +230,136 @@ describe('ScrollService', () => {
});
});
describe('#isLocationWithHash', () => {
it('should return true when the location has a hash', () => {
platformLocation.hash = 'anchor';
expect(scrollService.isLocationWithHash()).toBe(true);
});
it('should return false when the location has no hash', () => {
platformLocation.hash = '';
expect(scrollService.isLocationWithHash()).toBe(false);
});
});
describe('#needToFixScrollPosition', async() => {
it('should return true when popState event was fired after a back navigation if the browser supports ' +
'scrollRestoration`. Otherwise, needToFixScrollPosition() returns false', () => {
if (scrollService.supportManualScrollRestoration) {
location.go('/initial-url1');
// We simulate a scroll down
location.replaceState('/initial-url1', 'hack', {scrollPosition: [2000, 0]});
location.go('/initial-url2');
location.back();
expect(scrollService.popStateFired).toBe(true);
expect(scrollService.scrollPosition).toEqual([2000, 0]);
expect(scrollService.needToFixScrollPosition()).toBe(true);
} else {
location.go('/initial-url1');
location.go('/initial-url2');
location.back();
expect(scrollService.popStateFired).toBe(false); // popStateFired is always false
expect(scrollService.scrollPosition).toEqual([0, 0]); // scrollPosition always equals [0, 0]
expect(scrollService.needToFixScrollPosition()).toBe(false);
}
});
it('should return true when popState event was fired after a forward navigation if the browser supports ' +
'scrollRestoration`. Otherwise, needToFixScrollPosition() returns false', () => {
if (scrollService.supportManualScrollRestoration) {
location.go('/initial-url1');
location.go('/initial-url2');
// We simulate a scroll down
location.replaceState('/initial-url1', 'hack', {scrollPosition: [2000, 0]});
location.back();
scrollService.popStateFired = false;
scrollService.scrollPosition = [0, 0];
location.forward();
expect(scrollService.popStateFired).toBe(true);
expect(scrollService.scrollPosition).toEqual([2000, 0]);
expect(scrollService.needToFixScrollPosition()).toBe(true);
} else {
location.go('/initial-url1');
location.go('/initial-url2');
location.back();
location.forward();
expect(scrollService.popStateFired).toBe(false); // popStateFired is always false
expect(scrollService.scrollPosition).toEqual([0, 0]); // scrollPosition always equals [0, 0]
expect(scrollService.needToFixScrollPosition()).toBe(false);
}
});
});
describe('#scrollAfterRender', async() => {
let scrollSpy: jasmine.Spy;
let scrollToTopSpy: jasmine.Spy;
let needToFixScrollPositionSpy: jasmine.Spy;
let scrollToPosition: jasmine.Spy;
let isLocationWithHashSpy: jasmine.Spy;
let getStoredScrollPositionSpy: jasmine.Spy;
const scrollDelay = 500;
beforeEach(() => {
scrollSpy = spyOn(scrollService, 'scroll');
scrollToTopSpy = spyOn(scrollService, 'scrollToTop');
scrollToPosition = spyOn(scrollService, 'scrollToPosition');
needToFixScrollPositionSpy = spyOn(scrollService, 'needToFixScrollPosition');
getStoredScrollPositionSpy = spyOn(scrollService, 'getStoredScrollPosition');
isLocationWithHashSpy = spyOn(scrollService, 'isLocationWithHash');
});
it('should call `scroll` when we navigate to a location with anchor', fakeAsync(() => {
needToFixScrollPositionSpy.and.returnValue(false);
getStoredScrollPositionSpy.and.returnValue(null);
isLocationWithHashSpy.and.returnValue(true);
scrollService.scrollAfterRender(scrollDelay);
expect(scrollSpy).not.toHaveBeenCalled();
tick(scrollDelay);
expect(scrollSpy).toHaveBeenCalled();
}));
it('should call `scrollToTop` when we navigate to a location without anchor', fakeAsync(() => {
needToFixScrollPositionSpy.and.returnValue(false);
getStoredScrollPositionSpy.and.returnValue(null);
isLocationWithHashSpy.and.returnValue(false);
scrollService.scrollAfterRender(scrollDelay);
expect(scrollToTopSpy).toHaveBeenCalled();
tick(scrollDelay);
expect(scrollSpy).not.toHaveBeenCalled();
}));
it('should call `viewportScroller.scrollToPosition` when we reload a page', fakeAsync(() => {
getStoredScrollPositionSpy.and.returnValue([0, 1000]);
scrollService.scrollAfterRender(scrollDelay);
expect(viewportScrollerStub.scrollToPosition).toHaveBeenCalled();
expect(getStoredScrollPositionSpy).toHaveBeenCalled();
}));
it('should call `scrollToPosition` after a popState', fakeAsync(() => {
needToFixScrollPositionSpy.and.returnValue(true);
getStoredScrollPositionSpy.and.returnValue(null);
scrollService.scrollAfterRender(scrollDelay);
expect(scrollToPosition).toHaveBeenCalled();
tick(scrollDelay);
expect(scrollSpy).not.toHaveBeenCalled();
expect(scrollToTopSpy).not.toHaveBeenCalled();
}));
});
});
+108 -3
View File
@@ -1,5 +1,5 @@
import { Injectable, Inject } from '@angular/core';
import { PlatformLocation } from '@angular/common';
import { Location, PlatformLocation, ViewportScroller } from '@angular/common';
import { DOCUMENT } from '@angular/common';
import { fromEvent } from 'rxjs';
@@ -13,6 +13,13 @@ export class ScrollService {
private _topOffset: number | null;
private _topOfPageElement: Element;
// true when popState event has been fired.
popStateFired = false;
// scroll position which has to be restored after the popState event
scrollPosition: [number, number] = [0, 0];
// true when the browser supports `scrollTo`, `scrollX`, `scrollY` and `scrollRestoration`
supportManualScrollRestoration: boolean;
// Offset from the top of the document to bottom of any static elements
// at the top (e.g. toolbar) + some margin
get topOffset() {
@@ -32,9 +39,37 @@ export class ScrollService {
constructor(
@Inject(DOCUMENT) private document: any,
private location: PlatformLocation) {
private platformLocation: PlatformLocation,
private viewportScroller: ViewportScroller,
private location: Location) {
// On resize, the toolbar might change height, so "invalidate" the top offset.
fromEvent(window, 'resize').subscribe(() => this._topOffset = null);
try {
this.supportManualScrollRestoration = !!window && !!window.scrollTo && 'scrollX' in window
&& 'scrollY' in window && !!history && !!history.scrollRestoration;
} catch {
this.supportManualScrollRestoration = false;
}
// Change scroll restoration strategy to `manual` if it's supported
if (this.supportManualScrollRestoration) {
history.scrollRestoration = 'manual';
// we have to detect forward and back navigation thanks to popState event
this.location.subscribe(event => {
// the type is `hashchange` when the fragment identifier of the URL has changed. It allows us to go to position
// just before a click on an anchor
if (event.type === 'hashchange') {
this.scrollToPosition();
} else {
// The popstate event is always triggered by doing a browser action such as a click on the back or forward button.
// It can be follow by a event of type `hashchange`.
this.popStateFired = true;
// we always should have a scrollPosition in our state history
this.scrollPosition = event.state ? event.state['scrollPosition'] : null;
}
});
}
}
/**
@@ -50,6 +85,44 @@ export class ScrollService {
this.scrollToElement(element);
}
/**
* test if the current location has a hash
*/
isLocationWithHash(): boolean {
return !!this.getCurrentHash();
}
/**
* When we load a document, we have to scroll to the correct position depending on whether this is a new location,
* a back/forward in the history, or a refresh
* @param delay before we scroll to the good position
*/
scrollAfterRender(delay: number) {
// If we do rendering following a refresh, we use the scroll position from the storage.
const storedScrollPosition = this.getStoredScrollPosition();
if (storedScrollPosition) {
this.viewportScroller.scrollToPosition(storedScrollPosition);
} else {
if (this.needToFixScrollPosition()) {
// The document was reloaded following a popState `event` (called by the forward/back button), so we manage
// the scroll position
this.scrollToPosition();
} else {
// The document was loaded either of the following cases: a direct navigation via typing the URL in the
// address bar or a click on a link. If the location contains a hash, we have to wait for async
// layout.
if (this.isLocationWithHash()) {
// Scroll 500ms after the new document has been inserted into the doc-viewer.
// The delay is to allow time for async layout to complete.
setTimeout(() => this.scroll(), delay);
} else {
// If the location doesn't contain a hash, we scroll to the top of the page.
this.scrollToTop();
}
}
}
}
/**
* Scroll to the element.
* Don't scroll if no element.
@@ -79,10 +152,42 @@ export class ScrollService {
this.scrollToElement(this.topOfPageElement);
}
scrollToPosition() {
this.viewportScroller.scrollToPosition(this.scrollPosition);
this.popStateFired = false;
}
/**
* Update the state with scroll position into history.
*/
updateScrollPositionInHistory() {
if (this.supportManualScrollRestoration) {
const currentScrollPosition = this.viewportScroller.getScrollPosition();
this.location.replaceState(this.location.path(true), undefined, {scrollPosition: currentScrollPosition});
window.sessionStorage.setItem('scrollPosition', currentScrollPosition.toString());
}
}
getStoredScrollPosition(): [number, number] | null {
const position = window.sessionStorage.getItem('scrollPosition');
return position ? JSON.parse('[' + position + ']') : null;
}
removeStoredScrollPosition() {
window.sessionStorage.removeItem('scrollPosition');
}
/**
* Check if the scroll position need to be manually fixed after popState event
*/
needToFixScrollPosition(): boolean {
return this.popStateFired && this.scrollPosition && this.supportManualScrollRestoration;
}
/**
* Return the hash fragment from the `PlatformLocation`, minus the leading `#`.
*/
private getCurrentHash() {
return decodeURIComponent(this.location.hash.replace(/^#/, ''));
return decodeURIComponent(this.platformLocation.hash.replace(/^#/, ''));
}
}
+1
View File
@@ -47,6 +47,7 @@ aio-shell.page-resources mat-toolbar.mat-toolbar {
// DOCS PAGES OVERRIDE: HAMBURGER
aio-shell.folder-api mat-toolbar.mat-toolbar,
aio-shell.folder-cli mat-toolbar.mat-toolbar,
aio-shell.folder-docs mat-toolbar.mat-toolbar,
aio-shell.folder-guide mat-toolbar.mat-toolbar,
aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
+6 -13
View File
@@ -74,6 +74,12 @@
vertical-align: top;
}
}
&.property-table {
td {
vertical-align: top;
}
}
}
.class-overview {
@@ -87,19 +93,6 @@
.short-description {
margin: 6px 0 0 10px;
}
.properties-table {
font-size: 14px;
thead th {
&:nth-child(1) {
width: 20%;
}
&:nth-child(2) {
width: 20%;
}
}
}
}
.breadcrumb-container {
@@ -7,10 +7,14 @@ describe(browser.baseUrl, () => {
const stripQuery = (url: string) => url.replace(/\?.*$/, '');
const stripTrailingSlash = (url: string) => url.replace(/\/$/, '');
beforeAll(done => page.init().then(done));
beforeAll(() => page.init());
beforeEach(() => browser.waitForAngularEnabled(false));
afterEach(() => browser.waitForAngularEnabled(true));
afterEach(async () => {
await page.unregisterSw();
await browser.waitForAngularEnabled(true);
});
describe('(with sitemap URLs)', () => {
page.sitemapUrls.forEach((path, i) => {
@@ -34,7 +38,7 @@ describe(browser.baseUrl, () => {
const actualUrl = await getCurrentUrl();
expect(actualUrl).toBe(expectedUrl);
}, 60000);
}, 120000);
});
});
+14 -7
View File
@@ -38,19 +38,14 @@ export class SitePage {
}
/**
* Navigate to a URL, disable animations, unregister the ServiceWorker, and wait for Angular.
* Navigate to a URL, disable animations, wait for Angular and unregister the ServiceWorker.
* (The SW is unregistered to ensure that subsequent requests are passed through to the server.)
*/
async goTo(url: string) {
const unregisterServiceWorker = (cb: () => void) => navigator.serviceWorker
.getRegistrations()
.then(regs => Promise.all(regs.map(reg => reg.unregister())))
.then(cb);
await browser.get(url || this.baseUrl);
await browser.executeScript('document.body.classList.add(\'no-animations\')');
await browser.executeAsyncScript(unregisterServiceWorker);
await browser.waitForAngular();
await this.unregisterSw();
};
/**
@@ -60,4 +55,16 @@ export class SitePage {
// Make an initial request to unregister the ServiceWorker.
await this.goTo('');
}
/**
* Unregister the ServiceWorker (if registered).
*/
async unregisterSw() {
const unregisterSwFn = (cb: () => void) => navigator.serviceWorker
.getRegistrations()
.then(regs => Promise.all(regs.map(reg => reg.unregister())))
.then(cb);
await browser.executeAsyncScript(unregisterSwFn);
}
}
@@ -4,10 +4,14 @@ import { SitePage } from './site.po';
describe(browser.baseUrl, () => {
const page = new SitePage();
beforeAll(done => page.init().then(done));
beforeAll(() => page.init());
beforeEach(() => browser.waitForAngularEnabled(false));
afterEach(() => browser.waitForAngularEnabled(true));
afterEach(async () => {
await page.unregisterSw();
await browser.waitForAngularEnabled(true);
});
describe('(smoke tests)', () => {
it('should show the home page', () => {
+1 -1
View File
@@ -12,7 +12,7 @@
},
"engines": {
"node": ">=10.9.0 <11.0.0",
"yarn": ">=1.10.1 <1.13.0"
"yarn": ">=1.10.1 <1.14.0"
},
"keywords": [],
"author": "",
@@ -1,10 +1,14 @@
module.exports = function processCliCommands() {
module.exports = function processCliCommands(createDocMessage) {
return {
$runAfter: ['extra-docs-added'],
$runBefore: ['rendering-docs'],
$process(docs) {
const navigationDoc = docs.find(doc => doc.docType === 'navigation-json');
const navigationNode = navigationDoc && navigationDoc.data['SideNav'].find(node => node.title === 'CLI Commands');
const navigationNode = navigationDoc && navigationDoc.data['SideNav'].find(node => node.children && node.children.length && node.children[0].url === 'cli');
if (!navigationNode) {
throw new Error(createDocMessage('Missing `cli` url - CLI Commands must include a first child node with url set at `cli`', navigationDoc));
}
docs.forEach(doc => {
if (doc.docType === 'cli-command') {
@@ -14,9 +18,7 @@ module.exports = function processCliCommands() {
processOptions(doc, doc.options);
// Add to navigation doc
if (navigationNode) {
navigationNode.children.push({ url: doc.path, title: `ng ${doc.name}` });
}
navigationNode.children.push({ url: doc.path, title: `ng ${doc.name}` });
}
});
}
@@ -28,11 +30,6 @@ function processOptions(container, options) {
container.namedOptions = [];
options.forEach(option => {
if (option.type === 'boolean' && option.default === undefined) {
option.default = false;
}
// Ignore any hidden options
if (option.hidden) { return; }
@@ -1,41 +1,51 @@
const testPackage = require('../../helpers/test-package');
const processorFactory = require('./processCliCommands');
const Dgeni = require('dgeni');
describe('processCliCommands processor', () => {
let dgeni, injector, processor, createDocMessage;
const navigationStub = {
docType: 'navigation-json',
data: {
SideNav: [{
children: [{'url': 'cli'}]
}]
}
};
beforeEach(() => {
dgeni = new Dgeni([testPackage('cli-docs-package')]);
injector = dgeni.configureInjector();
processor = injector.get('processCliCommands');
createDocMessage = injector.get('createDocMessage');
});
it('should be available on the injector', () => {
const dgeni = new Dgeni([testPackage('cli-docs-package')]);
const injector = dgeni.configureInjector();
const processor = injector.get('processCliCommands');
expect(processor.$process).toBeDefined();
});
it('should run after the correct processor', () => {
const processor = processorFactory();
expect(processor.$runAfter).toEqual(['extra-docs-added']);
});
it('should run before the correct processor', () => {
const processor = processorFactory();
expect(processor.$runBefore).toEqual(['rendering-docs']);
});
it('should collect the names (name + aliases)', () => {
const processor = processorFactory();
const doc = {
docType: 'cli-command',
name: 'name',
commandAliases: ['alias1', 'alias2'],
options: [],
};
processor.$process([doc]);
processor.$process([doc, navigationStub]);
expect(doc.names).toEqual(['name', 'alias1', 'alias2']);
});
describe('options', () => {
it('should remove the hidden options', () => {
const processor = processorFactory();
const doc = {
docType: 'cli-command',
name: 'name',
@@ -47,7 +57,7 @@ describe('processCliCommands processor', () => {
{ name: 'option4', hidden: true },
],
};
processor.$process([doc]);
processor.$process([doc, navigationStub]);
expect(doc.namedOptions).toEqual([
jasmine.objectContaining({ name: 'option1' }),
jasmine.objectContaining({ name: 'option3' }),
@@ -55,7 +65,6 @@ describe('processCliCommands processor', () => {
});
it('should collect the non-hidden positional and named options', () => {
const processor = processorFactory();
const doc = {
docType: 'cli-command',
name: 'name',
@@ -67,7 +76,7 @@ describe('processCliCommands processor', () => {
{ name: 'positional2', hidden: true, positional: 1},
],
};
processor.$process([doc]);
processor.$process([doc, navigationStub]);
expect(doc.positionalOptions).toEqual([
jasmine.objectContaining({ name: 'positional1', positional: 0}),
]);
@@ -77,7 +86,6 @@ describe('processCliCommands processor', () => {
});
it('should sort the named options into order by name', () => {
const processor = processorFactory();
const doc = {
docType: 'cli-command',
name: 'name',
@@ -88,7 +96,7 @@ describe('processCliCommands processor', () => {
{ name: 'b' },
],
};
processor.$process([doc]);
processor.$process([doc, navigationStub]);
expect(doc.namedOptions).toEqual([
jasmine.objectContaining({ name: 'a' }),
jasmine.objectContaining({ name: 'b' }),
@@ -99,7 +107,6 @@ describe('processCliCommands processor', () => {
describe('subcommands', () => {
it('should convert subcommands hash into a collection', () => {
const processor = processorFactory();
const doc = {
docType: 'cli-command',
name: 'name',
@@ -124,7 +131,7 @@ describe('processCliCommands processor', () => {
},
}],
};
processor.$process([doc]);
processor.$process([doc, navigationStub]);
expect(doc.options[0].subcommands).toEqual([
jasmine.objectContaining({ name: 'subcommand1' }),
jasmine.objectContaining({ name: 'subcommand2' }),
@@ -132,7 +139,6 @@ describe('processCliCommands processor', () => {
});
it('should remove the hidden subcommand options', () => {
const processor = processorFactory();
const doc = {
docType: 'cli-command',
name: 'name',
@@ -157,7 +163,7 @@ describe('processCliCommands processor', () => {
},
}],
};
processor.$process([doc]);
processor.$process([doc, navigationStub]);
expect(doc.options[0].subcommands[0].namedOptions).toEqual([
jasmine.objectContaining({ name: 'subcommand1-option1' }),
]);
@@ -167,7 +173,6 @@ describe('processCliCommands processor', () => {
});
it('should collect the non-hidden positional arguments and named options', () => {
const processor = processorFactory();
const doc = {
docType: 'cli-command',
name: 'name',
@@ -192,7 +197,7 @@ describe('processCliCommands processor', () => {
},
}],
};
processor.$process([doc]);
processor.$process([doc, navigationStub]);
expect(doc.options[0].subcommands[0].positionalOptions).toEqual([
jasmine.objectContaining({ name: 'subcommand1-option2', positional: 0}),
]);
@@ -205,7 +210,6 @@ describe('processCliCommands processor', () => {
});
it('should sort the named subcommand options into order by name', () => {
const processor = processorFactory();
const doc = {
docType: 'cli-command',
name: 'name',
@@ -224,7 +228,7 @@ describe('processCliCommands processor', () => {
}
}],
};
processor.$process([doc]);
processor.$process([doc, navigationStub]);
expect(doc.options[0].subcommands[0].namedOptions).toEqual([
jasmine.objectContaining({ name: 'a' }),
jasmine.objectContaining({ name: 'b' }),
@@ -233,8 +237,7 @@ describe('processCliCommands processor', () => {
});
});
it('should add the command to the CLI node in the navigation doc', () => {
const processor = processorFactory();
it('should add the command to the CLI node in the navigation doc if there is a first child node with a `cli` url', () => {
const command = {
docType: 'cli-command',
name: 'command1',
@@ -247,18 +250,55 @@ describe('processCliCommands processor', () => {
data: {
SideNav: [
{ url: 'some/page', title: 'Some Page' },
{ url: 'cli', title: 'CLI Commands', children: [
{ url: 'cli', title: 'Using the CLI' },
]},
{ url: 'other/page', title: 'Other Page' },
{
title: 'CLI Commands',
tooltip: 'Angular CLI command reference',
children: [
{
'title': 'Overview',
'url': 'cli'
}
]
},
{ url: 'other/page', title: 'Other Page' }
]
}
};
processor.$process([command, navigation]);
expect(navigation.data.SideNav[1].title).toEqual('CLI Commands');
expect(navigation.data.SideNav[1].children).toEqual([
{ url: 'cli', title: 'Using the CLI' },
{ url: 'cli', title: 'Overview' },
{ url: 'cli/command1', title: 'ng command1' },
]);
});
it('should complain if there is no child with `cli` url', () => {
const command = {
docType: 'cli-command',
name: 'command1',
commandAliases: ['alias1', 'alias2'],
options: [],
path: 'cli/command1',
};
const navigation = {
docType: 'navigation-json',
data: {
SideNav: [
{ url: 'some/page', title: 'Some Page' },
{
title: 'CLI Commands',
tooltip: 'Angular CLI command reference',
children: [
{
'title': 'Overview',
'url': 'client'
}
]
},
{ url: 'other/page', title: 'Other Page' }
]
}
};
expect(() => processor.$process([command, navigation])).toThrowError(createDocMessage('Missing `cli` url - CLI Commands must include a first child node with url set at `cli`', navigation));
});
});
+15 -12
View File
@@ -798,9 +798,10 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
app-root-path@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.0.1.tgz#cd62dcf8e4fd5a417efc664d2e5b10653c651b46"
app-root-path@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a"
integrity sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=
append-transform@^0.4.0:
version "0.4.0"
@@ -1976,16 +1977,17 @@ code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
codelyzer@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.2.1.tgz#d56eaacefca7e8138aac0a630e484bdb09988544"
codelyzer@~4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.5.0.tgz#a65ddeeeca2894653253a89bfa229118ff9f59b1"
integrity sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==
dependencies:
app-root-path "^2.0.1"
app-root-path "^2.1.0"
css-selector-tokenizer "^0.7.0"
cssauron "^1.4.0"
semver-dsl "^1.0.1"
source-map "^0.5.6"
sprintf-js "^1.0.3"
source-map "^0.5.7"
sprintf-js "^1.1.1"
coffee-script@^1.12.5:
version "1.12.7"
@@ -9291,9 +9293,10 @@ split-string@^3.0.1, split-string@^3.0.2:
dependencies:
extend-shallow "^3.0.0"
sprintf-js@^1.0.3:
version "1.1.1"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c"
sprintf-js@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
sprintf-js@~1.0.2:
version "1.0.3"
@@ -23,7 +23,7 @@
"src/assets"
],
"styles": [
"src/styles.css"
"src/styles.scss"
],
"scripts": []
},
@@ -82,7 +82,7 @@
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"src/styles.css"
"src/styles.scss"
],
"scripts": [],
"assets": [
@@ -1,20 +0,0 @@
import { AppPage } from './app.po';
import { browser } from 'protractor';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getTitleText()).toEqual('Welcome to demo!');
});
afterEach(async () => {
const logs = await browser.manage().logs().get('browser');
expect(logs).toEqual([]);
});
});
-11
View File
@@ -1,11 +0,0 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/') as Promise<any>;
}
getTitleText() {
return element(by.css('app-root h1')).getText() as Promise<string>;
}
}
-14
View File
@@ -1,14 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Demo</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
+3 -15
View File
@@ -7,18 +7,12 @@ function testBazel() {
bazel version
rm -rf demo
# Create project
ng new demo --collection=@angular/bazel --defaults --skip-git
ng new demo --collection=@angular/bazel --defaults --skip-git --style=scss
node replace_angular_repo.js "./demo/WORKSPACE"
cd demo
# TODO(kyliau) Remove this once the type annotations are added to AppPage
# https://github.com/angular/angular-cli/pull/13406
cp ../app.po.ts ./e2e/src/
cp ../package.json.replace ./package.json
# Run build
# TODO(kyliau): Use `bazel build` for now. Running `ng build` requires
# node_modules to be available in project directory.
bazel build //src:bundle
# Run test
ng generate component widget --style=css
ng build
ng test
ng e2e
}
@@ -26,13 +20,7 @@ function testBazel() {
function testNonBazel() {
# Replace angular.json that uses Bazel builder with the default generated by CLI
cp ../angular.json.original ./angular.json
# TODO(kyliau) Remove this once the additional assertion is added to CLI
cp ../app.e2e-spec.ts ./e2e/src/
# TODO(kyliau) Remove this once web_package rule is in use
cp ../index.html ./src/
rm -rf dist src/main.dev.ts src/main.prod.ts
# Just make a symlink instead of full yarn install to expose node_modules
ln -s $(bazel info output_base)/external/npm/node_modules node_modules
ng build --progress=false
ng test --progress=false --watch=false
ng e2e --configuration=ci
+92 -66
View File
@@ -2,12 +2,12 @@
# yarn lockfile v1
"@angular-devkit/architect@0.12.1":
version "0.12.1"
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.12.1.tgz#397768d1ccd0cef76db96d6b39db8aebad68c031"
integrity sha512-1ozBP0ZAApkSfuPpZ7b9vShU8smNxb98jW+65S12cPOxv1bVVxCj5sTmC3sSfXapgq/pMzblbaVSKOG7Ajz0vQ==
"@angular-devkit/architect@0.13.0-rc.0":
version "0.13.0-rc.0"
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.13.0-rc.0.tgz#d9bc43a3811f293269cf488539b72ce27afc6cdb"
integrity sha512-abqtT5qyfTL29hf9be1MnaSVjIMJXJq+Oc+FZJ4RyQ+Sjs2zo+DjAJo62P1vS55JkLE1TFpEcjHkg118Cz7yOw==
dependencies:
"@angular-devkit/core" "7.2.1"
"@angular-devkit/core" "7.3.0-rc.0"
rxjs "6.3.3"
"@angular-devkit/architect@^0.10.6":
@@ -40,12 +40,12 @@
rxjs "6.3.3"
source-map "0.7.3"
"@angular-devkit/core@7.2.1":
version "7.2.1"
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.2.1.tgz#8c6df59eab77bcc98a348c8cdf9eb217c8b751a5"
integrity sha512-zOozPswSM1cTkltw5LeSPoZ/fJ2d3vN304IVgKgrM5/Fs54bd7nTaBcAK+HvjKS+5KmykYrXW47Q4CdFJikluQ==
"@angular-devkit/core@7.3.0-rc.0":
version "7.3.0-rc.0"
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.3.0-rc.0.tgz#e555a08d85259855ff1946f4268936a1aadd38f1"
integrity sha512-0vHuw1gIMh79tI+gRxCMn89U1DnjmBnqybVktaf9YXi9xshxd+nnFb31v7n1tJQVQiQNzGxk3hviFnkzxLZipw==
dependencies:
ajv "6.6.2"
ajv "6.7.0"
chokidar "2.0.4"
fast-json-stable-stringify "2.0.0"
rxjs "6.3.3"
@@ -59,16 +59,16 @@
"@angular-devkit/core" "7.1.3"
rxjs "6.3.3"
"@angular-devkit/schematics@7.2.1":
version "7.2.1"
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.2.1.tgz#9c1c784f4a81a3a840fa4a1435948c6203be6062"
integrity sha512-jEhwkeDn8exgJBfUwMc6rdtDkxHJkUmKPTn4M436bkMMMa9KFPFbPpzp9weKpB3SbRjM3Mu90JprO4C7qDtCcg==
"@angular-devkit/schematics@7.3.0-rc.0":
version "7.3.0-rc.0"
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.3.0-rc.0.tgz#9f1e1f6942da36b12c81241398ed6ca8b2e65875"
integrity sha512-noqcQIOvah2G126DTFKY5Kiga8UwI9cKzyhQdNlf+8hAZpnWwTURItQ5xuMJg/XfRQLUSg9gWS2h1cI9AD7mxQ==
dependencies:
"@angular-devkit/core" "7.2.1"
"@angular-devkit/core" "7.3.0-rc.0"
rxjs "6.3.3"
"@angular/bazel@file:../../dist/packages-dist/bazel":
version "7.2.0"
version "8.0.0-beta.0"
dependencies:
"@angular-devkit/architect" "^0.10.6"
"@angular-devkit/core" "^7.0.4"
@@ -81,16 +81,20 @@
tsickle "0.34.0"
"@angular/cli@file:../../node_modules/@angular/cli":
version "7.2.1"
version "7.3.0-rc.0"
dependencies:
"@angular-devkit/architect" "0.12.1"
"@angular-devkit/core" "7.2.1"
"@angular-devkit/schematics" "7.2.1"
"@schematics/angular" "7.2.1"
"@schematics/update" "0.12.1"
"@angular-devkit/architect" "0.13.0-rc.0"
"@angular-devkit/core" "7.3.0-rc.0"
"@angular-devkit/schematics" "7.3.0-rc.0"
"@schematics/angular" "7.3.0-rc.0"
"@schematics/update" "0.13.0-rc.0"
"@yarnpkg/lockfile" "1.1.0"
ini "1.3.5"
inquirer "6.2.1"
opn "5.3.0"
semver "5.5.1"
npm-package-arg "6.1.0"
opn "5.4.0"
pacote "9.4.0"
semver "5.6.0"
symbol-observable "1.2.0"
"@bazel/bazel-darwin_x64@0.21.0":
@@ -125,13 +129,13 @@
source-map-support "0.5.9"
tsutils "2.27.2"
"@schematics/angular@7.2.1":
version "7.2.1"
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-7.2.1.tgz#9eeab1354ec8d970121cc067e9636098ab84e152"
integrity sha512-UdqU8udVr693BZ6uaZ7+el/VFlTjrmp56OS+6YaziyAko84e1Q1Fcx+fwdHugy4V3YmQhTVsyOPSEsphnwSwOA==
"@schematics/angular@7.3.0-rc.0":
version "7.3.0-rc.0"
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-7.3.0-rc.0.tgz#7519aa692dcaed63b9caa7d824846511905b1bfc"
integrity sha512-yjCHgLSAqQKVZrZgf8F37cPQthhucIA10ofpIHPEZrvHwKBQhM9K3yfB7uYgkj4gzPTdREedb7Rm3/HY45L/1A==
dependencies:
"@angular-devkit/core" "7.2.1"
"@angular-devkit/schematics" "7.2.1"
"@angular-devkit/core" "7.3.0-rc.0"
"@angular-devkit/schematics" "7.3.0-rc.0"
typescript "3.2.2"
"@schematics/angular@^7.0.4":
@@ -143,18 +147,18 @@
"@angular-devkit/schematics" "7.1.3"
typescript "3.1.6"
"@schematics/update@0.12.1":
version "0.12.1"
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.12.1.tgz#44d853321ae8a56c43a579c0639d26d625001037"
integrity sha512-P92tDxy0AA1NPhaThiJ7fIFxIC4jzlGK7sJlpbnRREBImsI/O9gmGaV8Kjy+75vaEjqpWaU2oj1hnWqkmxSK1A==
"@schematics/update@0.13.0-rc.0":
version "0.13.0-rc.0"
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.13.0-rc.0.tgz#3d5bb6ce7d8d1ea44a0e0a644022bc655b80ae80"
integrity sha512-XoU3TnaDcIFX7TU37bfjfAW0tI1tRD5DYQFHDBNOgS+78InGvR9+1CVzRJ4uWOjk0i+ZzDaGbYyR0iA47jSOTA==
dependencies:
"@angular-devkit/core" "7.2.1"
"@angular-devkit/schematics" "7.2.1"
"@angular-devkit/core" "7.3.0-rc.0"
"@angular-devkit/schematics" "7.3.0-rc.0"
"@yarnpkg/lockfile" "1.1.0"
ini "1.3.5"
pacote "9.1.1"
pacote "9.4.0"
rxjs "6.3.3"
semver "5.5.1"
semver "5.6.0"
semver-intersect "1.4.0"
"@types/node@6.0.84":
@@ -204,10 +208,10 @@ ajv@6.5.3:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ajv@6.6.2:
version "6.6.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d"
integrity sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==
ajv@6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96"
integrity sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==
dependencies:
fast-deep-equal "^2.0.1"
fast-json-stable-stringify "^2.0.0"
@@ -328,7 +332,7 @@ binary-extensions@^1.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14"
integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==
bluebird@^3.5.1, bluebird@^3.5.2:
bluebird@^3.5.1, bluebird@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7"
integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==
@@ -379,7 +383,7 @@ bytebuffer@~5:
dependencies:
long "~3"
cacache@^11.0.1, cacache@^11.2.0:
cacache@^11.0.1:
version "11.3.1"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.1.tgz#d09d25f6c4aca7a6d305d141ae332613aa1d515f"
integrity sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==
@@ -399,6 +403,26 @@ cacache@^11.0.1, cacache@^11.2.0:
unique-filename "^1.1.0"
y18n "^4.0.0"
cacache@^11.3.2:
version "11.3.2"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa"
integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==
dependencies:
bluebird "^3.5.3"
chownr "^1.1.1"
figgy-pudding "^3.5.1"
glob "^7.1.3"
graceful-fs "^4.1.15"
lru-cache "^5.1.1"
mississippi "^3.0.0"
mkdirp "^0.5.1"
move-concurrently "^1.0.1"
promise-inflight "^1.0.1"
rimraf "^2.6.2"
ssri "^6.0.1"
unique-filename "^1.1.1"
y18n "^4.0.0"
cache-base@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
@@ -877,7 +901,7 @@ glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
graceful-fs@^4.1.11, graceful-fs@^4.1.2:
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2:
version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
@@ -1260,6 +1284,13 @@ lru-cache@^4.1.2, lru-cache@^4.1.3:
pseudomap "^1.0.2"
yallist "^2.1.2"
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
dependencies:
yallist "^3.0.2"
make-fetch-happen@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083"
@@ -1489,7 +1520,7 @@ npm-bundled@^1.0.1:
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979"
integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==
npm-package-arg@^6.0.0, npm-package-arg@^6.1.0:
npm-package-arg@6.1.0, npm-package-arg@^6.0.0, npm-package-arg@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1"
integrity sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==
@@ -1507,7 +1538,7 @@ npm-packlist@^1.1.12, npm-packlist@^1.1.6:
ignore-walk "^3.0.1"
npm-bundled "^1.0.1"
npm-pick-manifest@^2.1.0:
npm-pick-manifest@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz#32111d2a9562638bb2c8f2bf27f7f3092c8fae40"
integrity sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA==
@@ -1585,10 +1616,10 @@ onetime@^2.0.0:
dependencies:
mimic-fn "^1.0.0"
opn@5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c"
integrity sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==
opn@5.4.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035"
integrity sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==
dependencies:
is-wsl "^1.1.0"
@@ -1622,17 +1653,17 @@ osenv@^0.1.4, osenv@^0.1.5:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
pacote@9.1.1:
version "9.1.1"
resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.1.1.tgz#25091f75a25021de8be8d34cc6408728fca3579b"
integrity sha512-f28Rq5ozzKAA9YwIKw61/ipwAatUZseYmVssDbHHaexF0wRIVotapVEZPAjOT7Eu3LYVqEp0NVpNizoAnYBUaA==
pacote@9.4.0:
version "9.4.0"
resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.4.0.tgz#af979abdeb175cd347c3e33be3241af1ed254807"
integrity sha512-WQ1KL/phGMkedYEQx9ODsjj7xvwLSpdFJJdEXrLyw5SILMxcTNt5DTxT2Z93fXuLFYJBlZJdnwdalrQdB/rX5w==
dependencies:
bluebird "^3.5.2"
cacache "^11.2.0"
bluebird "^3.5.3"
cacache "^11.3.2"
figgy-pudding "^3.5.1"
get-stream "^4.1.0"
glob "^7.1.3"
lru-cache "^4.1.3"
lru-cache "^5.1.1"
make-fetch-happen "^4.0.1"
minimatch "^3.0.4"
minipass "^2.3.5"
@@ -1641,7 +1672,7 @@ pacote@9.1.1:
normalize-package-data "^2.4.0"
npm-package-arg "^6.1.0"
npm-packlist "^1.1.12"
npm-pick-manifest "^2.1.0"
npm-pick-manifest "^2.2.3"
npm-registry-fetch "^3.8.0"
osenv "^0.1.5"
promise-inflight "^1.0.1"
@@ -1651,7 +1682,7 @@ pacote@9.1.1:
safe-buffer "^5.1.2"
semver "^5.6.0"
ssri "^6.0.1"
tar "^4.4.6"
tar "^4.4.8"
unique-filename "^1.1.1"
which "^1.3.1"
@@ -1913,11 +1944,6 @@ semver-intersect@1.4.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
semver@5.5.1:
version "5.5.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==
set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
@@ -2170,7 +2196,7 @@ symbol-observable@1.2.0:
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
tar@^4, tar@^4.4.6:
tar@^4, tar@^4.4.8:
version "4.4.8"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d"
integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==
+5
View File
@@ -37,9 +37,14 @@ ts_devserver(
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary", "rollup_bundle")
filegroup(
name = "empty_node_modules",
)
rollup_bundle(
name = "bundle",
entry_point = "src/main",
node_modules = ":empty_node_modules",
deps = ["//src"],
)
+16 -16
View File
@@ -2,24 +2,24 @@
# yarn lockfile v1
"@bazel/bazel-darwin_x64@0.18.0":
version "0.18.0"
resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.18.0.tgz#bab437605a702279d42f59caa4741bb327eb7dbc"
integrity sha512-um2OzgLL2Gd/W6joOpvrSTcqpnupliPNpwe/uE7sB0huBSJ/4Im0w2IlCTI6C7OfgMcbpUj4YxgUa9T6u6WY6w==
"@bazel/bazel-darwin_x64@0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.20.0.tgz#648d61c32a3c5fccb7bf70b753071b6e54b11f21"
integrity sha512-zeoeVK504341GfnaxdaB4pFzQV0YOK1HLiYj3/ocamPFxAJRh9abvKB8iOpqD5Oal0j7VsINxnXCjovp9a4urA==
"@bazel/bazel-linux_x64@0.18.0":
version "0.18.0"
resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.18.0.tgz#0c02b2404ec95c180e17615cc7079ee07df48a69"
integrity sha512-Rq8X8bL6SgQvbOHnfPhSgF6hp+f6Fbt2w6pRmBlFvV1J+CeUyrSrrRXfnnO1bjIuq05Ur3mV8ULA0qK6rtA5lQ==
"@bazel/bazel-linux_x64@0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.20.0.tgz#2568628a0d0b85dcc69d0ab701b1d6e10551357d"
integrity sha512-PpHzoEqfXty8dc1/p1tVFXtbPyrE1n0N79QmYePjJ5mJMyW7uBF/zV4IajYY8+IpJEcDVq5v4BavSexOmVJRmA==
"@bazel/bazel-win32_x64@0.18.0":
version "0.18.0"
resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.18.0.tgz#aa4575fb00066dcf59a6d464971774dea6a0bafd"
integrity sha512-U2TbfK8B7dc3JqXSFwj2oXCQrxEaSzCCUkAHjAOIGOKzx/HLKIKs+NJj9IQkLLr7BsMU+Qqzo8aqo11E+Vs+aA==
"@bazel/bazel-win32_x64@0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.20.0.tgz#af7d041dae4c066e7aa8618949e2de1aad07495e"
integrity sha512-3bqHXFBvLnbvNzr1KCQ1zryTYvHMoQffaWVekbckgPyT2VPEj3abuB91+DrRYmZdPjcgPYnjnyanxZHDkKuF2g==
"@bazel/bazel@file:../../node_modules/@bazel/bazel":
version "0.18.0"
version "0.20.0"
optionalDependencies:
"@bazel/bazel-darwin_x64" "0.18.0"
"@bazel/bazel-linux_x64" "0.18.0"
"@bazel/bazel-win32_x64" "0.18.0"
"@bazel/bazel-darwin_x64" "0.20.0"
"@bazel/bazel-linux_x64" "0.20.0"
"@bazel/bazel-win32_x64" "0.20.0"
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "angular-srcs",
"version": "7.2.2",
"version": "7.2.3",
"private": true,
"branchPattern": "2.0.*",
"description": "Angular - a web framework for modern web apps",
@@ -9,7 +9,7 @@
"license": "MIT",
"engines": {
"node": ">=10.9.0 <11.0.0",
"yarn": ">=1.10.1 <1.13.0"
"yarn": ">=1.10.1 <1.14.0"
},
"repository": {
"type": "git",
@@ -34,7 +34,7 @@
"@angular-devkit/architect": "^0.10.6",
"@angular-devkit/build-optimizer": "^0.12.2",
"@angular-devkit/core": "^7.0.4",
"@angular-devkit/schematics": "^7.0.4",
"@angular-devkit/schematics": "^7.3.0-rc.0",
"@bazel/karma": "~0.22.1",
"@bazel/typescript": "~0.22.1",
"@schematics/angular": "^7.0.4",
@@ -94,8 +94,8 @@
"// 2": "devDependencies are not used under Bazel. Many can be removed after test.sh is deleted.",
"// 3": "when updating @bazel/bazel version you also need to update the RBE settings in .bazelrc (see https://github.com/angular/angular/pull/27935)",
"devDependencies": {
"@angular/cli": "^7.2.1",
"@bazel/bazel": "~0.21.0",
"@angular/cli": "^7.3.0-rc.0",
"@bazel/bazel": "~0.22.0",
"@bazel/buildifier": "^0.19.2",
"@bazel/ibazel": "~0.9.0",
"@types/angular": "^1.6.47",
@@ -135,7 +135,7 @@
"rewire": "2.5.2",
"rollup-plugin-commonjs": "8.1.0",
"rxjs": "^6.3.0",
"sauce-connect": "https://saucelabs.com/downloads/sc-4.5.2-linux.tar.gz",
"sauce-connect": "https://saucelabs.com/downloads/sc-4.5.3-linux.tar.gz",
"semver": "5.4.1",
"systemjs": "0.18.10",
"tslint": "5.7.0",
+1 -1
View File
@@ -10,7 +10,6 @@ ng_module(
"src/**/*.ts",
],
),
module_name = "@angular/animations",
deps = [
"//packages/core",
],
@@ -30,6 +29,7 @@ ng_package(
# Do not add more to this list.
# Dependencies on the full npm_package cause long re-builds.
visibility = [
"//packages/compiler-cli/integrationtest:__pkg__",
"//packages/compiler/test:__pkg__",
],
deps = [
-1
View File
@@ -12,7 +12,6 @@ ng_module(
"src/**/*.ts",
],
),
module_name = "@angular/animations/browser",
deps = [
"//packages/animations",
"//packages/core",
@@ -26,7 +26,7 @@ const SELF_TOKEN_REGEX = new RegExp(`\s*${SELF_TOKEN}\s*,?`, 'g');
*
* 1. Overlap of animations
* Given that a CSS property cannot be animated in more than one place at the same time, it's
* important that this behaviour is detected and validated. The way in which this occurs is that
* important that this behavior is detected and validated. The way in which this occurs is that
* each time a style property is examined, a string-map containing the property will be updated with
* the start and end times for when the property is used within an animation step.
*
@@ -7,7 +7,6 @@ load("//tools:defaults.bzl", "ng_module")
ng_module(
name = "testing",
srcs = glob(["**/*.ts"]),
module_name = "@angular/animations/browser/testing",
deps = [
"//packages/animations",
"//packages/animations/browser",
@@ -671,8 +671,8 @@ export function animate(
*
* ```typescript
* group([
* animate("1s", { background: "black" }))
* animate("2s", { color: "white" }))
* animate("1s", style({ background: "black" })),
* animate("2s", style({ color: "white" }))
* ])
* ```
*
@@ -708,7 +708,7 @@ export function group(
* ```typescript
* sequence([
* style({ opacity: 0 })),
* animate("1s", { opacity: 1 }))
* animate("1s", style({ opacity: 1 }))
* ])
* ```
*
+1 -1
View File
@@ -14,7 +14,7 @@
"dependencies": {
"@angular-devkit/architect": "^0.10.6",
"@angular-devkit/core": "^7.0.4",
"@angular-devkit/schematics": "^7.0.4",
"@angular-devkit/schematics": "^7.3.0-rc.0",
"@bazel/typescript": "^0.22.1",
"@schematics/angular": "^7.0.4",
"@types/node": "6.0.84",
+5 -2
View File
@@ -8,6 +8,7 @@
/// <reference types='node'/>
import {spawn, spawnSync} from 'child_process';
import {join} from 'path';
import {Observable, Subject} from 'rxjs';
export type Executable = 'bazel' | 'ibazel';
@@ -17,7 +18,8 @@ export function runBazel(
projectDir: string, executable: Executable, command: Command, workspaceTarget: string,
flags: string[]): Observable<void> {
const doneSubject = new Subject<void>();
const buildProcess = spawn(executable, [command, workspaceTarget, ...flags], {
const bin = join(projectDir, 'node_modules', '.bin', executable);
const buildProcess = spawn(bin, [command, workspaceTarget, ...flags], {
cwd: projectDir,
stdio: 'inherit',
shell: false,
@@ -35,7 +37,8 @@ export function runBazel(
}
export function checkInstallation(executable: Executable, projectDir: string) {
const child = spawnSync(executable, ['version'], {
const bin = join(projectDir, 'node_modules', '.bin', executable);
const child = spawnSync(bin, ['version'], {
cwd: projectDir,
shell: false,
});
+3 -2
View File
@@ -11,7 +11,7 @@
import {BuildEvent, Builder, BuilderConfiguration, BuilderContext} from '@angular-devkit/architect';
import {getSystemPath, resolve} from '@angular-devkit/core';
import {Observable, of } from 'rxjs';
import {catchError, map, tap} from 'rxjs/operators';
import {catchError, map} from 'rxjs/operators';
import {checkInstallation, runBazel} from './bazel';
import {Schema} from './schema';
@@ -28,7 +28,8 @@ class BazelBuilder implements Builder<Schema> {
if (!checkInstallation(executable, projectRoot)) {
throw new Error(
`Could not run ${executable}. Please make sure that the ` +
`"${executable}" command is available in the $PATH.`);
`"${executable}" command is installed by running ` +
`"npm install" or "yarn install".`);
}
// TODO: Support passing flags.
@@ -136,15 +136,13 @@ if (process.env['WEB_TEST_METADATA']) {
}
setConf(conf, 'directConnect', true, 'is set to true for chrome');
setConf(conf, 'chromeDriver', chromeDriver, 'is determined by the browsers attribute');
mergeCapabilities(
conf, {
browserName: 'chrome',
chromeOptions: {
binary: chromeBin,
args: args,
}
},
'is determined by the browsers attribute');
mergeCapabilities(conf, {
browserName: 'chrome',
chromeOptions: {
binary: chromeBin,
args: args,
}
});
}
if (webTestNamedFiles['FIREFOX']) {
// TODO(gmagolan): implement firefox support for protractor
@@ -12,6 +12,7 @@ ts_library(
"@npm//@types/node",
"@npm//jasmine",
"@npm//protractor",
"@npm//tslib",
],
data = [
"//:tsconfig.json",
@@ -21,21 +21,15 @@ import {Schema as BazelWorkspaceOptions} from './schema';
* Look for package.json file for package with `packageName` in node_modules and
* extract its version.
*/
function findVersion(projectName: string, packageName: string, host: Tree): string|null {
// Need to look in multiple locations because we could be working in a subtree.
const candidates = [
`node_modules/${packageName}/package.json`,
`${projectName}/node_modules/${packageName}/package.json`,
];
for (const candidate of candidates) {
if (host.exists(candidate)) {
try {
const packageJson = JSON.parse(host.read(candidate).toString());
if (packageJson.name === packageName && packageJson.version) {
return packageJson.version;
}
} catch {
function findVersion(packageName: string, host: Tree): string|null {
const candidate = `node_modules/${packageName}/package.json`;
if (host.exists(candidate)) {
try {
const packageJson = JSON.parse(host.read(candidate).toString());
if (packageJson.name === packageName && packageJson.version) {
return packageJson.version;
}
} catch {
}
}
return null;
@@ -72,23 +66,17 @@ function hasSassStylesheet(host: Tree) {
export default function(options: BazelWorkspaceOptions): Rule {
return (host: Tree, context: SchematicContext) => {
if (!options.name) {
throw new SchematicsException(`Invalid options, "name" is required.`);
const name = options.name || getWorkspace(host).defaultProject;
if (!name) {
throw new Error('Please provide a name for Bazel workspace');
}
validateProjectName(options.name);
let newProjectRoot = '';
try {
const workspace = getWorkspace(host);
newProjectRoot = workspace.newProjectRoot || '';
} catch {
}
const appDir = `${newProjectRoot}/${options.name}`;
validateProjectName(name);
// If the project already has some deps installed, Bazel should use existing
// versions.
const existingVersions = {
Angular: findVersion(options.name, '@angular/core', host),
RxJs: findVersion(options.name, 'rxjs', host),
Angular: findVersion('@angular/core', host),
RxJs: findVersion('rxjs', host),
};
Object.keys(existingVersions).forEach((name: 'Angular' | 'RxJs') => {
@@ -110,12 +98,11 @@ export default function(options: BazelWorkspaceOptions): Rule {
return mergeWith(apply(url('./files'), [
applyTemplates({
utils: strings,
...options,
name,
'dot': '.', ...workspaceVersions,
routing: hasRoutingModule(host),
sass: hasSassStylesheet(host),
}),
move(appDir),
]));
};
}
@@ -21,24 +21,24 @@ describe('Bazel-workspace Schematic', () => {
const options = {...defaultOptions};
const host = schematicRunner.runSchematic('bazel-workspace', options);
const files = host.files;
expect(files).toContain('/demo/.bazelignore');
expect(files).toContain('/demo/.bazelrc');
expect(files).toContain('/demo/BUILD.bazel');
expect(files).toContain('/demo/src/BUILD.bazel');
expect(files).toContain('/demo/WORKSPACE');
expect(files).toContain('/demo/yarn.lock');
expect(files).toContain('/.bazelignore');
expect(files).toContain('/.bazelrc');
expect(files).toContain('/BUILD.bazel');
expect(files).toContain('/src/BUILD.bazel');
expect(files).toContain('/WORKSPACE');
expect(files).toContain('/yarn.lock');
});
it('should find existing Angular version', () => {
let host = new UnitTestTree(new HostTree);
host.create('/demo/node_modules/@angular/core/package.json', JSON.stringify({
host.create('/node_modules/@angular/core/package.json', JSON.stringify({
name: '@angular/core',
version: '6.6.6',
}));
const options = {...defaultOptions};
host = schematicRunner.runSchematic('bazel-workspace', options, host);
expect(host.files).toContain('/demo/WORKSPACE');
const workspace = host.readContent('/demo/WORKSPACE');
expect(host.files).toContain('/WORKSPACE');
const workspace = host.readContent('/WORKSPACE');
expect(workspace).toMatch('ANGULAR_VERSION = "6.6.6"');
});
@@ -46,19 +46,19 @@ describe('Bazel-workspace Schematic', () => {
const options = {...defaultOptions, name: 'demo-app'};
const host = schematicRunner.runSchematic('bazel-workspace', options);
const {files} = host;
expect(files).toContain('/demo-app/src/BUILD.bazel');
const content = host.readContent('/demo-app/src/BUILD.bazel');
expect(files).toContain('/src/BUILD.bazel');
const content = host.readContent('/src/BUILD.bazel');
expect(content).toContain('entry_module = "demo_app/src/main.dev"');
});
it('should add router if project contains routing module', () => {
let host = new UnitTestTree(new HostTree);
host.create('/demo/src/app/app-routing.module.ts', '');
expect(host.files).toContain('/demo/src/app/app-routing.module.ts');
host.create('/src/app/app-routing.module.ts', '');
expect(host.files).toContain('/src/app/app-routing.module.ts');
const options = {...defaultOptions};
host = schematicRunner.runSchematic('bazel-workspace', options, host);
expect(host.files).toContain('/demo/src/BUILD.bazel');
const content = host.readContent('/demo/src/BUILD.bazel');
expect(host.files).toContain('/src/BUILD.bazel');
const content = host.readContent('/src/BUILD.bazel');
expect(content).toContain('@angular//packages/router');
});
@@ -66,16 +66,16 @@ describe('Bazel-workspace Schematic', () => {
it('should contain project name', () => {
const options = {...defaultOptions};
const host = schematicRunner.runSchematic('bazel-workspace', options);
expect(host.files).toContain('/demo/WORKSPACE');
const content = host.readContent('/demo/WORKSPACE');
expect(host.files).toContain('/WORKSPACE');
const content = host.readContent('/WORKSPACE');
expect(content).toContain('workspace(name = "demo")');
});
it('should convert dashes in name to underscore', () => {
const options = {...defaultOptions, name: 'demo-project'};
const host = schematicRunner.runSchematic('bazel-workspace', options);
expect(host.files).toContain('/demo-project/WORKSPACE');
const content = host.readContent('/demo-project/WORKSPACE');
expect(host.files).toContain('/WORKSPACE');
const content = host.readContent('/WORKSPACE');
expect(content).toContain('workspace(name = "demo_project"');
});
});
@@ -83,40 +83,25 @@ describe('Bazel-workspace Schematic', () => {
describe('SASS', () => {
let host = new UnitTestTree(new HostTree);
beforeAll(() => {
host.create('/demo/src/app/app.component.scss', '');
expect(host.files).toContain('/demo/src/app/app.component.scss');
host.create('/src/app/app.component.scss', '');
expect(host.files).toContain('/src/app/app.component.scss');
const options = {...defaultOptions};
host = schematicRunner.runSchematic('bazel-workspace', options, host);
expect(host.files).toContain('/demo/WORKSPACE');
expect(host.files).toContain('/demo/src/BUILD.bazel');
expect(host.files).toContain('/WORKSPACE');
expect(host.files).toContain('/src/BUILD.bazel');
});
it('should download rules_sass in WORKSPACE', () => {
const content = host.readContent('/demo/WORKSPACE');
it('should download and load rules_sass in WORKSPACE', () => {
const content = host.readContent('/WORKSPACE');
expect(content).toContain('RULES_SASS_VERSION');
expect(content).toContain('io_bazel_rules_sass');
});
it('should load sass_repositories in WORKSPACE', () => {
const content = host.readContent('/demo/WORKSPACE');
expect(content).toContain(
'load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")');
expect(content).toContain('sass_repositories()');
});
it('should add sass_binary rules in src/BUILD', () => {
const content = host.readContent('/demo/src/BUILD.bazel');
const content = host.readContent('/src/BUILD.bazel');
expect(content).toContain('load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")');
expect(content).toMatch(/sass_binary\((.*\n)+\)/);
});
it('should add SASS targets to assets of ng_module in src/BUILD', () => {
const content = host.readContent('/demo/src/BUILD.bazel');
expect(content).toContain(`
assets = glob([
"**/*.css",
"**/*.html",
]) + [":style_" + x for x in glob(["**/*.scss"])],`);
expect(content).toContain('glob(["**/*.scss"])');
});
});
});
+1 -1
View File
@@ -9,5 +9,5 @@ export interface Schema {
/**
* The name of the project.
*/
name: string;
name?: string;
}
@@ -15,6 +15,5 @@
}
},
"required": [
"name"
]
}
@@ -201,13 +201,16 @@ export default function(options: Schema): Rule {
validateProjectName(options.name);
return chain([
externalSchematic('@schematics/angular', 'ng-new', {
...options,
skipInstall: true,
}),
externalSchematic(
'@schematics/angular', 'ng-new',
{
...options,
}),
addDevDependenciesToPackageJson(options),
addDevAndProdMainForAot(options),
schematic('bazel-workspace', options),
schematic('bazel-workspace', options, {
scope: options.name,
}),
overwriteGitignore(options),
updateWorkspaceFileToUseBazelBuilder(options),
]);
+30 -1
View File
@@ -32,7 +32,18 @@
rxjs "6.3.3"
source-map "0.7.3"
"@angular-devkit/schematics@7.1.2", "@angular-devkit/schematics@^7.0.4":
"@angular-devkit/core@7.3.0-rc.0":
version "7.3.0-rc.0"
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.3.0-rc.0.tgz#e555a08d85259855ff1946f4268936a1aadd38f1"
integrity sha512-0vHuw1gIMh79tI+gRxCMn89U1DnjmBnqybVktaf9YXi9xshxd+nnFb31v7n1tJQVQiQNzGxk3hviFnkzxLZipw==
dependencies:
ajv "6.7.0"
chokidar "2.0.4"
fast-json-stable-stringify "2.0.0"
rxjs "6.3.3"
source-map "0.7.3"
"@angular-devkit/schematics@7.1.2":
version "7.1.2"
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.1.2.tgz#847639044417d044bf1bc87f64508a0c3f99fae2"
integrity sha512-NFhHLYWf9gpGQm0s19lq+nAw3CZ0udBpoBLzCm8Crlmu6+7aAXgw7Fv5P4ukWJ/e1m7NDGVids+B6kBGXaY6Ig==
@@ -40,6 +51,14 @@
"@angular-devkit/core" "7.1.2"
rxjs "6.3.3"
"@angular-devkit/schematics@^7.3.0-rc.0":
version "7.3.0-rc.0"
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.3.0-rc.0.tgz#9f1e1f6942da36b12c81241398ed6ca8b2e65875"
integrity sha512-noqcQIOvah2G126DTFKY5Kiga8UwI9cKzyhQdNlf+8hAZpnWwTURItQ5xuMJg/XfRQLUSg9gWS2h1cI9AD7mxQ==
dependencies:
"@angular-devkit/core" "7.3.0-rc.0"
rxjs "6.3.3"
"@bazel/typescript@^0.22.1":
version "0.22.1"
resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-0.22.1.tgz#b52c00e8560019e2f9d273d45c04785e0ec9d9bd"
@@ -79,6 +98,16 @@ ajv@6.5.3:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ajv@6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96"
integrity sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==
dependencies:
fast-deep-equal "^2.0.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
-1
View File
@@ -10,7 +10,6 @@ ts_library(
"src/**/*.ts",
],
),
module_name = "@angular/benchpress",
deps = [
"//packages:types",
"//packages/core",
+1 -1
View File
@@ -10,7 +10,6 @@ ng_module(
"src/**/*.ts",
],
),
module_name = "@angular/common",
deps = [
"//packages/core",
"@rxjs",
@@ -34,6 +33,7 @@ ng_package(
# Dependencies on the full npm_package cause long re-builds.
visibility = [
"//packages/bazel/test/ng_package:__pkg__",
"//packages/compiler-cli/integrationtest:__pkg__",
"//packages/compiler-cli/test:__pkg__",
"//packages/compiler-cli/test/diagnostics:__pkg__",
"//packages/compiler-cli/test/ngcc:__pkg__",
-1
View File
@@ -12,7 +12,6 @@ ng_module(
"src/**/*.ts",
],
),
module_name = "@angular/common/http",
deps = [
"//packages/common",
"//packages/core",
-1
View File
@@ -12,7 +12,6 @@ ng_module(
"src/**/*.ts",
],
),
module_name = "@angular/common/http/testing",
deps = [
"//packages/common/http",
"//packages/core",
-1
View File
@@ -8,7 +8,6 @@ ts_library(
["**/*.ts"],
exclude = ["closure-locale.ts"],
),
module_name = "@angular/common/locales",
)
npm_package(
+65 -41
View File
@@ -26,15 +26,61 @@ export class NgForOfContext<T> {
}
/**
* The `NgForOf` directive instantiates a template once per item from an iterable. The context
* for each instantiated template inherits from the outer context with the given loop variable
* set to the current item from the iterable.
* A [structural directive](guide/structural-directives) that renders
* a template for each item in a collection.
* The directive is placed on an element, which becomes the parent
* of the cloned templates.
*
* The `ngForOf` is generally used in the
* [shorthand form](guide/structural-directives#the-asterisk--prefix) `*ngFor`.
* In this form, the template to be rendered for each iteration is the content
* of an anchor element containing the directive.
*
* The following example shows the shorthand syntax with some options,
* contained in an `<li>` element.
*
* ```
* <li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>
* ```
*
* The shorthand form expands into a long form that uses the `ngForOf` selector
* on an `<ng-template>` element.
* The content of the `<ng-template>` element is the `<li>` element that held the
* short-form directive.
*
* Here is the expanded version of the short-form example.
*
* ```
* <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn">
* <li>...</li>
* </ng-template>
* ```
*
* Angular automatically expands the shorthand syntax as it compiles the template.
* The context for each embedded view is logically merged to the current component
* context according to its lexical position.
*
* When using the shorthand syntax, Angular allows only [one structural directive
* on an element](guide/structural-directives#one-structural-directive-per-host-element).
* If you want to iterate conditionally, for example,
* put the `*ngIf` on a container element that wraps the `*ngFor` element.
* For futher discussion, see
* [Structural Directives](guide/structural-directives#one-per-element).
*
* @usageNotes
*
* ### Local Variables
* ### Local variables
*
* `NgForOf` provides several exported values that can be aliased to local variables:
* `NgForOf` provides exported values that can be aliased to local variables.
* For example:
*
* ```
* <li *ngFor="let user of userObservable | async as users; index as i; first as isFirst">
* {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
* </li>
* ```
*
* The following exported values can be aliased to local variables:
*
* - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`).
* - `ngForOf: NgIterable<T>`: The value of the iterable expression. Useful when the expression is
@@ -46,55 +92,33 @@ export class NgForOfContext<T> {
* - `even: boolean`: True when the item has an even index in the iterable.
* - `odd: boolean`: True when the item has an odd index in the iterable.
*
* ```
* <li *ngFor="let user of userObservable | async as users; index as i; first as isFirst">
* {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
* </li>
* ```
*
* ### Change Propagation
* ### Change propagation
*
* When the contents of the iterator changes, `NgForOf` makes the corresponding changes to the DOM:
*
* * When an item is added, a new instance of the template is added to the DOM.
* * When an item is removed, its template instance is removed from the DOM.
* * When items are reordered, their respective templates are reordered in the DOM.
* * Otherwise, the DOM element for that item will remain the same.
*
* Angular uses object identity to track insertions and deletions within the iterator and reproduce
* those changes in the DOM. This has important implications for animations and any stateful
* controls (such as `<input>` elements which accept user input) that are present. Inserted rows can
* controls that are present, such as `<input>` elements that accept user input. Inserted rows can
* be animated in, deleted rows can be animated out, and unchanged rows retain any unsaved state
* such as user input.
* For more on animations, see [Transitions and Triggers](guide/transition-and-triggers).
*
* It is possible for the identities of elements in the iterator to change while the data does not.
* This can happen, for example, if the iterator produced from an RPC to the server, and that
* RPC is re-run. Even if the data hasn't changed, the second response will produce objects with
* different identities, and Angular will tear down the entire DOM and rebuild it (as if all old
* elements were deleted and all new elements inserted). This is an expensive operation and should
* be avoided if possible.
* The identities of elements in the iterator can change while the data does not.
* This can happen, for example, if the iterator is produced from an RPC to the server, and that
* RPC is re-run. Even if the data hasn't changed, the second response produces objects with
* different identities, and Angular must tear down the entire DOM and rebuild it (as if all old
* elements were deleted and all new elements inserted).
*
* To customize the default tracking algorithm, `NgForOf` supports `trackBy` option.
* `trackBy` takes a function which has two arguments: `index` and `item`.
* To avoid this expensive operation, you can customize the default tracking algorithm.
* by supplying the `trackBy` option to `NgForOf`.
* `trackBy` takes a function that has two arguments: `index` and `item`.
* If `trackBy` is given, Angular tracks changes by the return value of the function.
*
* ### Syntax
*
* - `<li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>`
*
* With `<ng-template>` element:
*
* ```
* <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn">
* <li>...</li>
* </ng-template>
* ```
*
* ### Example
*
* See a [live demo](http://plnkr.co/edit/KVuXxDp0qinGDyo307QW?p=preview) for a more detailed
* example.
*
* @see [Structural Directives](guide/structural-directives)
* @ngModule CommonModule
* @publicApi
*/
@@ -204,9 +228,9 @@ export class NgForOf<T> implements DoCheck {
}
/**
* Assert the correct type of the context for the template that `NgForOf` will render.
* Asserts the correct type of the context for the template that `NgForOf` will render.
*
* The presence of this method is a signal to the Ivy template type check compiler that the
* The presence of this method is a signal to the Ivy template type-check compiler that the
* `NgForOf` structural directive renders its template with a specific context type.
*/
static ngTemplateContextGuard<T>(dir: NgForOf<T>, ctx: any): ctx is NgForOfContext<T> {
+103 -57
View File
@@ -10,94 +10,140 @@ import {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef, ɵstri
/**
* Conditionally includes a template based on the value of an `expression`.
* A structural directive that conditionally includes a template based on the value of
* an expression coerced to Boolean.
* When the expression evaluates to true, Angular renders the template
* provided in a `then` clause, and when false or null,
* Angular renders the template provided in an optional `else` clause. The default
* template for the `else` clause is blank.
*
* `ngIf` evaluates the `expression` and then renders the `then` or `else` template in its place
* when expression is truthy or falsy respectively. Typically the:
* - `then` template is the inline template of `ngIf` unless bound to a different value.
* - `else` template is blank unless it is bound.
* A [shorthand form](guide/structural-directives#the-asterisk--prefix) of the directive,
* `*ngIf="condition"`, is generally used, provided
* as an attribute of the anchor element for the inserted template.
* Angular expands this into a more explicit version, in which the anchor element
* is contained in an `<ng-template>` element.
*
* Simple form with shorthand syntax:
*
* ```
* <div *ngIf="condition">Content to render when condition is true.</div>
* ```
*
* Simple form with expanded syntax:
*
* ```
* <ng-template [ngIf]="condition"><div>Content to render when condition is
* true.</div></ng-template>
* ```
*
* Form with an "else" block:
*
* ```
* <div *ngIf="condition; else elseBlock">Content to render when condition is true.</div>
* <ng-template #elseBlock>Content to render when condition is false.</ng-template>
* ```
*
* Shorthand form with "then" and "else" blocks:
*
* ```
* <div *ngIf="condition; then thenBlock else elseBlock"></div>
* <ng-template #thenBlock>Content to render when condition is true.</ng-template>
* <ng-template #elseBlock>Content to render when condition is false.</ng-template>
* ```
*
* Form with storing the value locally:
*
* ```
* <div *ngIf="condition as value; else elseBlock">{{value}}</div>
* <ng-template #elseBlock>Content to render when value is null.</ng-template>
* ```
*
* @usageNotes
*
* ### Most common usage
* The `*ngIf` directive is most commonly used to conditionally show an inline template,
* as seen in the following example.
* The default `else` template is blank.
*
* The most common usage of the `ngIf` directive is to conditionally show the inline template as
* seen in this example:
* {@example common/ngIf/ts/module.ts region='NgIfSimple'}
*
* ### Showing an alternative template using `else`
*
* If it is necessary to display a template when the `expression` is falsy use the `else` template
* binding as shown. Note that the `else` binding points to a `<ng-template>` labeled `#elseBlock`.
* The template can be defined anywhere in the component view but is typically placed right after
* To display a template when `expression` evaluates to false, use an `else` template
* binding as shown in the following example.
* The `else` binding points to an `<ng-template>` element labeled `#elseBlock`.
* The template can be defined anywhere in the component view, but is typically placed right after
* `ngIf` for readability.
*
* {@example common/ngIf/ts/module.ts region='NgIfElse'}
*
* ### Using non-inlined `then` template
* ### Using an external `then` template
*
* Usually the `then` template is the inlined template of the `ngIf`, but it can be changed using
* a binding (just like `else`). Because `then` and `else` are bindings, the template references can
* change at runtime as shown in this example.
* In the previous example, the then-clause template is specified inline, as the content of the
* tag that contains the `ngIf` directive. You can also specify a template that is defined
* externally, by referencing a labeled `<ng-template>` element. When you do this, you can
* change which template to use at runtime, as shown in the following example.
*
* {@example common/ngIf/ts/module.ts region='NgIfThenElse'}
*
* ### Storing conditional result in a variable
* ### Storing a conditional result in a variable
*
* A common pattern is that we need to show a set of properties from the same object. If the
* object is undefined, then we have to use the safe-traversal-operator `?.` to guard against
* dereferencing a `null` value. This is especially the case when waiting on async data such as
* when using the `async` pipe as shown in following example:
*
* ```
* Hello {{ (userStream|async)?.last }}, {{ (userStream|async)?.first }}!
* ```
*
* There are several inefficiencies in the above example:
* - We create multiple subscriptions on `userStream`. One for each `async` pipe, or two in the
* example above.
* - We cannot display an alternative screen while waiting for the data to arrive asynchronously.
* - We have to use the safe-traversal-operator `?.` to access properties, which is cumbersome.
* - We have to place the `async` pipe in parenthesis.
*
* A better way to do this is to use `ngIf` and store the result of the condition in a local
* variable as shown in the the example below:
* You might want to show a set of properties from the same object. If you are waiting
* for asynchronous data, the object can be undefined.
* In this case, you can use `ngIf` and store the result of the condition in a local
* variable as shown in the the following example.
*
* {@example common/ngIf/ts/module.ts region='NgIfAs'}
*
* Notice that:
* - We use only one `async` pipe and hence only one subscription gets created.
* - `ngIf` stores the result of the `userStream|async` in the local variable `user`.
* - The local `user` can then be bound repeatedly in a more efficient way.
* - No need to use the safe-traversal-operator `?.` to access properties as `ngIf` will only
* display the data if `userStream` returns a value.
* - We can display an alternative template while waiting for the data.
* This code uses only one `AsyncPipe`, so only one subscription is created.
* The conditional statement stores the result of `userStream|async` in the local variable `user`.
* You can then bind the local `user` repeatedly.
*
* ### Syntax
* The conditional displays the data only if `userStream` returns a value,
* so you don't need to use the
* [safe-navigation-operator](guide/template-syntax#safe-navigation-operator) (`?.`)
* to guard against null values when accessing properties.
* You can display an alternative template while waiting for the data.
*
* Simple form:
* - `<div *ngIf="condition">...</div>`
* - `<ng-template [ngIf]="condition"><div>...</div></ng-template>`
* ### Shorthand syntax
*
* The shorthand syntax `*ngIf` expands into two separate template specifications
* for the "then" and "else" clauses. For example, consider the following shorthand statement,
* that is meant to show a loading page while waiting for data to be loaded.
*
* Form with an else block:
* ```
* <div *ngIf="condition; else elseBlock">...</div>
* <ng-template #elseBlock>...</ng-template>
* <div class="hero-list" *ngIf="heroes else loading">
* ...
* </div>
*
* <ng-template #loading>
* <div>Loading...</div>
* </ng-template>
* ```
*
* Form with a `then` and `else` block:
* You can see that the "else" clause references the `<ng-template>`
* with the `#loading` label, and the template for the "then" clause
* is provided as the content of the anchor element.
*
* However, when Angular expands the shorthand syntax, it creates
* another `<ng-template>` tag, with `ngIf` and `ngIfElse` directives.
* The anchor element containing the template for the "then" clause becomes
* the content of this unlabeled `<ng-template>` tag.
*
* ```
* <div *ngIf="condition; then thenBlock else elseBlock"></div>
* <ng-template #thenBlock>...</ng-template>
* <ng-template #elseBlock>...</ng-template>
* <ng-template [ngIf]="hero-list" [ngIfElse]="loading">
* <div class="hero-list">
* ...
* </div>
* </ng-template>
*
* <ng-template #loading>
* <div>Loading...</div>
* </ng-template>
* ```
*
* Form with storing the value locally:
* ```
* <div *ngIf="condition as value; else elseBlock">{{value}}</div>
* <ng-template #elseBlock>...</ng-template>
* ```
* The presence of the implicit template object has implications for the nesting of
* structural directives. For more on this subject, see
* [Structural Directives](https://angular.io/guide/structural-directives#one-per-element).
*
* @ngModule CommonModule
* @publicApi
-1
View File
@@ -7,7 +7,6 @@ load("//tools:defaults.bzl", "ng_module")
ng_module(
name = "testing",
srcs = glob(["**/*.ts"]),
module_name = "@angular/common/testing",
deps = [
"//packages/common",
"//packages/core",
+3 -2
View File
@@ -20,7 +20,6 @@ ts_library(
"src/integrationtest/**/*.ts",
],
),
module_name = "@angular/compiler-cli",
tsconfig = ":tsconfig",
deps = [
"//packages/compiler",
@@ -48,7 +47,9 @@ npm_package(
],
# Do not add more to this list.
# Dependencies on the full npm_package cause long re-builds.
visibility = ["//visibility:private"],
visibility = [
"//packages/compiler-cli/integrationtest:__pkg__",
],
deps = [
":compiler-cli",
"//packages/compiler-cli/src/ngcc",
-28
View File
@@ -1,28 +0,0 @@
# Legacy docs for @angular/compiler-cli Developers
*Note from Igor: This doc is likely outdated now but I'm keeping it around because
offline_compiler_test.sh need to be converted to bazel/circleci (or deleted) and these docs seem
relevant to anyone who needs to understand those tests. Once that's done this file can be deleted.*
```
# Build Angular and the compiler
./build.sh
# Run the test once
# (First edit the LINKABLE_PKGS to use npm link instead of npm install)
$ ./scripts/ci/offline_compiler_test.sh
# Keep a package fresh in watch mode
./node_modules/.bin/tsc -p packages/compiler/tsconfig-build.json -w
# Recompile @angular/core module (needs to use tsc-ext to keep the metadata)
$ export NODE_PATH=${NODE_PATH}:$(pwd)/dist/all:$(pwd)/dist/tools
$ node dist/tools/@angular/compiler-cli/src/main -p packages/core/tsconfig-build.json
# Iterate on the test
$ cd /tmp/wherever/e2e_test.1464388257/
$ ./node_modules/.bin/ngc
$ ./node_modules/.bin/jasmine test/*_spec.js
```
@@ -0,0 +1,59 @@
package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_test")
load("//tools:defaults.bzl", "nodejs_binary")
nodejs_binary(
name = "ngc_bin",
data = [
"//packages/compiler-cli",
"@ngdeps//chokidar",
"@ngdeps//reflect-metadata",
],
entry_point = "angular/packages/compiler-cli/src/main.js",
)
nodejs_binary(
name = "ng_xi18n",
data = [
"//packages/compiler-cli",
"@ngdeps//chokidar",
"@ngdeps//reflect-metadata",
],
entry_point = "angular/packages/compiler-cli/src/extract_i18n.js",
)
nodejs_test(
name = "integrationtest",
data = [
":ngc_bin",
":ng_xi18n",
"@nodejs//:node",
"@ngdeps//domino",
"@ngdeps//chokidar",
"@ngdeps//source-map-support",
"@ngdeps//shelljs",
"@ngdeps//typescript",
"@ngdeps//reflect-metadata",
"@ngdeps//rxjs",
"@ngdeps//tslib",
"@ngdeps//jasmine/bin:jasmine",
"@ngdeps//zone.js",
"@ngdeps//xhr2",
"@ngdeps//@types/node",
"@ngdeps//@types/jasmine",
"//packages/animations:npm_package",
"//packages/common:npm_package",
"//packages/compiler:npm_package",
"//packages/compiler-cli:npm_package",
"//packages/core:npm_package",
"//packages/forms:npm_package",
"//packages/http:npm_package",
"//packages/platform-browser:npm_package",
"//packages/platform-browser-dynamic:npm_package",
"//packages/platform-server:npm_package",
"//packages/router:npm_package",
] + glob(["**/*"]),
entry_point = "angular/packages/compiler-cli/integrationtest/test.js",
tags = ["no-ivy-aot"],
)
@@ -1,26 +1,21 @@
{
"angularCompilerOptions": {
// For TypeScript 1.8, we have to lay out generated files
// in the same source directory with your code.
"genDir": "ng",
"flatModuleId": "flat_module",
"flatModuleOutFile": "index.js",
"skipTemplateCodegen": true
},
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"noImplicitAny": true,
"moduleResolution": "node",
"rootDir": "",
"declaration": true,
"lib": ["es6", "dom"],
"baseUrl": ".",
"declaration": true,
"experimentalDecorators": true,
"lib": ["es6", "dom"],
"moduleResolution": "node",
"noImplicitAny": true,
"outDir": "../node_modules/flat_module",
// Prevent scanning up the directory tree for types
"typeRoots": ["node_modules/@types"]
"rootDir": "",
"target": "es5"
},
"files": ["public-api.ts"]
}
}
@@ -1,24 +1,17 @@
{
"angularCompilerOptions": {
// For TypeScript 1.8, we have to lay out generated files
// in the same source directory with your code.
"genDir": ".",
"debug": true
},
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"noImplicitAny": true,
"moduleResolution": "node",
"rootDir": "",
"declaration": true,
"lib": [
"es6",
"dom"
],
"baseUrl": ".",
// don't auto-discover @types/fs-extra
"declaration": true,
"experimentalDecorators": true,
"lib": ["es6", "dom"],
"moduleResolution": "node",
"noImplicitAny": true,
"rootDir": "",
"target": "es5",
"types": []
}
}
}
@@ -13,9 +13,11 @@
<target>tervetuloa</target>
</trans-unit>
<trans-unit id="63a85808f03b8181e36a952e0fa38202c2304862" datatype="html">
<source>other-3rdP-component</source>
<target>other-3rdP-component</target>
<source>other-3rdP-component
multi-lines</source>
<target>other-3rdP-component
multi-lines</target>
</trans-unit>
</body>
</file>
</xliff>
</xliff>
@@ -8,7 +8,6 @@
import {ApplicationRef, NgModule, forwardRef} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {MATERIAL_SANITY_CHECKS, MdButtonModule} from '@angular/material';
import {ServerModule} from '@angular/platform-server';
import {FlatModule} from 'flat_module';
// Note: don't refer to third_party_src as we want to test that
@@ -60,7 +59,6 @@ export {SomeModule as JitSummariesSomeModule} from './jit_summaries';
imports: [
ServerModule,
FormsModule,
MdButtonModule,
ModuleUsingCustomElements,
SomeLibModule.withProviders(),
ThirdpartyModule,
@@ -69,9 +67,6 @@ export {SomeModule as JitSummariesSomeModule} from './jit_summaries';
providers: [
SomeService,
{provide: CUSTOM, useValue: forwardRef(() => ({name: 'some name'}))},
// disable sanity check for material because it throws an error when used server-side
// see https://github.com/angular/material2/issues/6292
{provide: MATERIAL_SANITY_CHECKS, useValue: false},
],
entryComponents: [
AnimateCmp,
@@ -0,0 +1,54 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const path = require('path');
const shx = require('shelljs');
const os = require('os');
const {runCommand, setupTestDirectory} = require('./test_helpers');
const ngcBin = require.resolve('./ngc_bin');
const xi18nBin = require.resolve('./ng_xi18n');
const nodeBin = require.resolve(`nodejs/bin/node${(os.platform() === 'win32' ? '.cmd' : '')}`);
const jasmineBin = require.resolve('ngdeps/node_modules/jasmine/bin/jasmine.js');
// Prepare the test directory before building the integration test output. This ensures that
// the test runs in an hermetic way and works on Windows.
const tmpDir = setupTestDirectory();
// Compile the "flat_module" Angular project using NGC.
runCommand(ngcBin, ['-p', 'flat_module/tsconfig-build.json']);
// Copy HTML asset files from the "flat_module" package to the NPM output. The "flat_module"
// has template code generation disabled and therefore needs to have the asset files included
// next to the JavaScript output.
shx.cp(
path.join(tmpDir, 'flat_module/src/*.html'), path.join(tmpDir, 'node_modules/flat_module/src'));
// Compile the "third_party" Angular project using NGC.
runCommand(ngcBin, ['-p', 'third_party_src/tsconfig-build.json']);
// Compile the main integration-test Angular project using NGC. Also uses a translated
// i18n file which will be used to verify the translated templates of components.
runCommand(ngcBin, [
'-p', 'tsconfig-build.json', '--i18nFile=src/messages.fi.xlf', '--locale=fi', '--i18nFormat=xlf'
]);
// Extract the i18n messages into various formats that will be verified
// later on by the "i18n_spec" within "test/".
runCommand(xi18nBin, ['-p', 'tsconfig-xi18n.json', '--i18nFormat=xlf', '--locale=fr']);
runCommand(
xi18nBin, ['-p', 'tsconfig-xi18n.json', '--i18nFormat=xlf2', '--outFile=messages.xliff2.xlf']);
runCommand(
xi18nBin, ['-p', 'tsconfig-xi18n.json', '--i18nFormat=xmb', '--outFile=custom_file.xmb']);
// Run the ngtools tests that verify that the public API provided by the "compiler-cli"
// is working as expected in real projects.
runCommand(nodeBin, [path.join(tmpDir, 'test/test_ngtools_api.js')]);
// Run all specs which verify the output from the previously built modules and i18n files.
runCommand(nodeBin, [jasmineBin, path.join(tmpDir, 'test/all_spec.js')]);
@@ -16,10 +16,12 @@ import {createComponent} from './util';
describe('template codegen output', () => {
const outDir = 'src';
it('should lower Decorators without reflect-metadata', () => {
const jsOutput = path.join(outDir, 'basic.js');
expect(fs.existsSync(jsOutput)).toBeTruthy();
expect(fs.readFileSync(jsOutput, {encoding: 'utf-8'})).not.toContain('Reflect.decorate');
it('should be able to lower annotations as static fields', () => {
const basicFilePath = path.join(outDir, 'basic.js');
expect(fs.existsSync(basicFilePath)).toBeTruthy();
const fileContent = fs.readFileSync(basicFilePath, 'utf8');
expect(fileContent).not.toContain('Reflect.decorate');
expect(fileContent).toContain('BasicComp.decorators = [');
});
it('should produce metadata.json outputs', () => {
@@ -36,8 +36,8 @@ const EXPECTED_XMB = `<?xml version="1.0" encoding="UTF-8" ?>
<messagebundle>
<msg id="126808141597411718"><source>node_modules/third_party/other_comp.d.ts:1,2</source>other-3rdP-component
multi-lines</msg>
<msg id="8136548302122759730" desc="desc" meaning="meaning"><source>src/basic.ts:1</source>translate me</msg>
<msg id="3492007542396725315"><source>src/basic.ts:5</source><source>src/entry_components.ts:1</source>Welcome</msg>
<msg id="8136548302122759730" desc="desc" meaning="meaning"><source>src/basic.html:1</source>translate me</msg>
<msg id="3492007542396725315"><source>src/basic.html:5</source><source>src/entry_components.ts:1</source>Welcome</msg>
</messagebundle>
`;
@@ -56,7 +56,7 @@ multi-lines</source>
<trans-unit id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4" datatype="html">
<source>translate me</source>
<context-group purpose="location">
<context context-type="sourcefile">src/basic.ts</context>
<context context-type="sourcefile">src/basic.html</context>
<context context-type="linenumber">1</context>
</context-group>
<note priority="1" from="description">desc</note>
@@ -65,7 +65,7 @@ multi-lines</source>
<trans-unit id="65cc4ab3b4c438e07c89be2b677d08369fb62da2" datatype="html">
<source>Welcome</source>
<context-group purpose="location">
<context context-type="sourcefile">src/basic.ts</context>
<context context-type="sourcefile">src/basic.html</context>
<context context-type="linenumber">5</context>
</context-group>
<context-group purpose="location">
@@ -94,7 +94,7 @@ multi-lines</source>
<notes>
<note category="description">desc</note>
<note category="meaning">meaning</note>
<note category="location">src/basic.ts:1</note>
<note category="location">src/basic.html:1</note>
</notes>
<segment>
<source>translate me</source>
@@ -102,7 +102,7 @@ multi-lines</source>
</unit>
<unit id="3492007542396725315">
<notes>
<note category="location">src/basic.ts:5</note>
<note category="location">src/basic.html:5</note>
<note category="location">src/entry_components.ts:1</note>
</notes>
<segment>
@@ -114,31 +114,31 @@ multi-lines</source>
`;
describe('template i18n extraction output', () => {
const outDir = 'out';
const outputDir = path.join(__dirname, '../xi18n-out');
it('should extract i18n messages as xmb', () => {
const xmbOutput = path.join(outDir, 'custom_file.xmb');
const xmbOutput = path.join(outputDir, 'custom_file.xmb');
expect(fs.existsSync(xmbOutput)).toBeTruthy();
const xmb = fs.readFileSync(xmbOutput, {encoding: 'utf-8'});
expect(xmb).toEqual(EXPECTED_XMB);
});
it('should extract i18n messages as xliff', () => {
const xlfOutput = path.join(outDir, 'messages.xlf');
const xlfOutput = path.join(outputDir, 'messages.xlf');
expect(fs.existsSync(xlfOutput)).toBeTruthy();
const xlf = fs.readFileSync(xlfOutput, {encoding: 'utf-8'});
expect(xlf).toEqual(EXPECTED_XLIFF);
});
it('should extract i18n messages as xliff version 2.0', () => {
const xlfOutput = path.join(outDir, 'messages.xliff2.xlf');
const xlfOutput = path.join(outputDir, 'messages.xliff2.xlf');
expect(fs.existsSync(xlfOutput)).toBeTruthy();
const xlf = fs.readFileSync(xlfOutput, {encoding: 'utf-8'});
expect(xlf).toEqual(EXPECTED_XLIFF2);
});
it('should not emit js', () => {
const files = fs.readdirSync(outDir);
const files = fs.readdirSync(outputDir);
files.forEach(f => expect(f).not.toMatch(/\.js$/));
});
});
@@ -13,7 +13,7 @@ import 'reflect-metadata';
import * as path from 'path';
import * as ts from 'typescript';
import * as assert from 'assert';
import {__NGTOOLS_PRIVATE_API_2, readConfiguration} from '@angular/compiler-cli';
import {createProgram, readConfiguration} from '@angular/compiler-cli';
/* tslint:disable:no-console */
/**
@@ -22,19 +22,10 @@ import {__NGTOOLS_PRIVATE_API_2, readConfiguration} from '@angular/compiler-cli'
* properly read and wrote.
*/
function main() {
console.log(`testing ngtools API...`);
Promise.resolve()
.then(() => lazyRoutesTest())
.then(() => {
console.log('All done!');
process.exit(0);
})
.catch((err) => {
console.error(err.stack);
console.error('Test failed');
process.exit(1);
});
Promise.resolve().then(() => lazyRoutesTest()).then(() => { process.exit(0); }).catch((err) => {
console.error(err.stack);
process.exit(1);
});
}
function lazyRoutesTest() {
@@ -43,13 +34,15 @@ function lazyRoutesTest() {
const config = readConfiguration(project);
const host = ts.createCompilerHost(config.options, true);
const program = ts.createProgram(config.rootNames, config.options, host);
const program = createProgram({
rootNames: config.rootNames,
options: config.options, host,
});
config.options.basePath = basePath;
config.options.rootDir = basePath;
const lazyRoutes = __NGTOOLS_PRIVATE_API_2.listLazyRoutes(
{program, host, angularCompilerOptions: config.options, entryModule: 'app.module#AppModule'});
const lazyRoutes = program.listLazyRoutes('app.module#AppModule');
const expectations: {[route: string]: string} = {
'./lazy.module#LazyModule': 'lazy.module.ts',
'./feature/feature.module#FeatureModule': 'feature/feature.module.ts',
@@ -61,17 +54,25 @@ function lazyRoutesTest() {
'feature/feature.module#FeatureModule': 'feature/feature.module.ts'
};
Object.keys(lazyRoutes).forEach((route: string) => {
assert(route in expectations, `Found a route that was not expected: "${route}".`);
lazyRoutes.forEach(lazyRoute => {
const routeName = lazyRoute.route;
// Normalize the module path and the expected module path so that these can be compared
// on Windows where path separators are not consistent with TypeScript internal paths.
const modulePath = path.normalize(lazyRoute.referencedModule.filePath);
const expectedModulePath = path.normalize(path.join(basePath, expectations[routeName]));
assert(routeName in expectations, `Found a route that was not expected: "${routeName}".`);
assert(
lazyRoutes[route] == path.join(basePath, expectations[route]),
`Route "${route}" does not point to the expected absolute path ` +
`"${path.join(basePath, expectations[route])}". It points to "${lazyRoutes[route]}"`);
modulePath === expectedModulePath,
`Route "${routeName}" does not point to the expected absolute path ` +
`"${expectedModulePath}". It points to "${modulePath}"`);
});
// Verify that all expectations were met.
assert.deepEqual(
Object.keys(lazyRoutes), Object.keys(expectations), `Expected routes listed to be: \n` +
lazyRoutes.map(lazyRoute => lazyRoute.route), Object.keys(expectations),
`Expected routes listed to be: \n` +
` ${JSON.stringify(Object.keys(expectations))}\n` +
`Actual:\n` +
` ${JSON.stringify(Object.keys(lazyRoutes))}\n`);
@@ -0,0 +1,164 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const child_process = require('child_process');
const fs = require('fs');
const path = require('path');
const shx = require('shelljs');
/** Manifest path that refers to the Bazel package that contains all test sources. */
const baseManifestPath = 'angular/packages/compiler-cli/integrationtest';
/**
* Temporary directory which will be used to build and run the integration tests. Note that
* this environment variable is automatically set by Bazel for such test actions.
*/
const tmpDir = process.env.TEST_TMPDIR;
/** Fine grained node modules which are required in order to run the integration test. */
const requiredNodeModules = {
'@angular/animations': resolveNpmTreeArtifact('angular/packages/animations/npm_package'),
'@angular/common': resolveNpmTreeArtifact('angular/packages/common/npm_package'),
'@angular/compiler': resolveNpmTreeArtifact('angular/packages/compiler/npm_package'),
'@angular/compiler-cli': resolveNpmTreeArtifact('angular/packages/compiler-cli/npm_package'),
'@angular/core': resolveNpmTreeArtifact('angular/packages/core/npm_package'),
'@angular/forms': resolveNpmTreeArtifact('angular/packages/forms/npm_package'),
'@angular/http': resolveNpmTreeArtifact('angular/packages/http/npm_package'),
'@angular/platform-browser':
resolveNpmTreeArtifact('angular/packages/platform-browser/npm_package'),
'@angular/platform-browser-dynamic':
resolveNpmTreeArtifact('angular/packages/platform-browser-dynamic/npm_package'),
'@angular/platform-server':
resolveNpmTreeArtifact('angular/packages/platform-server/npm_package'),
'@angular/router': resolveNpmTreeArtifact('angular/packages/router/npm_package'),
'@types/jasmine': resolveNpmTreeArtifact('ngdeps/node_modules/@types/jasmine'),
'@types/node': resolveNpmTreeArtifact('ngdeps/node_modules/@types/node'),
// Transitive dependencies which need to be specified because the Angular NPM packages
// depend on these without the Angular NPM packages being part of the Bazel managed deps.
// This means that transitive dependencies need to be manually declared as required.
'tslib': resolveNpmTreeArtifact('ngdeps/node_modules/tslib'),
'domino': resolveNpmTreeArtifact('ngdeps/node_modules/domino'),
'xhr2': resolveNpmTreeArtifact('ngdeps/node_modules/xhr2'),
// Fine grained dependencies which are used by the integration test Angular modules, and
// need to be symlinked so that they can be resolved by NodeJS or NGC.
'reflect-metadata': resolveNpmTreeArtifact('ngdeps/node_modules/reflect-metadata'),
'rxjs': resolveNpmTreeArtifact('ngdeps/node_modules/rxjs'),
'source-map-support': resolveNpmTreeArtifact('ngdeps/node_modules/source-map-support'),
'typescript': resolveNpmTreeArtifact('ngdeps/node_modules/typescript'),
'zone.js': resolveNpmTreeArtifact('ngdeps/node_modules/zone.js'),
};
/** Sets up the temporary test directory and returns the path to the directory. */
exports.setupTestDirectory = function() {
copySourceFilesToTempDir();
symlinkNodeModules();
return tmpDir;
};
/**
* Runs a given binary with the specified command line arguments. The working directory for
* the spawned process will be the temporary directory.
*/
exports.runCommand = function runCommand(binary, args = []) {
const ngcProcess = child_process.spawnSync(binary, args, {
stdio: 'inherit',
cwd: tmpDir,
env: {
...process.env,
// We need to set the "NODE_PATH" here because the built Angular NPM packages are symlinks
// which NodeJS resolves into the output location. This is problematic because the output
// location does not have the required dependencies of these NPM packages installed. This
// could be fixed by setting the NodeJS "--preserve-symlinks" option, but this would mean
// that transitive dependencies of fine-grained dependencies cannot be resolved either.
NODE_PATH: path.join(tmpDir, 'node_modules/')
}
});
if (ngcProcess.status !== 0) {
console.error(`Command ${binary} failed with arguments: "${args.join(' ')}". See error above.`);
process.exit(1);
}
};
/**
* Symlinks the specified node modules within the temporary directory. This is necessary because
* this test is an integration test and we don't want to rely on any path-mapped module resolution.
* Additionally, NGC expects types and imported packages to be within the project's root dir.
*/
function symlinkNodeModules() {
Object.keys(requiredNodeModules).forEach(importName => {
const outputPath = path.join(tmpDir, 'node_modules', importName);
const moduleDir = requiredNodeModules[importName];
findFilesWithinDirectory(moduleDir).forEach(filePath => {
const outputFilePath = path.join(outputPath, path.relative(moduleDir, filePath));
shx.mkdir('-p', path.dirname(outputFilePath));
fs.symlinkSync(filePath, outputFilePath);
});
});
}
/**
* Copies all source files for the integration test to a temporary directory. This
* is necessary because runfiles resolve on Windows to the original source location,
* and we don't want to pollute the workspace sources. This breaks hermeticity.
*/
function copySourceFilesToTempDir() {
getSourceFilesFromRunfiles().forEach(({realPath, relativeFilePath}) => {
const tmpFilePath = path.join(tmpDir, relativeFilePath);
shx.mkdir('-p', path.dirname(tmpFilePath));
shx.cp(realPath, tmpFilePath);
});
}
/**
* Gets all source files for the integration test by querying the Bazel runfiles.
* In case there is a runfiles manifest (e.g. on Windows), the source files are resolved
* through the manifest because on these platforms the runfiles are not symlinked and
* cannot be searched within the real filesystem.
*/
function getSourceFilesFromRunfiles() {
// Path to the Bazel runfiles manifest if present. This file is present if runfiles are
// not symlinked into the runfiles directory.
const runfilesManifestPath = process.env.RUNFILES_MANIFEST_FILE;
if (!runfilesManifestPath) {
const packageRunfilesDir = path.join(process.env.RUNFILES, baseManifestPath);
return findFilesWithinDirectory(packageRunfilesDir).map(filePath => ({
realPath: filePath,
relativeFilePath: path.relative(
packageRunfilesDir, filePath)
}));
}
return fs.readFileSync(runfilesManifestPath, 'utf8')
.split('\n')
.map(mapping => mapping.split(' '))
.filter(([runfilePath]) => runfilePath.startsWith(baseManifestPath))
.map(
([runfilePath, realPath]) =>
({realPath, relativeFilePath: path.relative(baseManifestPath, runfilePath)}));
}
/**
* Resolves a NPM package from the Bazel runfiles. We need to resolve the Bazel tree
* artifacts using a "resolve file" because the NodeJS module resolution does not allow
* resolving to directory paths.
*/
function resolveNpmTreeArtifact(manifestPath, resolveFile = 'package.json') {
return path.dirname(require.resolve(path.posix.join(manifestPath, resolveFile)));
}
/** Finds all files within a specified directory. */
function findFilesWithinDirectory(directoryPath) {
return shx.find(directoryPath).filter(filePath => !fs.statSync(filePath).isDirectory());
}
@@ -1,21 +1,17 @@
{
"angularCompilerOptions": {
// For TypeScript 1.8, we have to lay out generated files
// in the same source directory with your code.
"skipTemplateCodegen": true
},
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"noImplicitAny": true,
"moduleResolution": "node",
"rootDir": "",
"declaration": true,
"lib": ["es6", "dom"],
"baseUrl": ".",
"declaration": true,
"experimentalDecorators": true,
"lib": ["es6", "dom"],
"moduleResolution": "node",
"noImplicitAny": true,
"outDir": "../node_modules/third_party",
// Prevent scanning up the directory tree for types
"typeRoots": ["node_modules/@types"]
"rootDir": "",
"target": "es5"
}
}
}
@@ -1,40 +1,34 @@
{
"angularCompilerOptions": {
// For TypeScript 1.8, we have to lay out generated files
// in the same source directory with your code.
"genDir": ".",
"alwaysCompileGeneratedCode": true,
"annotationsAs": "static fields",
"debug": true,
"enableSummariesForJit": true,
"alwaysCompileGeneratedCode": true,
"i18nFormat": "xlf"
},
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
"skipLibCheck": true,
"moduleResolution": "node",
"rootDir": "",
"declaration": true,
"lib": ["es6", "dom"],
"baseUrl": ".",
// Prevent scanning up the directory tree for types
"typeRoots": ["node_modules/@types"],
"declaration": true,
"experimentalDecorators": true,
"lib": ["es6", "dom"],
"moduleResolution": "node",
"noImplicitAny": true,
"noUnusedLocals": true,
"sourceMap": true
"rootDir": "",
"skipLibCheck": true,
"sourceMap": true,
"strictNullChecks": true,
// compatible with the option. Disabled until the integration test support the strict flag.
// TODO(devversion): this has been enabled without the integration test code being
"strictPropertyInitialization": false,
"target": "es5"
},
"files": [
"src/module",
"src/bootstrap",
"test/all_spec",
"test/test_ngtools_api",
"benchmarks/src/tree/ng2/index_aot.ts",
"benchmarks/src/tree/ng2_switch/index_aot.ts",
"benchmarks/src/largetable/ng2/index_aot.ts",
"benchmarks/src/largetable/ng2_switch/index_aot.ts"
"test/test_ngtools_api"
]
}
@@ -1,39 +0,0 @@
{
"angularCompilerOptions": {
// For TypeScript 1.8, we have to lay out generated files
// in the same source directory with your code.
"genDir": ".",
"debug": true,
"enableSummariesForJit": true,
"alwaysCompileGeneratedCode": true
},
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
"skipLibCheck": true,
"moduleResolution": "node",
"rootDir": "",
"declaration": true,
"lib": ["es6", "dom"],
"baseUrl": ".",
// Prevent scanning up the directory tree for types
"typeRoots": ["node_modules/@types"],
"noUnusedLocals": true,
"sourceMap": true
},
"files": [
"src/module",
"src/bootstrap",
"test/all_spec",
"test/test_ngtools_api",
"benchmarks/src/tree/ng2/index_aot.ts",
"benchmarks/src/tree/ng2_switch/index_aot.ts",
"benchmarks/src/largetable/ng2/index_aot.ts",
"benchmarks/src/largetable/ng2_switch/index_aot.ts"
]
}
@@ -1,34 +1,26 @@
{
"angularCompilerOptions": {
// For TypeScript 1.8, we have to lay out generated files
// in the same source directory with your code.
"genDir": ".",
"debug": true,
"enableSummariesForJit": true
},
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"noImplicitAny": true,
"moduleResolution": "node",
"outDir": "./out",
"rootDir": "",
"declaration": true,
"lib": ["es6", "dom"],
"baseUrl": ".",
// Prevent scanning up the directory tree for types
"typeRoots": ["node_modules/@types"]
"declaration": true,
"experimentalDecorators": true,
"lib": ["es6", "dom"],
"moduleResolution": "node",
"noImplicitAny": true,
"outDir": "./xi18n-out",
"rootDir": "",
"skipLibCheck": true,
"target": "es5"
},
"files": [
"src/module",
"src/bootstrap",
"test/all_spec",
"test/test_ngtools_api",
"benchmarks/src/tree/ng2/index_aot.ts",
"benchmarks/src/tree/ng2_switch/index_aot.ts",
"benchmarks/src/largetable/ng2/index_aot.ts",
"benchmarks/src/largetable/ng2_switch/index_aot.ts"
"test/test_ngtools_api"
]
}
@@ -1,19 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
module.exports = {
target: 'node',
entry: './test/all_spec.js',
output: {filename: './all_spec.js'},
resolve: {extensions: ['.js']},
devtool: '#source-map',
module: {
loaders:
[{test: /\.js$/, exclude: /node_modules/, loaders: ['source-map-loader'], enforce: 'pre'}]
},
};
@@ -8,7 +8,6 @@ ts_library(
"*.ts",
"**/*.ts",
]),
module_name = "@angular/compiler-cli/src/ngcc",
deps = [
"//packages:types",
"//packages/compiler",
+1 -1
View File
@@ -23,7 +23,7 @@ yarn bazel test //packages/compiler-cli/src/ngcc/test
## Integration Testing
There are tests that check the behaviour of the overall executable:
There are tests that check the behavior of the overall executable:
```bash
yarn bazel test //packages/compiler-cli/test/ngcc
@@ -8,7 +8,6 @@ ts_library(
"index.ts",
"src/**/*.ts",
]),
module_name = "@angular/compiler-cli/src/ngtsc/annotations",
deps = [
"//packages/compiler",
"//packages/compiler-cli/src/ngtsc/diagnostics",
@@ -8,7 +8,6 @@ ts_library(
"index.ts",
"src/**/*.ts",
]),
module_name = "@angular/compiler-cli/src/ngtsc/diagnostics",
deps = [
"//packages/compiler",
"@ngdeps//typescript",
@@ -8,6 +8,5 @@ ts_library(
"index.ts",
"src/**/*.ts",
]),
module_name = "@angular/compiler-cli/src/ngtsc/host",
deps = ["@ngdeps//typescript"],
)
@@ -8,7 +8,6 @@ ts_library(
"index.ts",
"src/*.ts",
]),
module_name = "@angular/compiler-cli/src/ngtsc/metadata",
deps = [
"//packages:types",
"//packages/compiler",
@@ -8,7 +8,6 @@ ts_library(
"index.ts",
"src/**/*.ts",
]),
module_name = "@angular/compiler-cli/src/ngtsc/shims",
deps = [
"//packages/compiler",
"//packages/compiler-cli/src/ngtsc/host",
@@ -8,7 +8,6 @@ ts_library(
"index.ts",
"src/**/*.ts",
]),
module_name = "@angular/compiler-cli/src/ngtsc/switch",
deps = [
"//packages/compiler",
"//packages/compiler-cli/src/ngtsc/host",
@@ -8,7 +8,6 @@ ts_library(
"index.ts",
"src/**/*.ts",
]),
module_name = "@angular/compiler-cli/src/ngtsc/transform",
deps = [
"//packages/compiler",
"//packages/compiler-cli/src/ngtsc/diagnostics",
@@ -5,7 +5,6 @@ load("//tools:defaults.bzl", "ts_library")
ts_library(
name = "translator",
srcs = glob(["**/*.ts"]),
module_name = "@angular/compiler-cli/src/ngtsc/translator",
deps = [
"//packages:types",
"//packages/compiler",
@@ -5,7 +5,6 @@ load("//tools:defaults.bzl", "ts_library")
ts_library(
name = "typecheck",
srcs = glob(["**/*.ts"]),
module_name = "@angular/compiler-cli/src/ngtsc/typecheck",
deps = [
"//packages:types",
"//packages/compiler",
@@ -8,7 +8,6 @@ ts_library(
"index.ts",
"src/**/*.ts",
]),
module_name = "@angular/compiler-cli/src/ngtsc/util",
deps = [
"//packages:types",
"@ngdeps//@types/node",
+1 -1
View File
@@ -10,7 +10,6 @@ ts_library(
"src/**/*.ts",
],
),
module_name = "@angular/compiler",
)
ng_package(
@@ -27,6 +26,7 @@ ng_package(
# Do not add more to this list.
# Dependencies on the full npm_package cause long re-builds.
visibility = [
"//packages/compiler-cli/integrationtest:__pkg__",
"//packages/language-service/test:__pkg__",
],
deps = [
-1
View File
@@ -10,7 +10,6 @@ ng_module(
["**/*.ts"],
exclude = ["testing.ts"],
),
module_name = "@angular/compiler/testing",
deps = [
"//packages:types",
"//packages/compiler",
+1 -1
View File
@@ -10,7 +10,6 @@ ng_module(
"src/**/*.ts",
],
),
module_name = "@angular/core",
deps = [
"//packages:types",
"@ngdeps//zone.js",
@@ -33,6 +32,7 @@ ng_package(
# Dependencies on the full npm_package cause long re-builds.
visibility = [
"//packages/bazel/test/ng_package:__pkg__",
"//packages/compiler-cli/integrationtest:__pkg__",
"//packages/compiler-cli/test:__pkg__",
"//packages/compiler-cli/test/diagnostics:__pkg__",
"//packages/compiler-cli/test/ngcc:__pkg__",
+5 -3
View File
@@ -47,9 +47,11 @@ export abstract class TemplateRef<C> {
abstract get elementRef(): ElementRef;
/**
* Creates a view object and attaches it to the view container of the parent view.
* @param context The context for the new view, inherited from the anchor element.
* @returns The new view object.
* Instantiates an embedded view based on this template,
* and attaches it to the view container.
* @param context The data-binding context of the embedded view, as declared
* in the `<ng-template>` usage.
* @returns The new embedded view object.
*/
abstract createEmbeddedView(context: C): EmbeddedViewRef<C>;
-2
View File
@@ -240,8 +240,6 @@ export interface ContentChildDecorator {
/**
* Type of the ContentChild metadata.
*
* @see `ContentChild`.
*
* @publicApi
*/
export type ContentChild = Query;
+3 -3
View File
@@ -482,8 +482,8 @@ export interface Component extends Directive {
moduleId?: string;
/**
* The URL of a template file for an Angular component. If provided,
* do not supply an inline template using `template`.
* The relative path or absolute URL of a template file for an Angular component.
* If provided, do not supply an inline template using `template`.
*
*/
templateUrl?: string;
@@ -496,7 +496,7 @@ export interface Component extends Directive {
template?: string;
/**
* One or more URLs for files containing CSS stylesheets to use
* One or more relative paths or absolute URLs for files containing CSS stylesheets to use
* in this component.
*/
styleUrls?: string[];
+1 -1
View File
@@ -1114,7 +1114,7 @@ describe('content projection', () => {
* being re-assigned from one parent to another. Proposal: have compiler
* to remove all but the latest occurrence of <ng-content> so we generate
* only one P(n, m, 0) instruction. It would make it consistent with the
* current Angular behaviour:
* current Angular behavior:
* http://plnkr.co/edit/OAYkNawTDPkYBFTqovTP?p=preview
*/
it('should project nodes into the last available ng-content', () => {
+4 -4
View File
@@ -553,13 +553,13 @@ describe('query', () => {
});
/**
* BREAKING CHANGE: this tests asserts different behaviour as compared to Renderer2 when it
* BREAKING CHANGE: this tests asserts different behavior as compared to Renderer2 when it
* comes to descendants: false option and <ng-container>.
*
* Previous behaviour: queries with descendants: false would descend into <ng-container>.
* New behaviour: queries with descendants: false would NOT descend into <ng-container>.
* Previous behavior: queries with descendants: false would descend into <ng-container>.
* New behavior: queries with descendants: false would NOT descend into <ng-container>.
*
* Reasoning: the Renderer2 behaviour is inconsistent and hard to explain to users when it
* Reasoning: the Renderer2 behavior is inconsistent and hard to explain to users when it
* comes to descendants: false interpretation (see
* https://github.com/angular/angular/issues/14769#issuecomment-356609267) so we are changing
* it in ngIvy.
-1
View File
@@ -9,7 +9,6 @@ ng_module(
srcs = glob(
["**/*.ts"],
),
module_name = "@angular/core/testing",
deps = [
"//packages:types",
"//packages/core",

Some files were not shown because too many files have changed in this diff Show More