create Title object and children

This commit is contained in:
Andrzej Stepien 2023-09-07 11:39:09 +02:00
parent 87d041e28a
commit eb40822142
12 changed files with 202 additions and 1 deletions

View File

@ -17,7 +17,7 @@ export class Data {
} }
async getStories() { async getStories() {
return this.#db('stories') return this.#db('stories')
.select('*') .select('id','title','word_count')
} }
async getPublications() { async getPublications() {
return this.#db('pubs') return this.#db('pubs')

View File

@ -1,2 +1,27 @@
import dv from "./dv.mjs"
export default class Entity{
constructor(data){
if(data?.id){
if(!Number.isInteger(data.id)){throw new TypeError("id must be an integer!")}
this.id = data.id
}
}
async insert(db){
return db(this.table)
.insert(this)
}
async update(db){
return db(this.table)
.where('id',this.id)
.update(this)
}
async del(db){
if(!this?.id){throw new Error("cannot delete without an id!")}
return db(this.table)
.where('id',this.id)
this.del()
}
}

12
objects/Publication.mjs Normal file
View File

@ -0,0 +1,12 @@
import Title from "./Title.mjs";
import dv from "./dv.mjs";
export default class Publication extends Title{
constructor(data){
super(data)
if(data?.link){
if(!dv.isString(data.link)){throw new TypeError("link must be a string")}
this.link=data.link
}
}
}

10
objects/Story.mjs Normal file
View File

@ -0,0 +1,10 @@
import Title from "./Title.mjs"
export default class Story extends Title{
constructor(data){
super(data)
if(data?.word_count){
if(!Number.isInteger(data.word_count)){throw new TypeError("word_count must be integer!")}
this.word_count=data.word_count
}
}
}

16
objects/Title.mjs Normal file
View File

@ -0,0 +1,16 @@
import Entity from "./Entity.mjs";
import dv from "./dv.mjs";
//THIS CLASS WILL HANDLE JUNCTION TABLE STUFF
export default class Title extends Entity{
constructor(data){
super(data)
if(data?.title){
if(!dv.isString(data.title)){throw new TypeError("title must be a string")}
this.title=data.title
}
if(data?.genres){
if(!dv.isObject(data.genres)){throw new TypeError("genres must be an object")}
this.genres=data.genres
}
}
}

23
objects/dv.mjs Normal file
View File

@ -0,0 +1,23 @@
import { DateTime } from "luxon"
export default {
isNumber (n){
if(isNaN(n)){return false}
if (typeof n === "number") { return true }
return false
},
isString (s){
if (typeof s === 'string') { return true }
return false
},
dateStringIsValid(str){
if(str===null){return true}
if(DateTime.fromFormat(str,'yyyy-MM-dd').isValid){
return true
}
return false
},
isObject(objValue) {
return objValue && typeof objValue === 'object' && objValue.constructor === Object;
}
}

13
package-lock.json generated
View File

@ -11,10 +11,12 @@
"dependencies": { "dependencies": {
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
"chai": "^4.3.8", "chai": "^4.3.8",
"chai-as-promised": "^7.1.1",
"chai-http": "^4.4.0", "chai-http": "^4.4.0",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^4.18.2", "express": "^4.18.2",
"knex": "^2.5.1", "knex": "^2.5.1",
"lodash": "^4.17.21",
"luxon": "^3.4.3", "luxon": "^3.4.3",
"mocha": "^10.2.0", "mocha": "^10.2.0",
"pino": "^8.15.0", "pino": "^8.15.0",
@ -476,6 +478,17 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/chai-as-promised": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz",
"integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==",
"dependencies": {
"check-error": "^1.0.2"
},
"peerDependencies": {
"chai": ">= 2.1.2 < 5"
}
},
"node_modules/chai-http": { "node_modules/chai-http": {
"version": "4.4.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/chai-http/-/chai-http-4.4.0.tgz", "resolved": "https://registry.npmjs.org/chai-http/-/chai-http-4.4.0.tgz",

View File

@ -11,10 +11,12 @@
"dependencies": { "dependencies": {
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
"chai": "^4.3.8", "chai": "^4.3.8",
"chai-as-promised": "^7.1.1",
"chai-http": "^4.4.0", "chai-http": "^4.4.0",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^4.18.2", "express": "^4.18.2",
"knex": "^2.5.1", "knex": "^2.5.1",
"lodash": "^4.17.21",
"luxon": "^3.4.3", "luxon": "^3.4.3",
"mocha": "^10.2.0", "mocha": "^10.2.0",
"pino": "^8.15.0", "pino": "^8.15.0",

27
test/Entity.test.mjs Normal file
View File

@ -0,0 +1,27 @@
import { describe } from "mocha";
import Entity from "../objects/Entity.mjs";
import chaiAsPromised from "chai-as-promised";
import chai from "chai";
import { expect} from "chai";
import { testDb as db } from "../db.mjs";
chai.use(chaiAsPromised)
describe("tetsing Entity object",async function(){
it("should throw with code:400 if passed an invalid data.id",async function(){
expect(()=>{new Entity({id:"string"})}).to.throw(TypeError)
expect(()=>{new Entity({id:1.1})}).to.throw(TypeError)
expect(()=>{new Entity({id:{}})}).to.throw(TypeError)
expect(()=>{new Entity({id:[]})}).to.throw(TypeError)
})
it("should not throw if given a valid id",function(){
expect(()=>{new Entity({id:1})}).not.to.throw()
})
it(".delete() should throw if initialised without .id",function(){
const entity = new Entity()
return expect(entity.del(db)).to.eventually.be.rejectedWith(Error)
})
it(".delete() should throw if not passed a db",function(){
const entity = new Entity({id:1})
return expect(entity.del()).to.eventually.be.rejectedWith(Error)
})
})

19
test/Publication.test.mjs Normal file
View File

@ -0,0 +1,19 @@
import { describe } from "mocha";
import chaiAsPromised from "chai-as-promised";
import chai from "chai";
import { expect} from "chai";
import { testDb as db } from "../db.mjs";
import Publication from "../objects/Publication.mjs";
chai.use(chaiAsPromised)
describe("testing Publication object",function(){
it("should throw TypeError if passed invalid .link data",function(){
expect(()=>{new Publication({link:1})}).to.throw(TypeError)
expect(()=>{new Publication({link:[]})}).to.throw(TypeError)
expect(()=>{new Publication({link:{}})}).to.throw(TypeError)
})
it("should have a .link if initialised with valid data, and .link should be a string",function(){
const pub = new Publication({link:'string'})
expect(pub).to.contain.key('link')
expect(pub.link).to.be.a('string')
})
})

17
test/Story.test.mjs Normal file
View File

@ -0,0 +1,17 @@
import { describe } from "mocha";
import chaiAsPromised from "chai-as-promised";
import chai from "chai";
import { expect} from "chai";
import { testDb as db } from "../db.mjs";
import Story from "../objects/Story.mjs";
chai.use(chaiAsPromised)
describe("testing Story object",function(){
it("should throw TypeError if .word_count is not an integer",function(){
expect(()=>{new Story({word_count:1.1})}).to.throw(TypeError)
})
it("should have .word_count if created with valid data, and .word_count should be an integer",function(){
const story = new Story({word_count:100})
expect(story).to.contain.key('word_count')
expect(story.word_count).to.satisfy(Number.isInteger)
})
})

37
test/Title.test.mjs Normal file
View File

@ -0,0 +1,37 @@
import { describe } from "mocha";
import Title from "../objects/Title.mjs";
import chaiAsPromised from "chai-as-promised";
import chai from "chai";
import { expect} from "chai";
import { testDb as db } from "../db.mjs";
import _ from "lodash";
chai.use(chaiAsPromised)
describe("testing Title object",function(){
it("should throw if passed an invalid title",function(){
expect(()=>{new Title({title:1})}).to.throw()
expect(()=>{new Title({title:{}})}).to.throw()
expect(()=>{new Title({title:[]})}).to.throw()
})
it("should have .title if it has been passed a valid one, and it should be a string",function(){
const title = new Title({title:'Title'})
expect(title).to.contain.key('title')
expect(title.title).to.be.a('string')
})
it("should throw a TypeError if passed invalid .genres data",function(){
expect(()=>{new Title({genres:1})}).to.throw(TypeError)
expect(()=>{new Title({genres:"string"})}).to.throw(TypeError)
expect(()=>{new Title({genres:[]})}).to.throw(TypeError)
})
it("should have .genres if intitialised with valid data, and .genres should be an object",function(){
const story = new Title({genres:{fantasy:true,horror:false}})
expect(story).to.contain.key('genres')
expect(story.genres).to.be.a('object')
})
it("every value in correctly initialised .genres should be a boolean",function(){
const story = new Title({genres:{fantasy:true,horror:false}})
expect(story?.genres&&
Object.keys(story.genres).length>0&&
_.every(story.genres,genre=>{return typeof genre === 'boolean'})).to.equal(true)
})
})