From 313c2520f2a76529da3a3adb333281946f3e2152 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Tue, 17 Sep 2019 09:07:13 -0700 Subject: [PATCH] feat(menu): move test harness out of experimental --- .../mdc-menu/BUILD.bazel | 17 +-- .../mdc-menu/harness/BUILD.bazel | 35 ++++++ .../mdc-menu/harness/index.ts | 9 ++ .../mdc-menu/harness/menu-harness.spec.ts | 117 +----------------- .../mdc-menu/harness/menu-harness.ts | 4 +- .../mdc-menu/harness/menu-item-harness.ts | 4 +- .../mdc-menu/harness/public-api.ts | 10 ++ src/material/menu/testing/BUILD.bazel | 47 +++++++ src/material/menu/testing/index.ts | 9 ++ .../menu/testing}/menu-harness-filters.ts | 0 .../menu/testing/menu-harness.spec.ts | 7 ++ .../menu/testing/menu-harness.ts} | 4 +- .../menu/testing/menu-item-harness.ts} | 4 +- src/material/menu/testing/public-api.ts | 11 ++ src/material/menu/testing/shared.spec.ts | 91 ++++++++++++++ test/karma-system-config.js | 2 + 16 files changed, 234 insertions(+), 137 deletions(-) create mode 100644 src/material-experimental/mdc-menu/harness/BUILD.bazel create mode 100644 src/material-experimental/mdc-menu/harness/index.ts create mode 100644 src/material-experimental/mdc-menu/harness/public-api.ts create mode 100644 src/material/menu/testing/BUILD.bazel create mode 100644 src/material/menu/testing/index.ts rename src/{material-experimental/mdc-menu/harness => material/menu/testing}/menu-harness-filters.ts (100%) create mode 100644 src/material/menu/testing/menu-harness.spec.ts rename src/{material-experimental/mdc-menu/harness/mdc-menu-harness.ts => material/menu/testing/menu-harness.ts} (95%) rename src/{material-experimental/mdc-menu/harness/mdc-menu-item-harness.ts => material/menu/testing/menu-item-harness.ts} (90%) create mode 100644 src/material/menu/testing/public-api.ts create mode 100644 src/material/menu/testing/shared.spec.ts diff --git a/src/material-experimental/mdc-menu/BUILD.bazel b/src/material-experimental/mdc-menu/BUILD.bazel index 2ed61bec3c3e..b6572ce11092 100644 --- a/src/material-experimental/mdc-menu/BUILD.bazel +++ b/src/material-experimental/mdc-menu/BUILD.bazel @@ -2,7 +2,7 @@ package(default_visibility = ["//visibility:public"]) load("@io_bazel_rules_sass//:defs.bzl", "sass_binary", "sass_library") load("//src/e2e-app:test_suite.bzl", "e2e_test_suite") -load("//tools:defaults.bzl", "ng_e2e_test_library", "ng_module", "ng_test_library", "ng_web_test_suite", "ts_library") +load("//tools:defaults.bzl", "ng_e2e_test_library", "ng_module", "ng_test_library", "ng_web_test_suite") ng_module( name = "mdc-menu", @@ -10,7 +10,6 @@ ng_module( ["**/*.ts"], exclude = [ "**/*.spec.ts", - "harness/**", ], ), assets = [":menu_scss"] + glob(["**/*.html"]), @@ -25,18 +24,6 @@ ng_module( ], ) -ts_library( - name = "harness", - srcs = glob( - ["harness/**/*.ts"], - exclude = ["**/*.spec.ts"], - ), - deps = [ - "//src/cdk/coercion", - "//src/cdk/testing", - ], -) - sass_library( name = "mdc_menu_scss_lib", srcs = glob(["**/_*.scss"]), @@ -65,7 +52,6 @@ ng_test_library( exclude = ["**/*.e2e.spec.ts"], ), deps = [ - ":harness", ":mdc-menu", "//src/cdk/a11y", "//src/cdk/bidi", @@ -74,7 +60,6 @@ ng_test_library( "//src/cdk/private/testing", "//src/cdk/scrolling", "//src/cdk/testing", - "//src/cdk/testing/testbed", "//src/material/core", "//src/material/menu", "@npm//@angular/platform-browser", diff --git a/src/material-experimental/mdc-menu/harness/BUILD.bazel b/src/material-experimental/mdc-menu/harness/BUILD.bazel new file mode 100644 index 000000000000..0a7360c03f20 --- /dev/null +++ b/src/material-experimental/mdc-menu/harness/BUILD.bazel @@ -0,0 +1,35 @@ +package(default_visibility = ["//visibility:public"]) + +load("//tools:defaults.bzl", "ng_module", "ng_test_library", "ng_web_test_suite") + +ng_module( + name = "testing", + srcs = glob( + ["**/*.ts"], + exclude = ["**/*.spec.ts"], + ), + module_name = "@angular/material-experimental/mdc-menu/testing", + deps = [ + "//src/cdk/coercion", + "//src/cdk/testing", + "//src/material/menu/testing", + ], +) + +ng_test_library( + name = "unit_tests_lib", + srcs = glob(["**/*.spec.ts"]), + deps = [ + ":testing", + "//src/material-experimental/mdc-menu", + "//src/material/menu/testing:harness_tests_lib", + ], +) + +ng_web_test_suite( + name = "unit_tests", + deps = [ + ":unit_tests_lib", + "//src/material-experimental:mdc_require_config.js", + ], +) diff --git a/src/material-experimental/mdc-menu/harness/index.ts b/src/material-experimental/mdc-menu/harness/index.ts new file mode 100644 index 000000000000..676ca90f1ffa --- /dev/null +++ b/src/material-experimental/mdc-menu/harness/index.ts @@ -0,0 +1,9 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './public-api'; diff --git a/src/material-experimental/mdc-menu/harness/menu-harness.spec.ts b/src/material-experimental/mdc-menu/harness/menu-harness.spec.ts index ce10815a3806..df3d4f2f578d 100644 --- a/src/material-experimental/mdc-menu/harness/menu-harness.spec.ts +++ b/src/material-experimental/mdc-menu/harness/menu-harness.spec.ts @@ -1,116 +1,7 @@ -import {HarnessLoader} from '@angular/cdk/testing'; -import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; -import {Component, Type} from '@angular/core'; -import {ComponentFixture, TestBed, inject} from '@angular/core/testing'; -import {MatMenuModule} from '@angular/material/menu'; -import {OverlayContainer} from '@angular/cdk/overlay'; -import {MatMenuModule as MatMdcMenuModule} from '../index'; -import {MatMenuHarness as MatMdcMenuHarness} from './mdc-menu-harness'; +import {runHarnessTests} from '@angular/material/menu/testing/shared.spec'; +import {MatMenuModule} from '../index'; import {MatMenuHarness} from './menu-harness'; -let fixture: ComponentFixture; -let loader: HarnessLoader; -let menuHarness: typeof MatMenuHarness; -let overlayContainer: OverlayContainer; - -describe('MatMenuHarness', () => { - describe('non-MDC-based', () => { - beforeEach(async () => { - await prepareTests(MatMenuModule, MenuHarnessTest); - menuHarness = MatMenuHarness; - }); - - runTests(); - }); - - describe('MDC-based', () => { - beforeEach(async () => { - await prepareTests(MatMdcMenuModule, MenuHarnessTest); - // Public APIs are the same as MatMenuHarness, but cast is necessary because of different - // private fields. - menuHarness = MatMdcMenuHarness as any; - }); - - runTests(); - }); +describe('MDC-based MatMenuHarness', () => { + runHarnessTests(MatMenuModule, MatMenuHarness); }); - -/** Shared test setup logic. */ -async function prepareTests(moduleType: Type, fixtureType: Type) { - await TestBed.configureTestingModule({ - imports: [moduleType], - declarations: [fixtureType], - }).compileComponents(); - - fixture = TestBed.createComponent(fixtureType); - fixture.detectChanges(); - loader = TestbedHarnessEnvironment.loader(fixture); - inject([OverlayContainer], (oc: OverlayContainer) => { - overlayContainer = oc; - })(); -} - -/** Shared tests to run on both the original and MDC-based menues. */ -function runTests() { - afterEach(() => { - // Angular won't call this for us so we need to do it ourselves to avoid leaks. - overlayContainer.ngOnDestroy(); - overlayContainer = null!; - }); - - it('should load all menu harnesses', async () => { - const menues = await loader.getAllHarnesses(menuHarness); - expect(menues.length).toBe(2); - }); - - it('should load menu with exact text', async () => { - const menus = await loader.getAllHarnesses(menuHarness.with({triggerText: 'Settings'})); - expect(menus.length).toBe(1); - expect(await menus[0].getTriggerText()).toBe('Settings'); - }); - - it('should load menu with regex label match', async () => { - const menus = await loader.getAllHarnesses(menuHarness.with({triggerText: /settings/i})); - expect(menus.length).toBe(1); - expect(await menus[0].getTriggerText()).toBe('Settings'); - }); - - it('should get disabled state', async () => { - const [enabledMenu, disabledMenu] = await loader.getAllHarnesses(menuHarness); - expect(await enabledMenu.isDisabled()).toBe(false); - expect(await disabledMenu.isDisabled()).toBe(true); - }); - - it('should get menu text', async () => { - const [firstMenu, secondMenu] = await loader.getAllHarnesses(menuHarness); - expect(await firstMenu.getTriggerText()).toBe('Settings'); - expect(await secondMenu.getTriggerText()).toBe('Disabled menu'); - }); - - it('should focus and blur a menu', async () => { - const menu = await loader.getHarness(menuHarness.with({triggerText: 'Settings'})); - expect(getActiveElementId()).not.toBe('settings'); - await menu.focus(); - expect(getActiveElementId()).toBe('settings'); - await menu.blur(); - expect(getActiveElementId()).not.toBe('settings'); - }); -} - -function getActiveElementId() { - return document.activeElement ? document.activeElement.id : ''; -} - -@Component({ - template: ` - - - - - Profile - Account - - ` -}) -class MenuHarnessTest { } - diff --git a/src/material-experimental/mdc-menu/harness/menu-harness.ts b/src/material-experimental/mdc-menu/harness/menu-harness.ts index d9b245d269b7..6f1daaa6e510 100644 --- a/src/material-experimental/mdc-menu/harness/menu-harness.ts +++ b/src/material-experimental/mdc-menu/harness/menu-harness.ts @@ -8,11 +8,11 @@ import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; -import {MenuHarnessFilters} from './menu-harness-filters'; import {MatMenuItemHarness} from './menu-item-harness'; +import {MenuHarnessFilters} from '@angular/material/menu/testing/menu-harness-filters'; /** - * Harness for interacting with a standard mat-menu in tests. + * Harness for interacting with a MDC-based mat-menu in tests. * @dynamic */ export class MatMenuHarness extends ComponentHarness { diff --git a/src/material-experimental/mdc-menu/harness/menu-item-harness.ts b/src/material-experimental/mdc-menu/harness/menu-item-harness.ts index 224a338e5b8c..74832d91f68d 100644 --- a/src/material-experimental/mdc-menu/harness/menu-item-harness.ts +++ b/src/material-experimental/mdc-menu/harness/menu-item-harness.ts @@ -8,7 +8,7 @@ import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; -import {MenuItemHarnessFilters} from './menu-harness-filters'; +import {MenuItemHarnessFilters} from '@angular/material/menu/testing/menu-harness-filters'; /** @@ -26,7 +26,7 @@ export class MatMenuItemHarness extends ComponentHarness { * @return a `HarnessPredicate` configured with the given options. */ static with(options: MenuItemHarnessFilters = {}): HarnessPredicate { - return new HarnessPredicate(MatMenuItemHarness, options); // TODO: add options here + return new HarnessPredicate(MatMenuItemHarness, options); } /** Gets a boolean promise indicating if the menu is disabled. */ diff --git a/src/material-experimental/mdc-menu/harness/public-api.ts b/src/material-experimental/mdc-menu/harness/public-api.ts new file mode 100644 index 000000000000..51a2a711a677 --- /dev/null +++ b/src/material-experimental/mdc-menu/harness/public-api.ts @@ -0,0 +1,10 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './menu-harness'; +export * from './menu-item-harness'; diff --git a/src/material/menu/testing/BUILD.bazel b/src/material/menu/testing/BUILD.bazel new file mode 100644 index 000000000000..5e238b5de24f --- /dev/null +++ b/src/material/menu/testing/BUILD.bazel @@ -0,0 +1,47 @@ +package(default_visibility = ["//visibility:public"]) + +load("//tools:defaults.bzl", "ng_module", "ng_test_library", "ng_web_test_suite") + +ng_module( + name = "testing", + srcs = glob( + ["**/*.ts"], + exclude = ["**/*.spec.ts"], + ), + module_name = "@angular/material/menu/testing", + deps = [ + "//src/cdk/coercion", + "//src/cdk/testing", + ], +) + +ng_test_library( + name = "harness_tests_lib", + srcs = ["shared.spec.ts"], + deps = [ + ":testing", + "//src/cdk/overlay", + "//src/cdk/testing", + "//src/cdk/testing/testbed", + "//src/material/menu", + "@npm//@angular/platform-browser", + ], +) + +ng_test_library( + name = "unit_tests_lib", + srcs = glob( + ["**/*.spec.ts"], + exclude = ["shared.spec.ts"], + ), + deps = [ + ":harness_tests_lib", + ":testing", + "//src/material/menu", + ], +) + +ng_web_test_suite( + name = "unit_tests", + deps = [":unit_tests_lib"], +) diff --git a/src/material/menu/testing/index.ts b/src/material/menu/testing/index.ts new file mode 100644 index 000000000000..676ca90f1ffa --- /dev/null +++ b/src/material/menu/testing/index.ts @@ -0,0 +1,9 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './public-api'; diff --git a/src/material-experimental/mdc-menu/harness/menu-harness-filters.ts b/src/material/menu/testing/menu-harness-filters.ts similarity index 100% rename from src/material-experimental/mdc-menu/harness/menu-harness-filters.ts rename to src/material/menu/testing/menu-harness-filters.ts diff --git a/src/material/menu/testing/menu-harness.spec.ts b/src/material/menu/testing/menu-harness.spec.ts new file mode 100644 index 000000000000..b9a0163b6846 --- /dev/null +++ b/src/material/menu/testing/menu-harness.spec.ts @@ -0,0 +1,7 @@ +import {MatMenuModule} from '@angular/material/menu'; +import {runHarnessTests} from '@angular/material/menu/testing/shared.spec'; +import {MatMenuHarness} from './menu-harness'; + +describe('Non-MDC-based MatMenuHarness', () => { + runHarnessTests(MatMenuModule, MatMenuHarness); +}); diff --git a/src/material-experimental/mdc-menu/harness/mdc-menu-harness.ts b/src/material/menu/testing/menu-harness.ts similarity index 95% rename from src/material-experimental/mdc-menu/harness/mdc-menu-harness.ts rename to src/material/menu/testing/menu-harness.ts index 5f3b21a0040e..d9b245d269b7 100644 --- a/src/material-experimental/mdc-menu/harness/mdc-menu-harness.ts +++ b/src/material/menu/testing/menu-harness.ts @@ -8,11 +8,11 @@ import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; -import {MatMenuItemHarness} from './mdc-menu-item-harness'; import {MenuHarnessFilters} from './menu-harness-filters'; +import {MatMenuItemHarness} from './menu-item-harness'; /** - * Harness for interacting with a MDC-based mat-menu in tests. + * Harness for interacting with a standard mat-menu in tests. * @dynamic */ export class MatMenuHarness extends ComponentHarness { diff --git a/src/material-experimental/mdc-menu/harness/mdc-menu-item-harness.ts b/src/material/menu/testing/menu-item-harness.ts similarity index 90% rename from src/material-experimental/mdc-menu/harness/mdc-menu-item-harness.ts rename to src/material/menu/testing/menu-item-harness.ts index ca4c7ed50056..fb2babcea5b9 100644 --- a/src/material-experimental/mdc-menu/harness/mdc-menu-item-harness.ts +++ b/src/material/menu/testing/menu-item-harness.ts @@ -8,7 +8,7 @@ import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; -import {MenuItemHarnessFilters} from './menu-harness-filters'; +import {MenuItemHarnessFilters} from '@angular/material/menu/testing/menu-harness-filters'; /** @@ -26,7 +26,7 @@ export class MatMenuItemHarness extends ComponentHarness { * @return a `HarnessPredicate` configured with the given options. */ static with(options: MenuItemHarnessFilters = {}): HarnessPredicate { - return new HarnessPredicate(MatMenuItemHarness, options); + return new HarnessPredicate(MatMenuItemHarness, options); // TODO: add options here } /** Gets a boolean promise indicating if the menu is disabled. */ diff --git a/src/material/menu/testing/public-api.ts b/src/material/menu/testing/public-api.ts new file mode 100644 index 000000000000..86a398009730 --- /dev/null +++ b/src/material/menu/testing/public-api.ts @@ -0,0 +1,11 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './menu-harness'; +export * from './menu-harness-filters'; +export * from './menu-item-harness'; diff --git a/src/material/menu/testing/shared.spec.ts b/src/material/menu/testing/shared.spec.ts new file mode 100644 index 000000000000..2e13c381f909 --- /dev/null +++ b/src/material/menu/testing/shared.spec.ts @@ -0,0 +1,91 @@ +import {OverlayContainer} from '@angular/cdk/overlay'; +import {HarnessLoader} from '@angular/cdk/testing'; +import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; +import {Component} from '@angular/core'; +import {ComponentFixture, inject, TestBed} from '@angular/core/testing'; +import {MatMenuModule} from '@angular/material/menu'; +import {MatMenuHarness} from './menu-harness'; + +/** Shared tests to run on both the original and MDC-based menues. */ +export function runHarnessTests( + menuModule: typeof MatMenuModule, menuHarness: typeof MatMenuHarness) { + let fixture: ComponentFixture; + let loader: HarnessLoader; + let overlayContainer: OverlayContainer; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [menuModule], + declarations: [MenuHarnessTest], + }).compileComponents(); + + fixture = TestBed.createComponent(MenuHarnessTest); + fixture.detectChanges(); + loader = TestbedHarnessEnvironment.loader(fixture); + inject([OverlayContainer], (oc: OverlayContainer) => { + overlayContainer = oc; + })(); + }); + + afterEach(() => { + // Angular won't call this for us so we need to do it ourselves to avoid leaks. + overlayContainer.ngOnDestroy(); + overlayContainer = null!; + }); + + it('should load all menu harnesses', async () => { + const menues = await loader.getAllHarnesses(menuHarness); + expect(menues.length).toBe(2); + }); + + it('should load menu with exact text', async () => { + const menus = await loader.getAllHarnesses(menuHarness.with({triggerText: 'Settings'})); + expect(menus.length).toBe(1); + expect(await menus[0].getTriggerText()).toBe('Settings'); + }); + + it('should load menu with regex label match', async () => { + const menus = await loader.getAllHarnesses(menuHarness.with({triggerText: /settings/i})); + expect(menus.length).toBe(1); + expect(await menus[0].getTriggerText()).toBe('Settings'); + }); + + it('should get disabled state', async () => { + const [enabledMenu, disabledMenu] = await loader.getAllHarnesses(menuHarness); + expect(await enabledMenu.isDisabled()).toBe(false); + expect(await disabledMenu.isDisabled()).toBe(true); + }); + + it('should get menu text', async () => { + const [firstMenu, secondMenu] = await loader.getAllHarnesses(menuHarness); + expect(await firstMenu.getTriggerText()).toBe('Settings'); + expect(await secondMenu.getTriggerText()).toBe('Disabled menu'); + }); + + it('should focus and blur a menu', async () => { + const menu = await loader.getHarness(menuHarness.with({triggerText: 'Settings'})); + expect(getActiveElementId()).not.toBe('settings'); + await menu.focus(); + expect(getActiveElementId()).toBe('settings'); + await menu.blur(); + expect(getActiveElementId()).not.toBe('settings'); + }); +} + +function getActiveElementId() { + return document.activeElement ? document.activeElement.id : ''; +} + +@Component({ + template: ` + + + + + Profile + Account + + ` +}) +class MenuHarnessTest { } + diff --git a/test/karma-system-config.js b/test/karma-system-config.js index 59b810bee89c..8c70bd466160 100644 --- a/test/karma-system-config.js +++ b/test/karma-system-config.js @@ -120,6 +120,8 @@ System.config({ '@angular/material/input': 'dist/packages/material/input/index.js', '@angular/material/list': 'dist/packages/material/list/index.js', '@angular/material/menu': 'dist/packages/material/menu/index.js', + '@angular/material/menu/testing': 'dist/packages/material/menu/testing/index.js', + '@angular/material/menu/testing/shared.spec': 'dist/packages/material/menu/testing/shared.spec.js', '@angular/material/paginator': 'dist/packages/material/paginator/index.js', '@angular/material/progress-bar': 'dist/packages/material/progress-bar/index.js', '@angular/material/progress-spinner': 'dist/packages/material/progress-spinner/index.js',