From 745cc30139146d3bbbed0cd81d651e39380aec4a Mon Sep 17 00:00:00 2001 From: Kam Date: Mon, 24 Aug 2026 16:49:11 +0300 Subject: [PATCH] refactor(docs-infra): remove example code that nothing references The `built-in-directives` and `structural-directives` example apps are no longer referenced. Two guide rewrites moved their pages to inline code fences and dropped the last references without removing the apps: #69134 for structural directives, and #69822 for built-in directives, whose page is gone entirely. Both apps sat inside the `embeddable` glob, so they were still compiled as preview components on every build. The example e2e suites are excluded from every consumer by design: previews ignore `*.e2e-spec.ts` and `*.po.ts`, and the zip and StackBlitz pipelines both list the suffix in `EXCLUDE_FILES`. They could not run in any case, since every spec declares a `driver` and never assigns it before calling `driver.get('')`, left over from an abandoned protractor to selenium migration. The eslint configuration in the same directory is also unused. Nothing in the repository depends on eslint, and `tsconfig.eslint.json` extends a path that no longer exists. (cherry picked from commit 90fc9475f24d5839588978923ead5b6adbefbe54) --- adev/src/content/examples/.eslintrc.json | 212 ------------- .../accessibility/e2e/src/app.e2e-spec.ts | 26 -- .../e2e/src/app.e2e-spec.ts | 21 -- .../animations/e2e/src/app.e2e-spec.ts | 299 ------------------ .../examples/animations/e2e/src/auto.po.ts | 19 -- .../animations/e2e/src/enter-leave.po.ts | 19 -- .../animations/e2e/src/filter-stagger.po.ts | 19 -- .../animations/e2e/src/hero-groups.ts | 19 -- .../animations/e2e/src/open-close.po.ts | 27 -- .../animations/e2e/src/querying.po.ts | 14 - .../animations/e2e/src/status-slider.po.ts | 19 -- .../examples/animations/e2e/src/toggle.po.ts | 26 -- .../examples/animations/e2e/src/util.ts | 23 -- .../e2e/src/app.e2e-spec.ts | 37 --- .../e2e/src/app.e2e-spec.ts | 85 ----- .../built-in-directives/example-config.json | 0 .../src/app/app.component.css | 75 ----- .../src/app/app.component.html | 262 --------------- .../src/app/app.component.ts | 165 ---------- .../app/item-detail/item-detail.component.css | 0 .../item-detail/item-detail.component.html | 3 - .../app/item-detail/item-detail.component.ts | 12 - .../src/app/item-switch.component.ts | 57 ---- .../built-in-directives/src/app/item.ts | 25 -- .../built-in-directives/src/index.html | 13 - .../examples/built-in-directives/src/main.ts | 5 - .../built-in-directives/stackblitz.json | 10 - .../dynamic-form/e2e/src/app.e2e-spec.ts | 34 -- .../examples/elements/e2e/src/app.e2e-spec.ts | 97 ------ .../form-validation/e2e/src/app.e2e-spec.ts | 249 --------------- .../forms-overview/e2e/src/app.e2e-spec.ts | 15 - .../examples/forms/e2e/src/app.e2e-spec.ts | 71 ----- .../examples/i18n/e2e/src/app.e2e-spec.ts | 51 --- .../reactive-forms/e2e/src/app.e2e-spec.ts | 181 ----------- .../e2e/src/app.e2e-spec.ts | 15 - .../e2e/src/app.e2e-spec.ts | 43 --- .../e2e/src/app.e2e-spec.ts | 73 ----- .../structural-directives/example-config.json | 0 .../src/app/app.component.css | 71 ----- .../src/app/app.component.html | 187 ----------- .../src/app/app.component.ts | 30 -- .../src/app/hero-switch.components.ts | 47 --- .../src/app/hero.component.ts | 23 -- .../structural-directives/src/app/hero.ts | 13 - .../src/app/if-loaded.directive.ts | 34 -- .../src/app/loading-state.ts | 5 - .../structural-directives/src/app/scrap.txt | 20 -- .../src/app/trigonometry.directive.ts | 47 --- .../structural-directives/src/index.html | 14 - .../structural-directives/src/main.ts | 5 - .../structural-directives/stackblitz.json | 13 - .../src/content/examples/tsconfig.eslint.json | 6 - .../v21-game-world/e2e/src/app.e2e-spec.ts | 204 ------------ 53 files changed, 3040 deletions(-) delete mode 100644 adev/src/content/examples/.eslintrc.json delete mode 100644 adev/src/content/examples/accessibility/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/angular-compiler-options/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/auto.po.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/enter-leave.po.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/filter-stagger.po.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/hero-groups.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/open-close.po.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/querying.po.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/status-slider.po.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/toggle.po.ts delete mode 100644 adev/src/content/examples/animations/e2e/src/util.ts delete mode 100644 adev/src/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/built-in-directives/example-config.json delete mode 100644 adev/src/content/examples/built-in-directives/src/app/app.component.css delete mode 100644 adev/src/content/examples/built-in-directives/src/app/app.component.html delete mode 100644 adev/src/content/examples/built-in-directives/src/app/app.component.ts delete mode 100644 adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.css delete mode 100644 adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.html delete mode 100644 adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts delete mode 100644 adev/src/content/examples/built-in-directives/src/app/item-switch.component.ts delete mode 100644 adev/src/content/examples/built-in-directives/src/app/item.ts delete mode 100644 adev/src/content/examples/built-in-directives/src/index.html delete mode 100644 adev/src/content/examples/built-in-directives/src/main.ts delete mode 100644 adev/src/content/examples/built-in-directives/stackblitz.json delete mode 100644 adev/src/content/examples/dynamic-form/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/elements/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/form-validation/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/forms-overview/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/forms/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/i18n/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/routing-with-urlmatcher/e2e/src/app.e2e-spec.ts delete mode 100755 adev/src/content/examples/service-worker-getting-started/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/structural-directives/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/structural-directives/example-config.json delete mode 100644 adev/src/content/examples/structural-directives/src/app/app.component.css delete mode 100644 adev/src/content/examples/structural-directives/src/app/app.component.html delete mode 100644 adev/src/content/examples/structural-directives/src/app/app.component.ts delete mode 100644 adev/src/content/examples/structural-directives/src/app/hero-switch.components.ts delete mode 100644 adev/src/content/examples/structural-directives/src/app/hero.component.ts delete mode 100644 adev/src/content/examples/structural-directives/src/app/hero.ts delete mode 100644 adev/src/content/examples/structural-directives/src/app/if-loaded.directive.ts delete mode 100644 adev/src/content/examples/structural-directives/src/app/loading-state.ts delete mode 100644 adev/src/content/examples/structural-directives/src/app/scrap.txt delete mode 100644 adev/src/content/examples/structural-directives/src/app/trigonometry.directive.ts delete mode 100644 adev/src/content/examples/structural-directives/src/index.html delete mode 100644 adev/src/content/examples/structural-directives/src/main.ts delete mode 100644 adev/src/content/examples/structural-directives/stackblitz.json delete mode 100644 adev/src/content/examples/tsconfig.eslint.json delete mode 100644 adev/src/content/examples/v21-game-world/e2e/src/app.e2e-spec.ts diff --git a/adev/src/content/examples/.eslintrc.json b/adev/src/content/examples/.eslintrc.json deleted file mode 100644 index 3a94305ee73..00000000000 --- a/adev/src/content/examples/.eslintrc.json +++ /dev/null @@ -1,212 +0,0 @@ -{ - "root": true, - "ignorePatterns": ["*.js", "styleguide/**/*.avoid.ts"], - "overrides": [ - { - "files": ["*.html"], - "extends": ["plugin:@angular-eslint/template/recommended"], - "rules": { - "@angular-eslint/template/alt-text": "error", - "@angular-eslint/template/elements-content": "error", - "@angular-eslint/template/label-has-associated-control": "error", - "@angular-eslint/template/table-scope": "error", - "@angular-eslint/template/valid-aria": "error", - "@angular-eslint/template/click-events-have-key-events": "error", - "@angular-eslint/template/eqeqeq": "off", - "@angular-eslint/template/mouse-events-have-key-events": "error", - "@angular-eslint/template/no-autofocus": "error", - "@angular-eslint/template/no-distracting-elements": "error", - "@angular-eslint/template/no-positive-tabindex": "error" - } - }, - { - "files": ["*.ts"], - "extends": [ - "plugin:@angular-eslint/template/process-inline-templates" - ], - "parserOptions": { - "createDefaultProgram": false, - "project": "content/examples/tsconfig.eslint.json" - }, - "plugins": [ - "@typescript-eslint", - "@angular-eslint", "eslint-plugin-import", "eslint-plugin-jsdoc", "eslint-plugin-prefer-arrow"], - "rules": { - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/explicit-member-accessibility": "off", - "sort-keys": "off", - "@angular-eslint/component-class-suffix": "error", - - "@angular-eslint/contextual-lifecycle": "error", - "@angular-eslint/directive-class-suffix": "error", - - "@angular-eslint/no-conflicting-lifecycle": "error", - "@angular-eslint/no-host-metadata-property": "error", - "@angular-eslint/no-input-rename": "error", - "@angular-eslint/no-inputs-metadata-property": "error", - "@angular-eslint/no-output-native": "error", - "@angular-eslint/no-output-on-prefix": "error", - "@angular-eslint/no-output-rename": "error", - "@angular-eslint/no-outputs-metadata-property": "error", - "@angular-eslint/use-lifecycle-interface": "error", - "@angular-eslint/use-pipe-transform-interface": "error", - "@typescript-eslint/adjacent-overload-signatures": "error", - "@typescript-eslint/array-type": "off", - - "@typescript-eslint/consistent-type-assertions": "error", - "@typescript-eslint/no-empty-function": "off", - "@typescript-eslint/no-empty-interface": "error", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-inferrable-types": [ - "error", - { - "ignoreParameters": true - } - ], - "@typescript-eslint/no-misused-new": "error", - "@typescript-eslint/no-namespace": "error", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/prefer-for-of": "error", - "@typescript-eslint/prefer-function-type": "error", - "@typescript-eslint/prefer-namespace-keyword": "error", - "@typescript-eslint/triple-slash-reference": [ - "error", - { - "path": "always", - "types": "prefer-import", - "lib": "always" - } - ], - "@typescript-eslint/unified-signatures": "error", - "complexity": "off", - "constructor-super": "error", - "eqeqeq": ["error", "smart"], - "guard-for-in": "error", - "id-blacklist": [ - "error", - "any", - "Number", - "number", - "String", - "string", - "Boolean", - "boolean", - "Undefined", - "undefined" - ], - "id-match": "error", - "import/no-deprecated": "warn", - "jsdoc/no-types": "error", - "max-classes-per-file": "off", - "no-bitwise": "error", - "no-caller": "error", - "no-cond-assign": "error", - - "no-debugger": "error", - "no-empty": "off", - "no-eval": "error", - "no-fallthrough": "error", - "no-invalid-this": "off", - "no-new-wrappers": "error", - "no-restricted-imports": [ - "error", - { - "name": "rxjs/Rx", - "message": "Please import directly from 'rxjs' instead" - } - ], - "no-throw-literal": "error", - "no-undef-init": "error", - "no-unsafe-finally": "error", - "no-unused-labels": "error", - "no-var": "error", - "object-shorthand": "error", - "one-var": ["error", "never"], - "prefer-const": "error", - "radix": "error", - "use-isnan": "error", - "valid-typeof": "off", - "arrow-body-style": "error", - "arrow-parens": "off", - "comma-dangle": "off", - "curly": "error", - "eol-last": "error", - "jsdoc/check-alignment": "error", - "new-parens": "error", - "no-multiple-empty-lines": "off", - "no-trailing-spaces": "error", - "quote-props": ["error", "as-needed"], - "space-before-function-paren": [ - "error", - { - "anonymous": "never", - "asyncArrow": "always", - "named": "never" - } - ], - "@typescript-eslint/semi": ["error", "always"], - "@typescript-eslint/type-annotation-spacing": "error", - - "@typescript-eslint/ban-types": "error", - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "", // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). - "style": "kebab-case" - } - ], - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": ["app", "toh"], - "style": "camelCase" - } - ], - "dot-notation": "off", - "@typescript-eslint/dot-notation": ["error", {"allowIndexSignaturePropertyAccess": true}], - "indent": "off", - "max-len": ["error", {"code": 120, "ignoreUrls": true}], - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "singleline": { - "delimiter": "comma", - "requireLast": false - } - } - ], - "@typescript-eslint/member-ordering": "off", - "@typescript-eslint/naming-convention": "off", - "no-console": ["error", {"allow": ["log", "warn", "error"]}], - "no-empty-function": "off", - "@typescript-eslint/no-non-null-assertion": "off", // TODO: Fix the code violating this rule and enable it. - "no-restricted-syntax": [ - "error", - { - "selector": "CallExpression[callee.name=/^(fdescribe|fit)$/]", - "message": "Don't keep jasmine focus methods." - } - ], - "no-shadow": "off", - "@typescript-eslint/no-shadow": "error", - "no-tabs": "error", - "no-underscore-dangle": "off", - "no-unused-expressions": "off", - "@typescript-eslint/no-unused-expressions": "error", - "no-use-before-define": "off", - "prefer-arrow/prefer-arrow-functions": "off", - "quotes": "off", - "@typescript-eslint/quotes": [ - "error", - "single", - {"avoidEscape": true, "allowTemplateLiterals": true} - ], - "semi": "error" - } - } - ] -} diff --git a/adev/src/content/examples/accessibility/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/accessibility/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 2b66e003610..00000000000 --- a/adev/src/content/examples/accessibility/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Accessibility example e2e tests', () => { - let driver: webdriver.WebDriver; - - beforeEach(async () => { - await driver.get(''); - }); - - it('should display Accessibility Example', async () => { - expect(await driver.findElement(webdriver.By.css('h1')).getText()).toEqual( - 'Accessibility Example', - ); - }); - - it('should take a number and change progressbar width', async () => { - const input = driver.findElement(webdriver.By.css('input')); - await input.sendKeys('16'); - expect(await input.getAttribute('value')).toEqual('16'); - expect( - await driver - .findElement(webdriver.By.css('app-example-progressbar div')) - .getCssValue('width'), - ).toBe('48px'); - }); -}); diff --git a/adev/src/content/examples/angular-compiler-options/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/angular-compiler-options/e2e/src/app.e2e-spec.ts deleted file mode 100644 index b9f8cc9fa75..00000000000 --- a/adev/src/content/examples/angular-compiler-options/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('workspace-project App', () => { - let driver: webdriver.WebDriver; - - beforeEach(async () => { - await driver.get(''); - }); - - // Add your e2e tests here - - afterEach(async () => { - // Assert that there are no errors emitted from the browser - const logs = await driver.manage().logs().get(webdriver.logging.Type.BROWSER); - expect(logs).not.toContain( - jasmine.objectContaining({ - level: webdriver.logging.Level.SEVERE, - } as webdriver.logging.Entry), - ); - }); -}); diff --git a/adev/src/content/examples/animations/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/animations/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 9182cceb269..00000000000 --- a/adev/src/content/examples/animations/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,299 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; -import * as openClose from './open-close.po'; -import * as statusSlider from './status-slider.po'; -import * as toggle from './toggle.po'; -import * as enterLeave from './enter-leave.po'; -import * as auto from './auto.po'; -import * as filterStagger from './filter-stagger.po'; -import * as heroGroups from './hero-groups'; -import {getLinkById, sleepFor} from './util'; -import {getComponentSection, getToggleButton} from './querying.po'; - -describe('Animation Tests', () => { - let driver: webdriver.WebDriver; - const routingAnimationDuration = 350; - - const newPageSleepFor = (ms = 0) => sleepFor(ms + routingAnimationDuration); - - beforeAll(async () => { - await driver.get(''); - }); - - describe('Open/Close Component', () => { - const closedHeight = '100px'; - const openHeight = '200px'; - - beforeAll(async () => { - await (await getLinkById(driver, 'open-close')).click(); - await newPageSleepFor(300); - }); - - it('should be open', async () => { - const toggleButton = await openClose.getToggleButton(driver); - const container = await openClose.getComponentContainer(driver); - let text = await container.getText(); - - if (text.includes('Closed')) { - await toggleButton.click(); - await driver.wait(async () => (await container.getCssValue('height')) === openHeight, 2000); - } - - text = await container.getText(); - const containerHeight = await container.getCssValue('height'); - - expect(text).toContain('The box is now Open!'); - expect(containerHeight).toBe(openHeight); - }); - - it('should be closed', async () => { - const toggleButton = await openClose.getToggleButton(driver); - const container = await openClose.getComponentContainer(driver); - let text = await container.getText(); - - if (text.includes('Open')) { - await toggleButton.click(); - await driver.wait( - async () => (await container.getCssValue('height')) === closedHeight, - 2000, - ); - } - - text = await container.getText(); - const containerHeight = await container.getCssValue('height'); - - expect(text).toContain('The box is now Closed!'); - expect(containerHeight).toBe(closedHeight); - }); - - it('should log animation events', async () => { - const toggleButton = await openClose.getToggleButton(driver); - const loggingCheckbox = await openClose.getLoggingCheckbox(driver); - await loggingCheckbox.click(); - await toggleButton.click(); - - const logs = await driver.manage().logs().get(webdriver.logging.Type.BROWSER); - const animationMessages = logs.filter(({message}) => message.includes('Animation')); - - expect(animationMessages.length).toBeGreaterThan(0); - }); - }); - - describe('Status Slider Component', () => { - const activeColor = 'rgba(117, 70, 0, 1)'; - const inactiveColor = 'rgba(0, 0, 255, 1)'; - - beforeAll(async () => { - await (await getLinkById(driver, 'status')).click(); - await newPageSleepFor(2000); - }); - - it('should be inactive with a blue background', async () => { - const toggleButton = await statusSlider.getToggleButton(driver); - const container = await statusSlider.getComponentContainer(driver); - let text = await container.getText(); - - if (text === 'Active') { - await toggleButton.click(); - await driver.wait( - async () => (await container.getCssValue('backgroundColor')) === inactiveColor, - 3000, - ); - } - - text = await container.getText(); - const bgColor = await container.getCssValue('backgroundColor'); - - expect(text).toBe('Inactive'); - expect(bgColor).toBe(inactiveColor); - }); - - it('should be active with an orange background', async () => { - const toggleButton = await statusSlider.getToggleButton(driver); - const container = await statusSlider.getComponentContainer(driver); - let text = await container.getText(); - - if (text === 'Inactive') { - await toggleButton.click(); - await driver.wait( - async () => (await container.getCssValue('backgroundColor')) === activeColor, - 3000, - ); - } - - text = await container.getText(); - const bgColor = await container.getCssValue('backgroundColor'); - - expect(text).toBe('Active'); - expect(bgColor).toBe(activeColor); - }); - }); - - describe('Toggle Animations Component', () => { - beforeAll(async () => { - await (await getLinkById(driver, 'toggle')).click(); - await newPageSleepFor(); - }); - - it('should disabled animations on the child element', async () => { - const toggleButton = await toggle.getToggleAnimationsButton(driver); - - await toggleButton.click(); - - const container = await toggle.getComponentContainer(driver); - const cssClasses = await container.getAttribute('class'); - - expect(cssClasses).toContain('ng-animate-disabled'); - }); - }); - - describe('Enter/Leave Component', () => { - beforeAll(async () => { - await (await getLinkById(driver, 'enter-leave')).click(); - await newPageSleepFor(100); - }); - - it('should attach a flyInOut trigger to the list of items', async () => { - const heroesList = await enterLeave.getHeroesList(driver); - const hero = heroesList[0]; - const cssClasses = await hero.getAttribute('class'); - const transform = await hero.getCssValue('transform'); - - expect(cssClasses).toContain('ng-trigger-flyInOut'); - expect(transform).toBe('matrix(1, 0, 0, 1, 0, 0)'); - }); - - it('should remove the hero from the list when clicked', async () => { - const heroesList = await enterLeave.getHeroesList(driver); - const total = heroesList.length; - const hero = heroesList[0]; - - await hero.click(); - await driver.wait(async () => (await enterLeave.getHeroesList(driver)).length < total, 2000); - }); - }); - - describe('Auto Calculation Component', () => { - beforeAll(async () => { - await (await getLinkById(driver, 'auto')).click(); - await newPageSleepFor(); - }); - - it('should attach a shrinkOut trigger to the list of items', async () => { - const heroesList = await auto.getHeroesList(driver); - const hero = heroesList[0]; - const cssClasses = await hero.getAttribute('class'); - - expect(cssClasses).toContain('ng-trigger-shrinkOut'); - }); - - it('should remove the hero from the list when clicked', async () => { - const heroesList = await auto.getHeroesList(driver); - const total = heroesList.length; - const hero = heroesList[0]; - - await hero.click(); - await driver.wait(async () => (await auto.getHeroesList(driver)).length < total, 2000); - }); - }); - - describe('Filter/Stagger Component', () => { - beforeAll(async () => { - await (await getLinkById(driver, 'heroes')).click(); - await newPageSleepFor(); - }); - - it('should attach a filterAnimations trigger to the list container', async () => { - const heroesList = await filterStagger.getComponentContainer(driver); - const cssClasses = await heroesList.getAttribute('class'); - - expect(cssClasses).toContain('ng-trigger-filterAnimation'); - }); - - it('should filter down the list when a search is performed', async () => { - const heroesList = await filterStagger.getHeroesList(driver); - const total = heroesList.length; - - const input = await filterStagger.getInput(driver); - await input.sendKeys('Mag'); - - await driver.wait(async () => (await filterStagger.getHeroesList(driver)).length === 2, 2000); - - const newTotal = (await filterStagger.getHeroesList(driver)).length; - expect(newTotal).toBeLessThan(total); - }); - }); - - describe('Hero Groups Component', () => { - beforeAll(async () => { - await (await getLinkById(driver, 'hero-groups')).click(); - await newPageSleepFor(400); - }); - - it('should attach a flyInOut trigger to the list of items', async () => { - const heroesList = await heroGroups.getHeroesList(driver); - const hero = heroesList[0]; - const cssClasses = await hero.getAttribute('class'); - const transform = await hero.getCssValue('transform'); - const opacity = await hero.getCssValue('opacity'); - - expect(cssClasses).toContain('ng-trigger-flyInOut'); - expect(transform).toBe('matrix(1, 0, 0, 1, 0, 0)'); - expect(opacity).toBe('1'); - }); - - it('should remove the hero from the list when clicked', async () => { - const heroesList = await heroGroups.getHeroesList(driver); - const total = heroesList.length; - const hero = heroesList[0]; - - await hero.click(); - await driver.wait(async () => (await heroGroups.getHeroesList(driver)).length < total, 2000); - }); - }); - - describe('Querying Component', () => { - const queryingAnimationDuration = 2500; - - beforeAll(async () => { - await (await getLinkById(driver, 'querying')).click(); - await newPageSleepFor(queryingAnimationDuration); - }); - - it('should toggle the section', async () => { - const toggleButton = await getToggleButton(driver); - const section = await getComponentSection(driver); - - expect(await section.isDisplayed()).toBe(true); - - // toggling off - await toggleButton.click(); - await newPageSleepFor(queryingAnimationDuration); - const sectionsOff = await driver.findElements(webdriver.By.css('app-querying section')); - expect(sectionsOff.length).toBe(0); - - // toggling on - await toggleButton.click(); - await newPageSleepFor(queryingAnimationDuration); - const sectionsOn = await driver.findElements(webdriver.By.css('app-querying section')); - expect(sectionsOn.length).toBe(1); - await newPageSleepFor(queryingAnimationDuration); - }); - - it(`should disable the button for the animation's duration`, async () => { - const toggleButton = await getToggleButton(driver); - expect(await toggleButton.isEnabled()).toBe(true); - - // toggling off - await toggleButton.click(); - expect(await toggleButton.isEnabled()).toBe(false); - await newPageSleepFor(queryingAnimationDuration); - expect(await toggleButton.isEnabled()).toBe(true); - - // toggling on - await toggleButton.click(); - expect(await toggleButton.isEnabled()).toBe(false); - await newPageSleepFor(queryingAnimationDuration); - expect(await toggleButton.isEnabled()).toBe(true); - }); - }); -}); diff --git a/adev/src/content/examples/animations/e2e/src/auto.po.ts b/adev/src/content/examples/animations/e2e/src/auto.po.ts deleted file mode 100644 index 427321bff16..00000000000 --- a/adev/src/content/examples/animations/e2e/src/auto.po.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; -import {locate} from './util'; - -export function getPage(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-hero-list-auto-page')); -} - -export function getComponent(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-hero-list-auto')); -} - -export async function getComponentContainer(driver: webdriver.WebDriver) { - return locate(driver, webdriver.By.css('app-hero-list-auto'), webdriver.By.css('ul')); -} - -export async function getHeroesList(driver: webdriver.WebDriver) { - const container = await getComponentContainer(driver); - return container.findElements(webdriver.By.css('li')); -} diff --git a/adev/src/content/examples/animations/e2e/src/enter-leave.po.ts b/adev/src/content/examples/animations/e2e/src/enter-leave.po.ts deleted file mode 100644 index ce5b176f65c..00000000000 --- a/adev/src/content/examples/animations/e2e/src/enter-leave.po.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; -import {locate} from './util'; - -export function getPage(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-hero-list-enter-leave-page')); -} - -export function getComponent(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-hero-list-enter-leave')); -} - -export async function getComponentContainer(driver: webdriver.WebDriver) { - return locate(driver, webdriver.By.css('app-hero-list-enter-leave'), webdriver.By.css('ul')); -} - -export async function getHeroesList(driver: webdriver.WebDriver) { - const container = await getComponentContainer(driver); - return container.findElements(webdriver.By.css('li')); -} diff --git a/adev/src/content/examples/animations/e2e/src/filter-stagger.po.ts b/adev/src/content/examples/animations/e2e/src/filter-stagger.po.ts deleted file mode 100644 index 1f44e3d7384..00000000000 --- a/adev/src/content/examples/animations/e2e/src/filter-stagger.po.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; -import {locate} from './util'; - -export function getPage(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-hero-list-page')); -} - -export async function getComponentContainer(driver: webdriver.WebDriver) { - return locate(driver, webdriver.By.css('app-hero-list-page'), webdriver.By.css('ul')); -} - -export async function getHeroesList(driver: webdriver.WebDriver) { - const container = await getComponentContainer(driver); - return container.findElements(webdriver.By.css('li')); -} - -export async function getInput(driver: webdriver.WebDriver) { - return locate(driver, webdriver.By.css('app-hero-list-page'), webdriver.By.css('input')); -} diff --git a/adev/src/content/examples/animations/e2e/src/hero-groups.ts b/adev/src/content/examples/animations/e2e/src/hero-groups.ts deleted file mode 100644 index 227a95dc544..00000000000 --- a/adev/src/content/examples/animations/e2e/src/hero-groups.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; -import {locate} from './util'; - -export function getPage(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-hero-list-groups-page')); -} - -export function getComponent(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-hero-list-groups')); -} - -export async function getComponentContainer(driver: webdriver.WebDriver) { - return locate(driver, webdriver.By.css('app-hero-list-groups'), webdriver.By.css('ul')); -} - -export async function getHeroesList(driver: webdriver.WebDriver) { - const container = await getComponentContainer(driver); - return container.findElements(webdriver.By.css('li')); -} diff --git a/adev/src/content/examples/animations/e2e/src/open-close.po.ts b/adev/src/content/examples/animations/e2e/src/open-close.po.ts deleted file mode 100644 index 292db95d9ed..00000000000 --- a/adev/src/content/examples/animations/e2e/src/open-close.po.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; -import {locate} from './util'; - -export function getPage(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-open-close-page')); -} - -export function getComponent(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-open-close')); -} - -export async function getToggleButton(driver: webdriver.WebDriver) { - const comp = await getComponent(driver); - return comp.findElement(webdriver.By.xpath('.//button[normalize-space()="Toggle Open/Close"]')); -} - -export async function getLoggingCheckbox(driver: webdriver.WebDriver) { - return locate( - driver, - webdriver.By.css('app-open-close-page'), - webdriver.By.css('section > input[type="checkbox"]'), - ); -} - -export async function getComponentContainer(driver: webdriver.WebDriver) { - return locate(driver, webdriver.By.css('app-open-close'), webdriver.By.css('div')); -} diff --git a/adev/src/content/examples/animations/e2e/src/querying.po.ts b/adev/src/content/examples/animations/e2e/src/querying.po.ts deleted file mode 100644 index aa83ee5565b..00000000000 --- a/adev/src/content/examples/animations/e2e/src/querying.po.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; -import {locate} from './util'; - -export function getComponent(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-querying')); -} - -export async function getToggleButton(driver: webdriver.WebDriver) { - return locate(driver, webdriver.By.css('app-querying'), webdriver.By.className('toggle')); -} - -export async function getComponentSection(driver: webdriver.WebDriver) { - return locate(driver, webdriver.By.css('app-querying'), webdriver.By.css('section')); -} diff --git a/adev/src/content/examples/animations/e2e/src/status-slider.po.ts b/adev/src/content/examples/animations/e2e/src/status-slider.po.ts deleted file mode 100644 index a498689e131..00000000000 --- a/adev/src/content/examples/animations/e2e/src/status-slider.po.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; -import {locate} from './util'; - -export function getPage(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-status-slider-page')); -} - -export function getComponent(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-status-slider')); -} - -export async function getToggleButton(driver: webdriver.WebDriver) { - const comp = await getComponent(driver); - return comp.findElement(webdriver.By.xpath('.//button[normalize-space()="Toggle Status"]')); -} - -export async function getComponentContainer(driver: webdriver.WebDriver) { - return locate(driver, webdriver.By.css('app-status-slider'), webdriver.By.css('div')); -} diff --git a/adev/src/content/examples/animations/e2e/src/toggle.po.ts b/adev/src/content/examples/animations/e2e/src/toggle.po.ts deleted file mode 100644 index 454782e59ba..00000000000 --- a/adev/src/content/examples/animations/e2e/src/toggle.po.ts +++ /dev/null @@ -1,26 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; -import {locate} from './util'; - -export function getPage(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-toggle-animations-child-page')); -} - -export function getComponent(driver: webdriver.WebDriver) { - return driver.findElement(webdriver.By.css('app-open-close-toggle')); -} - -export async function getToggleButton(driver: webdriver.WebDriver) { - const comp = await getComponent(driver); - return comp.findElement(webdriver.By.xpath('.//button[normalize-space()="Toggle Open/Closed"]')); -} - -export async function getToggleAnimationsButton(driver: webdriver.WebDriver) { - const comp = await getComponent(driver); - return comp.findElement(webdriver.By.xpath('.//button[normalize-space()="Toggle Animations"]')); -} - -export async function getComponentContainer(driver: webdriver.WebDriver) { - const comp = await getComponent(driver); - const divs = await comp.findElements(webdriver.By.css('div')); - return divs[0]; -} diff --git a/adev/src/content/examples/animations/e2e/src/util.ts b/adev/src/content/examples/animations/e2e/src/util.ts deleted file mode 100644 index c10f9553b00..00000000000 --- a/adev/src/content/examples/animations/e2e/src/util.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -/** - * locate(parent, finder1, finder2) => parent.findElement(finder1).findElement(finder2); - */ -export async function locate( - parent: webdriver.WebDriver | webdriver.WebElement, - ...locators: webdriver.Locator[] -): Promise { - let current: webdriver.WebElement = await parent.findElement(locators[0]); - for (let i = 1; i < locators.length; i++) { - current = await current.findElement(locators[i]); - } - return current; -} - -export async function sleepFor(time = 1000) { - return new Promise((resolve) => setTimeout(resolve, time)); -} - -export function getLinkById(driver: webdriver.WebDriver, id: string) { - return driver.findElement(webdriver.By.css(`a[id=${id}]`)); -} diff --git a/adev/src/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 97da4f1e5c8..00000000000 --- a/adev/src/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Attribute directives', () => { - let driver: webdriver.WebDriver; - const title = 'My First Attribute Directive'; - - beforeAll(async () => { - await driver.get(''); - }); - - it(`should display correct title: ${title}`, async () => { - expect(await driver.findElement(webdriver.By.css('h1')).getText()).toEqual(title); - }); - - it('should be able to select green highlight', async () => { - const paragraphs = await driver.findElements(webdriver.By.css('p')); - let highlightedEle: webdriver.WebElement | null = null; - for (const p of paragraphs) { - if ((await p.getText()).includes('Highlight me!')) { - highlightedEle = p; - break; - } - } - const lightGreen = 'rgba(144, 238, 144, 1)'; - const getBgColor = () => highlightedEle!.getCssValue('background-color'); - - expect(await getBgColor()).not.toEqual(lightGreen); - - const greenRb = (await driver.findElements(webdriver.By.css('input')))[0]; - await greenRb.click(); - await driver.actions().move({origin: highlightedEle!}).perform(); - - // Wait for up to 4s for the background color to be updated, - // to account for slow environments (e.g. CI). - await driver.wait(async () => (await getBgColor()) === lightGreen, 4000); - }); -}); diff --git a/adev/src/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts deleted file mode 100644 index a99075a0fd9..00000000000 --- a/adev/src/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,85 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Built-in Directives', () => { - let driver: webdriver.WebDriver; - - beforeAll(async () => { - await driver.get(''); - }); - - it('should have title Built-in Directives', async () => { - const title = (await driver.findElements(webdriver.By.css('h1')))[0]; - expect(await title.getText()).toEqual('Built-in Directives'); - }); - - it('should change first Teapot header', async () => { - const firstLabel = (await driver.findElements(webdriver.By.css('p')))[0]; - const firstInput = (await driver.findElements(webdriver.By.css('input')))[0]; - - expect(await firstLabel.getText()).toEqual('Current item name: Teapot'); - await firstInput.sendKeys('abc'); - expect(await firstLabel.getText()).toEqual('Current item name: Teapotabc'); - }); - - it('should modify sentence when modified checkbox checked', async () => { - const modifiedChkbxLabel = ( - await driver.findElements(webdriver.By.css('input[type="checkbox"]')) - )[1]; - const modifiedSentence = (await driver.findElements(webdriver.By.css('div')))[1]; - - await modifiedChkbxLabel.click(); - expect(await modifiedSentence.getText()).toContain('modified'); - }); - - it('should modify sentence when normal checkbox checked', async () => { - const normalChkbxLabel = ( - await driver.findElements(webdriver.By.css('input[type="checkbox"]')) - )[4]; - const normalSentence = (await driver.findElements(webdriver.By.css('div')))[7]; - - await normalChkbxLabel.click(); - expect(await normalSentence.getText()).toContain('normal weight and, extra large'); - }); - - it('should toggle app-item-detail', async () => { - const toggleButton = (await driver.findElements(webdriver.By.css('button')))[3]; - const toggledDiv = (await driver.findElements(webdriver.By.css('app-item-detail')))[0]; - - await toggleButton.click(); - expect(await toggledDiv.isDisplayed()).toBe(true); - }); - - it('should hide app-item-detail', async () => { - const hiddenMessage = (await driver.findElements(webdriver.By.css('p')))[10]; - const hiddenDiv = (await driver.findElements(webdriver.By.css('app-item-detail')))[2]; - - expect(await hiddenMessage.getText()).toContain('in the DOM'); - expect(await hiddenDiv.isDisplayed()).toBe(true); - }); - - it('should have 10 lists each containing the string Teapot', async () => { - const boxes = await driver.findElements(webdriver.By.css('.box')); - const teapotBoxes: webdriver.WebElement[] = []; - for (const b of boxes) { - if ((await b.getText()).includes('Teapot')) { - teapotBoxes.push(b); - } - } - expect(teapotBoxes.length).toBe(10); - }); - - it('should switch case', async () => { - const tvRadioButton = (await driver.findElements(webdriver.By.css('input[type="radio"]')))[3]; - const tvDiv = driver.findElement(webdriver.By.css('app-lost-item')); - - const fishbowlRadioButton = ( - await driver.findElements(webdriver.By.css('input[type="radio"]')) - )[4]; - const fishbowlDiv = driver.findElement(webdriver.By.css('app-unknown-item')); - - await tvRadioButton.click(); - expect(await tvDiv.getText()).toContain('Television'); - await fishbowlRadioButton.click(); - expect(await fishbowlDiv.getText()).toContain('mysterious'); - }); -}); diff --git a/adev/src/content/examples/built-in-directives/example-config.json b/adev/src/content/examples/built-in-directives/example-config.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/built-in-directives/src/app/app.component.css b/adev/src/content/examples/built-in-directives/src/app/app.component.css deleted file mode 100644 index 52cccf1628a..00000000000 --- a/adev/src/content/examples/built-in-directives/src/app/app.component.css +++ /dev/null @@ -1,75 +0,0 @@ - -button { - font-size: 100%; - margin: 0 2px; -} - -div[ng-reflect-ng-switch], app-unknown-item { - margin: .5rem 0; - display: block; -} - -#noTrackByCnt, -#withTrackByCnt { - color: darkred; - max-width: 450px; - margin: 4px; -} - -img { - height: 100px; -} - -.box { - border: 1px solid black; - padding: 6px; - max-width: 450px; -} - -.child-div { - margin-left: 1em; - font-weight: normal; -} - -.context { - margin-left: 1em; -} - -.hidden { - display: none; -} - -.parent-div { - margin-top: 1em; - font-weight: bold; -} - -.course { - font-weight: bold; - font-size: x-large; -} - -.helpful { - color: red; -} - -.saveable { - color: limegreen; -} - -.study, -.modified { - font-family: "Brush Script MT", cursive; - font-size: 2rem; -} - -.toe { - margin-left: 1em; - font-style: italic; -} - - -.to-toc { - margin-top: 10px; - display: block; -} diff --git a/adev/src/content/examples/built-in-directives/src/app/app.component.html b/adev/src/content/examples/built-in-directives/src/app/app.component.html deleted file mode 100644 index 093f105c9a5..00000000000 --- a/adev/src/content/examples/built-in-directives/src/app/app.component.html +++ /dev/null @@ -1,262 +0,0 @@ -

