feat: mirror v-can guard chains
This commit is contained in:
@@ -18,8 +18,8 @@ describe('transformCan', () => {
|
||||
<p v-cannot>Refus</p>
|
||||
`)
|
||||
|
||||
expect(code).toContain(`v-if="__can__(['employee', 'view'])"`)
|
||||
expect(code).toContain(`v-if="!(__can__(['employee', 'view']))"`)
|
||||
expect(code).toContain(`v-if="__can__('employee', 'view')"`)
|
||||
expect(code).toContain(`v-if="!(__can__('employee', 'view'))"`)
|
||||
})
|
||||
|
||||
it('merges existing v-if expressions with the generated guard', () => {
|
||||
@@ -27,7 +27,7 @@ describe('transformCan', () => {
|
||||
<div v-if="isReady" v-can="can.contract.create" />
|
||||
`)
|
||||
|
||||
expect(code).toContain(`v-if="(isReady) && __can__(['contract', 'create'])"`)
|
||||
expect(code).toContain(`v-if="(isReady) && __can__('contract', 'create')"`)
|
||||
})
|
||||
|
||||
it('throws when v-cannot is used without a preceding v-can', () => {
|
||||
@@ -36,7 +36,7 @@ describe('transformCan', () => {
|
||||
id: TEST_FILE,
|
||||
})
|
||||
|
||||
expect(exec).toThrow(/must immediately follow its `v-can`/)
|
||||
expect(exec).toThrow(/without an expression must immediately follow/)
|
||||
})
|
||||
|
||||
it('throws when the expression does not start with can.*', () => {
|
||||
@@ -48,15 +48,61 @@ describe('transformCan', () => {
|
||||
expect(exec).toThrow(/expressions must start with `can\.`/)
|
||||
})
|
||||
|
||||
it('throws when v-can is added to a v-else branch', () => {
|
||||
it('mirrors guards across v-if / v-else-if / v-else chains when the first branch uses v-can', () => {
|
||||
const code = runTransform(`
|
||||
<div v-if="ready" v-can="can.employee.view"></div>
|
||||
<div v-else-if="later"></div>
|
||||
<div v-else></div>
|
||||
<p v-cannot>Denied</p>
|
||||
`)
|
||||
|
||||
expect(code).toContain(`v-if="(ready) && __can__('employee', 'view')"`)
|
||||
expect(code).toContain(`v-else-if="(later) && __can__('employee', 'view')"`)
|
||||
expect(code).toContain(`v-else-if="__can__('employee', 'view')"`)
|
||||
expect(code).toContain(`v-if="!(__can__('employee', 'view'))"`)
|
||||
})
|
||||
|
||||
it('throws when branches declare different v-can expressions', () => {
|
||||
const exec = () => transformCan({
|
||||
code: buildSFC(`
|
||||
<div v-if="ready"></div>
|
||||
<div v-else v-can="can.employee.view"></div>
|
||||
<div v-if="ready" v-can="can.employee.view"></div>
|
||||
<div v-else v-can="can.contract.create"></div>
|
||||
`),
|
||||
id: TEST_FILE,
|
||||
})
|
||||
|
||||
expect(exec).toThrow(/cannot be used on `v-else`/)
|
||||
expect(exec).toThrow(/must match across every branch/)
|
||||
})
|
||||
|
||||
it('allows explicit expressions on v-cannot without a preceding v-can', () => {
|
||||
const code = runTransform('<p v-cannot="can.employee.view">Denied</p>')
|
||||
expect(code).toContain(`v-if="!(__can__('employee', 'view'))"`)
|
||||
})
|
||||
|
||||
it('requires adjacent placement for v-cannot without an expression', () => {
|
||||
const exec = () => transformCan({
|
||||
code: buildSFC(`
|
||||
<div v-can="can.employee.view">Allowed</div>
|
||||
<div>
|
||||
<p v-cannot>Denied</p>
|
||||
</div>
|
||||
`),
|
||||
id: TEST_FILE,
|
||||
})
|
||||
|
||||
expect(exec).toThrow(/without an expression must immediately follow/)
|
||||
})
|
||||
|
||||
it('requires adjacency even when only empty siblings exist between v-can and v-cannot', () => {
|
||||
const exec = () => transformCan({
|
||||
code: buildSFC(`
|
||||
<div v-can="can.employee.view">Allowed</div>
|
||||
<div></div>
|
||||
<div v-cannot>Denied</div>
|
||||
`),
|
||||
id: TEST_FILE,
|
||||
})
|
||||
|
||||
expect(exec).toThrow(/without an expression must immediately follow/)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user