Skip to content

Commit

Permalink
test(loader): add isolation tests
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Apr 30, 2024
1 parent ea310e9 commit b9d4778
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 49 deletions.
31 changes: 18 additions & 13 deletions packages/loader/src/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export abstract class Loader<T extends Loader.Options = Loader.Options> extends
return options.id!
}

async ensure(parent: Context, options: Omit<Entry.Options, 'id'>) {
async _ensure(parent: Context, options: Omit<Entry.Options, 'id'>) {
const id = this.ensureId(options)
const entry = this.entries[id] ??= new Entry(this)
await entry.update(parent, options as Entry.Options)
Expand All @@ -260,18 +260,22 @@ export abstract class Loader<T extends Loader.Options = Loader.Options> extends
if (!targetEntry?.fork) throw new Error(`entry ${target} not found`)
targetEntry.options.config.splice(index, 0, options)
this.writeConfig()
return this.ensure(targetEntry.fork.ctx, options)
return this._ensure(targetEntry.fork.ctx, options)
}

remove(id: string, passive = false) {
_remove(id: string) {
const entry = this.entries[id]
if (!entry) return
entry.stop()
}

remove(id: string) {
const entry = this.entries[id]
if (!entry) throw new Error(`entry ${id} not found`)
entry.stop()
entry.unlink()
delete this.entries[id]
if (!passive && entry.parent.scope.isActive) {
entry.unlink()
this.writeConfig()
}
this.writeConfig()
}

teleport(id: string, target: string, index = Infinity) {
Expand Down Expand Up @@ -304,11 +308,10 @@ export abstract class Loader<T extends Loader.Options = Loader.Options> extends

async start() {
await this.readConfig()
this.root.options.config = this.config
this.root.update(this.app, {
id: '',
name: 'cordis/group',
config: [],
config: this.config,
})
this.app.emit('config')

Expand All @@ -327,6 +330,7 @@ export abstract class Loader<T extends Loader.Options = Loader.Options> extends
export const kGroup = Symbol.for('cordis.group')

export interface GroupOptions {
name?: string
initial?: Omit<Entry.Options, 'id'>[]
allowed?: string[]
}
Expand All @@ -336,7 +340,7 @@ export function createGroup(config?: Entry.Options[], options: GroupOptions = {}

function group(ctx: Context, config: Entry.Options[]) {
for (const options of config) {
ctx.loader.ensure(ctx, options)
ctx.loader._ensure(ctx, options)
}

ctx.accept((neo: Entry.Options[]) => {
Expand All @@ -348,23 +352,24 @@ export function createGroup(config?: Entry.Options[], options: GroupOptions = {}
// update inner plugins
for (const id in { ...oldMap, ...neoMap }) {
if (!neoMap[id]) {
ctx.loader.remove(id, true)
ctx.loader._remove(id)
} else {
ctx.loader.ensure(ctx, neoMap[id])
ctx.loader._ensure(ctx, neoMap[id])
}
}
}, { passive: true })

ctx.on('dispose', () => {
for (const entry of ctx.scope.config as Entry.Options[]) {
ctx.loader.remove(entry.id, true)
ctx.loader._remove(entry.id)
}
})
}

defineProperty(group, 'inject', ['loader'])
defineProperty(group, 'reusable', true)
defineProperty(group, kGroup, options)
if (options.name) defineProperty(group, 'name', options.name)

return group
}
Expand Down
189 changes: 153 additions & 36 deletions packages/loader/tests/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,21 +122,20 @@ describe('@cordisjs/loader', () => {
root.plugin(MockLoader)

const dispose = mock.fn()
const foo = mock.fn((ctx: Context) => {

const foo = defineProperty(root.loader.mock('foo', (ctx: Context) => {
ctx.on('dispose', dispose)
})
defineProperty(foo, 'inject', ['bar'])
class Bar extends Service {
}), 'inject', ['bar'])

const Bar = root.loader.mock('bar', class Bar extends Service {
static [Service.provide] = 'bar'
static [Service.immediate] = true
}
class Qux extends Service {
})

const Qux = root.loader.mock('qux', class Qux extends Service {
static [Service.provide] = 'qux'
static [Service.immediate] = true
}
root.loader.mock('foo', foo)
root.loader.mock('bar', Bar)
root.loader.mock('qux', Qux)
})

it('basic support', async () => {
await root.loader.restart([{
Expand All @@ -147,66 +146,184 @@ describe('@cordisjs/loader', () => {
name: 'qux',
}, {
id: '3',
name: 'cordis/group',
config: [{
id: '4',
name: 'foo',
}],
name: 'foo',
}])
expect(root.registry.get(foo)).to.be.ok
expect(root.registry.get(Bar)).to.be.ok
expect(root.registry.get(Qux)).to.be.ok
expect(foo.mock.calls).to.have.length(1)
expect(dispose.mock.calls).to.have.length(0)
})

it('isolate', async () => {
root.loader.config = [{
it('add isolate on injector (relavent)', async () => {
foo.mock.resetCalls()
dispose.mock.resetCalls()
await root.loader.restart([{
id: '1',
name: 'bar',
}, {
id: '2',
name: 'qux',
}, {
id: '3',
name: 'cordis/group',
name: 'foo',
isolate: {
bar: true,
},
config: [{
id: '4',
name: 'foo',
}],
}]
}])

expect(dispose.mock.calls).to.have.length(0)
await root.loader.start()
await new Promise((resolve) => setTimeout(resolve, 0))
expect(foo.mock.calls).to.have.length(1)
expect(foo.mock.calls).to.have.length(0)
expect(dispose.mock.calls).to.have.length(1)
})

root.loader.config = [{
it('add isolate on injector (irrelavent)', async () => {
foo.mock.resetCalls()
dispose.mock.resetCalls()
await root.loader.restart([{
id: '1',
name: 'bar',
}, {
id: '2',
name: 'qux',
}, {
id: '3',
name: 'cordis/group',
name: 'foo',
isolate: {
bar: false,
bar: true,
qux: true,
},
config: [{
id: '4',
name: 'foo',
}],
}]
}])

await root.loader.start()
await new Promise((resolve) => setTimeout(resolve, 0))
expect(foo.mock.calls).to.have.length(2)
expect(foo.mock.calls).to.have.length(0)
expect(dispose.mock.calls).to.have.length(0)
})

it('remove isolate on injector (relavent)', async () => {
foo.mock.resetCalls()
dispose.mock.resetCalls()
await root.loader.restart([{
id: '1',
name: 'bar',
}, {
id: '2',
name: 'qux',
}, {
id: '3',
name: 'foo',
isolate: {
qux: true,
},
}])

await new Promise((resolve) => setTimeout(resolve, 0))
expect(foo.mock.calls).to.have.length(1)
expect(dispose.mock.calls).to.have.length(0)
})

it('remove isolate on injector (irrelavent)', async () => {
foo.mock.resetCalls()
dispose.mock.resetCalls()
await root.loader.restart([{
id: '1',
name: 'bar',
}, {
id: '2',
name: 'qux',
}, {
id: '3',
name: 'foo',
}])

await new Promise((resolve) => setTimeout(resolve, 0))
expect(foo.mock.calls).to.have.length(0)
expect(dispose.mock.calls).to.have.length(0)
})

it('add isolate on provider (relavent)', async () => {
foo.mock.resetCalls()
dispose.mock.resetCalls()
await root.loader.restart([{
id: '1',
name: 'bar',
isolate: {
bar: 'custom',
},
}, {
id: '2',
name: 'qux',
}, {
id: '3',
name: 'foo',
}])

await new Promise((resolve) => setTimeout(resolve, 0))
expect(foo.mock.calls).to.have.length(0)
expect(dispose.mock.calls).to.have.length(1)
})

it('add isolate on provider (irrelavent)', async () => {
foo.mock.resetCalls()
dispose.mock.resetCalls()
await root.loader.restart([{
id: '1',
name: 'bar',
isolate: {
bar: 'custom',
},
}, {
id: '2',
name: 'qux',
isolate: {
qux: 'custom',
},
}, {
id: '3',
name: 'foo',
}])

await new Promise((resolve) => setTimeout(resolve, 0))
expect(foo.mock.calls).to.have.length(0)
expect(dispose.mock.calls).to.have.length(0)
})

it('remove isolate on provider (relavent)', async () => {
foo.mock.resetCalls()
dispose.mock.resetCalls()
await root.loader.restart([{
id: '1',
name: 'bar',
}, {
id: '2',
name: 'qux',
}, {
id: '3',
name: 'foo',
}])

await new Promise((resolve) => setTimeout(resolve, 0))
expect(foo.mock.calls).to.have.length(1)
expect(dispose.mock.calls).to.have.length(0)
})

it('remove isolate on provider (irrelavent)', async () => {
foo.mock.resetCalls()
dispose.mock.resetCalls()
await root.loader.restart([{
id: '1',
name: 'bar',
}, {
id: '2',
name: 'qux',
}, {
id: '3',
name: 'foo',
}])

await new Promise((resolve) => setTimeout(resolve, 0))
expect(foo.mock.calls).to.have.length(0)
expect(dispose.mock.calls).to.have.length(0)
})
})
})

0 comments on commit b9d4778

Please sign in to comment.