diff --git a/packages/components/package.json b/packages/components/package.json index 6081e4dacc7..5b7a61a3519 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -62,6 +62,7 @@ "ember-concurrency": "^4.0.4", "ember-element-helper": "^0.8.6", "ember-focus-trap": "^1.1.1", + "ember-intl": "^7.3.0", "ember-modifier": "^4.2.2", "ember-power-select": "^8.7.1", "ember-stargate": "^1.0.2", @@ -94,7 +95,6 @@ "babel-plugin-ember-template-compilation": "^2.4.1", "concurrently": "^9.1.2", "ember-basic-dropdown": "^8.6.1", - "ember-intl": "^7.3.0", "ember-source": "^6.4.0", "ember-template-lint": "^7.0.2", "ember-template-lint-plugin-prettier": "^5.0.0", diff --git a/packages/components/src/components/hds/advanced-table/index.ts b/packages/components/src/components/hds/advanced-table/index.ts index a5bfae87784..a41d38c219b 100644 --- a/packages/components/src/components/hds/advanced-table/index.ts +++ b/packages/components/src/components/hds/advanced-table/index.ts @@ -10,6 +10,7 @@ import { tracked } from '@glimmer/tracking'; import { guidFor } from '@ember/object/internals'; import { service } from '@ember/service'; import { modifier } from 'ember-modifier'; +import { isDestroyed, isDestroying } from '@ember/destroyable'; import HdsAdvancedTableTableModel from './models/table.ts'; import type Owner from '@ember/owner'; @@ -559,7 +560,7 @@ export default class HdsAdvancedTable extends Component { } } - async resolveLinkToExternal() { - this.linkToExternal = await hdsResolveLinkToExternal( - this.args.isRouteExternal - ); + resolveLinkToExternal() { + this.linkToExternal = hdsResolveLinkToExternal(this.args.isRouteExternal); } /** * Determines if a @href value is "external" (it adds target="_blank" rel="noopener noreferrer") diff --git a/packages/components/src/services/hds-intl.ts b/packages/components/src/services/hds-intl.ts index d126b94486c..2b29ef35b5b 100644 --- a/packages/components/src/services/hds-intl.ts +++ b/packages/components/src/services/hds-intl.ts @@ -4,7 +4,7 @@ */ import Service from '@ember/service'; -import { getOwner } from '@ember/owner'; +import { service } from '@ember/service'; import { isPresent } from '@ember/utils'; import { assert } from '@ember/debug'; @@ -18,18 +18,7 @@ export type HdsIntlTOptions = FormatMessageParameters[1] & { }; export default class HdsIntlService extends Service { - get intl(): IntlService | undefined { - const owner = getOwner(this); - - if ( - typeof owner?.factoryFor === 'function' && - owner.factoryFor('service:intl') - ) { - return owner.lookup('service:intl'); - } - - return undefined; - } + @service('intl') declare intl: IntlService; t(key: string, options: HdsIntlTOptions): string { const { default: defaultString, ...restOptions } = options; diff --git a/packages/components/src/utils/hds-resolve-link-to-external.ts b/packages/components/src/utils/hds-resolve-link-to-external.ts index 100a416495b..3b31193bb06 100644 --- a/packages/components/src/utils/hds-resolve-link-to-external.ts +++ b/packages/components/src/utils/hds-resolve-link-to-external.ts @@ -5,26 +5,29 @@ import { LinkTo } from '@ember/routing'; import { assert } from '@ember/debug'; +import { + dependencySatisfies, + macroCondition, + importSync, +} from '@embroider/macros'; /** * Resolves the correct component to use for the `LinkTo`. * * @param isRouteExternal - If true, will return the `LinkToExternal` component. If `ember-engines` is not installed, an assertion will be thrown. - * @returns A promise resolving to the correct component to use for the `LinkTo`. + * @returns The correct component to use for the `LinkTo`. */ -export async function hdsResolveLinkToExternal( +export function hdsResolveLinkToExternal( isRouteExternal?: boolean -): Promise { +): typeof LinkTo { if (isRouteExternal) { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const mod = await import( - // @ts-expect-error: we list this as optional peer dependency + if (macroCondition(dependencySatisfies('ember-engines', '*'))) { + // Use importSync for compile-time conditional import + const module = importSync( 'ember-engines/components/link-to-external-component' - ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - return mod.default as typeof LinkTo; - } catch { + ) as { default: typeof LinkTo }; + return module.default; + } else { assert( `@isRouteExternal is only available when using the "ember-engines" addon. Please install it to use this feature.`, false diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad1b87b62f9..dfb690f53f7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -151,6 +151,9 @@ importers: ember-focus-trap: specifier: ^1.1.1 version: 1.1.1(ember-source@6.5.0(@glimmer/component@2.0.0)(rsvp@4.8.5)) + ember-intl: + specifier: ^7.3.0 + version: 7.3.1(@ember/test-helpers@4.0.5(@babel/core@7.28.0)(@glint/template@1.5.2)(ember-source@6.5.0(@glimmer/component@2.0.0)(rsvp@4.8.5)))(@glint/template@1.5.2)(typescript@5.9.2)(webpack@5.101.0) ember-modifier: specifier: ^4.2.2 version: 4.2.2(@babel/core@7.28.0) @@ -242,9 +245,6 @@ importers: ember-basic-dropdown: specifier: ^8.6.1 version: 8.6.2(@babel/core@7.28.0)(@ember/string@4.0.1)(@ember/test-helpers@4.0.5(@babel/core@7.28.0)(@glint/template@1.5.2)(ember-source@6.5.0(@glimmer/component@2.0.0)(rsvp@4.8.5)))(@glimmer/component@2.0.0)(@glint/environment-ember-loose@1.5.2(@glimmer/component@2.0.0)(@glint/template@1.5.2)(ember-cli-htmlbars@6.3.0)(ember-modifier@4.2.2(@babel/core@7.28.0)))(@glint/template@1.5.2)(ember-source@6.5.0(@glimmer/component@2.0.0)(rsvp@4.8.5)) - ember-intl: - specifier: ^7.3.0 - version: 7.3.1(@ember/test-helpers@4.0.5(@babel/core@7.28.0)(@glint/template@1.5.2)(ember-source@6.5.0(@glimmer/component@2.0.0)(rsvp@4.8.5)))(@glint/template@1.5.2)(typescript@5.9.2)(webpack@5.101.0) ember-source: specifier: ^6.4.0 version: 6.5.0(@glimmer/component@2.0.0)(rsvp@4.8.5) diff --git a/showcase/tests/integration/components/hds/advanced-table/index-test.js b/showcase/tests/integration/components/hds/advanced-table/index-test.js index a2a3e91adcc..888edfd7d27 100644 --- a/showcase/tests/integration/components/hds/advanced-table/index-test.js +++ b/showcase/tests/integration/components/hds/advanced-table/index-test.js @@ -376,7 +376,8 @@ const hbsNestedAdvancedTable = hbs` `; -const hbsResizableColumnsAdvancedTable = hbs`
+const hbsResizableColumnsAdvancedTable = hbs`{{!-- template-lint-disable no-inline-styles --}} +
@@ -386,7 +387,7 @@ const hbsResizableColumnsAdvancedTable = hbs`
{{B.data.col2}} -
`; +
{{!-- template-lint-enable no-inline-styles --}}`; module('Integration | Component | hds/advanced-table/index', function (hooks) { setupRenderingTest(hooks); @@ -727,10 +728,14 @@ module('Integration | Component | hds/advanced-table/index', function (hooks) { ); await focus(firstThElement); await focus(firstReorderHandle); + // need to flush the frame to let the RAF waiter finish doing its thing + await new Promise((resolve) => requestAnimationFrame(resolve)); + assert.dom(firstReorderHandle).isFocused(); await triggerKeyEvent(firstReorderHandle, 'keydown', 'ArrowRight'); let columnOrder = await getColumnOrder(this.columns); + await settled(); assert.deepEqual( columnOrder, [this.columns[1].key, this.columns[0].key, this.columns[2].key], @@ -740,6 +745,8 @@ module('Integration | Component | hds/advanced-table/index', function (hooks) { await triggerKeyEvent(firstReorderHandle, 'keydown', 'ArrowRight'); columnOrder = await getColumnOrder(this.columns); + // doing this because request animation frame stuff + await settled(); assert.deepEqual( columnOrder, [this.columns[1].key, this.columns[2].key, this.columns[0].key], @@ -749,6 +756,7 @@ module('Integration | Component | hds/advanced-table/index', function (hooks) { await triggerKeyEvent(firstReorderHandle, 'keydown', 'ArrowLeft'); columnOrder = await getColumnOrder(this.columns); + await settled(); assert.deepEqual( columnOrder, [this.columns[1].key, this.columns[0].key, this.columns[2].key], @@ -842,7 +850,7 @@ module('Integration | Component | hds/advanced-table/index', function (hooks) { ]; // when dealing with dynamic columns, you must handle the order of all potential columns rather than just the ones currently rendered - // inital column order is 'artist', 'album', 'year', 'genre' + // initial column order is 'artist', 'album', 'year', 'genre' const initialColumnOrder = availableColumns.map((col) => col.key); // initially set the columns in the reverse order to ensure the table respects the column order and ommit the genre column @@ -876,6 +884,7 @@ module('Integration | Component | hds/advanced-table/index', function (hooks) { // make sure the initial column order is correct based on the columnOrder let columnOrder = await getColumnOrder(this.columns); + await settled(); assert.deepEqual( columnOrder, ['artist', 'album', 'year'], diff --git a/showcase/tests/integration/components/hds/dropdown/toggle/icon-test.js b/showcase/tests/integration/components/hds/dropdown/toggle/icon-test.js index da588ef9110..e03d2bc1f71 100644 --- a/showcase/tests/integration/components/hds/dropdown/toggle/icon-test.js +++ b/showcase/tests/integration/components/hds/dropdown/toggle/icon-test.js @@ -3,13 +3,13 @@ * SPDX-License-Identifier: MPL-2.0 */ -import { module, skip, test } from 'qunit'; +import { module, test } from 'qunit'; import { setupRenderingTest } from 'showcase/tests/helpers'; import { render, resetOnerror, - settled, setupOnerror, + waitFor, } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; @@ -40,21 +40,22 @@ module('Integration | Component | hds/dropdown/toggle/icon', function (hooks) { // IMAGE (AVATAR) - test('if an @imageSrc is declared and exists the image should render in the component', async function (assert) { + test('if an @imageSrc is declared and also exists, the image should render in the component', async function (assert) { await render( hbs``, ); assert.dom('img').exists(); }); - skip('if an @imageSrc is declared but does not exist, the flight icon should render in the component', async function (assert) { - this.set('imageSrc', '/assets/images/avatar.png'); + // Need the extra await settled here because the test is flaky otherwise; would fail 1/6 times the test was run. After adding the extra settled, ran the test 20 times in a row and the test passed each time. + test('if an @imageSrc is declared but the file does not exist, the user icon should render in the component', async function (assert) { await render( - hbs``, + hbs``, ); - // we load the image dynamically to cover this usecase and also to prevent this test from intermittently failing for no obvious reason - this.set('imageSrc', '/assets/images/avatar-broken.png'); - await settled(); + + await waitFor('.hds-icon.hds-icon-user'); assert.dom('img').doesNotExist(); assert.dom('#test-toggle-icon .hds-icon.hds-icon-user').exists(); }); diff --git a/showcase/tests/integration/components/hds/popover-primitive/index-test.js b/showcase/tests/integration/components/hds/popover-primitive/index-test.js index 98a98dcdfd5..42fce3e8920 100644 --- a/showcase/tests/integration/components/hds/popover-primitive/index-test.js +++ b/showcase/tests/integration/components/hds/popover-primitive/index-test.js @@ -169,6 +169,7 @@ module( .dom('[data-test-id="popover-content"]') .isNotVisible('The popover is hidden again by the new toggle'); }); + // we have to skip this test because no CSS classes are applied to the popover primitive but I want to leave this test here so we don't think a test is missing. skip('it should toggle the popover visibility on click', async function (assert) { await render(hbs` @@ -207,7 +208,7 @@ module( as |PP| >
-