Built-in Directives

- -

Built-in attribute directives

- -

NgModel (two-way) Binding

- -
-

NgModel examples

-

Current item name: {{ currentItem.name }}

-

- - -

- -

- - - - -

- -

- - -

- -

- -

-
- -
-

NgClass Binding

- -

currentClasses is {{ currentClasses | json }}

- -
This div is initially saveable, unchanged, and special.
- - - - -
- This div should be {{ canSave ? '' : 'not' }} saveable, - {{ isUnchanged ? 'unchanged' : 'modified' }} and {{ isSpecial ? '' : 'not' }} special after - clicking "Refresh". -
-

- - -
This div is special
- -
Helpful study course
-
Study course
- - -
-

NgStyle Binding

-
This div is x-large or smaller.
- -

[ngStyle] binding to currentStyles - CSS property names

-

currentStyles is {{ currentStyles | json }}

- - -
- This div is initially italic, normal weight, and extra large (24px). -
- - -
- | - -| - - -

-
- This div should be {{ canSave ? 'italic' : 'plain' }}, - {{ isUnchanged ? 'normal weight' : 'bold' }} and, - {{ isSpecial ? 'extra large' : 'normal size' }} after clicking "Refresh". -
- -
-

Built-in structural directives

-

NgIf Binding

-
-

