Add initial project files and configurations for clawd_code
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import "package:test/test.dart";
|
||||
import "package:clawd_code/src/utils/array_utils.dart";
|
||||
|
||||
|
||||
void main() {
|
||||
group("intersperse", () {
|
||||
test("adds separator between elements", () {
|
||||
final result = intersperse([1, 2, 3], (_) => 0);
|
||||
expect(result, equals([1, 0, 2, 0, 3]));
|
||||
});
|
||||
|
||||
test("empty list stays empty", () {
|
||||
expect(intersperse([], (_) => 0), isEmpty);
|
||||
});
|
||||
|
||||
test("single element no separator", () {
|
||||
expect(intersperse([42], (_) => 0), equals([42]));
|
||||
});
|
||||
});
|
||||
|
||||
group("countWhere", () {
|
||||
test("counts matching elements", () {
|
||||
expect(countWhere([1, 2, 3, 4, 5], (x) => x % 2 == 0), equals(2));
|
||||
});
|
||||
|
||||
test("zero when none match", () {
|
||||
expect(countWhere([1, 3, 5], (x) => x % 2 == 0), equals(0));
|
||||
});
|
||||
});
|
||||
|
||||
group("uniq", () {
|
||||
test("removes duplicates preserving order", () {
|
||||
expect(uniq([1, 2, 1, 3, 2, 4]), equals([1, 2, 3, 4]));
|
||||
});
|
||||
|
||||
test("empty stays empty", () {
|
||||
expect(uniq([]), isEmpty);
|
||||
});
|
||||
|
||||
test("strings work too", () {
|
||||
expect(uniq(["a", "b", "a", "c"]), equals(["a", "b", "c"]));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import "package:test/test.dart";
|
||||
import "package:clawd_code/src/utils/format_utils.dart";
|
||||
|
||||
|
||||
void main() {
|
||||
group("formatFileSize", () {
|
||||
test("bytes when under 1kb", () {
|
||||
expect(formatFileSize(512), equals("512 bytes"));
|
||||
});
|
||||
|
||||
test("KB format", () {
|
||||
expect(formatFileSize(2048), equals("2KB"));
|
||||
});
|
||||
|
||||
test("MB format", () {
|
||||
expect(formatFileSize(1024 * 1024 * 3), equals("3MB"));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
group("formatSecondsShort", () {
|
||||
test("formats ms as seconds", () {
|
||||
expect(formatSecondsShort(1500), equals("1.5s"));
|
||||
});
|
||||
});
|
||||
|
||||
group("formatDuration", () {
|
||||
test("seconds only", () {
|
||||
expect(formatDuration(5000), equals("5s"));
|
||||
});
|
||||
|
||||
test("minutes and seconds", () {
|
||||
expect(formatDuration(90000), equals("1m 30s"));
|
||||
});
|
||||
|
||||
test("zero returns 0s", () {
|
||||
expect(formatDuration(0), equals("0s"));
|
||||
});
|
||||
});
|
||||
|
||||
group("formatNumber", () {
|
||||
test("small numbers as-is", () {
|
||||
expect(formatNumber(42), equals("42"));
|
||||
});
|
||||
|
||||
test("thousands", () {
|
||||
final result = formatNumber(1500);
|
||||
expect(result.contains("k"), isTrue);
|
||||
});
|
||||
|
||||
test("millions", () {
|
||||
expect(formatNumber(2000000), equals("2m"));
|
||||
});
|
||||
});
|
||||
|
||||
group("formatTokens", () {
|
||||
test("strips trailing .0", () {
|
||||
expect(formatTokens(1000), isNot(contains(".0")));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import "package:test/test.dart";
|
||||
import "package:clawd_code/src/utils/model_cost.dart";
|
||||
|
||||
|
||||
void main() {
|
||||
group("getCanonicalModelName", () {
|
||||
test("strips date suffix", () {
|
||||
expect(getCanonicalModelName("claude-sonnet-4-6-20241022"), equals("claude-sonnet-4-6"));
|
||||
});
|
||||
|
||||
test("known model unchanged", () {
|
||||
expect(getCanonicalModelName("claude-sonnet-4-6"), equals("claude-sonnet-4-6"));
|
||||
});
|
||||
});
|
||||
|
||||
group("getModelCosts", () {
|
||||
test("returns correct costs for known model", () {
|
||||
final costs = getModelCosts("claude-sonnet-4-6");
|
||||
expect(costs.inputTokens, equals(3.0));
|
||||
expect(costs.outputTokens, equals(15.0));
|
||||
});
|
||||
|
||||
test("unknown model returns fallback", () {
|
||||
final costs = getModelCosts("totally-made-up-model");
|
||||
// should not throw, just returns default
|
||||
expect(costs.inputTokens, greaterThan(0));
|
||||
});
|
||||
});
|
||||
|
||||
group("calculateUSDCost", () {
|
||||
test("zero usage is zero cost", () {
|
||||
final usage = TokenUsage(inputTokens: 0, outputTokens: 0);
|
||||
expect(calculateUSDCost("claude-sonnet-4-6", usage), equals(0.0));
|
||||
});
|
||||
|
||||
test("1M input tokens at \$3 rate", () {
|
||||
final usage = TokenUsage(inputTokens: 1000000, outputTokens: 0);
|
||||
final cost = calculateUSDCost("claude-sonnet-4-6", usage);
|
||||
expect(cost, closeTo(3.0, 0.001));
|
||||
});
|
||||
});
|
||||
|
||||
group("formatModelPricing", () {
|
||||
test("formats expected string", () {
|
||||
final result = formatModelPricing(costTier3_15);
|
||||
expect(result, contains("3"));
|
||||
expect(result, contains("15"));
|
||||
expect(result, contains("Mtok"));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import "package:test/test.dart";
|
||||
import "package:clawd_code/src/utils/semver_utils.dart";
|
||||
|
||||
|
||||
void main() {
|
||||
group("semverOrder", () {
|
||||
test("equal versions return 0", () {
|
||||
expect(semverOrder("1.2.3", "1.2.3"), equals(0));
|
||||
});
|
||||
|
||||
test("greater major returns 1", () {
|
||||
expect(semverOrder("2.0.0", "1.0.0"), equals(1));
|
||||
});
|
||||
|
||||
test("lesser patch returns -1", () {
|
||||
expect(semverOrder("1.2.2", "1.2.3"), equals(-1));
|
||||
});
|
||||
|
||||
test("strips v prefix", () {
|
||||
expect(semverOrder("v1.0.0", "1.0.0"), equals(0));
|
||||
});
|
||||
});
|
||||
|
||||
group("semverGt / semverLt", () {
|
||||
test("gt works", () {
|
||||
expect(semverGt("2.0.0", "1.9.9"), isTrue);
|
||||
expect(semverGt("1.0.0", "2.0.0"), isFalse);
|
||||
});
|
||||
|
||||
test("lt works", () {
|
||||
expect(semverLt("1.0.0", "1.0.1"), isTrue);
|
||||
});
|
||||
});
|
||||
|
||||
group("semverSatisfies", () {
|
||||
test("caret range", () {
|
||||
expect(semverSatisfies("1.2.3", "^1.0.0"), isTrue);
|
||||
expect(semverSatisfies("2.0.0", "^1.0.0"), isFalse);
|
||||
});
|
||||
|
||||
test("tilde range", () {
|
||||
expect(semverSatisfies("1.2.5", "~1.2.0"), isTrue);
|
||||
expect(semverSatisfies("1.3.0", "~1.2.0"), isFalse);
|
||||
});
|
||||
|
||||
test("gte range", () {
|
||||
expect(semverSatisfies("3.0.0", ">=2.0.0"), isTrue);
|
||||
expect(semverSatisfies("1.9.9", ">=2.0.0"), isFalse);
|
||||
});
|
||||
|
||||
test("exact match", () {
|
||||
expect(semverSatisfies("1.2.3", "1.2.3"), isTrue);
|
||||
expect(semverSatisfies("1.2.4", "1.2.3"), isFalse);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import "package:test/test.dart";
|
||||
import "package:clawd_code/src/utils/string_utils.dart";
|
||||
|
||||
|
||||
void main() {
|
||||
group("escapeRegExp", () {
|
||||
test("escapes dot and star", () {
|
||||
expect(escapeRegExp("a.b*c"), equals(r"a\.b\*c"));
|
||||
});
|
||||
|
||||
test("plain string unchanged", () {
|
||||
expect(escapeRegExp("hello"), equals("hello"));
|
||||
});
|
||||
});
|
||||
|
||||
group("capitalize", () {
|
||||
test("uppercases first char", () {
|
||||
expect(capitalize("foo"), equals("Foo"));
|
||||
});
|
||||
|
||||
test("empty string stays empty", () {
|
||||
expect(capitalize(""), equals(""));
|
||||
});
|
||||
|
||||
test("doesnt lowercase rest", () {
|
||||
expect(capitalize("fOOBAR"), equals("FOOBAR"));
|
||||
});
|
||||
});
|
||||
|
||||
group("plural", () {
|
||||
test("singular for 1", () {
|
||||
expect(plural(1, "file"), equals("file"));
|
||||
});
|
||||
|
||||
test("appends s for other counts", () {
|
||||
expect(plural(3, "file"), equals("files"));
|
||||
});
|
||||
|
||||
test("uses custom plural form", () {
|
||||
expect(plural(2, "entry", "entries"), equals("entries"));
|
||||
});
|
||||
});
|
||||
|
||||
group("firstLineOf", () {
|
||||
test("returns full string when no newline", () {
|
||||
expect(firstLineOf("hello world"), equals("hello world"));
|
||||
});
|
||||
|
||||
test("returns only first line", () {
|
||||
expect(firstLineOf("line1\nline2\nline3"), equals("line1"));
|
||||
});
|
||||
});
|
||||
|
||||
group("countChar", () {
|
||||
test("counts occurrences", () {
|
||||
expect(countChar("banana", "a"), equals(3));
|
||||
});
|
||||
|
||||
test("zero when not found", () {
|
||||
expect(countChar("hello", "z"), equals(0));
|
||||
});
|
||||
});
|
||||
|
||||
group("truncate", () {
|
||||
test("short string unchanged", () {
|
||||
expect(truncate("hi", 10), equals("hi"));
|
||||
});
|
||||
|
||||
test("truncates long string with ellipsis", () {
|
||||
final result = truncate("hello world", 8);
|
||||
expect(result.length, lessThanOrEqualTo(8));
|
||||
expect(result.endsWith("..."), isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user