diff --git a/vendor/wheels/tests/_assets/seeder/includethrow/seeds.cfm b/vendor/wheels/tests/_assets/seeder/includethrow/seeds.cfm
new file mode 100644
index 0000000000..030a502468
--- /dev/null
+++ b/vendor/wheels/tests/_assets/seeder/includethrow/seeds.cfm
@@ -0,0 +1,9 @@
+
+
+seedOnce(
+ modelName = "author",
+ uniqueProperties = "firstName",
+ properties = {firstName: "SeederThrowOK99", lastName: "ThrowOK"}
+);
+throw(type = "SeederIncludeBoom", message = "intentional include throw");
+
diff --git a/vendor/wheels/tests/_assets/seeder/seeds.cfm b/vendor/wheels/tests/_assets/seeder/seeds.cfm
index 40581e0a27..f0e3ad66e3 100644
--- a/vendor/wheels/tests/_assets/seeder/seeds.cfm
+++ b/vendor/wheels/tests/_assets/seeder/seeds.cfm
@@ -1,5 +1,8 @@
-
+
-// This seed file is used by the test suite.
-// It intentionally does nothing — tests that need seeded records use seedOnce() directly.
+seedOnce(
+ modelName = "author",
+ uniqueProperties = "firstName",
+ properties = {firstName: "SeederMainOK99", lastName: "MainSeed"}
+);
diff --git a/vendor/wheels/tests/_assets/seeder/stray/seeds/orphaned.cfm b/vendor/wheels/tests/_assets/seeder/stray/seeds/orphaned.cfm
new file mode 100644
index 0000000000..192255dceb
--- /dev/null
+++ b/vendor/wheels/tests/_assets/seeder/stray/seeds/orphaned.cfm
@@ -0,0 +1,8 @@
+
+
+seedOnce(
+ modelName = "author",
+ uniqueProperties = "firstName",
+ properties = {firstName: "SeederStrayOrphan99", lastName: "StrayOrphan"}
+);
+
diff --git a/vendor/wheels/tests/_assets/seeder/withenv/seeds.cfm b/vendor/wheels/tests/_assets/seeder/withenv/seeds.cfm
index 10b8a2a452..06efd6ef95 100644
--- a/vendor/wheels/tests/_assets/seeder/withenv/seeds.cfm
+++ b/vendor/wheels/tests/_assets/seeder/withenv/seeds.cfm
@@ -1,4 +1,8 @@
-
+
-// Main seeds - runs before environment-specific seeds
+seedOnce(
+ modelName = "author",
+ uniqueProperties = "firstName",
+ properties = {firstName: "SeederEnvMain99", lastName: "EnvMain"}
+);
diff --git a/vendor/wheels/tests/_assets/seeder/withenv/seeds/testing.cfm b/vendor/wheels/tests/_assets/seeder/withenv/seeds/testing.cfm
index 06057043aa..b078cd0fef 100644
--- a/vendor/wheels/tests/_assets/seeder/withenv/seeds/testing.cfm
+++ b/vendor/wheels/tests/_assets/seeder/withenv/seeds/testing.cfm
@@ -1,4 +1,8 @@
-
+
-// Testing environment seeds - runs after main seeds.cfm
+seedOnce(
+ modelName = "author",
+ uniqueProperties = "firstName",
+ properties = {firstName: "SeederEnvTest99", lastName: "EnvTest"}
+);
diff --git a/vendor/wheels/tests/specs/seederSpec.cfc b/vendor/wheels/tests/specs/seederSpec.cfc
index f4ac163588..05f9893fda 100644
--- a/vendor/wheels/tests/specs/seederSpec.cfc
+++ b/vendor/wheels/tests/specs/seederSpec.cfc
@@ -1,3 +1,12 @@
+/**
+ * Seeder suite plus hardener proofs for desk IDs S1–S10. Desk IDs stay locked.
+ *
+ * HOLD (pin unflipped, current behavior only):
+ * S4 — seedOnce interpolates unique values into WHERE (quote-escape only).
+ * S5 — generateSeeds is not transactional (a mixed list can leave rows).
+ *
+ * This is the only seeder spec file. Do not invent wheels.tests.specs.seeder.
+ */
component extends="wheels.WheelsTest" {
function beforeAll() {
@@ -12,8 +21,10 @@ component extends="wheels.WheelsTest" {
describe("init()", () => {
- it("initializes with default seed path", () => {
+ it("S9: default seedPath is ExpandPath of /app/db/", () => {
local.s = CreateObject("component", "wheels.Seeder").init();
+ expect(local.s.seedMappingPath).toBe("/app/db/");
+ expect(local.s.seedPath).toBe(ExpandPath("/app/db/"));
expect(local.s.seedPath).toInclude("app");
});
@@ -39,6 +50,21 @@ component extends="wheels.WheelsTest" {
expect(local.s.hasSeedFiles()).toBeFalse();
});
+ it("S3: hasSeedFiles is true for a stray seeds/*.cfm that runSeeds will not include", () => {
+ // hasSeedFiles() returns true if ANY seeds/*.cfm exists.
+ // runSeeds() only includes seeds.cfm + seeds/.cfm.
+ local.s = CreateObject("component", "wheels.Seeder").init(
+ seedPath = "/wheels/tests/_assets/seeder/stray/"
+ );
+ expect(local.s.hasSeedFiles()).toBeTrue();
+
+ $deleteAuthorByFirstName("SeederStrayOrphan99");
+ local.result = local.s.runSeeds(environment = "testing");
+ expect(local.result.success).toBeFalse();
+ expect(local.result.message).toInclude("No seed files found");
+ expect(IsObject(model("author").findOne(where = "firstName = 'SeederStrayOrphan99'"))).toBeFalse();
+ });
+
});
describe("runSeeds()", () => {
@@ -52,21 +78,60 @@ component extends="wheels.WheelsTest" {
expect(local.result.message).toInclude("No seed files found");
});
- it("runs main seeds.cfm file", () => {
+ it("S1: runs main seeds.cfm and creates the fixture record", () => {
+ $deleteAuthorByFirstName("SeederMainOK99");
+
local.s = CreateObject("component", "wheels.Seeder").init(
seedPath = "/wheels/tests/_assets/seeder/"
);
local.result = local.s.runSeeds(environment = "testing");
+
expect(local.result.success).toBeTrue();
- expect(local.result.totalCreated).toBeGTE(0);
+ expect(local.result.totalCreated).toBe(1);
+ expect(local.result.totalSkipped).toBe(0);
+ local.created = model("author").findOne(where = "firstName = 'SeederMainOK99'");
+ expect(IsObject(local.created)).toBeTrue();
+ expect(local.created.lastName).toBe("MainSeed");
+ local.created.delete();
});
- it("includes environment-specific seeds when available", () => {
+ it("S2: includes environment-specific seeds when available", () => {
+ $deleteAuthorByFirstName("SeederEnvMain99");
+ $deleteAuthorByFirstName("SeederEnvTest99");
+
local.s = CreateObject("component", "wheels.Seeder").init(
seedPath = "/wheels/tests/_assets/seeder/withenv/"
);
local.result = local.s.runSeeds(environment = "testing");
+
expect(local.result.success).toBeTrue();
+ expect(local.result.totalCreated).toBe(2);
+ expect(local.result.environment).toBe("testing");
+ local.mainRow = model("author").findOne(where = "firstName = 'SeederEnvMain99'");
+ local.envRow = model("author").findOne(where = "firstName = 'SeederEnvTest99'");
+ expect(IsObject(local.mainRow)).toBeTrue();
+ expect(IsObject(local.envRow)).toBeTrue();
+ expect(local.mainRow.lastName).toBe("EnvMain");
+ expect(local.envRow.lastName).toBe("EnvTest");
+ local.mainRow.delete();
+ local.envRow.delete();
+ });
+
+ it("S2: an environment without a matching file does not include seeds/testing.cfm", () => {
+ $deleteAuthorByFirstName("SeederEnvMain99");
+ $deleteAuthorByFirstName("SeederEnvTest99");
+
+ local.s = CreateObject("component", "wheels.Seeder").init(
+ seedPath = "/wheels/tests/_assets/seeder/withenv/"
+ );
+ local.result = local.s.runSeeds(environment = "development");
+
+ expect(local.result.success).toBeTrue();
+ expect(local.result.totalCreated).toBe(1);
+ expect(local.result.environment).toBe("development");
+ expect(IsObject(model("author").findOne(where = "firstName = 'SeederEnvMain99'"))).toBeTrue();
+ expect(IsObject(model("author").findOne(where = "firstName = 'SeederEnvTest99'"))).toBeFalse();
+ $deleteAuthorByFirstName("SeederEnvMain99");
});
it("returns failure and rolls back when a seedOnce entry fails validation", () => {
@@ -93,6 +158,75 @@ component extends="wheels.WheelsTest" {
expect(IsObject(local.leaked)).toBeFalse();
});
+ it("S7: include-throw is caught, reported, and rolled back", () => {
+ $deleteAuthorByFirstName("SeederThrowOK99");
+
+ local.s = CreateObject("component", "wheels.Seeder").init(
+ seedPath = "/wheels/tests/_assets/seeder/includethrow/"
+ );
+ local.result = local.s.runSeeds(environment = "testing");
+
+ expect(local.result.success).toBeFalse();
+ expect(local.result.message).toInclude("Seed failed:");
+ expect(local.result.message).toInclude("intentional include throw");
+ expect(StructKeyExists(local.result, "detail")).toBeTrue();
+ expect(IsObject(model("author").findOne(where = "firstName = 'SeederThrowOK99'"))).toBeFalse();
+ });
+
+ it("S8: request.$wheelsSeeder is left set after a successful run", () => {
+ $deleteAuthorByFirstName("SeederMainOK99");
+ StructDelete(request, "$wheelsSeeder");
+
+ local.s = CreateObject("component", "wheels.Seeder").init(
+ seedPath = "/wheels/tests/_assets/seeder/"
+ );
+ local.result = local.s.runSeeds(environment = "testing");
+
+ expect(local.result.success).toBeTrue();
+ expect(StructKeyExists(request, "$wheelsSeeder")).toBeTrue();
+ expect(request.$wheelsSeeder.seedMappingPath).toBe("/wheels/tests/_assets/seeder/");
+ $deleteAuthorByFirstName("SeederMainOK99");
+ });
+
+ it("S8: a later run still sees request.$wheelsSeeder", () => {
+ $deleteAuthorByFirstName("SeederMainOK99");
+ $deleteAuthorByFirstName("SeederEnvMain99");
+ $deleteAuthorByFirstName("SeederEnvTest99");
+ StructDelete(request, "$wheelsSeeder");
+
+ local.first = CreateObject("component", "wheels.Seeder").init(
+ seedPath = "/wheels/tests/_assets/seeder/"
+ );
+ local.first.runSeeds(environment = "testing");
+ expect(StructKeyExists(request, "$wheelsSeeder")).toBeTrue();
+
+ local.second = CreateObject("component", "wheels.Seeder").init(
+ seedPath = "/wheels/tests/_assets/seeder/withenv/"
+ );
+ local.second.runSeeds(environment = "testing");
+
+ // Never cleared — a later run overwrites the leftover, it does not delete it.
+ expect(StructKeyExists(request, "$wheelsSeeder")).toBeTrue();
+ expect(request.$wheelsSeeder.seedMappingPath).toBe("/wheels/tests/_assets/seeder/withenv/");
+ $deleteAuthorByFirstName("SeederMainOK99");
+ $deleteAuthorByFirstName("SeederEnvMain99");
+ $deleteAuthorByFirstName("SeederEnvTest99");
+ });
+
+ it("S8: the include-throw catch path also leaves request.$wheelsSeeder set", () => {
+ $deleteAuthorByFirstName("SeederThrowOK99");
+ StructDelete(request, "$wheelsSeeder");
+
+ local.s = CreateObject("component", "wheels.Seeder").init(
+ seedPath = "/wheels/tests/_assets/seeder/includethrow/"
+ );
+ local.result = local.s.runSeeds(environment = "testing");
+
+ expect(local.result.success).toBeFalse();
+ expect(StructKeyExists(request, "$wheelsSeeder")).toBeTrue();
+ expect(request.$wheelsSeeder.seedMappingPath).toBe("/wheels/tests/_assets/seeder/includethrow/");
+ });
+
it("throws when the environment name contains path traversal characters", () => {
expect(function() {
seeder.runSeeds(environment = "../../../app/somefile");
@@ -173,6 +307,42 @@ component extends="wheels.WheelsTest" {
local.author.delete();
});
+ it("S4 HOLD: unique values are interpolated into WHERE with quote-escape only", () => {
+ // HOLD pin: seedOnce builds `prop = 'escaped'` via
+ // Replace(val, "'", "''") and hands that string to findOne(where=).
+ // It does not bind parameters. After the query layer processes
+ // the interpolated clause, an apostrophe in the unique value
+ // does not match the stored row — the second call creates again.
+ // Do not flip to parameterized WHERE.
+ local.uniqueFirst = "O'Brien_#Replace(CreateUUID(), '-', '', 'all')#";
+
+ local.first = seeder.seedOnce(
+ modelName = "author",
+ uniqueProperties = "firstName",
+ properties = {firstName: local.uniqueFirst, lastName: "QuoteEscape"}
+ );
+ expect(local.first.action).toBe("created");
+ expect(StructKeyExists(local.first, "key")).toBeTrue();
+
+ local.second = seeder.seedOnce(
+ modelName = "author",
+ uniqueProperties = "firstName",
+ properties = {firstName: local.uniqueFirst, lastName: "QuoteEscape"}
+ );
+ expect(local.second.action).toBe("created");
+ expect(StructKeyExists(local.second, "key")).toBeTrue();
+ expect(local.second.key).notToBe(local.first.key);
+
+ local.firstRow = model("author").findByKey(local.first.key);
+ if (IsObject(local.firstRow)) {
+ local.firstRow.delete();
+ }
+ local.secondRow = model("author").findByKey(local.second.key);
+ if (IsObject(local.secondRow)) {
+ local.secondRow.delete();
+ }
+ });
+
it("counts failed entries and reports them in the result", () => {
seeder.totalFailed = 0;
@@ -283,6 +453,78 @@ component extends="wheels.WheelsTest" {
expect(StructKeyExists(local.result.seeded[1], "error")).toBeTrue();
});
+ it("S5 HOLD: generateSeeds is not transactional — a mixed list can leave rows", () => {
+ // HOLD pin: generateSeeds has no transaction. Author rows persist
+ // even though the missing model forces overall success=false.
+ // Do not wrap generateSeeds in a transaction.
+ local.beforeQuery = model("Author").findAll(select = "id");
+ local.beforeIds = ValueList(local.beforeQuery.id);
+
+ local.gen = CreateObject("component", "wheels.Seeder").init();
+ local.result = local.gen.generateSeeds(
+ models = "Author,NoSuchModel_SeederS5",
+ count = 1
+ );
+
+ expect(local.result.success).toBeFalse();
+ expect(local.result.totalCreated).toBe(1);
+ expect(local.result.totalFailed).toBe(1);
+ expect(ArrayLen(local.result.seeded)).toBe(2);
+ expect(local.result.seeded[1].model).toBe("Author");
+ expect(local.result.seeded[1].success).toBeTrue();
+ expect(local.result.seeded[2].success).toBeFalse();
+
+ local.afterQuery = model("Author").findAll(select = "id");
+ local.afterIds = ValueList(local.afterQuery.id);
+ expect(ListLen(local.afterIds) - ListLen(local.beforeIds)).toBe(1);
+
+ if (Len(local.beforeIds)) {
+ model("Author").deleteAll(where = "id NOT IN (#local.beforeIds#)", instantiate = false);
+ } else {
+ model("Author").deleteAll(instantiate = false);
+ }
+ });
+
+ it("S6: count=0 reports overall failure even when the per-model entry succeeds", () => {
+ // success requires totalCreated>0. The per-model loop does not
+ // run (1 <= 0), so seededCount==count and the entry is success=true.
+ local.beforeQuery = model("Author").findAll(select = "id");
+ local.beforeIds = ValueList(local.beforeQuery.id);
+
+ local.gen = CreateObject("component", "wheels.Seeder").init();
+ local.result = local.gen.generateSeeds(models = "Author", count = 0);
+
+ expect(local.result.success).toBeFalse();
+ expect(local.result.totalCreated).toBe(0);
+ expect(local.result.totalFailed).toBe(0);
+ expect(ArrayLen(local.result.seeded)).toBe(1);
+ expect(local.result.seeded[1].count).toBe(0);
+ expect(local.result.seeded[1].success).toBeTrue();
+
+ local.afterQuery = model("Author").findAll(select = "id");
+ expect(ValueList(local.afterQuery.id)).toBe(local.beforeIds);
+ });
+
+ it("S6: a negative count creates no rows and marks the model failed", () => {
+ // The for-loop does not run. seededCount (0) != count (-1), so
+ // the entry is success=false and totalFailed increments.
+ local.beforeQuery = model("Author").findAll(select = "id");
+ local.beforeIds = ValueList(local.beforeQuery.id);
+
+ local.gen = CreateObject("component", "wheels.Seeder").init();
+ local.result = local.gen.generateSeeds(models = "Author", count = -1);
+
+ expect(local.result.success).toBeFalse();
+ expect(local.result.totalCreated).toBe(0);
+ expect(local.result.totalFailed).toBe(1);
+ expect(ArrayLen(local.result.seeded)).toBe(1);
+ expect(local.result.seeded[1].count).toBe(0);
+ expect(local.result.seeded[1].success).toBeFalse();
+
+ local.afterQuery = model("Author").findAll(select = "id");
+ expect(ValueList(local.afterQuery.id)).toBe(local.beforeIds);
+ });
+
it("reports failure (not silent success) when an explicit list resolves to no models", () => {
local.gen = CreateObject("component", "wheels.Seeder").init();
// A delimiter-only list is a non-blank value (so it does NOT fall
@@ -318,8 +560,114 @@ component extends="wheels.WheelsTest" {
});
+ describe("$generateTestData()", () => {
+
+ it("S10: email names return an example.com address", () => {
+ expect(seeder.$generateTestData(propertyName = "email", propertyType = "string", index = 1)).toBe("test1@example.com");
+ expect(seeder.$generateTestData(propertyName = "userEmail", propertyType = "integer", index = 4)).toBe("test4@example.com");
+ });
+
+ it("S10: firstname / fname cycle the first-name list", () => {
+ expect(seeder.$generateTestData(propertyName = "firstName", propertyType = "string", index = 1)).toBe("John");
+ expect(seeder.$generateTestData(propertyName = "fname", propertyType = "string", index = 2)).toBe("Jane");
+ expect(seeder.$generateTestData(propertyName = "firstName", propertyType = "string", index = 11)).toBe("John");
+ });
+
+ it("S10: lastname / lname cycle the last-name list", () => {
+ expect(seeder.$generateTestData(propertyName = "lastName", propertyType = "string", index = 1)).toBe("Smith");
+ expect(seeder.$generateTestData(propertyName = "lname", propertyType = "string", index = 2)).toBe("Johnson");
+ });
+
+ it("S10: exact name and username return TestUserN", () => {
+ expect(seeder.$generateTestData(propertyName = "name", propertyType = "string", index = 3)).toBe("TestUser3");
+ expect(seeder.$generateTestData(propertyName = "userName", propertyType = "string", index = 3)).toBe("TestUser3");
+ expect(seeder.$generateTestData(propertyName = "displayName", propertyType = "string", index = 3)).toBe("displayName Test 3");
+ });
+
+ it("S10: phone / mobile, address / street, and geo names", () => {
+ expect(seeder.$generateTestData(propertyName = "phone", propertyType = "string", index = 1)).toBe("555-1001");
+ expect(seeder.$generateTestData(propertyName = "mobile", propertyType = "string", index = 2)).toBe("555-1002");
+ expect(seeder.$generateTestData(propertyName = "address", propertyType = "string", index = 4)).toBe("4 Test Street");
+ expect(seeder.$generateTestData(propertyName = "street", propertyType = "string", index = 4)).toBe("4 Test Street");
+ expect(seeder.$generateTestData(propertyName = "city", propertyType = "string", index = 1)).toBe("New York");
+ expect(seeder.$generateTestData(propertyName = "city", propertyType = "string", index = 2)).toBe("Los Angeles");
+ expect(seeder.$generateTestData(propertyName = "state", propertyType = "string", index = 1)).toBe("CA");
+ expect(seeder.$generateTestData(propertyName = "province", propertyType = "string", index = 2)).toBe("TX");
+ expect(seeder.$generateTestData(propertyName = "zip", propertyType = "string", index = 1)).toBe("10001");
+ expect(seeder.$generateTestData(propertyName = "postal", propertyType = "string", index = 2)).toBe("10002");
+ });
+
+ it("S10: url / website and password names", () => {
+ expect(seeder.$generateTestData(propertyName = "url", propertyType = "string", index = 5)).toBe("https://example5.com");
+ expect(seeder.$generateTestData(propertyName = "website", propertyType = "string", index = 5)).toBe("https://example5.com");
+ expect(seeder.$generateTestData(propertyName = "password", propertyType = "string", index = 5)).toBe("TestPass5!");
+ });
+
+ it("S10: boolean type and active / enabled / published names", () => {
+ expect(seeder.$generateTestData(propertyName = "flag", propertyType = "boolean", index = 1)).toBeTrue();
+ expect(seeder.$generateTestData(propertyName = "flag", propertyType = "boolean", index = 2)).toBeFalse();
+ expect(seeder.$generateTestData(propertyName = "isActive", propertyType = "string", index = 1)).toBeTrue();
+ expect(seeder.$generateTestData(propertyName = "enabled", propertyType = "string", index = 2)).toBeFalse();
+ // publishedAt matches "published" before the later date-name branch.
+ expect(seeder.$generateTestData(propertyName = "publishedAt", propertyType = "string", index = 1)).toBeTrue();
+ });
+
+ it("S10: integer / numeric type — age, price, quantity, and default", () => {
+ expect(seeder.$generateTestData(propertyName = "age", propertyType = "integer", index = 1)).toBe(21);
+ expect(seeder.$generateTestData(propertyName = "price", propertyType = "numeric", index = 1)).toBe(10.99);
+ expect(seeder.$generateTestData(propertyName = "cost", propertyType = "integer", index = 2)).toBe(20.99);
+ expect(seeder.$generateTestData(propertyName = "amount", propertyType = "integer", index = 3)).toBe(30.99);
+ expect(seeder.$generateTestData(propertyName = "quantity", propertyType = "integer", index = 2)).toBe(10);
+ expect(seeder.$generateTestData(propertyName = "count", propertyType = "integer", index = 3)).toBe(15);
+ expect(seeder.$generateTestData(propertyName = "views", propertyType = "integer", index = 7)).toBe(7);
+ });
+
+ it("S10: date type and date / birthday / dob names", () => {
+ local.typed = seeder.$generateTestData(propertyName = "foo", propertyType = "date", index = 3);
+ expect(IsDate(local.typed)).toBeTrue();
+ expect(DateDiff("d", local.typed, Now())).toBe(3);
+
+ local.named = seeder.$generateTestData(propertyName = "startDate", propertyType = "string", index = 2);
+ expect(IsDate(local.named)).toBeTrue();
+ expect(DateDiff("d", local.named, Now())).toBe(2);
+
+ local.birthday = seeder.$generateTestData(propertyName = "birthday", propertyType = "string", index = 1);
+ expect(IsDate(local.birthday)).toBeTrue();
+ local.dob = seeder.$generateTestData(propertyName = "dob", propertyType = "datetime", index = 4);
+ expect(IsDate(local.dob)).toBeTrue();
+ expect(DateDiff("d", local.dob, Now())).toBe(4);
+ });
+
+ it("S10: text type and description / content / body / title / status", () => {
+ local.lorem = "This is test content 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
+ expect(seeder.$generateTestData(propertyName = "foo", propertyType = "text", index = 1)).toBe(local.lorem);
+ expect(seeder.$generateTestData(propertyName = "description", propertyType = "string", index = 1)).toBe(local.lorem);
+ expect(seeder.$generateTestData(propertyName = "content", propertyType = "string", index = 1)).toBe(local.lorem);
+ expect(seeder.$generateTestData(propertyName = "body", propertyType = "string", index = 1)).toBe(local.lorem);
+ expect(seeder.$generateTestData(propertyName = "title", propertyType = "string", index = 8)).toBe("Test Title 8");
+ expect(seeder.$generateTestData(propertyName = "subject", propertyType = "string", index = 8)).toBe("Test Title 8");
+ expect(seeder.$generateTestData(propertyName = "status", propertyType = "string", index = 1)).toBe("pending");
+ expect(seeder.$generateTestData(propertyName = "status", propertyType = "string", index = 2)).toBe("active");
+ expect(seeder.$generateTestData(propertyName = "status", propertyType = "string", index = 5)).toBe("pending");
+ });
+
+ it("S10: unmatched names fall through to the default string", () => {
+ expect(seeder.$generateTestData(propertyName = "zzz", propertyType = "string", index = 9)).toBe("zzz Test 9");
+ expect(seeder.$generateTestData(propertyName = "notes", index = 1)).toBe("notes Test 1");
+ });
+
+ });
+
});
}
+ public void function $deleteAuthorByFirstName(required string firstName) {
+ local.escaped = Replace(arguments.firstName, "'", "''", "all");
+ local.record = model("author").findOne(where = "firstName = '#local.escaped#'");
+ if (IsObject(local.record)) {
+ local.record.delete();
+ }
+ }
+
}