If isActive is true, app-item-detail will render:

- - - - - -
-

If currentCustomer isn't null, say hello to Laura:

- -
Hello, {{ currentCustomer.name }}
- -

nullCustomer is null by default. NgIf guards against null. Give it a value to show it:

- -
- Hello, {{ nullCustomer }} -
- - - -

NgIf binding with template (no *)

- -Add {{ currentItem.name }} with template -
- -

Show/hide vs. NgIf

- -
Show with class
-
Hide with class
- -

ItemDetail is in the DOM but hidden

- - -
Show with style
-
Hide with style
- -
-

NgFor Binding

- -
- -
{{ item.name }}
- -
- -

*ngFor with ItemDetailComponent element

-
- - - -
- -

*ngFor with index

-

with semi-colon separator

-
- -
{{ i + 1 }} - {{ item.name }}
- -
- -

with comma separator

-
-
{{ i + 1 }} - {{ item.name }}
-
- -

*ngFor trackBy

- - - - -

without trackBy

-
-
({{ item.id }}) {{ item.name }}
- -
- Item DOM elements change #{{ itemsNoTrackByCount }} without trackBy -
-
- -

with trackBy

-
-
- ({{ item.id }}) {{ item.name }} -
- -
- Item DOM elements change #{{ itemsWithTrackByCount }} with trackBy -
-
- -


