predicates.spec.js
1 import { db, staff } from './microshaft.db.js' 2 import { Text, Data, fact, Link } from './lib.js' 3 4 /** 5 * @type {import('entail').Suite} 6 */ 7 export const testMore = { 8 'test facts': async (assert) => { 9 const Person = fact({ the: 'person', name: String }) 10 const Job = fact({ the: 'job', title: String }) 11 12 const Employee = fact({ name: String, job: String }).where( 13 ({ this: employee, name, job }) => [ 14 Person({ this: employee, name }), 15 Job({ this: employee, title: job }), 16 ] 17 ) 18 19 const job = 'Computer programmer' 20 assert.deepEqual(await Employee.match({ job }).query({ from: db }), [ 21 Employee.assert({ 22 this: Link.of(staff.alyssa), 23 job, 24 name: 'Hacker Alyssa P', 25 }), 26 Employee.assert({ this: Link.of(staff.cy), job, name: 'Fect Cy D' }), 27 ]) 28 29 const ComputerPeople = Employee.where(({ this: employee, name, job }) => [ 30 Employee({ this: employee, name, job }), 31 Text.match({ this: job, pattern: 'Computer*' }), 32 ]) 33 34 assert.deepEqual(await ComputerPeople().query({ from: db }), [ 35 Employee.assert({ 36 this: Link.of(staff.ben), 37 name: 'Bitdiddle Ben', 38 job: 'Computer wizard', 39 }), 40 Employee.assert({ 41 this: Link.of(staff.alyssa), 42 name: 'Hacker Alyssa P', 43 job: 'Computer programmer', 44 }), 45 Employee.assert({ 46 this: Link.of(staff.cy), 47 name: 'Fect Cy D', 48 job: 'Computer programmer', 49 }), 50 Employee.assert({ 51 this: Link.of(staff.lem), 52 name: 'Tweakit Lem E', 53 job: 'Computer technician', 54 }), 55 Employee.assert({ 56 this: Link.of(staff.louis), 57 name: 'Reasoner Louis', 58 job: 'Computer programmer trainee', 59 }), 60 ]) 61 }, 62 63 'test supervisor': async (assert) => { 64 const Job = fact({ the: 'job', title: String, salary: Number }) 65 const Person = fact({ the: 'person', name: String }) 66 const Supervisor = fact({ 67 the: 'job', 68 supervisor: Object, 69 }) 70 71 const Employee = fact({ 72 name: String, 73 salary: Number, 74 }).where(({ this: employee, name, salary, _ }) => [ 75 Person({ this: employee, name }), 76 Job({ this: employee, salary, title: _ }), 77 Employee.claim({ this: employee, name, salary }), 78 ]) 79 80 const Manager = fact({ 81 employee: String, 82 manager: String, 83 }) 84 .with({ subordinate: Object, supervisor: Object }) 85 .where(({ employee, supervisor, subordinate, manager, _ }) => [ 86 Employee({ this: subordinate, name: employee, salary: _ }), 87 Employee({ this: supervisor, name: manager, salary: _ }), 88 Supervisor({ this: subordinate, supervisor }), 89 Manager.claim({ employee, manager }), 90 ]) 91 92 assert.deepEqual( 93 new Set(await Manager().query({ from: db })), 94 new Set([ 95 Manager.assert({ 96 employee: 'Hacker Alyssa P', 97 manager: 'Bitdiddle Ben', 98 }), 99 Manager.assert({ employee: 'Fect Cy D', manager: 'Bitdiddle Ben' }), 100 Manager.assert({ employee: 'Tweakit Lem E', manager: 'Bitdiddle Ben' }), 101 Manager.assert({ 102 employee: 'Reasoner Louis', 103 manager: 'Hacker Alyssa P', 104 }), 105 Manager.assert({ 106 employee: 'Bitdiddle Ben', 107 manager: 'Warbucks Oliver', 108 }), 109 Manager.assert({ 110 employee: 'Scrooge Eben', 111 manager: 'Warbucks Oliver', 112 }), 113 Manager.assert({ 114 employee: 'Cratchet Robert', 115 manager: 'Scrooge Eben', 116 }), 117 Manager.assert({ employee: 'Aull DeWitt', manager: 'Warbucks Oliver' }), 118 ]) 119 ) 120 121 assert.deepEqual( 122 await Manager.match({ manager: 'Warbucks Oliver' }).query({ from: db }), 123 [ 124 Manager.assert({ 125 employee: 'Scrooge Eben', 126 manager: 'Warbucks Oliver', 127 }), 128 Manager.assert({ 129 employee: 'Bitdiddle Ben', 130 manager: 'Warbucks Oliver', 131 }), 132 Manager.assert({ 133 employee: 'Aull DeWitt', 134 manager: 'Warbucks Oliver', 135 }), 136 ] 137 ) 138 }, 139 140 'test salary': async (assert) => { 141 const Job = fact({ the: 'job', title: String, salary: Number }) 142 const Person = fact({ the: 'person', name: String }) 143 144 const Employee = fact({ 145 name: String, 146 salary: Number, 147 }).where(({ this: employee, name, salary, _ }) => [ 148 Person({ this: employee, name }), 149 Job({ this: employee, salary, title: _ }), 150 Employee.claim({ this: employee, name, salary }), 151 ]) 152 153 const NonPoorEmployees = Employee.where(({ name, salary, _ }) => [ 154 Employee({ this: _, name, salary }), 155 Data.greater({ this: salary, than: 30_000 }), 156 NonPoorEmployees.claim({ name, salary }), 157 ]) 158 159 assert.deepEqual(await NonPoorEmployees().query({ from: db }), [ 160 NonPoorEmployees.assert({ name: 'Warbucks Oliver', salary: 150_000 }), 161 NonPoorEmployees.assert({ name: 'Scrooge Eben', salary: 75_000 }), 162 NonPoorEmployees.assert({ name: 'Bitdiddle Ben', salary: 60_000 }), 163 NonPoorEmployees.assert({ name: 'Hacker Alyssa P', salary: 40_000 }), 164 NonPoorEmployees.assert({ name: 'Fect Cy D', salary: 35_000 }), 165 ]) 166 167 const L2Employees = Employee.where((employee) => [ 168 NonPoorEmployees(employee), 169 Data.less({ this: employee.salary, than: 100_000 }), 170 ]) 171 172 assert.deepEqual(await L2Employees().query({ from: db }), [ 173 L2Employees.assert({ name: 'Scrooge Eben', salary: 75_000 }), 174 L2Employees.assert({ name: 'Bitdiddle Ben', salary: 60_000 }), 175 L2Employees.assert({ name: 'Hacker Alyssa P', salary: 40_000 }), 176 L2Employees.assert({ name: 'Fect Cy D', salary: 35_000 }), 177 ]) 178 }, 179 'test address': async (assert) => { 180 const Job = fact({ the: 'job', title: String, salary: Number }) 181 const Person = fact({ the: 'person', name: String, address: String }) 182 183 const Employee = fact({ 184 name: String, 185 address: String, 186 }).where(({ _, ...employee }) => [ 187 Person(employee), 188 Job({ this: employee.this, title: _, salary: _ }), 189 ]) 190 191 const WhoLivesInCambridge = Employee.where((employee) => [ 192 Employee(employee), 193 Text.includes({ this: employee.address, slice: 'Cambridge' }), 194 ]) 195 196 assert.deepEqual(await WhoLivesInCambridge().query({ from: db }), [ 197 Employee.assert({ 198 this: Link.of(staff.alyssa), 199 name: 'Hacker Alyssa P', 200 address: 'Cambridge, Mass Ave 78', 201 }), 202 Employee.assert({ 203 this: Link.of(staff.cy), 204 name: 'Fect Cy D', 205 address: 'Cambridge, Ames Street 3', 206 }), 207 ]) 208 }, 209 'test employee with non comp supervisor ': async (assert) => { 210 const Job = fact({ the: 'job', title: String }) 211 const Person = fact({ the: 'person', name: String }) 212 const Supervisor = fact({ 213 the: 'job', 214 supervisor: Object, 215 }) 216 const Employee = fact({ 217 name: String, 218 job: String, 219 }).where(({ _, ...employee }) => [ 220 Person(employee), 221 Job({ this: employee.this, title: employee.job }), 222 ]) 223 224 const ManagedByWheel = fact({ 225 employeeName: String, 226 supervisorName: String, 227 }) 228 .with({ 229 employee: Object, 230 employeeJob: String, 231 supervisor: Object, 232 supervisorJob: String, 233 }) 234 .where( 235 ({ 236 employee, 237 employeeName, 238 employeeJob, 239 supervisor, 240 supervisorName, 241 supervisorJob, 242 }) => [ 243 Employee({ this: employee, name: employeeName, job: employeeJob }), 244 Supervisor({ this: employee, supervisor }), 245 Employee({ 246 this: supervisor, 247 name: supervisorName, 248 job: supervisorJob, 249 }), 250 Text.match({ this: employeeJob, pattern: 'Computer*' }), 251 Text.not({ this: supervisorJob, pattern: 'Computer*' }), 252 ManagedByWheel.claim({ employeeName, supervisorName }), 253 ] 254 ) 255 256 assert.deepEqual(await ManagedByWheel().query({ from: db }), [ 257 ManagedByWheel.assert({ 258 employeeName: 'Bitdiddle Ben', 259 supervisorName: 'Warbucks Oliver', 260 }), 261 ]) 262 }, 263 }