# test.rules/shared/selectors/specifier.selector.test.ts

> 23 lines of code and 0 definitions.

Tree: Codebase Testing
Language: typescript
Canonical: https://banes-lab.com/anatomy/testing#file-testing-test-rules-shared-selectors-specifier-selector-test-ts
Source text: https://banes-lab.com/source/testing/test.rules/shared/selectors/specifier.selector.test.ts.txt

Listed in [test.rules/shared/selectors](https://banes-lab.com/api/source/testing/test.rules/shared/selectors.md), after [test.rules/shared/selectors/sink.selector.test.ts](https://banes-lab.com/source/testing/test.rules/shared/selectors/sink.selector.test.ts.md) and before [test.rules/shared/selectors/syntax.selector.test.ts](https://banes-lab.com/source/testing/test.rules/shared/selectors/syntax.selector.test.ts.md).

## Contained in

- [test.rules/shared/selectors](https://banes-lab.com/anatomy/testing/folder-testing-test-rules-shared-selectors.md)

## Source

```typescript
import { describe, expect, it } from "vitest";
import { specifierNodes, specifiersOf } from "@ssot/govlab/shared/selectors/specifier.selector.ts";
import ts from "typescript";

const CODE = [
    'import { a } from "./a.ts";',
    'import type { B } from "@scope/b";',
    'export { c } from "../c.ts";',
    'const d = await import("./d.ts");',
    'const e = "./not-a-specifier.ts";',
].join("\n");

describe("specifiersOf", () => {
    it("reads every import, re-export and dynamic import specifier, and no other string", () => {
        expect(specifiersOf("probe.ts", CODE)).toStrictEqual(["./a.ts", "@scope/b", "../c.ts", "./d.ts"]);
    });
});

describe("specifierNodes", () => {
    it("returns the literal nodes so a caller can report or rewrite at their position", () => {
        const source = ts.createSourceFile("probe.ts", CODE, ts.ScriptTarget.Latest, true);
        const [first] = specifierNodes(source);
        expect(first?.text).toBe("./a.ts");
        expect(first?.getStart(source)).toBe(CODE.indexOf('"./a.ts"'));
    });
});
```