- -

with trackBy and semi-colon separator

-
- -
({{ item.id }}) {{ item.name }}
- -
- -

with trackBy and comma separator

-
-
({{ item.id }}) {{ item.name }}
-
- -

with trackBy and space separator

-
-
({{ item.id }}) {{ item.name }}
-
- -

with generic trackById function

-
-
({{ item.id }}) {{ item.name }}
-
- -
-

NgSwitch Binding

- -

Pick your favorite item

-
- -
- - -
- - - - - - -
Are you as bright as {{ currentItem.name }}?
- - - -
- diff --git a/adev/src/content/examples/built-in-directives/src/app/app.component.ts b/adev/src/content/examples/built-in-directives/src/app/app.component.ts deleted file mode 100644 index c4ef56275f3..00000000000 --- a/adev/src/content/examples/built-in-directives/src/app/app.component.ts +++ /dev/null @@ -1,165 +0,0 @@ -import {Component, OnInit} from '@angular/core'; -import {JsonPipe, NgClass, NgStyle} from '@angular/common'; -// #docregion import-ng-if -import {NgIf} from '@angular/common'; -// #enddocregion import-ng-if -// #docregion import-ng-for -import {NgFor} from '@angular/common'; -// #enddocregion import-ng-for -// #docregion import-ng-switch -import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common'; -// #enddocregion import-ng-switch -// #docregion import-forms-module -import {FormsModule} from '@angular/forms'; -// #enddocregion import-forms-module -import {Item} from './item'; -import {ItemDetailComponent} from './item-detail/item-detail.component'; -import {ItemSwitchComponents} from './item-switch.component'; -import {StoutItemComponent} from './item-switch.component'; - -// #docregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module -@Component({ - // #enddocregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.css'], - - imports: [ - NgClass, - NgStyle, - // #docregion import-ng-if - NgIf, // <-- import into the component - // #enddocregion import-ng-if - // #docregion import-ng-for - NgFor, // <-- import into the component - // #enddocregion import-ng-for - // #docregion import-ng-switch - NgSwitch, // <-- import into the component - NgSwitchCase, - NgSwitchDefault, - // #enddocregion import-ng-switch - // #docregion import-forms-module - FormsModule, // <--- import into the component - // #enddocregion import-forms-module - JsonPipe, - ItemDetailComponent, - ItemSwitchComponents, - StoutItemComponent, - // #docregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module - ], -}) -export class AppComponent implements OnInit { - // #enddocregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module - canSave = true; - isSpecial = true; - isUnchanged = true; - - isActive = true; - nullCustomer: string | null = null; - currentCustomer = { - name: 'Laura', - }; - - item!: Item; // defined to demonstrate template context precedence - items: Item[] = []; - - // #docregion item - currentItem!: Item; - // #enddocregion item - - // trackBy change counting - itemsNoTrackByCount = 0; - itemsWithTrackByCount = 0; - itemsWithTrackByCountReset = 0; - itemIdIncrement = 1; - - // #docregion setClasses - currentClasses: Record = {}; - // #enddocregion setClasses - - // #docregion setStyles - currentStyles: Record = {}; - // #enddocregion setStyles - - ngOnInit() { - this.resetItems(); - this.setCurrentClasses(); - this.setCurrentStyles(); - this.itemsNoTrackByCount = 0; - } - - setUppercaseName(name: string) { - this.currentItem.name = name.toUpperCase(); - } - - // #docregion setClasses - setCurrentClasses() { - // CSS classes: added/removed per current state of component properties - this.currentClasses = { - saveable: this.canSave, - modified: !this.isUnchanged, - special: this.isSpecial, - }; - } - // #enddocregion setClasses - - // #docregion setStyles - setCurrentStyles() { - // CSS styles: set per current state of component properties - this.currentStyles = { - 'font-style': this.canSave ? 'italic' : 'normal', - 'font-weight': !this.isUnchanged ? 'bold' : 'normal', - 'font-size': this.isSpecial ? '24px' : '12px', - }; - } - // #enddocregion setStyles - - isActiveToggle() { - this.isActive = !this.isActive; - } - - giveNullCustomerValue() { - this.nullCustomer = 'Kelly'; - } - - resetItems() { - this.items = Item.items.map((item) => item.clone()); - this.currentItem = this.items[0]; - this.item = this.currentItem; - } - - resetList() { - this.resetItems(); - this.itemsWithTrackByCountReset = 0; - this.itemsNoTrackByCount = ++this.itemsNoTrackByCount; - } - - changeIds() { - this.items.forEach((i) => (i.id += 1 * this.itemIdIncrement)); - this.itemsWithTrackByCountReset = -1; - this.itemsNoTrackByCount = ++this.itemsNoTrackByCount; - this.itemsWithTrackByCount = ++this.itemsWithTrackByCount; - } - - clearTrackByCounts() { - this.resetItems(); - this.itemsNoTrackByCount = 0; - this.itemsWithTrackByCount = 0; - this.itemIdIncrement = 1; - } - // #docregion trackByItems - trackByItems(index: number, item: Item): number { - return item.id; - } - // #enddocregion trackByItems - - trackById(index: number, item: any): number { - return item.id; - } - - getValue(event: Event): string { - return (event.target as HTMLInputElement).value; - } - // #docregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module -} -// #enddocregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module diff --git a/adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.css b/adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.css deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.html b/adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.html deleted file mode 100644 index 5326dc804c5..00000000000 --- a/adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- {{ item()?.name }} -
diff --git a/adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts b/adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts deleted file mode 100644 index d49b2b37bf2..00000000000 --- a/adev/src/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {Component, input} from '@angular/core'; - -import {Item} from '../item'; - -@Component({ - selector: 'app-item-detail', - templateUrl: './item-detail.component.html', - styleUrls: ['./item-detail.component.css'], -}) -export class ItemDetailComponent { - readonly item = input(); -} diff --git a/adev/src/content/examples/built-in-directives/src/app/item-switch.component.ts b/adev/src/content/examples/built-in-directives/src/app/item-switch.component.ts deleted file mode 100644 index 833224d4c4e..00000000000 --- a/adev/src/content/examples/built-in-directives/src/app/item-switch.component.ts +++ /dev/null @@ -1,57 +0,0 @@ -import {Component, computed, input} from '@angular/core'; -import {Item} from './item'; - -@Component({ - selector: 'app-stout-item', - template: "I'm a little {{item().name}}, short and stout!", -}) - -// #docregion input -export class StoutItemComponent { - item = input.required(); -} -// #enddocregion input - -@Component({ - selector: 'app-best-item', - template: 'This is the brightest {{item().name}} in town.', -}) -export class BestItemComponent { - item = input.required(); -} - -@Component({ - selector: 'app-device-item', - template: 'Which is the slimmest {{item().name}}?', -}) -export class DeviceItemComponent { - item = input.required(); -} - -@Component({ - selector: 'app-lost-item', - template: 'Has anyone seen my {{item().name}}?', -}) -export class LostItemComponent { - item = input.required(); -} - -@Component({ - selector: 'app-unknown-item', - template: '{{message()}}', -}) -export class UnknownItemComponent { - readonly item = input(undefined); - readonly message = computed(() => { - const itemName = this.item()?.name; - return itemName ? `${itemName} is strange and mysterious.` : 'A mystery wrapped in a fishbowl.'; - }); -} - -export const ItemSwitchComponents = [ - StoutItemComponent, - BestItemComponent, - DeviceItemComponent, - LostItemComponent, - UnknownItemComponent, -]; diff --git a/adev/src/content/examples/built-in-directives/src/app/item.ts b/adev/src/content/examples/built-in-directives/src/app/item.ts deleted file mode 100644 index c9714f6b6c1..00000000000 --- a/adev/src/content/examples/built-in-directives/src/app/item.ts +++ /dev/null @@ -1,25 +0,0 @@ -export class Item { - static nextId = 0; - - static items: Item[] = [ - new Item(0, 'Teapot', 'stout'), - new Item(1, 'Lamp', 'bright'), - new Item(2, 'Phone', 'slim'), - new Item(3, 'Television', 'vintage'), - new Item(4, 'Fishbowl'), - ]; - - constructor( - public id: number, - public name?: string, - public feature?: string, - public url?: string, - public rate = 100, - ) { - this.id = id ? id : Item.nextId++; - } - - clone(): Item { - return Object.assign(new Item(this.id), this); - } -} diff --git a/adev/src/content/examples/built-in-directives/src/index.html b/adev/src/content/examples/built-in-directives/src/index.html deleted file mode 100644 index be6c2554285..00000000000 --- a/adev/src/content/examples/built-in-directives/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - BuiltInDirectives - - - - - - - - diff --git a/adev/src/content/examples/built-in-directives/src/main.ts b/adev/src/content/examples/built-in-directives/src/main.ts deleted file mode 100644 index 9f16c6cce60..00000000000 --- a/adev/src/content/examples/built-in-directives/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {bootstrapApplication} from '@angular/platform-browser'; - -import {AppComponent} from './app/app.component'; - -bootstrapApplication(AppComponent).catch((err) => console.error(err)); diff --git a/adev/src/content/examples/built-in-directives/stackblitz.json b/adev/src/content/examples/built-in-directives/stackblitz.json deleted file mode 100644 index 6824495335c..00000000000 --- a/adev/src/content/examples/built-in-directives/stackblitz.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "description": "Built-in Directives", - "files": [ - "!**/*.d.ts", - "!**/*.js", - "!**/*.[1,2].*" - ], - "file": "src/app/app.component.ts", - "tags": ["Built-in Directives"] -} diff --git a/adev/src/content/examples/dynamic-form/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/dynamic-form/e2e/src/app.e2e-spec.ts deleted file mode 100644 index e3790401adc..00000000000 --- a/adev/src/content/examples/dynamic-form/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Dynamic Form', () => { - let driver: webdriver.WebDriver; - - beforeAll(async () => { - await driver.get(''); - }); - - it('should submit form', async () => { - const firstNameElement = ( - await driver.findElements(webdriver.By.css('input[id=firstName]')) - )[0]; - expect(await firstNameElement.getAttribute('value')).toEqual('Bombasto'); - - const emailElement = (await driver.findElements(webdriver.By.css('input[id=emailAddress]')))[0]; - const email = 'test@test.com'; - await emailElement.sendKeys(email); - expect(await emailElement.getAttribute('value')).toEqual(email); - - await (await driver.findElement(webdriver.By.css('select option[value="solid"]'))).click(); - await (await driver.findElements(webdriver.By.css('button')))[0].click(); - - const strongs = await driver.findElements(webdriver.By.css('strong')); - let found = false; - for (const s of strongs) { - if ((await s.getText()).includes('Saved the following values')) { - found = true; - break; - } - } - expect(found).toBe(true); - }); -}); diff --git a/adev/src/content/examples/elements/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/elements/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 5424275b548..00000000000 --- a/adev/src/content/examples/elements/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,97 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Elements', () => { - let driver: webdriver.WebDriver; - - const click = async (elem: webdriver.WebElement) => { - await driver.wait(webdriver.until.elementIsVisible(elem), 5000); - await elem.click(); - }; - - const waitForText = async (elem: webdriver.WebElement) => { - await driver.wait(async () => /\S/.test(await elem.getText()), 5000); - }; - - const isPresent = async (locator: webdriver.Locator) => { - const els = await driver.findElements(locator); - return els.length > 0; - }; - - beforeEach(async () => { - await driver.get(''); - }); - - describe('popup component', () => { - it('should be displayed on button click', async () => { - const popupComponentLocator = webdriver.By.css('popup-component'); - expect(await isPresent(popupComponentLocator)).toBe(false); - - const popupButtons = await driver.findElements(webdriver.By.css('button')); - await click(popupButtons[0]); - expect(await isPresent(popupComponentLocator)).toBe(true); - }); - - it('should display the specified message', async () => { - const messageInput = await driver.findElement(webdriver.By.css('input')); - await messageInput.clear(); - await messageInput.sendKeys('Angular rocks!'); - - const popupButtons = await driver.findElements(webdriver.By.css('button')); - await click(popupButtons[0]); - - const popupComponent = await driver.findElement(webdriver.By.css('popup-component')); - await waitForText(popupComponent); - - expect(await popupComponent.getText()).toContain('Popup: Angular rocks!'); - }); - - it('should be closed on "close" button click', async () => { - const popupComponentLocator = webdriver.By.css('popup-component'); - const popupButtons = await driver.findElements(webdriver.By.css('button')); - await click(popupButtons[0]); - expect(await isPresent(popupComponentLocator)).toBe(true); - - const popupComponent = await driver.findElement(popupComponentLocator); - const closeButton = await popupComponent.findElement(webdriver.By.css('button')); - await click(closeButton); - expect(await isPresent(popupComponentLocator)).toBe(false); - }); - }); - - describe('popup element', () => { - it('should be displayed on button click', async () => { - const popupElementLocator = webdriver.By.css('popup-element'); - expect(await isPresent(popupElementLocator)).toBe(false); - - const popupButtons = await driver.findElements(webdriver.By.css('button')); - await click(popupButtons[1]); - expect(await isPresent(popupElementLocator)).toBe(true); - }); - - it('should display the specified message', async () => { - const messageInput = await driver.findElement(webdriver.By.css('input')); - await messageInput.clear(); - await messageInput.sendKeys('Angular rocks!'); - - const popupButtons = await driver.findElements(webdriver.By.css('button')); - await click(popupButtons[1]); - - const popupElement = await driver.findElement(webdriver.By.css('popup-element')); - await waitForText(popupElement); - - expect(await popupElement.getText()).toContain('Popup: Angular rocks!'); - }); - - it('should be closed on "close" button click', async () => { - const popupElementLocator = webdriver.By.css('popup-element'); - const popupButtons = await driver.findElements(webdriver.By.css('button')); - await click(popupButtons[1]); - expect(await isPresent(popupElementLocator)).toBe(true); - - const popupElement = await driver.findElement(popupElementLocator); - const closeButton = await popupElement.findElement(webdriver.By.css('button')); - await click(closeButton); - expect(await isPresent(popupElementLocator)).toBe(false); - }); - }); -}); diff --git a/adev/src/content/examples/form-validation/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/form-validation/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 722345924b4..00000000000 --- a/adev/src/content/examples/form-validation/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,249 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -// THESE TESTS ARE INCOMPLETE -describe('Form Validation Tests', () => { - let driver: webdriver.WebDriver; - - beforeAll(async () => { - await driver.get(''); - }); - - describe('Template-driven form', () => { - beforeAll(() => { - getPage('app-actor-form-template'); - }); - - tests('Template-Driven Form'); - bobTests(); - asyncValidationTests(); - crossValidationTests(); - }); - - describe('Reactive form', () => { - beforeAll(() => { - getPage('app-actor-form-reactive'); - }); - - tests('Reactive Form'); - bobTests(); - asyncValidationTests(); - crossValidationTests(); - }); - - const testName = 'Test Name'; - - let page: { - sectionTag: string; - section: () => webdriver.WebElement; - form: () => webdriver.WebElement; - title: () => webdriver.WebElement; - nameInput: () => webdriver.WebElement; - roleInput: () => webdriver.WebElement; - skillSelect: () => webdriver.WebElement; - skillOption: () => webdriver.WebElement; - errorMessages: () => Promise; - actorFormButtons: () => Promise; - actorSubmitted: () => webdriver.WebElement; - roleErrors: () => webdriver.WebElement; - crossValidationErrorMessage: () => webdriver.WebElement; - }; - - function getPage(sectionTag: string) { - const sec = () => driver.findElement(webdriver.By.css(sectionTag)); - - page = { - sectionTag, - section: sec, - form: () => sec().findElement(webdriver.By.css('form')), - title: () => sec().findElement(webdriver.By.css('h2')), - nameInput: () => sec().findElement(webdriver.By.css('#name')), - roleInput: () => sec().findElement(webdriver.By.css('#role')), - skillSelect: () => sec().findElement(webdriver.By.css('#skill')), - skillOption: () => sec().findElement(webdriver.By.css('#skill option')), - errorMessages: () => sec().findElements(webdriver.By.css('div.alert')), - actorFormButtons: () => sec().findElements(webdriver.By.css('button')), - actorSubmitted: () => sec().findElement(webdriver.By.css('.submitted-message')), - roleErrors: () => sec().findElement(webdriver.By.css('.role-errors')), - crossValidationErrorMessage: () => - sec().findElement(webdriver.By.css('.cross-validation-error-message')), - }; - } - - function tests(title: string) { - it('should display correct title', async () => { - expect(await page.title().getText()).toContain(title); - }); - - it('should not display submitted message before submit', async () => { - const p = await page.actorSubmitted().findElements(webdriver.By.css('p')); - expect(p.length).toBe(0); - }); - - it('should have form buttons', async () => { - expect((await page.actorFormButtons()).length).toEqual(2); - }); - - it('should have error at start', async () => { - await expectFormIsInvalid(); - }); - - it('should have disabled submit button', async () => { - expect(await (await page.actorFormButtons())[0].isEnabled()).toBe(false); - }); - - it('resetting name to valid name should clear errors', async () => { - const ele = page.nameInput(); - expect(await ele.isDisplayed()).toBe(true, 'nameInput should exist'); - await ele.clear(); - await ele.sendKeys(testName); - await expectFormIsValid(); - }); - - it('should produce "required" error after clearing name', async () => { - await page.nameInput().clear(); - await page.nameInput().sendKeys('x', webdriver.Key.BACK_SPACE); - expect(await page.form().getAttribute('class')).toMatch('ng-invalid'); - expect(await (await page.errorMessages())[0].getText()).toContain('required'); - }); - - it('should produce "at least 4 characters" error when name="x"', async () => { - await page.nameInput().clear(); - await page.nameInput().sendKeys('x'); - await expectFormIsInvalid(); - expect(await (await page.errorMessages())[0].getText()).toContain('at least 4 characters'); - }); - - it('resetting name to valid name again should clear errors', async () => { - await page.nameInput().sendKeys(testName); - await expectFormIsValid(); - }); - - it('should have enabled submit button', async () => { - const submitBtn = (await page.actorFormButtons())[0]; - expect(await submitBtn.isEnabled()).toBe(true); - }); - - it('should hide form after submit', async () => { - await (await page.actorFormButtons())[0].click(); - const forms = await driver.findElements(webdriver.By.css(`${page.sectionTag} form`)); - expect(forms.length === 0 || !(await forms[0].isDisplayed())).toBe(true); - }); - - it('submitted form should be displayed', async () => { - const p = await page.actorSubmitted().findElements(webdriver.By.css('p')); - expect(p.length).toBeGreaterThan(0); - }); - - it('submitted form should have new actor name', async () => { - expect(await page.actorSubmitted().getText()).toContain(testName); - }); - - it('clicking edit button should reveal form again', async () => { - const newFormBtn = page.actorSubmitted().findElement(webdriver.By.css('button')); - await newFormBtn.click(); - const p = await page.actorSubmitted().findElements(webdriver.By.css('p')); - expect(p.length).toBe(0, 'submitted hidden again'); - expect(await page.title().isDisplayed()).toBe(true, 'can see form title'); - }); - } - - async function expectFormIsValid() { - expect(await page.form().getAttribute('class')).toMatch('ng-valid'); - } - - async function expectFormIsInvalid() { - expect(await page.form().getAttribute('class')).toMatch('ng-invalid'); - } - - async function triggerRoleValidation() { - await driver.findElement(webdriver.By.css('app-root')).click(); - } - - async function waitForAlterEgoValidation() { - await new Promise((resolve) => setTimeout(resolve, 400)); - } - - function bobTests() { - const emsg = 'Name cannot be Bob.'; - - it('should produce "no bob" error after setting name to "Bobby"', async () => { - await page.skillSelect().click(); - await page.skillOption().click(); - - await page.nameInput().clear(); - await page.nameInput().sendKeys('Bobby'); - await expectFormIsInvalid(); - expect(await (await page.errorMessages())[0].getText()).toBe(emsg); - }); - - it('should be ok again with valid name', async () => { - await page.nameInput().clear(); - await page.nameInput().sendKeys(testName); - await expectFormIsValid(); - }); - } - - function asyncValidationTests() { - const emsg = 'Role is already taken.'; - - it(`should produce "${emsg}" error after setting role to Eric`, async () => { - await page.roleInput().clear(); - await page.roleInput().sendKeys('Eric'); - - await triggerRoleValidation(); - await waitForAlterEgoValidation(); - - await expectFormIsInvalid(); - expect(await page.roleErrors().getText()).toBe(emsg); - }); - - it('should be ok again with different values', async () => { - await page.roleInput().clear(); - await page.roleInput().sendKeys('John'); - - await triggerRoleValidation(); - await waitForAlterEgoValidation(); - - await expectFormIsValid(); - const roleErrors = await driver.findElements( - webdriver.By.css(`${page.sectionTag} .role-errors`), - ); - expect(roleErrors.length).toBe(0); - }); - } - - function crossValidationTests() { - const emsg = 'Name cannot match role.'; - - it(`should produce "${emsg}" error after setting name and role to the same value`, async () => { - await page.nameInput().clear(); - await page.nameInput().sendKeys('Romeo'); - - await page.roleInput().clear(); - await page.roleInput().sendKeys('Romeo'); - - await triggerRoleValidation(); - await waitForAlterEgoValidation(); - - await expectFormIsInvalid(); - expect(await page.crossValidationErrorMessage().getText()).toBe(emsg); - }); - - it('should be ok again with different values', async () => { - await page.nameInput().clear(); - await page.nameInput().sendKeys('Romeo'); - - await page.roleInput().clear(); - await page.roleInput().sendKeys('Juliet'); - - await triggerRoleValidation(); - await waitForAlterEgoValidation(); - - await expectFormIsValid(); - const crossErrors = await driver.findElements( - webdriver.By.css(`${page.sectionTag} .cross-validation-error-message`), - ); - expect(crossErrors.length).toBe(0); - }); - } -}); diff --git a/adev/src/content/examples/forms-overview/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/forms-overview/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 8daf57e6a84..00000000000 --- a/adev/src/content/examples/forms-overview/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('forms-overview App', () => { - let driver: webdriver.WebDriver; - - beforeEach(async () => { - await driver.get(''); - }); - - it('should display a title', async () => { - expect(await driver.findElement(webdriver.By.css('h1, h2')).getText()).toEqual( - 'Forms Overview', - ); - }); -}); diff --git a/adev/src/content/examples/forms/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/forms/e2e/src/app.e2e-spec.ts deleted file mode 100644 index b8171053506..00000000000 --- a/adev/src/content/examples/forms/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Forms Tests', () => { - let driver: webdriver.WebDriver; - - beforeEach(async () => { - await driver.get(''); - }); - - it('should display correct title', async () => { - const h1s = await driver.findElements(webdriver.By.css('h1')); - expect(await h1s[0].getText()).toEqual('Actor Form'); - }); - - it('should not display message before submit', async () => { - const h2s = await driver.findElements(webdriver.By.css('h2')); - expect(h2s.length === 0 || !(await h2s[0].isDisplayed())).toBe(true); - }); - - it('should hide form after submit', async () => { - const ele = (await driver.findElements(webdriver.By.css('h1')))[0]; - expect(await ele.isDisplayed()).toBe(true); - - const b = (await driver.findElements(webdriver.By.css('button[type=submit]')))[0]; - await b.click(); - const h1s = await driver.findElements(webdriver.By.css('h1')); - expect(h1s.length === 0 || !(await h1s[0].isDisplayed())).toBe(true); - }); - - it('should display message after submit', async () => { - const b = (await driver.findElements(webdriver.By.css('button[type=submit]')))[0]; - await b.click(); - expect(await (await driver.findElement(webdriver.By.css('h2'))).getText()).toContain( - 'You submitted the following', - ); - }); - - it('should hide form after submit', async () => { - const studioEle = (await driver.findElements(webdriver.By.css('input[name=studio]')))[0]; - expect(await studioEle.isDisplayed()).toBe(true); - - const submitButtonEle = (await driver.findElements(webdriver.By.css('button[type=submit]')))[0]; - await submitButtonEle.click(); - const studioEles = await driver.findElements(webdriver.By.css('input[name=studio]')); - expect(studioEles.length === 0 || !(await studioEles[0].isDisplayed())).toBe(true); - }); - - it('should reflect submitted data after submit', async () => { - const studioEle = (await driver.findElements(webdriver.By.css('input[name=studio]')))[0]; - const value = await studioEle.getAttribute('value'); - const test = 'testing 1 2 3'; - const newValue = value + test; - - await studioEle.sendKeys(test); - expect(await studioEle.getAttribute('value')).toEqual(newValue); - - const b = (await driver.findElements(webdriver.By.css('button[type=submit]')))[0]; - await b.click(); - - const divs = await driver.findElements(webdriver.By.css('div')); - let foundStudio = false; - let foundNewValue = false; - for (const d of divs) { - const text = await d.getText(); - if (text.includes('Studio')) foundStudio = true; - if (text.includes(newValue)) foundNewValue = true; - } - expect(foundStudio).toBe(true, 'cannot locate "Studio" label'); - expect(foundNewValue).toBe(true, `cannot locate div with this text: ${newValue}`); - }); -}); diff --git a/adev/src/content/examples/i18n/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/i18n/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 768e9b9c80a..00000000000 --- a/adev/src/content/examples/i18n/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('i18n E2E Tests', () => { - let driver: webdriver.WebDriver; - - beforeEach(async () => { - await driver.get(''); - }); - - it('should display i18n translated welcome: Bonjour !', async () => { - expect(await (await driver.findElement(webdriver.By.css('h1'))).getText()).toEqual( - 'Bonjour i18n !', - ); - }); - - it('should display the node texts without elements', async () => { - expect(await (await driver.findElement(webdriver.By.css('app-root'))).getText()).toContain( - `Je n'affiche aucun élément`, - ); - }); - - it('should display the translated title attribute', async () => { - const title = await (await driver.findElement(webdriver.By.css('img'))).getAttribute('title'); - expect(title).toBe(`Logo d'Angular`); - }); - - it('should display the ICU plural expression', async () => { - const spans = await driver.findElements(webdriver.By.css('span')); - expect(await spans[0].getText()).toBe(`Mis à jour à l'instant`); - }); - - it('should display the ICU select expression', async () => { - const spans = await driver.findElements(webdriver.By.css('span')); - const buttons = await driver.findElements(webdriver.By.css('button')); - expect(await spans[1].getText()).toBe(`L'auteur est une femme`); - await buttons[2].click(); - expect(await spans[1].getText()).toBe(`L'auteur est un homme`); - }); - - it('should display the nested expression', async () => { - const spans = await driver.findElements(webdriver.By.css('span')); - const buttons = await driver.findElements(webdriver.By.css('button')); - expect(await spans[2].getText()).toBe(`Mis à jour: à l'instant`); - await buttons[0].click(); - expect(await spans[2].getText()).toBe(`Mis à jour: il y a une minute`); - await buttons[0].click(); - await buttons[0].click(); - await buttons[4].click(); - expect(await spans[2].getText()).toBe(`Mis à jour: il y a 3 minutes par autre`); - }); -}); diff --git a/adev/src/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 3161eb59ef2..00000000000 --- a/adev/src/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,181 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Reactive forms', () => { - let driver: webdriver.WebDriver; - - const getNameEditor = () => driver.findElement(webdriver.By.css('app-name-editor')); - const getProfileEditor = () => driver.findElement(webdriver.By.css('app-profile-editor')); - - const findNavButton = async (text: string) => { - const buttons = await driver.findElements(webdriver.By.css('app-root > nav > button')); - for (const b of buttons) { - if ((await b.getText()).includes(text)) { - return b; - } - } - throw new Error(`Nav button "${text}" not found`); - }; - - beforeAll(async () => { - await driver.get(''); - }); - - describe('Name Editor', () => { - const nameText = 'John Smith'; - - beforeAll(async () => { - await (await findNavButton('Name Editor')).click(); - }); - - beforeEach(async () => { - const nameInput = await (await getNameEditor()).findElement(webdriver.By.css('input')); - await nameInput.clear(); - }); - - it('should update the name value when the name control is updated', async () => { - const nameInput = await (await getNameEditor()).findElement(webdriver.By.css('input')); - await nameInput.sendKeys(nameText); - - const value = await nameInput.getAttribute('value'); - expect(value).toBe(nameText); - }); - - it('should update the name control when the Update Name button is clicked', async () => { - const nameInput = await (await getNameEditor()).findElement(webdriver.By.css('input')); - const updateButton = await ( - await getNameEditor() - ).findElement(webdriver.By.xpath('.//button[normalize-space()="Update Name"]')); - - await nameInput.sendKeys(nameText); - const value1 = await nameInput.getAttribute('value'); - expect(value1).toBe(nameText); - - await updateButton.click(); - const value2 = await nameInput.getAttribute('value'); - expect(value2).toBe('Nancy'); - }); - - it('should update the displayed control value when the name control updated', async () => { - const nameInput = await (await getNameEditor()).findElement(webdriver.By.css('input')); - await nameInput.sendKeys(nameText); - - const paragraphs = await (await getNameEditor()).findElements(webdriver.By.css('p')); - let valueElement: webdriver.WebElement | null = null; - for (const p of paragraphs) { - if ((await p.getText()).includes('Value:')) { - valueElement = p; - break; - } - } - const nameValueElement = await valueElement!.getText(); - const nameValue = nameValueElement.toString().replace('Value: ', ''); - - expect(nameValue).toBe(nameText); - }); - }); - - describe('Profile Editor', () => { - const profile: Record = { - firstName: 'John', - lastName: 'Smith', - street: '345 South Lane', - city: 'Northtown', - state: 'XX', - zip: 12345, - }; - - beforeAll(async () => { - await (await findNavButton('Profile Editor')).click(); - }); - - beforeEach(async () => { - await driver.get(''); - await (await findNavButton('Profile Editor')).click(); - }); - - it('should be invalid by default', async () => { - expect(await (await getProfileEditor()).getText()).toContain('Form Status: INVALID'); - }); - - it('should be valid if the First Name is filled in', async () => { - const firstNameInput = await getInput('firstName'); - await firstNameInput.clear(); - await firstNameInput.sendKeys('John Smith'); - - expect(await (await getProfileEditor()).getText()).toContain('Form Status: VALID'); - }); - - it('should update the name when the button is clicked', async () => { - const firstNameInput = await getInput('firstName'); - const streetInput = await getInput('street'); - const updateButton = await ( - await getProfileEditor() - ).findElement(webdriver.By.xpath('.//button[normalize-space()="Update Profile"]')); - - await firstNameInput.clear(); - await streetInput.clear(); - await firstNameInput.sendKeys('John'); - await streetInput.sendKeys('345 Smith Lane'); - const firstNameInitial = await firstNameInput.getAttribute('value'); - const streetNameInitial = await streetInput.getAttribute('value'); - - expect(firstNameInitial).toBe('John'); - expect(streetNameInitial).toBe('345 Smith Lane'); - await updateButton.click(); - - const nameValue = await firstNameInput.getAttribute('value'); - const streetValue = await streetInput.getAttribute('value'); - - expect(nameValue).toBe('Nancy'); - expect(streetValue).toBe('123 Drew Street'); - }); - - it('should add an alias field when the Add Alias button is clicked', async () => { - const addAliasButton = await driver.findElement( - webdriver.By.xpath('.//button[normalize-space()="+ Add another alias"]'), - ); - await addAliasButton.click(); - - const labels = await (await getProfileEditor()).findElements(webdriver.By.css('label')); - const aliasLabels: webdriver.WebElement[] = []; - for (const l of labels) { - if ((await l.getText()).includes('Alias')) { - aliasLabels.push(l); - } - } - - expect(aliasLabels.length).toBe(2); - }); - - it('should update the displayed form value when form inputs are updated', async () => { - const aliasText = 'Johnny'; - for (const key of Object.keys(profile)) { - await (await getInput(key)).sendKeys(`${profile[key]}`); - } - - const aliasInput = ( - await (await getProfileEditor()).findElements(webdriver.By.css('#alias-0')) - )[0]; - await aliasInput.sendKeys(aliasText); - - const paragraphs = await (await getProfileEditor()).findElements(webdriver.By.css('p')); - let formValueElement: webdriver.WebElement | null = null; - for (const p of paragraphs) { - if ((await p.getText()).includes('Form Value:')) { - formValueElement = p; - break; - } - } - const formValue = await formValueElement!.getText(); - const formJson = JSON.parse(formValue.toString().replace('Form Value:', '')); - - expect(profile['firstName']).toBe(formJson.firstName); - expect(profile['lastName']).toBe(formJson.lastName); - expect(formJson.aliases[0]).toBe(aliasText); - }); - }); - - function getInput(key: string) { - return driver.findElement(webdriver.By.css(`input[formcontrolname=${key}]`)); - } -}); diff --git a/adev/src/content/examples/routing-with-urlmatcher/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/routing-with-urlmatcher/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 1085a2c569a..00000000000 --- a/adev/src/content/examples/routing-with-urlmatcher/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Routing with Custom Matching', () => { - let driver: webdriver.WebDriver; - - beforeAll(async () => { - await driver.get(''); - }); - - it('should display Routing with Custom Matching', async () => { - expect(await (await driver.findElement(webdriver.By.css('h2'))).getText()).toEqual( - 'Routing with Custom Matching', - ); - }); -}); diff --git a/adev/src/content/examples/service-worker-getting-started/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/service-worker-getting-started/e2e/src/app.e2e-spec.ts deleted file mode 100755 index b0d6b47c80c..00000000000 --- a/adev/src/content/examples/service-worker-getting-started/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('sw-example App', () => { - let driver: webdriver.WebDriver; - - beforeEach(async () => { - await driver.get(''); - }); - - it('should display welcome message', async () => { - expect(await (await driver.findElement(webdriver.By.css('h1, app-root h1'))).getText()).toEqual( - 'Welcome to Service Workers!', - ); - }); - - it('should display the Angular logo', async () => { - const imgs = await driver.findElements(webdriver.By.css('img')); - expect(imgs.length).toBeGreaterThan(0); - }); - - it('should show a header for the list of links', async () => { - const listHeader = await driver.findElement(webdriver.By.css('app-root > h2')); - expect(await listHeader.getText()).toEqual('Here are some links to help you start:'); - }); - - it('should show a list of links', async () => { - const items = await driver.findElements(webdriver.By.css('ul > li > h2 > a')); - - expect(items.length).toBe(4); - expect(await items[0].getText()).toBe('Angular Service Worker Intro'); - expect(await items[1].getText()).toBe('Tour of Heroes'); - expect(await items[2].getText()).toBe('CLI Documentation'); - expect(await items[3].getText()).toBe('Angular blog'); - }); - - // Check for a rejected promise as the service worker is not enabled - it('SwUpdate.checkForUpdate() should return a rejected promise', async () => { - const button = await driver.findElement(webdriver.By.css('button')); - const rejectMessage = await driver.findElement(webdriver.By.css('p')); - await button.click(); - expect(await rejectMessage.getText()).toContain('rejected: '); - }); -}); diff --git a/adev/src/content/examples/structural-directives/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/structural-directives/e2e/src/app.e2e-spec.ts deleted file mode 100644 index ea6394e21c6..00000000000 --- a/adev/src/content/examples/structural-directives/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Structural Directives', () => { - let driver: webdriver.WebDriver; - - beforeAll(async () => { - await driver.get(''); - }); - - it('first div should show hero name with *ngIf', async () => { - const allDivs = await driver.findElements(webdriver.By.css('div')); - expect(await allDivs[0].getText()).toEqual('Dr. Nice'); - }); - - it('first li should show hero name with *ngFor', async () => { - const allLis = await driver.findElements(webdriver.By.css('li')); - expect(await allLis[0].getText()).toEqual('Dr. Nice'); - }); - - it('ngSwitch have two instances', async () => { - const happyHeroEls = await driver.findElements(webdriver.By.css('app-happy-hero')); - expect(happyHeroEls.length).toEqual(2); - }); - - it('should toggle *ngIf="hero" with a button', async () => { - const buttons = await driver.findElements(webdriver.By.css('button')); - let toggleHeroButton: webdriver.WebElement | null = null; - for (const b of buttons) { - if ((await b.getText()).includes('Toggle hero')) { - toggleHeroButton = b; - break; - } - } - - const paragraphs = await driver.findElements(webdriver.By.css('p')); - let paragraph: webdriver.WebElement | null = null; - for (const p of paragraphs) { - if ((await p.getText()).includes('I turned the corner')) { - paragraph = p; - break; - } - } - - expect(await paragraph!.getText()).toContain('I waved'); - await toggleHeroButton!.click(); - expect(await paragraph!.getText()).not.toContain('I waved'); - }); - - it('appUnless should show 3 paragraph (A)s and (B)s at the start', async () => { - const paragraph = await driver.findElements(webdriver.By.css('p.unless')); - expect(paragraph.length).toEqual(3); - for (let i = 0; i < 3; i++) { - expect(await paragraph[i].getText()).toContain('(A)'); - } - }); - - it('appUnless should show 1 paragraph (B) after toggling condition', async () => { - const buttons = await driver.findElements(webdriver.By.css('button')); - let toggleConditionButton: webdriver.WebElement | null = null; - for (const b of buttons) { - if ((await b.getText()).includes('Toggle condition')) { - toggleConditionButton = b; - break; - } - } - - await toggleConditionButton!.click(); - - const paragraph = await driver.findElements(webdriver.By.css('p.unless')); - expect(paragraph.length).toEqual(1); - expect(await paragraph[0].getText()).toContain('(B)'); - }); -}); diff --git a/adev/src/content/examples/structural-directives/example-config.json b/adev/src/content/examples/structural-directives/example-config.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/structural-directives/src/app/app.component.css b/adev/src/content/examples/structural-directives/src/app/app.component.css deleted file mode 100644 index 132e7864311..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/app.component.css +++ /dev/null @@ -1,71 +0,0 @@ -/* #docregion */ -button { - min-width: 100px; - font-size: 100%; -} - -.box { - border: 1px solid gray; - max-width: 600px; - padding: 4px; -} -.choices { - font-style: italic; -} - -code, .code { - background-color: #eee; - color: black; - font-family: Courier, sans-serif; - font-size: 85%; -} - -div.code { - width: 400px; -} - -.heroic { - font-size: 150%; - font-weight: bold; -} - -hr { - margin: 40px 0; -} - -.odd { - background-color: palegoldenrod; -} - -td, th { - text-align: left; - vertical-align: top; -} - -p span { - color: red; - font-size: 70%; -} - -.unless { - border: 2px solid; - padding: 6px; -} - -p.unless { - width: 500px; -} - -button.a, span.a, .unless.a { - color: red; - border-color: gold; - background-color: yellow; - font-size: 100%; -} - -button.b, span.b, .unless.b { - color: black; - border-color: green; - background-color: lightgreen; - font-size: 100%; -} diff --git a/adev/src/content/examples/structural-directives/src/app/app.component.html b/adev/src/content/examples/structural-directives/src/app/app.component.html deleted file mode 100644 index 1e521ad0a99..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/app.component.html +++ /dev/null @@ -1,187 +0,0 @@ - - -

