/ test / predicates.spec.js
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  }