Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { logWarning } from './warning-helper';

const warnedUsages = new Set<string>();

const NESTED_CLASS_NAME_REGEXP = /^(Dx[io][A-Z]\w+)Component$/;
const NESTED_CLASS_NAME_REGEXP = /^_*(Dx[io][A-Z]\w+)Component$/;

type DeprecatedConfigEntry = Record<string, string>;

Expand All @@ -32,7 +32,7 @@ function getHostMapping(host: INestedOptionContainer | undefined): DeprecatedCon
while (current && !visited.has(current)) {
visited.add(current);

const ctorName = current.constructor?.name;
const ctorName = current.constructor?.name?.replace(/^_+/, '');
if (ctorName && Object.prototype.hasOwnProperty.call(DEPRECATED_CONFIG_COMPONENTS, ctorName)) {
return DEPRECATED_CONFIG_COMPONENTS[ctorName] as DeprecatedConfigEntry;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { NestedOptionHost } from 'devextreme-angular';

// The warning is reached through NestedOptionHost.setNestedOption(), so these
// tests drive the real integration point rather than the internal helper.
//
// esbuild renames a class that self-references in its decorator metadata to
// `_ClassName`, so at runtime `constructor.name` is `_DxiItemComponent` /
// `_DxAccordionComponent`. We fake that here to lock in the underscore-tolerant
// lookup in getLegacySelector (regex) and getHostMapping (map key normalization).

function fakeHost(ctorName: string): any {
return { constructor: { name: ctorName } };
}

function fakeNestedOption(ctorName: string): any {
return {
constructor: { name: ctorName },
// setNestedOption calls this before warning; a no-op is enough.
setHost() {},
};
}

describe('deprecated nested config warning', () => {
let warnSpy: jasmine.Spy;

beforeEach(() => {
warnSpy = spyOn(console, 'warn');
});

it('resolves the legacy mapping and warns exactly once when esbuild prefixes class names with "_"', () => {
const host = new NestedOptionHost();
host.setHost(fakeHost('_DxAccordionComponent'));

// Register the same legacy usage twice: the cache must collapse it to one warning.
host.setNestedOption(fakeNestedOption('_DxiItemComponent'));
host.setNestedOption(fakeNestedOption('_DxiItemComponent'));

expect(warnSpy).toHaveBeenCalledTimes(1);

const message = warnSpy.calls.mostRecent().args[0] as string;
expect(message).toContain('W3001');
expect(message).toContain('legacy dxi-item');
expect(message).toContain('dxi-accordion-item');
});

it('does not warn when the new named configuration component is used', () => {
const host = new NestedOptionHost();
host.setHost(fakeHost('_DxAccordionComponent'));

host.setNestedOption(fakeNestedOption('_DxiAccordionItemComponent'));

expect(warnSpy).not.toHaveBeenCalled();
});
});
Loading