Structural Directives

- -

Conditional display of hero

- -
- -
{{ hero.name }}
- -
- -

List of heroes

- -
    -
  • {{ hero.name }}
  • -
- -
- -

NgIf

- -

Expression is true and ngIf is true. This paragraph is in the DOM.

-

Expression is false and ngIf is false. This paragraph is not in the DOM.

- -

Expression sets display to "block". This paragraph is visible.

-

- Expression sets display to "none". This paragraph is hidden but still in the DOM. -

- -

NgIf with template

-

<ng-template> element

- - -
{{ hero.name }}
-
- - -
- -

<ng-container>

- -

*ngIf with a <ng-container>

- - - - -

- I turned the corner - and saw {{ hero.name }}. I waved - and continued on my way. -

- - -

- I turned the corner - and saw {{ hero.name }}. I waved - and continued on my way. -

- -

<select> with <span>

- -
- Pick your favorite hero () -
- - -

<select> with <ng-container>

- -
- Pick your favorite hero () -
- - -

- -
- -

NgFor

- -
-

- <div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" - [class.odd]="odd"> -

- -
- ({{ i }}) {{ hero.name }} -
- - -

- <ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" - [ngForTrackBy]="trackById"/> -

- - -
({{ i }}) {{ hero.name }}
-
- -
-
- -

