| // Copyright 2026 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| import {assert} from 'chai'; | |
| import {describe, it} from 'mocha'; | |
| import * as path from 'node:path'; | |
| import {GnLabel} from '../../utils/gn_label.ts'; | |
| describe('GnLabel', () => { | |
| const rootDir = path.resolve('/root'); | |
| const currentDir = path.resolve(rootDir, 'front_end/core/common'); | |
| describe('parse', () => { | |
| it('parses GN labels with target names', () => { | |
| const label = GnLabel.parse('//front_end/core/common:bundle'); | |
| assert.isNotNull(label); | |
| assert.strictEqual(label.dirPath, 'front_end/core/common'); | |
| assert.strictEqual(label.name, 'bundle'); | |
| }); | |
| it('parses GN labels without explicit target names using directory name', () => { | |
| const label = GnLabel.parse('//front_end/core/common'); | |
| assert.isNotNull(label); | |
| assert.strictEqual(label.dirPath, 'front_end/core/common'); | |
| assert.strictEqual(label.name, 'common'); | |
| }); | |
| it('parses root-level GN labels with explicit target names', () => { | |
| const label = GnLabel.parse('//:root_target'); | |
| assert.isNotNull(label); | |
| assert.strictEqual(label.dirPath, ''); | |
| assert.strictEqual(label.name, 'root_target'); | |
| }); | |
| it('parses top-level single directory GN labels without explicit target', () => { | |
| const label = GnLabel.parse('//scripts'); | |
| assert.isNotNull(label); | |
| assert.strictEqual(label.dirPath, 'scripts'); | |
| assert.strictEqual(label.name, 'scripts'); | |
| }); | |
| it('returns null for relative or invalid GN labels', () => { | |
| assert.isNull(GnLabel.parse(':bundle')); | |
| assert.isNull(GnLabel.parse('../common:bundle')); | |
| assert.isNull(GnLabel.parse('front_end/core/common')); | |
| assert.isNull(GnLabel.parse('')); | |
| }); | |
| }); | |
| describe('properties', () => { | |
| it('formats toString as full GN label', () => { | |
| const label = new GnLabel('front_end/core/common', 'bundle'); | |
| assert.strictEqual(label.toString(), '//front_end/core/common:bundle'); | |
| }); | |
| it('computes bundleLabel', () => { | |
| const label = new GnLabel('front_end/core/common', 'other_target'); | |
| assert.strictEqual(label.bundleLabel, '//front_end/core/common:bundle'); | |
| }); | |
| it('computes dirName from dirPath', () => { | |
| const label = new GnLabel('front_end/core/common', 'bundle'); | |
| assert.strictEqual(label.dirName, 'common'); | |
| }); | |
| it('identifies consumer targets correctly', () => { | |
| const consumerLabel = new GnLabel('front_end/core/common', 'bundle'); | |
| assert.isTrue(consumerLabel.isConsumerTarget); | |
| const standardLabel = new GnLabel('front_end/core/common', 'common'); | |
| assert.isFalse(standardLabel.isConsumerTarget); | |
| }); | |
| }); | |
| describe('resolveDeclaredDep', () => { | |
| it('resolves absolute GN labels', () => { | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep( | |
| '//front_end/core/common:bundle', | |
| currentDir, | |
| rootDir, | |
| ), | |
| '//front_end/core/common:bundle', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep( | |
| '//front_end/core/common', | |
| currentDir, | |
| rootDir, | |
| ), | |
| '//front_end/core/common:common', | |
| ); | |
| }); | |
| it('resolves absolute GN labels containing relative path segments', () => { | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep( | |
| '//front_end/core/../core/common:bundle', | |
| currentDir, | |
| rootDir, | |
| ), | |
| '//front_end/core/common:bundle', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep( | |
| '//front_end/core/../core/common', | |
| currentDir, | |
| rootDir, | |
| ), | |
| '//front_end/core/common:common', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep( | |
| '//front_end/panels/timeline/../../core/sdk:bundle', | |
| currentDir, | |
| rootDir, | |
| ), | |
| '//front_end/core/sdk:bundle', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep( | |
| '//front_end/./core/common:bundle', | |
| currentDir, | |
| rootDir, | |
| ), | |
| '//front_end/core/common:bundle', | |
| ); | |
| }); | |
| it('resolves relative target within the current directory', () => { | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep(':bundle', currentDir, rootDir), | |
| '//front_end/core/common:bundle', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep(':common', currentDir, rootDir), | |
| '//front_end/core/common:common', | |
| ); | |
| }); | |
| it('resolves relative paths with explicit target', () => { | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep('../sdk:bundle', currentDir, rootDir), | |
| '//front_end/core/sdk:bundle', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep('./sub_dir:custom', currentDir, rootDir), | |
| '//front_end/core/common/sub_dir:custom', | |
| ); | |
| }); | |
| it('resolves relative paths without explicit target using directory name', () => { | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep('../sdk', currentDir, rootDir), | |
| '//front_end/core/sdk:sdk', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep('./sub_dir', currentDir, rootDir), | |
| '//front_end/core/common/sub_dir:sub_dir', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.resolveDeclaredDep('.', currentDir, rootDir), | |
| '//front_end/core/common:common', | |
| ); | |
| }); | |
| }); | |
| describe('toRelativeDep', () => { | |
| it('formats relative dep when target is in current directory', () => { | |
| const bundleLabel = new GnLabel('front_end/core/common', 'bundle'); | |
| assert.strictEqual( | |
| bundleLabel.toRelativeDep(currentDir, rootDir), | |
| ':bundle', | |
| ); | |
| const commonLabel = new GnLabel('front_end/core/common', 'common'); | |
| assert.strictEqual( | |
| commonLabel.toRelativeDep(currentDir, rootDir), | |
| ':common', | |
| ); | |
| }); | |
| it('formats relative dep when target name matches directory name', () => { | |
| const sdkLabel = new GnLabel('front_end/core/sdk', 'sdk'); | |
| assert.strictEqual(sdkLabel.toRelativeDep(currentDir, rootDir), '../sdk'); | |
| const subDirLabel = new GnLabel( | |
| 'front_end/core/common/sub_dir', | |
| 'sub_dir', | |
| ); | |
| assert.strictEqual( | |
| subDirLabel.toRelativeDep(currentDir, rootDir), | |
| 'sub_dir', | |
| ); | |
| }); | |
| it('formats relative dep with target name when target name differs from directory name', () => { | |
| const sdkBundleLabel = new GnLabel('front_end/core/sdk', 'bundle'); | |
| assert.strictEqual( | |
| sdkBundleLabel.toRelativeDep(currentDir, rootDir), | |
| '../sdk:bundle', | |
| ); | |
| const subDirCustomLabel = new GnLabel( | |
| 'front_end/core/common/sub_dir', | |
| 'custom', | |
| ); | |
| assert.strictEqual( | |
| subDirCustomLabel.toRelativeDep(currentDir, rootDir), | |
| 'sub_dir:custom', | |
| ); | |
| }); | |
| }); | |
| describe('formatRelativeDep', () => { | |
| it('normalizes absolute label to relative dep from currentDir', () => { | |
| assert.strictEqual( | |
| GnLabel.formatRelativeDep('//front_end/core/sdk:bundle', currentDir, rootDir), | |
| '../sdk:bundle', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.formatRelativeDep('//front_end/core/common:bundle', currentDir, rootDir), | |
| ':bundle', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.formatRelativeDep('//front_end/core/common:common', currentDir, rootDir), | |
| ':common', | |
| ); | |
| }); | |
| it('normalizes shorthand local label', () => { | |
| assert.strictEqual( | |
| GnLabel.formatRelativeDep(':bundle', currentDir, rootDir), | |
| ':bundle', | |
| ); | |
| }); | |
| it('normalizes existing relative label', () => { | |
| assert.strictEqual( | |
| GnLabel.formatRelativeDep('../sdk:bundle', currentDir, rootDir), | |
| '../sdk:bundle', | |
| ); | |
| assert.strictEqual( | |
| GnLabel.formatRelativeDep('../../panels/animation:bundle', currentDir, rootDir), | |
| '../../panels/animation:bundle', | |
| ); | |
| }); | |
| }); | |
| }); |