You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
4.0 KiB
JavaScript

"use strict";
const expect = require("chai").expect;
const dm = require("../src");
/* FIXME: Slot rule testing */
/* FIXME: Function guard signature matching */
let GitSource = dm.createTrait("GitSource", {
stringify: dm.function([], dm.string())
});
let GithubSource, CrytoGitSource, ExternalGitSource, sourceOne, sourceTwo, randomGitSource;
describe("traits", () => {
it("should allow valid trait implementations", () => {
GithubSource = dm.createType("GithubSource", {
username: dm.string(),
repository: dm.string()
}).implements(GitSource, {
stringify: dm.guard([], dm.string(), function () {
return `https://github.com/${this.username}/${this.repository}.git`;
})
});
CrytoGitSource = dm.createType("CrytoGitSource", {
username: dm.string(),
repository: dm.string()
}).implements(GitSource, {
stringify: dm.guard([], dm.string(), function () {
return `http://git.cryto.net/${this.username}/${this.repository}.git`;
})
});
});
it("should produce working trait functionality", () => {
sourceOne = GithubSource({
username: "joepie91",
repository: "node-bhttp"
});
expect(sourceOne.stringify()).to.equal("https://github.com/joepie91/node-bhttp.git");
sourceTwo = CrytoGitSource({
username: "joepie91",
repository: "node-bhttp"
});
expect(sourceTwo.stringify()).to.equal("http://git.cryto.net/joepie91/node-bhttp.git");
});
let guardedFunc = dm.guard([GitSource], dm.nothing(), function (source) {
expect(source.stringify()).to.be.a("string");
});
it("should allow an instance of any type with the correct trait to be passed into a trait-guarded function", () => {
guardedFunc(sourceOne);
guardedFunc(sourceTwo);
});
it("should reject an instance of a type that does not have the correct trait", () => {
let SomeType = dm.createType("SomeType", {
value: dm.string()
});
let instance = SomeType({
value: "foo"
});
expect(() => {
guardedFunc(instance);
}).to.throw("Expected object of a type with the GitSource trait, got an instance of SomeType instead");
});
it(" ... even if that type has an otherwise compatible-looking method", () => {
let SomeOtherType = dm.createType("SomeOtherType", {
value: dm.string(),
stringify: dm.function([], dm.string())
});
let instance = SomeOtherType({
value: "foo",
stringify: dm.guard([], dm.string(), function () {
return "this is not a URL at all";
})
});
expect(() => {
guardedFunc(instance);
}).to.throw("Expected object of a type with the GitSource trait, got an instance of SomeOtherType instead");
});
it("should reject a trait implementation that does not meet the trait definition", () => {
expect(() => {
let InvalidType = dm.createType("InvalidType", {
value: dm.string()
}).implements(GitSource, {
stringify: "this is not a function"
});
}).to.throw("Expected a guarded function () → string, got a string instead");
});
it("should reject an empty trait implementation when the trait definition does not allow that", () => {
expect(() => {
let InvalidType = dm.createType("InvalidType", {
value: dm.string()
}).implements(GitSource, {
});
}).to.throw("Value is required for property 'stringify'");
});
it("should allow for specifying slot rules", () => {
ExternalGitSource = dm.createType("ExternalGitSource", {
sourceName: dm.string()
}).implements(GitSource, {
stringify: dm.slot()
});
});
it("should allow specifying a value for that slot", () => {
randomGitSource = ExternalGitSource({
sourceName: "randomGit",
stringify: dm.guard([], dm.string(), function () {
return "https://randomgit.example.com/repo.git"
})
});
});
it("should have produced a working slot value", () => {
expect(randomGitSource.stringify()).to.equal("https://randomgit.example.com/repo.git");
});
it("should reject an invalid slot value in the instance", () => {
expect(() => {
ExternalGitSource({
sourceName: "randomGit",
stringify: "foo"
});
}).to.throw("Expected a guarded function () → string, got a string instead");
});
});