NgSwitch

- -
Pick your favorite hero
-

- - -

- -

NgSwitch

- -
- - - - -
- -

NgSwitch with <ng-template>

-
- - - - - - - - - - - - -
- -
- -
- -

IfLoadedDirective

- - -
- -

TrigonometryDirective

- - -
    -
  • sin(30°): {{ s }}
  • -
  • cos(30°): {{ c }}
  • -
  • tan(30°): {{ t }}
  • -
- diff --git a/adev/src/content/examples/structural-directives/src/app/app.component.ts b/adev/src/content/examples/structural-directives/src/app/app.component.ts deleted file mode 100644 index f4f377a005c..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/app.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {Component} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {FormsModule} from '@angular/forms'; - -import {heroSwitchComponents} from './hero-switch.components'; -import {HeroComponent} from './hero.component'; -import {TrigonometryDirective} from './trigonometry.directive'; - -import {Hero, heroes} from './hero'; - -@Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.css'], - imports: [CommonModule, FormsModule, heroSwitchComponents, HeroComponent, TrigonometryDirective], -}) -export class AppComponent { - heroes = heroes; - hero: Hero | null = this.heroes[0]; - // #docregion condition - condition = false; - // #enddocregion condition - logs: string[] = []; - showSad = true; - status = 'ready'; - - trackById(index: number, hero: Hero): number { - return hero.id; - } -} diff --git a/adev/src/content/examples/structural-directives/src/app/hero-switch.components.ts b/adev/src/content/examples/structural-directives/src/app/hero-switch.components.ts deleted file mode 100644 index 9d2b14c2e1d..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/hero-switch.components.ts +++ /dev/null @@ -1,47 +0,0 @@ -// #docregion -import {Component, computed, input} from '@angular/core'; -import {Hero} from './hero'; - -@Component({ - selector: 'app-happy-hero', - template: 'Wow. You like {{hero().name}}. What a happy hero ... just like you.', -}) -export class HappyHeroComponent { - readonly hero = input.required(); -} - -@Component({ - selector: 'app-sad-hero', - template: 'You like {{hero().name}}? Such a sad hero. Are you sad too?', -}) -export class SadHeroComponent { - readonly hero = input.required(); -} - -@Component({ - selector: 'app-confused-hero', - template: 'Are you as confused as {{hero().name}}?', -}) -export class ConfusedHeroComponent { - readonly hero = input.required(); -} - -@Component({ - selector: 'app-unknown-hero', - template: '{{message()}}', -}) -export class UnknownHeroComponent { - readonly hero = input.required(); - - readonly message = computed(() => { - const heroName = this.hero()?.name; - return heroName ? `${heroName} is strange and mysterious.` : 'Are you feeling indecisive?'; - }); -} - -export const heroSwitchComponents = [ - HappyHeroComponent, - SadHeroComponent, - ConfusedHeroComponent, - UnknownHeroComponent, -]; diff --git a/adev/src/content/examples/structural-directives/src/app/hero.component.ts b/adev/src/content/examples/structural-directives/src/app/hero.component.ts deleted file mode 100644 index 87c7070f998..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/hero.component.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {Component} from '@angular/core'; -import {JsonPipe} from '@angular/common'; - -import {IfLoadedDirective} from './if-loaded.directive'; - -import {LoadingState} from './loading-state'; -import {Hero, heroes} from './hero'; - -@Component({ - selector: 'app-hero', - template: ` - -

