| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- import { pipe } from '@codama/visitors-core';
- import { describe, expect, test } from 'vitest';
- import {
- addToImportMap,
- createImportMap,
- importMapToString,
- mergeImportMaps,
- parseImportInput,
- removeFromImportMap,
- } from '../../src/utils';
- describe('createImportMap', () => {
- test('it creates an empty import map', () => {
- expect(createImportMap()).toStrictEqual(new Map());
- });
- });
- describe('parseImportInput', () => {
- test('it parses simple identifiers', () => {
- expect(parseImportInput('myFunction')).toStrictEqual({
- importedIdentifier: 'myFunction',
- isType: false,
- usedIdentifier: 'myFunction',
- });
- });
- test('it parses type-only identifiers', () => {
- expect(parseImportInput('type MyType')).toStrictEqual({
- importedIdentifier: 'MyType',
- isType: true,
- usedIdentifier: 'MyType',
- });
- });
- test('it parses aliased identifiers', () => {
- expect(parseImportInput('myFunction as myAliasedFunction')).toStrictEqual({
- importedIdentifier: 'myFunction',
- isType: false,
- usedIdentifier: 'myAliasedFunction',
- });
- });
- test('it parses type-only aliased identifiers', () => {
- expect(parseImportInput('type MyType as MyAliasedType')).toStrictEqual({
- importedIdentifier: 'MyType',
- isType: true,
- usedIdentifier: 'MyAliasedType',
- });
- });
- test('it parses unrecognised patterns as-is', () => {
- expect(parseImportInput('!some weird #input')).toStrictEqual({
- importedIdentifier: '!some weird #input',
- isType: false,
- usedIdentifier: '!some weird #input',
- });
- });
- });
- describe('mergeImportMaps', () => {
- test('it returns an empty map when merging empty maps', () => {
- expect(mergeImportMaps([])).toStrictEqual(new Map());
- });
- test('it returns the first map as-is when merging a single map', () => {
- const map = createImportMap();
- expect(mergeImportMaps([map])).toBe(map);
- });
- test('it add all modules from the merged maps', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['import1']);
- const map2 = addToImportMap(createImportMap(), 'module-b', ['import2']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([
- ['module-a', new Map([['import1', parseImportInput('import1')]])],
- ['module-b', new Map([['import2', parseImportInput('import2')]])],
- ]),
- );
- });
- test('it merges imports from the same module', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['import1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['import2']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([
- [
- 'module-a',
- new Map([
- ['import1', parseImportInput('import1')],
- ['import2', parseImportInput('import2')],
- ]),
- ],
- ]),
- );
- });
- test('it keeps the same import from the same module only once', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['import1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['import1']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([['module-a', new Map([['import1', parseImportInput('import1')]])]]),
- );
- });
- test('it keeps multiple instances of the same import when one is aliased', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['import1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['import1 as alias1']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([
- [
- 'module-a',
- new Map([
- ['import1', parseImportInput('import1')],
- ['alias1', parseImportInput('import1 as alias1')],
- ]),
- ],
- ]),
- );
- });
- test('it keeps multiple instances of the same import when both are aliased to different names', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['import1 as alias1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['import1 as alias2']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([
- [
- 'module-a',
- new Map([
- ['alias1', parseImportInput('import1 as alias1')],
- ['alias2', parseImportInput('import1 as alias2')],
- ]),
- ],
- ]),
- );
- });
- test('it keeps the same import from the same module when aliased to the same name', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['import1 as alias1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['import1 as alias1']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([['module-a', new Map([['alias1', parseImportInput('import1 as alias1')]])]]),
- );
- });
- test('it keeps the same type-only import from the same module only once', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['type import1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['type import1']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([['module-a', new Map([['import1', parseImportInput('type import1')]])]]),
- );
- });
- test('it keeps the same type-only import with the same aliased name from the same module only once', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['type import1 as alias1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['type import1 as alias1']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([['module-a', new Map([['alias1', parseImportInput('type import1 as alias1')]])]]),
- );
- });
- test('it only keep the non-type variant instead of the type-only variant when both have the same name', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['type import1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['import1']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([['module-a', new Map([['import1', parseImportInput('import1')]])]]),
- );
- });
- test('it only keep the non-type variant instead of the type-only variant when both are aliased to the same name', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['type import1 as alias1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['import1 as alias1']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([['module-a', new Map([['alias1', parseImportInput('import1 as alias1')]])]]),
- );
- });
- test('it keeps both the non-type and type-only imports when the former is aliased', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['import1 as alias1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['type import1']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([
- [
- 'module-a',
- new Map([
- ['alias1', parseImportInput('import1 as alias1')],
- ['import1', parseImportInput('type import1')],
- ]),
- ],
- ]),
- );
- });
- test('it keeps both the non-type and type-only imports when the latter is aliased', () => {
- const map1 = addToImportMap(createImportMap(), 'module-a', ['import1']);
- const map2 = addToImportMap(createImportMap(), 'module-a', ['type import1 as alias1']);
- expect(mergeImportMaps([map1, map2])).toStrictEqual(
- new Map([
- [
- 'module-a',
- new Map([
- ['import1', parseImportInput('import1')],
- ['alias1', parseImportInput('type import1 as alias1')],
- ]),
- ],
- ]),
- );
- });
- });
- describe('addToImportMap', () => {
- test('it adds imports to an empty import map', () => {
- expect(
- addToImportMap(createImportMap(), 'module-a', ['import1', 'type import2', 'import3 as alias3']),
- ).toStrictEqual(
- new Map([
- [
- 'module-a',
- new Map([
- ['import1', parseImportInput('import1')],
- ['import2', parseImportInput('type import2')],
- ['alias3', parseImportInput('import3 as alias3')],
- ]),
- ],
- ]),
- );
- });
- test('it adds imports to an existing import map', () => {
- expect(
- pipe(
- createImportMap(),
- m => addToImportMap(m, 'module-a', ['import1']),
- m => addToImportMap(m, 'module-b', ['import2']),
- ),
- ).toStrictEqual(
- new Map([
- ['module-a', new Map([['import1', parseImportInput('import1')]])],
- ['module-b', new Map([['import2', parseImportInput('import2')]])],
- ]),
- );
- });
- });
- describe('removeFromImportMap', () => {
- test('it removes type-only imports from an existing import map', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', ['import1', 'type import2']);
- expect(removeFromImportMap(importMap, 'module-a', ['import1'])).toStrictEqual(
- new Map([['module-a', new Map([['import2', parseImportInput('type import2')]])]]),
- );
- });
- test('it removes type-only imports from an existing import map', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', ['import1', 'type import2']);
- expect(removeFromImportMap(importMap, 'module-a', ['import2'])).toStrictEqual(
- new Map([['module-a', new Map([['import1', parseImportInput('import1')]])]]),
- );
- });
- test('it removes aliased imports from an existing import map using the aliased name', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', ['import1', 'import2 as alias2']);
- expect(removeFromImportMap(importMap, 'module-a', ['alias2'])).toStrictEqual(
- new Map([['module-a', new Map([['import1', parseImportInput('import1')]])]]),
- );
- });
- test('it removes multiple imports from the same module', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', [
- 'import1',
- 'import2 as alias2',
- 'type import3',
- ]);
- expect(removeFromImportMap(importMap, 'module-a', ['alias2', 'import3'])).toStrictEqual(
- new Map([['module-a', new Map([['import1', parseImportInput('import1')]])]]),
- );
- });
- test('it removes the module map when it is empty', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', ['import1', 'import2']);
- expect(removeFromImportMap(importMap, 'module-a', ['import1', 'import2'])).toStrictEqual(new Map());
- });
- });
- describe('importMapToString', () => {
- test('it converts an import map to a valid import statement', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', ['import1', 'import2', 'import3']);
- expect(importMapToString(importMap)).toBe("import { import1, import2, import3 } from 'module-a';");
- });
- test('it supports type-only import statements', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', ['type import1']);
- expect(importMapToString(importMap)).toBe("import { type import1 } from 'module-a';");
- });
- test('it supports aliased import statements', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', ['import1 as alias1']);
- expect(importMapToString(importMap)).toBe("import { import1 as alias1 } from 'module-a';");
- });
- test('it supports aliased type-only import statements', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', ['type import1 as alias1']);
- expect(importMapToString(importMap)).toBe("import { type import1 as alias1 } from 'module-a';");
- });
- test('it orders import items alphabetically', () => {
- const importMap = addToImportMap(createImportMap(), 'module-a', ['import3', 'import1', 'import2']);
- expect(importMapToString(importMap)).toBe("import { import1, import2, import3 } from 'module-a';");
- });
- test('it orders import statements alphabetically', () => {
- const importMap = pipe(
- createImportMap(),
- m => addToImportMap(m, 'module-b', ['import2']),
- m => addToImportMap(m, 'module-a', ['import1']),
- );
- expect(importMapToString(importMap)).toBe(
- "import { import1 } from 'module-a';\nimport { import2 } from 'module-b';",
- );
- });
- test('it places absolute imports before relative imports', () => {
- const importMap = pipe(
- createImportMap(),
- m => addToImportMap(m, './relative-module', ['import1']),
- m => addToImportMap(m, 'absolute-module', ['import2']),
- );
- expect(importMapToString(importMap)).toBe(
- "import { import2 } from 'absolute-module';\nimport { import1 } from './relative-module';",
- );
- });
- test('it replaces internal modules with their actual paths', () => {
- const importMap = addToImportMap(createImportMap(), 'generatedAccounts', ['myAccount']);
- expect(importMapToString(importMap)).toBe("import { myAccount } from '../accounts';");
- });
- test('it can override the paths of internal modules', () => {
- const importMap = addToImportMap(createImportMap(), 'generatedAccounts', ['myAccount']);
- expect(importMapToString(importMap, { generatedAccounts: '.' })).toBe("import { myAccount } from '.';");
- });
- test('it replaces placeholder kit packages with their @solana/kit', () => {
- const importMap = addToImportMap(createImportMap(), 'solanaAddresses', ['type Address']);
- expect(importMapToString(importMap)).toBe("import { type Address } from '@solana/kit';");
- });
- test('it can use granular packages when replacing placeholder kit packages', () => {
- const importMap = addToImportMap(createImportMap(), 'solanaAddresses', ['type Address']);
- expect(importMapToString(importMap, {}, true)).toBe("import { type Address } from '@solana/addresses';");
- });
- test('it can override the module of placeholder kit packages', () => {
- const importMap = addToImportMap(createImportMap(), 'solanaAddresses', ['type Address']);
- expect(importMapToString(importMap, { solanaAddresses: '@acme/solana-addresses' })).toBe(
- "import { type Address } from '@acme/solana-addresses';",
- );
- });
- });
|