Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | /** * `access.role` — the **Record Access** matrix (the ACL pivot). * * The generic `createAndEditModel` helper drives the captures; this spec only * adds what the matrix needs to be deterministic. Two things are specific: * * 1. **The row set is filtered.** The matrix rows are the whole * `access.aclTarget` dropdown — every role, user and organization in the * graph — so an unfiltered capture drifts with whatever else the database * holds (other specs, leftovers from earlier runs). The `filters` declaration * narrows the grid to the `all: (all records)` wildcard row, which is the * tri-state evidence row: `find` cycled to Allow, `get` cycled to Deny and * the remaining verbs left blank, with no row-edit column (every editable * column of the pivot is a click-to-cycle cell). * 2. **The run ends with the cells released.** The edit phase clears both cells * back to "Not set", so the role owns no `access_acl` rows afterwards and the * suite's `cleanupModel` can delete it — a stored rule would trip the * `access_acl` foreign key and leave the role behind to pollute the next run. * The *persisted* state is still evidenced: `-tab-matrix-open` captures the * matrix of the loaded role, showing the Allow/Deny written by the create * phase. * * The matrix write/load/enforce path is additionally proved end-to-end by * `test.acl.flow` (steps 14-16) in `realm/blong-party`. */ import {expect, test} from '@feasibleone/blong-browser/playwright'; import {createAndEditModel} from '@feasibleone/blong-browser/playwright/model'; test.use({blongPermissions: true}); const ROLE_NAME = 'ACC-PLAY-Matrix'; test.describe('Access Role · Record Access matrix', () => { createAndEditModel(test, expect, { subject: 'access', object: 'role', fields: { 'role.roleName': ROLE_NAME, // `access_role.roleBit` is UNIQUE and the default 0 is already taken // by a seeded role: the insert would be silently ignored (MySQL // `INSERT IGNORE`) and the role row would never exist — a resource // without a role, which the browse cannot even show. The role spec // uses 999; the matrix takes the next free bit. 'role.roleBit': 998, 'role.description': 'ACC-PLAY matrix role', }, editFields: { 'role.description': 'ACC-PLAY matrix role edited', }, // Its own baseline names — `role.play.ts` drives the same entity. baselinePrefix: 'access-role-matrix', // The edit test opens its row through the role browse filter: without // this it would open whichever role happens to be listed first and // capture *that* role's matrix. The text matches this role only (the // other specs' descriptions carry 'ACC-PLAY role', not 'matrix role'). search: 'matrix role', details: [ { object: 'matrix', tab: 'Record Access', pivot: true, // Narrow the grid to the wildcard scope: the matrix otherwise // lists every role, user and organization in the graph. filters: {targetName: '(all records)'}, // Tri-state evidence in one row: `find` cycled to allow, `get` // cycled to deny and the remaining verbs left blank. The entity // comes from the pivot defaults, so no row-edit mode is involved. fields: { find: {widget: 'cycle', value: 'Allow'}, get: {widget: 'cycle', value: 'Deny'}, }, // Editing proof: the loaded allow/deny are cycled back to "Not // set", which also releases the ACL rules so the role stays // deletable. The load itself is the `-tab-matrix-open` capture. editFields: { find: {widget: 'cycle', value: 'Not set'}, get: {widget: 'cycle', value: 'Not set'}, }, }, ], }); }); |