{{ heroLoadingState.data | json }}

- `, - imports: [IfLoadedDirective, JsonPipe], -}) -export class HeroComponent { - heroLoadingState: LoadingState = {type: 'loading'}; - - onLoadHero(): void { - this.heroLoadingState = {type: 'loaded', data: heroes[0]}; - } -} diff --git a/adev/src/content/examples/structural-directives/src/app/hero.ts b/adev/src/content/examples/structural-directives/src/app/hero.ts deleted file mode 100644 index 56bc4a0f01f..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/hero.ts +++ /dev/null @@ -1,13 +0,0 @@ -// #docregion -export interface Hero { - id: number; - name: string; - emotion?: string; -} - -export const heroes: Hero[] = [ - {id: 1, name: 'Dr. Nice', emotion: 'happy'}, - {id: 2, name: 'RubberMan', emotion: 'sad'}, - {id: 3, name: 'Windstorm', emotion: 'confused'}, - {id: 4, name: 'Magneta'}, -]; diff --git a/adev/src/content/examples/structural-directives/src/app/if-loaded.directive.ts b/adev/src/content/examples/structural-directives/src/app/if-loaded.directive.ts deleted file mode 100644 index 5fde1d5a6ed..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/if-loaded.directive.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {Directive, effect, input, TemplateRef, ViewContainerRef} from '@angular/core'; - -import {Loaded, LoadingState} from './loading-state'; - -@Directive({ - selector: '[appIfLoaded]', -}) -export class IfLoadedDirective { - private isViewCreated = false; - - state = input.required>({alias: 'appIfLoaded'}); - - constructor( - private readonly viewContainerRef: ViewContainerRef, - private readonly templateRef: TemplateRef, - ) { - effect(() => { - if (!this.isViewCreated && this.state().type === 'loaded') { - this.viewContainerRef.createEmbeddedView(this.templateRef); - this.isViewCreated = true; - } else if (this.isViewCreated && this.state().type !== 'loaded') { - this.viewContainerRef.clear(); - this.isViewCreated = false; - } - }); - } - - static ngTemplateGuard_appIfLoaded( - dir: IfLoadedDirective, - state: LoadingState, - ): state is Loaded { - return true; - } -} diff --git a/adev/src/content/examples/structural-directives/src/app/loading-state.ts b/adev/src/content/examples/structural-directives/src/app/loading-state.ts deleted file mode 100644 index a5adbfe2d29..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/loading-state.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type Loaded = {type: 'loaded'; data: T}; - -export type Loading = {type: 'loading'}; - -export type LoadingState = Loaded | Loading; diff --git a/adev/src/content/examples/structural-directives/src/app/scrap.txt b/adev/src/content/examples/structural-directives/src/app/scrap.txt deleted file mode 100644 index d3773b72638..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/scrap.txt +++ /dev/null @@ -1,20 +0,0 @@ -// interesting but unused code - heroChooser(picker: HTMLFieldSetElement) { - let choices = picker.children; - this.favoriteHero = undefined; - for (let i = 0; i < choices.length; i++) { - let choice = choices[i].children[0] as HTMLInputElement; - if (choice.checked) { this.favoriteHero = this.heroes[i]; } - } - } - -

Switch with *ngFor repeated switchCases using <ng-container>

- -
- Your favorite hero is ... - - {{hero.name}} - - None of the above -
- diff --git a/adev/src/content/examples/structural-directives/src/app/trigonometry.directive.ts b/adev/src/content/examples/structural-directives/src/app/trigonometry.directive.ts deleted file mode 100644 index f209f0563da..00000000000 --- a/adev/src/content/examples/structural-directives/src/app/trigonometry.directive.ts +++ /dev/null @@ -1,47 +0,0 @@ -import {Directive, effect, input, TemplateRef, ViewContainerRef} from '@angular/core'; - -@Directive({ - selector: '[appTrigonometry]', -}) -export class TrigonometryDirective { - private isViewCreated = false; - private readonly context = new TrigonometryContext(); - - angleInDegrees = input.required({alias: 'appTrigonometry'}); - - constructor( - private readonly viewContainerRef: ViewContainerRef, - private readonly templateRef: TemplateRef, - ) { - effect(() => { - const angleInRadians = toRadians(this.angleInDegrees()); - this.context.sin = Math.sin(angleInRadians); - this.context.cos = Math.cos(angleInRadians); - this.context.tan = Math.tan(angleInRadians); - - if (!this.isViewCreated) { - this.viewContainerRef.createEmbeddedView(this.templateRef, this.context); - this.isViewCreated = true; - } - }); - } - - // Make sure the template checker knows the type of the context with which the - // template of this directive will be rendered - static ngTemplateContextGuard( - directive: TrigonometryDirective, - context: unknown, - ): context is TrigonometryContext { - return true; - } -} - -class TrigonometryContext { - sin = 0; - cos = 0; - tan = 0; -} - -function toRadians(degrees: number): number { - return degrees * (Math.PI / 180); -} diff --git a/adev/src/content/examples/structural-directives/src/index.html b/adev/src/content/examples/structural-directives/src/index.html deleted file mode 100644 index 653c268a6c2..00000000000 --- a/adev/src/content/examples/structural-directives/src/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Angular Structural Directives - - - - - - - - - diff --git a/adev/src/content/examples/structural-directives/src/main.ts b/adev/src/content/examples/structural-directives/src/main.ts deleted file mode 100644 index 9f16c6cce60..00000000000 --- a/adev/src/content/examples/structural-directives/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {bootstrapApplication} from '@angular/platform-browser'; - -import {AppComponent} from './app/app.component'; - -bootstrapApplication(AppComponent).catch((err) => console.error(err)); diff --git a/adev/src/content/examples/structural-directives/stackblitz.json b/adev/src/content/examples/structural-directives/stackblitz.json deleted file mode 100644 index 1580621675f..00000000000 --- a/adev/src/content/examples/structural-directives/stackblitz.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "description": "Structural directives", - "files": [ - "!**/*.d.ts", - "!**/*.js", - "!src/app/scrap.txt" - ], - "file": "src/app/app.component.ts", - "tags": [ - "structural", "directives", "template", "ngIf", - "ngSwitch", "ngFor" - ] -} diff --git a/adev/src/content/examples/tsconfig.eslint.json b/adev/src/content/examples/tsconfig.eslint.json deleted file mode 100644 index 4f4c8658c50..00000000000 --- a/adev/src/content/examples/tsconfig.eslint.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../../tools/examples/shared/boilerplate/cli/tsconfig.json", - "include": [ - "*/**/*.ts", - ], -} diff --git a/adev/src/content/examples/v21-game-world/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/v21-game-world/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 1fd7b079418..00000000000 --- a/adev/src/content/examples/v21-game-world/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,204 +0,0 @@ -import * as webdriver from 'selenium-webdriver'; - -describe('Angular v21 World', () => { - let driver: webdriver.WebDriver; - - const isPresent = async (locator: webdriver.Locator) => { - const els = await driver.findElements(locator); - return els.length > 0; - }; - - const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); - - beforeEach(async () => { - await driver.get(''); - }); - - async function getCharacterPosition(): Promise<{x: string; y: string}> { - const character = await driver.findElement(webdriver.By.css('.character')); - const left = await character.getCssValue('left'); - const top = await character.getCssValue('top'); - return {x: left, y: top}; - } - - it('should display the initial game state correctly', async () => { - // Character is visible - expect(await (await driver.findElement(webdriver.By.css('.character'))).isDisplayed()).toBe( - true, - ); - - // Info sign is shown with welcome message - const infoSign = await driver.findElement(webdriver.By.css('.info-sign')); - expect(await infoSign.isDisplayed()).toBe(true); - expect(await infoSign.getAttribute('src')).toContain('welcome-sign.png'); - - // D-pad is visible - expect(await (await driver.findElement(webdriver.By.css('.d-pad'))).isDisplayed()).toBe(true); - - // Explore button is not visible - expect(await isPresent(webdriver.By.css('.explore-button'))).toBe(false); - - // No keys are present - expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(0); - }); - - it('should move the character with the D-pad buttons', async () => { - const initialPosition = await getCharacterPosition(); - const leftButton = await driver.findElement(webdriver.By.css('.d-pad-button.left')); - - // Hold the button down for a short period to simulate walking - await driver.actions().move({origin: leftButton}).press().perform(); - await sleep(200); - await driver.actions().release().perform(); - - const newPosition = await getCharacterPosition(); - expect(newPosition.x).not.toEqual(initialPosition.x); - }); - - it('should move the character with keyboard arrow keys', async () => { - const initialPosition = await getCharacterPosition(); - - // Send arrow key press - const body = await driver.findElement(webdriver.By.css('body')); - await body.sendKeys(webdriver.Key.ARROW_RIGHT); - await sleep(200); - - const newPosition = await getCharacterPosition(); - expect(newPosition.x).not.toEqual(initialPosition.x); - }); - - it('should show explore button, open dialog, and collect a key when a destination is reached', async () => { - const body = await driver.findElement(webdriver.By.css('body')); - - // Move left until we reach the Palm Tree destination - for (let i = 0; i < 20; i++) { - await body.sendKeys(webdriver.Key.ARROW_LEFT); - await sleep(100); - } - - // Wait for the explore button to appear and check info sign - const exploreButtonLocator = webdriver.By.css('.explore-button'); - await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000); - const exploreButton = await driver.findElement(exploreButtonLocator); - expect(await exploreButton.isDisplayed()).toBe(true); - expect( - await (await driver.findElement(webdriver.By.css('.info-sign'))).getAttribute('src'), - ).toContain('enter-sign.png'); - - // Click explore button to open dialog - await exploreButton.click(); - const dialogLocator = webdriver.By.css('.dialog-overlay'); - await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000); - const dialog = await driver.findElement(dialogLocator); - expect(await dialog.isDisplayed()).toBe(true); - expect(await (await dialog.findElement(webdriver.By.css('h2'))).getText()).toEqual( - "What's new in Angular AI", - ); - - // Close the dialog - await (await dialog.findElement(webdriver.By.css('.close-button'))).click(); - await driver.wait(async () => !(await isPresent(dialogLocator)), 1000); - expect(await isPresent(dialogLocator)).toBe(false); - - // Check that one key has been collected - expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(1); - }); - - it('should show entry denied at castle without all keys', async () => { - const body = await driver.findElement(webdriver.By.css('body')); - - // Move to a position near the castle without collecting keys - for (let i = 0; i < 20; i++) { - await body.sendKeys(webdriver.Key.ARROW_RIGHT); - await sleep(100); - } - for (let i = 0; i < 20; i++) { - await body.sendKeys(webdriver.Key.ARROW_DOWN); - await sleep(100); - } - - await sleep(1000); // Settle - - // Check that the entry denied sign is shown and the button is not present - expect( - await (await driver.findElement(webdriver.By.css('.info-sign'))).getAttribute('src'), - ).toContain('entry-denied-sign.png'); - expect(await isPresent(webdriver.By.css('.explore-button'))).toBe(false); - }); - - it('should handle the full game flow and show congrats state', async () => { - const body = await driver.findElement(webdriver.By.css('body')); - const exploreButtonLocator = webdriver.By.css('.explore-button'); - const dialogLocator = webdriver.By.css('.dialog-overlay'); - const mascotLocator = webdriver.By.css('.mascot-icon'); - - // **Navigate to Palm Tree (d1) and collect the first key** - for (let i = 0; i < 20; i++) { - await body.sendKeys(webdriver.Key.ARROW_LEFT); - await sleep(100); - } - await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000); - await (await driver.findElement(exploreButtonLocator)).click(); - await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000); - let dialog = await driver.findElement(dialogLocator); - await (await dialog.findElement(webdriver.By.css('.close-button'))).click(); - await driver.wait(async () => !(await isPresent(dialogLocator)), 1000); - expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(1); - - // **Navigate to Red Door (d2) and collect the second key** - for (let i = 0; i < 15; i++) { - await body.sendKeys(webdriver.Key.ARROW_UP); - await sleep(100); - } - await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000); - await (await driver.findElement(exploreButtonLocator)).click(); - await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000); - dialog = await driver.findElement(dialogLocator); - await (await dialog.findElement(webdriver.By.css('.close-button'))).click(); - await driver.wait(async () => !(await isPresent(dialogLocator)), 1000); - expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(2); - - // **Navigate to Volcano (d3) and collect the third key** - for (let i = 0; i < 25; i++) { - await body.sendKeys(webdriver.Key.ARROW_RIGHT); - await sleep(100); - } - await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000); - await (await driver.findElement(exploreButtonLocator)).click(); - await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000); - dialog = await driver.findElement(dialogLocator); - await (await dialog.findElement(webdriver.By.css('.close-button'))).click(); - await driver.wait(async () => !(await isPresent(dialogLocator)), 1000); - expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(3); - - // **Navigate to Castle (d4) with all keys** - for (let i = 0; i < 15; i++) { - await body.sendKeys(webdriver.Key.ARROW_DOWN); - await sleep(100); - } - await sleep(1000); // Wait for character to settle - - // Check for correct sign and button visibility - expect( - await (await driver.findElement(webdriver.By.css('.info-sign'))).getAttribute('src'), - ).toContain('castle-sign.png'); - await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000); - - // **Open Castle dialog, close it, and see mascot and final sign** - await (await driver.findElement(exploreButtonLocator)).click(); - await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000); - dialog = await driver.findElement(dialogLocator); - await (await dialog.findElement(webdriver.By.css('.close-button'))).click(); - await driver.wait(async () => !(await isPresent(dialogLocator)), 1000); - - // Mascot appears - await driver.wait(webdriver.until.elementLocated(mascotLocator), 1000); - const mascot = await driver.findElement(mascotLocator); - expect(await mascot.isDisplayed()).toBe(true); - - // Congrats sign appears - expect( - await (await driver.findElement(webdriver.By.css('.info-sign'))).getAttribute('src'), - ).toContain('congrats-sign.png'); - }); -});