akm-cli 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/dist/{cli.js → src/cli.js} +712 -34
- package/dist/{commands → src/commands}/config-cli.js +47 -4
- package/dist/src/commands/distill.js +283 -0
- package/dist/src/commands/events.js +108 -0
- package/dist/src/commands/history.js +191 -0
- package/dist/{commands → src/commands}/installed-stashes.js +1 -1
- package/dist/src/commands/proposal.js +119 -0
- package/dist/src/commands/propose.js +171 -0
- package/dist/src/commands/reflect.js +193 -0
- package/dist/{commands → src/commands}/registry-search.js +71 -7
- package/dist/{commands → src/commands}/remember.js +12 -0
- package/dist/{commands → src/commands}/search.js +104 -4
- package/dist/{commands → src/commands}/self-update.js +4 -3
- package/dist/{commands → src/commands}/show.js +73 -0
- package/dist/{commands → src/commands}/source-add.js +5 -1
- package/dist/{commands → src/commands}/source-manage.js +7 -1
- package/dist/{core → src/core}/asset-ref.js +5 -5
- package/dist/{core → src/core}/asset-spec.js +12 -0
- package/dist/{core → src/core}/common.js +1 -1
- package/dist/{core → src/core}/config.js +203 -121
- package/dist/{core → src/core}/errors.js +4 -0
- package/dist/src/core/events.js +239 -0
- package/dist/src/core/lesson-lint.js +86 -0
- package/dist/src/core/proposals.js +406 -0
- package/dist/src/core/warn.js +72 -0
- package/dist/{core → src/core}/write-source.js +80 -5
- package/dist/{indexer → src/indexer}/db-search.js +114 -24
- package/dist/{indexer → src/indexer}/db.js +76 -23
- package/dist/{indexer → src/indexer}/file-context.js +0 -3
- package/dist/src/indexer/graph-boost.js +179 -0
- package/dist/src/indexer/graph-extraction.js +212 -0
- package/dist/{indexer → src/indexer}/indexer.js +88 -7
- package/dist/{indexer → src/indexer}/matchers.js +1 -1
- package/dist/src/indexer/memory-inference.js +263 -0
- package/dist/{indexer → src/indexer}/metadata.js +111 -3
- package/dist/{indexer → src/indexer}/search-source.js +4 -2
- package/dist/src/integrations/agent/config.js +292 -0
- package/dist/src/integrations/agent/detect.js +94 -0
- package/dist/src/integrations/agent/index.js +17 -0
- package/dist/src/integrations/agent/profiles.js +65 -0
- package/dist/src/integrations/agent/prompts.js +167 -0
- package/dist/src/integrations/agent/spawn.js +272 -0
- package/dist/{integrations → src/integrations}/github.js +9 -3
- package/dist/{integrations → src/integrations}/lockfile.js +0 -26
- package/dist/{llm → src/llm}/client.js +33 -2
- package/dist/{llm → src/llm}/embedders/remote.js +37 -3
- package/dist/src/llm/feature-gate.js +108 -0
- package/dist/src/llm/graph-extract.js +107 -0
- package/dist/src/llm/index-passes.js +35 -0
- package/dist/src/llm/memory-infer.js +86 -0
- package/dist/{output → src/output}/cli-hints.js +15 -2
- package/dist/{output → src/output}/renderers.js +63 -2
- package/dist/src/output/shapes.js +523 -0
- package/dist/src/output/text.js +1116 -0
- package/dist/{registry → src/registry}/build-index.js +19 -8
- package/dist/{registry → src/registry}/factory.js +0 -8
- package/dist/{registry → src/registry}/providers/static-index.js +6 -3
- package/dist/{registry → src/registry}/resolve.js +68 -2
- package/dist/{setup → src/setup}/setup.js +52 -5
- package/dist/{sources → src/sources}/providers/git.js +7 -15
- package/dist/{wiki → src/wiki}/wiki.js +54 -6
- package/dist/{workflows → src/workflows}/runs.js +37 -3
- package/dist/tests/add-website-source.test.js +119 -0
- package/dist/tests/agent/agent-config-loader.test.js +70 -0
- package/dist/tests/agent/agent-config.test.js +221 -0
- package/dist/tests/agent/agent-detect.test.js +100 -0
- package/dist/tests/agent/agent-spawn.test.js +234 -0
- package/dist/tests/agent-output.test.js +186 -0
- package/dist/tests/architecture/agent-no-llm-sdk-guard.test.js +103 -0
- package/dist/tests/architecture/agent-spawn-seam.test.js +193 -0
- package/dist/tests/architecture/llm-stateless-seam.test.js +112 -0
- package/dist/tests/asset-ref.test.js +192 -0
- package/dist/tests/asset-registry.test.js +103 -0
- package/dist/tests/asset-spec.test.js +241 -0
- package/dist/tests/bench/attribution.test.js +996 -0
- package/dist/tests/bench/cleanup-sigint.test.js +83 -0
- package/dist/tests/bench/cleanup.js +234 -0
- package/dist/tests/bench/cleanup.test.js +166 -0
- package/dist/tests/bench/cli.js +1018 -0
- package/dist/tests/bench/cli.test.js +445 -0
- package/dist/tests/bench/compare.test.js +556 -0
- package/dist/tests/bench/corpus.js +317 -0
- package/dist/tests/bench/corpus.test.js +258 -0
- package/dist/tests/bench/doctor.js +525 -0
- package/dist/tests/bench/driver.js +401 -0
- package/dist/tests/bench/driver.test.js +584 -0
- package/dist/tests/bench/environment.js +233 -0
- package/dist/tests/bench/environment.test.js +199 -0
- package/dist/tests/bench/evolve-metrics.js +179 -0
- package/dist/tests/bench/evolve-metrics.test.js +187 -0
- package/dist/tests/bench/evolve.js +647 -0
- package/dist/tests/bench/evolve.test.js +624 -0
- package/dist/tests/bench/failure-modes.test.js +349 -0
- package/dist/tests/bench/feedback-integrity.test.js +457 -0
- package/dist/tests/bench/leakage.test.js +228 -0
- package/dist/tests/bench/learning-curve.test.js +134 -0
- package/dist/tests/bench/metrics.js +2395 -0
- package/dist/tests/bench/metrics.test.js +1150 -0
- package/dist/tests/bench/no-os-tmpdir-invariant.test.js +43 -0
- package/dist/tests/bench/opencode-config.js +194 -0
- package/dist/tests/bench/opencode-config.test.js +370 -0
- package/dist/tests/bench/report.js +1885 -0
- package/dist/tests/bench/report.test.js +1038 -0
- package/dist/tests/bench/run-config.js +355 -0
- package/dist/tests/bench/run-config.test.js +298 -0
- package/dist/tests/bench/run-curate-test.js +32 -0
- package/dist/tests/bench/run-failing-tasks.js +56 -0
- package/dist/tests/bench/run-full-bench.js +51 -0
- package/dist/tests/bench/run-items36-targeted.js +69 -0
- package/dist/tests/bench/run-nano-quick.js +42 -0
- package/dist/tests/bench/run-waveg-targeted.js +62 -0
- package/dist/tests/bench/runner.js +699 -0
- package/dist/tests/bench/runner.test.js +958 -0
- package/dist/tests/bench/search-bridge.test.js +331 -0
- package/dist/tests/bench/tmp.js +131 -0
- package/dist/tests/bench/trajectory.js +116 -0
- package/dist/tests/bench/trajectory.test.js +127 -0
- package/dist/tests/bench/verifier.js +114 -0
- package/dist/tests/bench/verifier.test.js +118 -0
- package/dist/tests/bench/workflow-evaluator.js +557 -0
- package/dist/tests/bench/workflow-evaluator.test.js +421 -0
- package/dist/tests/bench/workflow-spec.js +345 -0
- package/dist/tests/bench/workflow-spec.test.js +363 -0
- package/dist/tests/bench/workflow-trace.js +472 -0
- package/dist/tests/bench/workflow-trace.test.js +254 -0
- package/dist/tests/benchmark-search-quality.js +536 -0
- package/dist/tests/benchmark-suite.js +1441 -0
- package/dist/tests/capture-cli.test.js +112 -0
- package/dist/tests/cli-errors.test.js +204 -0
- package/dist/tests/commands/events.test.js +370 -0
- package/dist/tests/commands/history.test.js +418 -0
- package/dist/tests/commands/import.test.js +103 -0
- package/dist/tests/commands/proposal-cli.test.js +209 -0
- package/dist/tests/commands/reflect-propose-cli.test.js +333 -0
- package/dist/tests/commands/remember.test.js +97 -0
- package/dist/tests/commands/scope-flags.test.js +300 -0
- package/dist/tests/commands/search.test.js +537 -0
- package/dist/tests/commands/show-indexer-parity.test.js +117 -0
- package/dist/tests/commands/show.test.js +294 -0
- package/dist/tests/common.test.js +266 -0
- package/dist/tests/completions.test.js +142 -0
- package/dist/tests/config-cli.test.js +193 -0
- package/dist/tests/config-llm-features.test.js +139 -0
- package/dist/tests/config.test.js +569 -0
- package/dist/tests/contracts/migration-baseline.test.js +43 -0
- package/dist/tests/contracts/reflect-propose-envelope.test.js +139 -0
- package/dist/tests/contracts/spec-helpers.js +46 -0
- package/dist/tests/contracts/v1-spec-section-11-proposal-queue.test.js +228 -0
- package/dist/tests/contracts/v1-spec-section-12-agent-config.test.js +56 -0
- package/dist/tests/contracts/v1-spec-section-13-lesson-type.test.js +34 -0
- package/dist/tests/contracts/v1-spec-section-14-llm-features.test.js +94 -0
- package/dist/tests/contracts/v1-spec-section-4-1-asset-types.test.js +39 -0
- package/dist/tests/contracts/v1-spec-section-4-2-quality-rules.test.js +44 -0
- package/dist/tests/contracts/v1-spec-section-5-configuration.test.js +47 -0
- package/dist/tests/contracts/v1-spec-section-6-orchestration.test.js +40 -0
- package/dist/tests/contracts/v1-spec-section-7-module-layout.test.js +58 -0
- package/dist/tests/contracts/v1-spec-section-8-extension-points.test.js +34 -0
- package/dist/tests/contracts/v1-spec-section-9-4-cli-surface.test.js +75 -0
- package/dist/tests/contracts/v1-spec-section-9-7-llm-agent-boundary.test.js +36 -0
- package/dist/tests/core/write-source.test.js +366 -0
- package/dist/tests/curate-command.test.js +87 -0
- package/dist/tests/db-scoring.test.js +201 -0
- package/dist/tests/db.test.js +654 -0
- package/dist/tests/distill-cli-flag.test.js +208 -0
- package/dist/tests/distill.test.js +515 -0
- package/dist/tests/docker-install.test.js +120 -0
- package/dist/tests/e2e.test.js +1419 -0
- package/dist/tests/embedder.test.js +340 -0
- package/dist/tests/embedding-model-config.test.js +379 -0
- package/dist/tests/feedback-command.test.js +172 -0
- package/dist/tests/file-context.test.js +552 -0
- package/dist/tests/fixtures/scripts/git/summarize-diff.js +9 -0
- package/dist/tests/fixtures/scripts/lint/eslint-check.js +7 -0
- package/dist/tests/fixtures/stashes/load.js +166 -0
- package/dist/tests/fixtures/stashes/load.test.js +97 -0
- package/dist/tests/fixtures/stashes/ranking-baseline/scripts/mem0-search.js +12 -0
- package/dist/tests/frontmatter.test.js +190 -0
- package/dist/tests/fts-field-weighting.test.js +254 -0
- package/dist/tests/fuzzy-search.test.js +230 -0
- package/dist/tests/git-provider-clone.test.js +45 -0
- package/dist/tests/github.test.js +161 -0
- package/dist/tests/graph-boost-ranking.test.js +305 -0
- package/dist/tests/graph-extraction.test.js +282 -0
- package/dist/tests/helpers/usage-events.js +8 -0
- package/dist/tests/index-pass-llm.test.js +161 -0
- package/dist/tests/indexer.test.js +570 -0
- package/dist/tests/info-command.test.js +166 -0
- package/dist/tests/init.test.js +69 -0
- package/dist/tests/install-script.test.js +246 -0
- package/dist/tests/integration/agent-real-profile.test.js +94 -0
- package/dist/tests/issue-36-repro.test.js +304 -0
- package/dist/tests/issues-191-194.test.js +160 -0
- package/dist/tests/lesson-lint.test.js +111 -0
- package/dist/tests/llm-client.test.js +115 -0
- package/dist/tests/llm-feature-gate.test.js +151 -0
- package/dist/tests/llm.test.js +139 -0
- package/dist/tests/lockfile.test.js +216 -0
- package/dist/tests/manifest.test.js +205 -0
- package/dist/tests/markdown.test.js +126 -0
- package/dist/tests/matchers-unit.test.js +189 -0
- package/dist/tests/memory-inference.test.js +299 -0
- package/dist/tests/merge-scoring.test.js +136 -0
- package/dist/tests/metadata.test.js +313 -0
- package/dist/tests/migration-help.test.js +89 -0
- package/dist/tests/origin-resolve.test.js +124 -0
- package/dist/tests/output-baseline.test.js +218 -0
- package/dist/tests/output-shapes-unit.test.js +478 -0
- package/dist/tests/parallel-search.test.js +272 -0
- package/dist/tests/parameter-metadata.test.js +365 -0
- package/dist/tests/paths.test.js +177 -0
- package/dist/tests/progressive-disclosure.test.js +280 -0
- package/dist/tests/proposals.test.js +279 -0
- package/dist/tests/proposed-quality.test.js +271 -0
- package/dist/tests/provider-registry.test.js +32 -0
- package/dist/tests/ranking-regression.test.js +548 -0
- package/dist/tests/reflect-propose.test.js +455 -0
- package/dist/tests/registry-build-index.test.js +394 -0
- package/dist/tests/registry-cli.test.js +290 -0
- package/dist/tests/registry-index-v2.test.js +430 -0
- package/dist/tests/registry-install.test.js +728 -0
- package/dist/tests/registry-providers/parity.test.js +189 -0
- package/dist/tests/registry-providers/skills-sh.test.js +309 -0
- package/dist/tests/registry-providers/static-index.test.js +238 -0
- package/dist/tests/registry-resolve.test.js +126 -0
- package/dist/tests/registry-search.test.js +923 -0
- package/dist/tests/remember-frontmatter.test.js +378 -0
- package/dist/tests/remember-unit.test.js +123 -0
- package/dist/tests/ripgrep-install.test.js +251 -0
- package/dist/tests/ripgrep-resolve.test.js +108 -0
- package/dist/tests/ripgrep.test.js +163 -0
- package/dist/tests/save-command.test.js +94 -0
- package/dist/tests/save-trust-qa-fixes.test.js +270 -0
- package/dist/tests/scoring-pipeline.test.js +648 -0
- package/dist/tests/search-include-proposed-cli.test.js +118 -0
- package/dist/tests/self-update.test.js +442 -0
- package/dist/tests/semantic-search-e2e.test.js +512 -0
- package/dist/tests/semantic-status.test.js +471 -0
- package/dist/tests/setup-run.integration.js +877 -0
- package/dist/tests/setup-wizard.test.js +198 -0
- package/dist/tests/setup.test.js +131 -0
- package/dist/tests/source-add.test.js +11 -0
- package/dist/tests/source-clone.test.js +254 -0
- package/dist/tests/source-manage.test.js +366 -0
- package/dist/tests/source-providers/filesystem.test.js +82 -0
- package/dist/tests/source-providers/git.test.js +252 -0
- package/dist/tests/source-providers/website.test.js +128 -0
- package/dist/tests/source-qa-fixes.test.js +286 -0
- package/dist/tests/source-registry.test.js +350 -0
- package/dist/tests/source-resolve.test.js +100 -0
- package/dist/tests/source-source.test.js +281 -0
- package/dist/tests/source.test.js +533 -0
- package/dist/tests/tar-utils-scan.test.js +73 -0
- package/dist/tests/toggle-components.test.js +73 -0
- package/dist/tests/usage-telemetry.test.js +265 -0
- package/dist/tests/utility-scoring.test.js +558 -0
- package/dist/tests/vault-load-error.test.js +78 -0
- package/dist/tests/vault-qa-fixes.test.js +194 -0
- package/dist/tests/vault.test.js +429 -0
- package/dist/tests/vector-search.test.js +608 -0
- package/dist/tests/walker.test.js +252 -0
- package/dist/tests/wave2-cluster-bc.test.js +228 -0
- package/dist/tests/wave2-cluster-d.test.js +180 -0
- package/dist/tests/wave2-cluster-e.test.js +179 -0
- package/dist/tests/wiki-qa-fixes.test.js +270 -0
- package/dist/tests/wiki.test.js +529 -0
- package/dist/tests/workflow-cli.test.js +271 -0
- package/dist/tests/workflow-markdown.test.js +171 -0
- package/dist/tests/workflow-path-escape.test.js +132 -0
- package/dist/tests/workflow-qa-fixes.test.js +395 -0
- package/dist/tests/workflows/indexer-rejection.test.js +213 -0
- package/docs/README.md +8 -0
- package/docs/migration/release-notes/0.7.0.md +244 -0
- package/package.json +2 -2
- package/dist/core/warn.js +0 -27
- package/dist/output/shapes.js +0 -212
- package/dist/output/text.js +0 -520
- /package/dist/{commands → src/commands}/completions.js +0 -0
- /package/dist/{commands → src/commands}/curate.js +0 -0
- /package/dist/{commands → src/commands}/info.js +0 -0
- /package/dist/{commands → src/commands}/init.js +0 -0
- /package/dist/{commands → src/commands}/install-audit.js +0 -0
- /package/dist/{commands → src/commands}/migration-help.js +0 -0
- /package/dist/{commands → src/commands}/source-clone.js +0 -0
- /package/dist/{commands → src/commands}/vault.js +0 -0
- /package/dist/{core → src/core}/asset-registry.js +0 -0
- /package/dist/{core → src/core}/frontmatter.js +0 -0
- /package/dist/{core → src/core}/markdown.js +0 -0
- /package/dist/{core → src/core}/paths.js +0 -0
- /package/dist/{indexer → src/indexer}/manifest.js +0 -0
- /package/dist/{indexer → src/indexer}/search-fields.js +0 -0
- /package/dist/{indexer → src/indexer}/semantic-status.js +0 -0
- /package/dist/{indexer → src/indexer}/usage-events.js +0 -0
- /package/dist/{indexer → src/indexer}/walker.js +0 -0
- /package/dist/{llm → src/llm}/embedder.js +0 -0
- /package/dist/{llm → src/llm}/embedders/cache.js +0 -0
- /package/dist/{llm → src/llm}/embedders/local.js +0 -0
- /package/dist/{llm → src/llm}/embedders/types.js +0 -0
- /package/dist/{llm → src/llm}/metadata-enhance.js +0 -0
- /package/dist/{output → src/output}/context.js +0 -0
- /package/dist/{registry → src/registry}/create-provider-registry.js +0 -0
- /package/dist/{registry → src/registry}/origin-resolve.js +0 -0
- /package/dist/{registry → src/registry}/providers/index.js +0 -0
- /package/dist/{registry → src/registry}/providers/skills-sh.js +0 -0
- /package/dist/{registry → src/registry}/providers/types.js +0 -0
- /package/dist/{registry → src/registry}/types.js +0 -0
- /package/dist/{setup → src/setup}/detect.js +0 -0
- /package/dist/{setup → src/setup}/ripgrep-install.js +0 -0
- /package/dist/{setup → src/setup}/ripgrep-resolve.js +0 -0
- /package/dist/{setup → src/setup}/steps.js +0 -0
- /package/dist/{sources → src/sources}/include.js +0 -0
- /package/dist/{sources → src/sources}/provider-factory.js +0 -0
- /package/dist/{sources → src/sources}/provider.js +0 -0
- /package/dist/{sources → src/sources}/providers/filesystem.js +0 -0
- /package/dist/{sources → src/sources}/providers/index.js +0 -0
- /package/dist/{sources → src/sources}/providers/install-types.js +0 -0
- /package/dist/{sources → src/sources}/providers/npm.js +0 -0
- /package/dist/{sources → src/sources}/providers/provider-utils.js +0 -0
- /package/dist/{sources → src/sources}/providers/sync-from-ref.js +0 -0
- /package/dist/{sources → src/sources}/providers/tar-utils.js +0 -0
- /package/dist/{sources → src/sources}/providers/website.js +0 -0
- /package/dist/{sources → src/sources}/resolve.js +0 -0
- /package/dist/{sources → src/sources}/types.js +0 -0
- /package/dist/{templates → src/templates}/wiki-templates.js +0 -0
- /package/dist/{version.js → src/version.js} +0 -0
- /package/dist/{workflows → src/workflows}/authoring.js +0 -0
- /package/dist/{workflows → src/workflows}/cli.js +0 -0
- /package/dist/{workflows → src/workflows}/db.js +0 -0
- /package/dist/{workflows → src/workflows}/document-cache.js +0 -0
- /package/dist/{workflows → src/workflows}/parser.js +0 -0
- /package/dist/{workflows → src/workflows}/renderer.js +0 -0
- /package/dist/{workflows → src/workflows}/schema.js +0 -0
- /package/dist/{workflows → src/workflows}/validator.js +0 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { addStash, listStashes, removeStash } from "../src/commands/source-manage";
|
|
6
|
+
import { loadConfig, saveConfig } from "../src/core/config";
|
|
7
|
+
const createdTmpDirs = [];
|
|
8
|
+
function createTmpDir(prefix = "akm-src-mgmt-") {
|
|
9
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
10
|
+
createdTmpDirs.push(dir);
|
|
11
|
+
return dir;
|
|
12
|
+
}
|
|
13
|
+
const originalXdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
14
|
+
const originalXdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
15
|
+
const originalAkmStashDir = process.env.AKM_STASH_DIR;
|
|
16
|
+
let testCacheDir = "";
|
|
17
|
+
let testConfigDir = "";
|
|
18
|
+
let testStashDir = "";
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
testCacheDir = createTmpDir("akm-src-cache-");
|
|
21
|
+
testConfigDir = createTmpDir("akm-src-config-");
|
|
22
|
+
testStashDir = createTmpDir("akm-src-stash-");
|
|
23
|
+
process.env.XDG_CACHE_HOME = testCacheDir;
|
|
24
|
+
process.env.XDG_CONFIG_HOME = testConfigDir;
|
|
25
|
+
process.env.AKM_STASH_DIR = testStashDir;
|
|
26
|
+
// Write initial config so loadConfig doesn't return defaults with stale caches
|
|
27
|
+
saveConfig({ semanticSearchMode: "auto" });
|
|
28
|
+
});
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
if (originalXdgCacheHome === undefined)
|
|
31
|
+
delete process.env.XDG_CACHE_HOME;
|
|
32
|
+
else
|
|
33
|
+
process.env.XDG_CACHE_HOME = originalXdgCacheHome;
|
|
34
|
+
if (originalXdgConfigHome === undefined)
|
|
35
|
+
delete process.env.XDG_CONFIG_HOME;
|
|
36
|
+
else
|
|
37
|
+
process.env.XDG_CONFIG_HOME = originalXdgConfigHome;
|
|
38
|
+
if (originalAkmStashDir === undefined)
|
|
39
|
+
delete process.env.AKM_STASH_DIR;
|
|
40
|
+
else
|
|
41
|
+
process.env.AKM_STASH_DIR = originalAkmStashDir;
|
|
42
|
+
for (const dir of createdTmpDirs) {
|
|
43
|
+
try {
|
|
44
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
45
|
+
}
|
|
46
|
+
catch { }
|
|
47
|
+
}
|
|
48
|
+
createdTmpDirs.length = 0;
|
|
49
|
+
});
|
|
50
|
+
// ── addStash ──────────────────────────────────────────────────────────
|
|
51
|
+
describe("addStash", () => {
|
|
52
|
+
test("adds a filesystem path", () => {
|
|
53
|
+
const stashPath = createTmpDir("akm-fs-source-");
|
|
54
|
+
const result = addStash({ target: stashPath });
|
|
55
|
+
expect(result.added).toBe(true);
|
|
56
|
+
expect(result.entry).toBeDefined();
|
|
57
|
+
expect(result.entry?.type).toBe("filesystem");
|
|
58
|
+
expect(result.entry?.path).toBe(path.resolve(stashPath));
|
|
59
|
+
// Verify persisted
|
|
60
|
+
const config = loadConfig();
|
|
61
|
+
expect(config.sources).toHaveLength(1);
|
|
62
|
+
expect(config.sources?.[0].type).toBe("filesystem");
|
|
63
|
+
expect(config.sources?.[0].path).toBe(path.resolve(stashPath));
|
|
64
|
+
});
|
|
65
|
+
test("adds a filesystem path with a name", () => {
|
|
66
|
+
const stashPath = createTmpDir("akm-fs-named-");
|
|
67
|
+
const result = addStash({ target: stashPath, name: "my-stash" });
|
|
68
|
+
expect(result.added).toBe(true);
|
|
69
|
+
expect(result.entry?.name).toBe("my-stash");
|
|
70
|
+
});
|
|
71
|
+
test("rejects duplicate filesystem paths", () => {
|
|
72
|
+
const stashPath = createTmpDir("akm-fs-dup-");
|
|
73
|
+
addStash({ target: stashPath });
|
|
74
|
+
const result = addStash({ target: stashPath });
|
|
75
|
+
expect(result.added).toBe(false);
|
|
76
|
+
expect(result.message).toContain("already configured");
|
|
77
|
+
});
|
|
78
|
+
test("normalizes relative filesystem paths", () => {
|
|
79
|
+
const stashPath = createTmpDir("akm-fs-rel-");
|
|
80
|
+
const relativePath = path.relative(process.cwd(), stashPath);
|
|
81
|
+
const result = addStash({ target: relativePath });
|
|
82
|
+
expect(result.added).toBe(true);
|
|
83
|
+
expect(result.entry?.path).toBe(path.resolve(stashPath));
|
|
84
|
+
});
|
|
85
|
+
test("deduplicates paths that resolve to the same directory", () => {
|
|
86
|
+
const stashPath = createTmpDir("akm-fs-equiv-");
|
|
87
|
+
addStash({ target: stashPath });
|
|
88
|
+
// Add again with trailing slash
|
|
89
|
+
const result = addStash({ target: `${stashPath}/` });
|
|
90
|
+
expect(result.added).toBe(false);
|
|
91
|
+
expect(result.message).toContain("already configured");
|
|
92
|
+
});
|
|
93
|
+
test("adds a URL source", () => {
|
|
94
|
+
const url = "https://example.com";
|
|
95
|
+
const result = addStash({ target: url, providerType: "website" });
|
|
96
|
+
expect(result.added).toBe(true);
|
|
97
|
+
expect(result.entry?.type).toBe("website");
|
|
98
|
+
expect(result.entry?.url).toBe(url);
|
|
99
|
+
const config = loadConfig();
|
|
100
|
+
expect(config.sources).toHaveLength(1);
|
|
101
|
+
expect(config.sources?.[0].type).toBe("website");
|
|
102
|
+
expect(config.sources?.[0].url).toBe(url);
|
|
103
|
+
});
|
|
104
|
+
test("adds a URL source with name and options", () => {
|
|
105
|
+
const url = "https://example.com";
|
|
106
|
+
const result = addStash({
|
|
107
|
+
target: url,
|
|
108
|
+
providerType: "website",
|
|
109
|
+
name: "my-source",
|
|
110
|
+
options: { searchType: "text" },
|
|
111
|
+
});
|
|
112
|
+
expect(result.added).toBe(true);
|
|
113
|
+
expect(result.entry?.name).toBe("my-source");
|
|
114
|
+
expect(result.entry?.options).toEqual({ searchType: "text" });
|
|
115
|
+
});
|
|
116
|
+
test("throws when URL source has no provider type", () => {
|
|
117
|
+
expect(() => addStash({ target: "https://example.com" })).toThrow("--provider is required");
|
|
118
|
+
});
|
|
119
|
+
test("rejects duplicate URL sources", () => {
|
|
120
|
+
const url = "https://example.com";
|
|
121
|
+
addStash({ target: url, providerType: "website" });
|
|
122
|
+
const result = addStash({ target: url, providerType: "website" });
|
|
123
|
+
expect(result.added).toBe(false);
|
|
124
|
+
expect(result.message).toContain("already configured");
|
|
125
|
+
});
|
|
126
|
+
test("supports custom provider types", () => {
|
|
127
|
+
const url = "https://custom.example.com";
|
|
128
|
+
const result = addStash({ target: url, providerType: "custom-provider" });
|
|
129
|
+
expect(result.added).toBe(true);
|
|
130
|
+
expect(result.entry?.type).toBe("custom-provider");
|
|
131
|
+
});
|
|
132
|
+
test("adds an http:// URL source", () => {
|
|
133
|
+
const url = "http://example.com";
|
|
134
|
+
const result = addStash({ target: url, providerType: "website" });
|
|
135
|
+
expect(result.added).toBe(true);
|
|
136
|
+
expect(result.entry?.url).toBe(url);
|
|
137
|
+
});
|
|
138
|
+
test("allows same URL with different provider types", () => {
|
|
139
|
+
const url = "https://shared.example.com";
|
|
140
|
+
addStash({ target: url, providerType: "website" });
|
|
141
|
+
// Same URL but different provider — deduplicates by URL regardless of type
|
|
142
|
+
const result = addStash({ target: url, providerType: "custom" });
|
|
143
|
+
expect(result.added).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
test("ignores options for filesystem sources", () => {
|
|
146
|
+
const fsPath = createTmpDir("akm-fs-opts-");
|
|
147
|
+
const result = addStash({ target: fsPath, options: { key: "value" } });
|
|
148
|
+
expect(result.added).toBe(true);
|
|
149
|
+
expect(result.entry?.options).toBeUndefined();
|
|
150
|
+
});
|
|
151
|
+
test("returned stashes array reflects new state", () => {
|
|
152
|
+
const fsPath = createTmpDir("akm-stashes-return-");
|
|
153
|
+
const result = addStash({ target: fsPath, name: "ret-test" });
|
|
154
|
+
expect(result.sources).toHaveLength(1);
|
|
155
|
+
expect(result.sources[0].name).toBe("ret-test");
|
|
156
|
+
});
|
|
157
|
+
test("can add multiple sources of different types", () => {
|
|
158
|
+
const fsPath = createTmpDir("akm-multi-fs-");
|
|
159
|
+
addStash({ target: fsPath });
|
|
160
|
+
addStash({ target: "https://example1.example.com", providerType: "website" });
|
|
161
|
+
addStash({ target: "https://custom.example.com", providerType: "custom-provider" });
|
|
162
|
+
const config = loadConfig();
|
|
163
|
+
expect(config.sources).toHaveLength(3);
|
|
164
|
+
expect(config.sources?.[0].type).toBe("filesystem");
|
|
165
|
+
expect(config.sources?.[1].type).toBe("website");
|
|
166
|
+
expect(config.sources?.[2].type).toBe("custom-provider");
|
|
167
|
+
});
|
|
168
|
+
test("preserves existing sources when adding", () => {
|
|
169
|
+
const config = loadConfig();
|
|
170
|
+
saveConfig({
|
|
171
|
+
...config,
|
|
172
|
+
sources: [{ type: "website", url: "https://existing.example.com", name: "existing" }],
|
|
173
|
+
});
|
|
174
|
+
const fsPath = createTmpDir("akm-preserve-");
|
|
175
|
+
addStash({ target: fsPath });
|
|
176
|
+
const updated = loadConfig();
|
|
177
|
+
expect(updated.sources).toHaveLength(2);
|
|
178
|
+
expect(updated.sources?.[0].url).toBe("https://existing.example.com");
|
|
179
|
+
expect(updated.sources?.[1].type).toBe("filesystem");
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
// ── removeStash ───────────────────────────────────────────────────────
|
|
183
|
+
describe("removeStash", () => {
|
|
184
|
+
test("removes a filesystem source by path", () => {
|
|
185
|
+
const fsPath = createTmpDir("akm-rm-fs-");
|
|
186
|
+
addStash({ target: fsPath });
|
|
187
|
+
const result = removeStash(fsPath);
|
|
188
|
+
expect(result.removed).toBe(true);
|
|
189
|
+
expect(result.entry?.type).toBe("filesystem");
|
|
190
|
+
expect(result.entry?.path).toBe(path.resolve(fsPath));
|
|
191
|
+
const config = loadConfig();
|
|
192
|
+
expect(config.sources).toHaveLength(0);
|
|
193
|
+
});
|
|
194
|
+
test("removes a URL source by URL", () => {
|
|
195
|
+
const url = "https://example.com";
|
|
196
|
+
addStash({ target: url, providerType: "website" });
|
|
197
|
+
const result = removeStash(url);
|
|
198
|
+
expect(result.removed).toBe(true);
|
|
199
|
+
expect(result.entry?.url).toBe(url);
|
|
200
|
+
const config = loadConfig();
|
|
201
|
+
expect(config.sources).toHaveLength(0);
|
|
202
|
+
});
|
|
203
|
+
test("removes a source by name", () => {
|
|
204
|
+
const url = "https://example.com";
|
|
205
|
+
addStash({ target: url, providerType: "website", name: "my-source" });
|
|
206
|
+
const result = removeStash("my-source");
|
|
207
|
+
expect(result.removed).toBe(true);
|
|
208
|
+
expect(result.entry?.name).toBe("my-source");
|
|
209
|
+
});
|
|
210
|
+
test("returns removed: false for non-existent source", () => {
|
|
211
|
+
const result = removeStash("/nonexistent/path");
|
|
212
|
+
expect(result.removed).toBe(false);
|
|
213
|
+
expect(result.message).toContain("No matching source found");
|
|
214
|
+
});
|
|
215
|
+
test("removes only the matched source, preserving others", () => {
|
|
216
|
+
const fsPath = createTmpDir("akm-rm-keep-");
|
|
217
|
+
addStash({ target: fsPath });
|
|
218
|
+
addStash({ target: "https://example.com", providerType: "website" });
|
|
219
|
+
removeStash(fsPath);
|
|
220
|
+
const config = loadConfig();
|
|
221
|
+
expect(config.sources).toHaveLength(1);
|
|
222
|
+
expect(config.sources?.[0].type).toBe("website");
|
|
223
|
+
});
|
|
224
|
+
test("prefers URL match over name match", () => {
|
|
225
|
+
const url = "https://example.com";
|
|
226
|
+
addStash({ target: url, providerType: "website", name: "my-source" });
|
|
227
|
+
addStash({ target: "https://other.example.com", providerType: "website", name: url });
|
|
228
|
+
// Should match by URL (first entry), not by name (second entry)
|
|
229
|
+
const result = removeStash(url);
|
|
230
|
+
expect(result.removed).toBe(true);
|
|
231
|
+
expect(result.entry?.name).toBe("my-source");
|
|
232
|
+
// The second entry (whose name matches the URL) should still exist
|
|
233
|
+
const config = loadConfig();
|
|
234
|
+
expect(config.sources).toHaveLength(1);
|
|
235
|
+
expect(config.sources?.[0].name).toBe(url);
|
|
236
|
+
});
|
|
237
|
+
test("prefers path match over name match", () => {
|
|
238
|
+
const fsPath = createTmpDir("akm-rm-prio-");
|
|
239
|
+
addStash({ target: fsPath, name: "path-source" });
|
|
240
|
+
addStash({ target: "https://other.example.com", providerType: "website", name: fsPath });
|
|
241
|
+
// Should match by path (first entry), not by name (second entry)
|
|
242
|
+
const result = removeStash(fsPath);
|
|
243
|
+
expect(result.removed).toBe(true);
|
|
244
|
+
expect(result.entry?.type).toBe("filesystem");
|
|
245
|
+
});
|
|
246
|
+
test("removes http:// URL source", () => {
|
|
247
|
+
const url = "http://example.com";
|
|
248
|
+
addStash({ target: url, providerType: "website" });
|
|
249
|
+
const result = removeStash(url);
|
|
250
|
+
expect(result.removed).toBe(true);
|
|
251
|
+
expect(result.entry?.url).toBe(url);
|
|
252
|
+
});
|
|
253
|
+
test("returned stashes array reflects new state", () => {
|
|
254
|
+
const fsPath = createTmpDir("akm-rm-ret-");
|
|
255
|
+
addStash({ target: fsPath, name: "rm-ret-test" });
|
|
256
|
+
addStash({ target: "https://keep.example.com", providerType: "website", name: "keep" });
|
|
257
|
+
const result = removeStash("rm-ret-test");
|
|
258
|
+
expect(result.sources).toHaveLength(1);
|
|
259
|
+
expect(result.sources[0].name).toBe("keep");
|
|
260
|
+
});
|
|
261
|
+
test("removes filesystem source by relative path that resolves correctly", () => {
|
|
262
|
+
const fsPath = createTmpDir("akm-rm-rel-");
|
|
263
|
+
addStash({ target: fsPath });
|
|
264
|
+
const relativePath = path.relative(process.cwd(), fsPath);
|
|
265
|
+
const result = removeStash(relativePath);
|
|
266
|
+
expect(result.removed).toBe(true);
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
// ── listStashes ────────────────────────────────────────────────────────
|
|
270
|
+
describe("listStashes", () => {
|
|
271
|
+
test("lists empty stash sources", () => {
|
|
272
|
+
const result = listStashes();
|
|
273
|
+
expect(result.localSources).toBeDefined();
|
|
274
|
+
expect(result.sources).toEqual([]);
|
|
275
|
+
expect(result.remoteSources).toBeUndefined();
|
|
276
|
+
});
|
|
277
|
+
test("lists filesystem stash sources", () => {
|
|
278
|
+
const fsPath = createTmpDir("akm-list-fs-");
|
|
279
|
+
addStash({ target: fsPath });
|
|
280
|
+
const result = listStashes();
|
|
281
|
+
expect(result.sources).toHaveLength(1);
|
|
282
|
+
expect(result.sources[0].type).toBe("filesystem");
|
|
283
|
+
});
|
|
284
|
+
test("lists URL stash sources", () => {
|
|
285
|
+
addStash({ target: "https://example.com", providerType: "website" });
|
|
286
|
+
const result = listStashes();
|
|
287
|
+
expect(result.sources).toHaveLength(1);
|
|
288
|
+
expect(result.sources[0].type).toBe("website");
|
|
289
|
+
expect(result.sources[0].url).toBe("https://example.com");
|
|
290
|
+
});
|
|
291
|
+
test("lists mixed source types", () => {
|
|
292
|
+
const fsPath = createTmpDir("akm-list-mixed-");
|
|
293
|
+
addStash({ target: fsPath });
|
|
294
|
+
addStash({ target: "https://example.com", providerType: "website" });
|
|
295
|
+
addStash({ target: "https://custom.example.com", providerType: "custom" });
|
|
296
|
+
const result = listStashes();
|
|
297
|
+
expect(result.sources).toHaveLength(3);
|
|
298
|
+
});
|
|
299
|
+
test("includes primary stash dir in localSources", () => {
|
|
300
|
+
const result = listStashes();
|
|
301
|
+
// The primary stash dir (from AKM_STASH_DIR) should always be first
|
|
302
|
+
expect(result.localSources.length).toBeGreaterThanOrEqual(1);
|
|
303
|
+
expect(result.localSources[0].path).toBe(path.resolve(testStashDir));
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
// ── Round-trip integration ──────────────────────────────────────────────────
|
|
307
|
+
describe("round-trip integration", () => {
|
|
308
|
+
test("add then list then remove filesystem source", () => {
|
|
309
|
+
const fsPath = createTmpDir("akm-roundtrip-fs-");
|
|
310
|
+
addStash({ target: fsPath, name: "roundtrip-test" });
|
|
311
|
+
const listed = listStashes();
|
|
312
|
+
expect(listed.sources.some((s) => s.name === "roundtrip-test")).toBe(true);
|
|
313
|
+
removeStash("roundtrip-test");
|
|
314
|
+
const afterRemove = listStashes();
|
|
315
|
+
expect(afterRemove.sources.some((s) => s.name === "roundtrip-test")).toBe(false);
|
|
316
|
+
});
|
|
317
|
+
test("add then list then remove URL source", () => {
|
|
318
|
+
const url = "https://roundtrip.example.com";
|
|
319
|
+
addStash({ target: url, providerType: "website", name: "rt-source" });
|
|
320
|
+
const listed = listStashes();
|
|
321
|
+
expect(listed.sources.some((s) => s.name === "rt-source")).toBe(true);
|
|
322
|
+
removeStash(url);
|
|
323
|
+
const afterRemove = listStashes();
|
|
324
|
+
expect(afterRemove.sources.some((s) => s.url === url)).toBe(false);
|
|
325
|
+
});
|
|
326
|
+
test("add then list then remove custom provider source", () => {
|
|
327
|
+
const url = "https://custom-roundtrip.example.com";
|
|
328
|
+
addStash({
|
|
329
|
+
target: url,
|
|
330
|
+
providerType: "my-custom",
|
|
331
|
+
name: "custom-rt",
|
|
332
|
+
options: { key: "value" },
|
|
333
|
+
});
|
|
334
|
+
const listed = listStashes();
|
|
335
|
+
const entry = listed.sources.find((s) => s.name === "custom-rt");
|
|
336
|
+
expect(entry).toBeDefined();
|
|
337
|
+
expect(entry?.type).toBe("my-custom");
|
|
338
|
+
expect(entry?.options).toEqual({ key: "value" });
|
|
339
|
+
removeStash("custom-rt");
|
|
340
|
+
const afterRemove = listStashes();
|
|
341
|
+
expect(afterRemove.sources.some((s) => s.name === "custom-rt")).toBe(false);
|
|
342
|
+
});
|
|
343
|
+
test("multiple adds and removes maintain order and integrity", () => {
|
|
344
|
+
const fs1 = createTmpDir("akm-multi-1-");
|
|
345
|
+
const fs2 = createTmpDir("akm-multi-2-");
|
|
346
|
+
const url1 = "https://v1.example.com";
|
|
347
|
+
const url2 = "https://v2.example.com";
|
|
348
|
+
addStash({ target: fs1, name: "fs1" });
|
|
349
|
+
addStash({ target: url1, providerType: "website", name: "v1" });
|
|
350
|
+
addStash({ target: fs2, name: "fs2" });
|
|
351
|
+
addStash({ target: url2, providerType: "website", name: "v2" });
|
|
352
|
+
let sources = listStashes().sources;
|
|
353
|
+
expect(sources).toHaveLength(4);
|
|
354
|
+
expect(sources.map((s) => s.name)).toEqual(["fs1", "v1", "fs2", "v2"]);
|
|
355
|
+
// Remove middle entry
|
|
356
|
+
removeStash("v1");
|
|
357
|
+
sources = listStashes().sources;
|
|
358
|
+
expect(sources).toHaveLength(3);
|
|
359
|
+
expect(sources.map((s) => s.name)).toEqual(["fs1", "fs2", "v2"]);
|
|
360
|
+
// Remove first entry
|
|
361
|
+
removeStash("fs1");
|
|
362
|
+
sources = listStashes().sources;
|
|
363
|
+
expect(sources).toHaveLength(2);
|
|
364
|
+
expect(sources.map((s) => s.name)).toEqual(["fs2", "v2"]);
|
|
365
|
+
});
|
|
366
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { afterAll, afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { resolveSourceProviderFactory } from "../../src/sources/provider-factory";
|
|
6
|
+
// Trigger self-registration
|
|
7
|
+
import "../../src/sources/providers/filesystem";
|
|
8
|
+
const createdTmpDirs = [];
|
|
9
|
+
function createTmpDir(prefix = "akm-fs-") {
|
|
10
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
11
|
+
createdTmpDirs.push(dir);
|
|
12
|
+
return dir;
|
|
13
|
+
}
|
|
14
|
+
const originalAkmStashDir = process.env.AKM_STASH_DIR;
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
process.env.AKM_STASH_DIR = createTmpDir("akm-fs-stash-");
|
|
17
|
+
});
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
if (originalAkmStashDir === undefined)
|
|
20
|
+
delete process.env.AKM_STASH_DIR;
|
|
21
|
+
else
|
|
22
|
+
process.env.AKM_STASH_DIR = originalAkmStashDir;
|
|
23
|
+
});
|
|
24
|
+
afterAll(() => {
|
|
25
|
+
for (const dir of createdTmpDirs) {
|
|
26
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
describe("FilesystemSourceProvider", () => {
|
|
30
|
+
test("self-registers as 'filesystem'", () => {
|
|
31
|
+
expect(resolveSourceProviderFactory("filesystem")).toBeTruthy();
|
|
32
|
+
});
|
|
33
|
+
test("init resolves and path returns the configured path", async () => {
|
|
34
|
+
const factory = resolveSourceProviderFactory("filesystem");
|
|
35
|
+
expect(factory).toBeTruthy();
|
|
36
|
+
if (!factory)
|
|
37
|
+
throw new Error("expected filesystem factory to be registered");
|
|
38
|
+
const stashDir = createTmpDir("akm-fs-init-");
|
|
39
|
+
const provider = factory({ type: "filesystem", path: stashDir, name: "mine" });
|
|
40
|
+
await provider.init({
|
|
41
|
+
name: "mine",
|
|
42
|
+
options: {},
|
|
43
|
+
cacheDir: stashDir,
|
|
44
|
+
resolveOption: (v) => (typeof v === "string" ? v : undefined),
|
|
45
|
+
});
|
|
46
|
+
expect(provider.kind).toBe("filesystem");
|
|
47
|
+
expect(provider.name).toBe("mine");
|
|
48
|
+
expect(provider.path()).toBe(stashDir);
|
|
49
|
+
});
|
|
50
|
+
test("path() returns the same value across calls (lifetime stability)", () => {
|
|
51
|
+
const factory = resolveSourceProviderFactory("filesystem");
|
|
52
|
+
expect(factory).toBeTruthy();
|
|
53
|
+
if (!factory)
|
|
54
|
+
throw new Error("expected filesystem factory to be registered");
|
|
55
|
+
const stashDir = createTmpDir("akm-fs-stable-");
|
|
56
|
+
const provider = factory({ type: "filesystem", path: stashDir, name: "stable" });
|
|
57
|
+
const first = provider.path();
|
|
58
|
+
const second = provider.path();
|
|
59
|
+
expect(second).toBe(first);
|
|
60
|
+
});
|
|
61
|
+
test("filesystem providers have no sync() (content is user-managed)", () => {
|
|
62
|
+
const factory = resolveSourceProviderFactory("filesystem");
|
|
63
|
+
expect(factory).toBeTruthy();
|
|
64
|
+
if (!factory)
|
|
65
|
+
throw new Error("expected filesystem factory to be registered");
|
|
66
|
+
const stashDir = createTmpDir("akm-fs-nosync-");
|
|
67
|
+
const provider = factory({ type: "filesystem", path: stashDir, name: "nosync" });
|
|
68
|
+
expect(provider.sync).toBeUndefined();
|
|
69
|
+
});
|
|
70
|
+
test("provider exposes only the v1 SourceProvider surface", () => {
|
|
71
|
+
const factory = resolveSourceProviderFactory("filesystem");
|
|
72
|
+
expect(factory).toBeTruthy();
|
|
73
|
+
if (!factory)
|
|
74
|
+
throw new Error("expected filesystem factory to be registered");
|
|
75
|
+
const stashDir = createTmpDir("akm-fs-iface-");
|
|
76
|
+
const provider = factory({ type: "filesystem", path: stashDir });
|
|
77
|
+
expect(provider.search).toBeUndefined();
|
|
78
|
+
expect(provider.show).toBeUndefined();
|
|
79
|
+
expect(provider.canShow).toBeUndefined();
|
|
80
|
+
expect(provider.getContentDir).toBeUndefined();
|
|
81
|
+
});
|
|
82
|
+
});
|