mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-11 13:56:15 -08:00
refactor(vast): [PKG-VAST-04] retain published types and add accurate runtime declarations
This commit is contained in:
1 parent
c162d2b3b3
commit
e5c73fa620
34 files changed
+7819
-1495
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from './fixtures.js'
|
||||
|
||||
test('docs Monaco worker consumes generated core types and runs a typed player example', async ({ page }) => {
|
||||
test('docs Monaco worker consumes generated core and published VAST types and runs a typed player example', async ({ page }, testInfo) => {
|
||||
await page.goto('/test/player.html?core=candidate&chapter=published')
|
||||
await page.addScriptTag({ url: '/assets/js/vs/loader.js' })
|
||||
const result = await page.evaluate(async () => {
|
||||
@@ -12,23 +12,36 @@ test('docs Monaco worker consumes generated core types and runs a typed player e
|
||||
const source = await (await fetch('/assets/ts/artplayer.d.ts')).text()
|
||||
const libraryUri = 'file:///artplayer.d.ts'
|
||||
const library = types.typescriptDefaults.addExtraLib(source, libraryUri)
|
||||
const vastSource = await (await fetch('/assets/ts/artplayer-plugin-vast.d.ts')).text()
|
||||
const vastLibraryUri = 'file:///artplayer-plugin-vast.d.ts'
|
||||
const vastLibrary = types.typescriptDefaults.addExtraLib(vastSource, vastLibraryUri)
|
||||
const model = api.editor.createModel(`
|
||||
const editorOption: Artplayer.OptionInput = { container: '.player', url: '/test/pattern.mp4', muted: true }
|
||||
const editorArt: Artplayer = new Artplayer(editorOption)
|
||||
const editorEvents: Artplayer.Emitter<{ value: [number] }> = new Artplayer.Emitter()
|
||||
editorEvents.emit('value', 1)
|
||||
const editorVastCallback: Parameters<typeof artplayerPluginVast>[0] = ({id, $container, imaPlayer}) => {
|
||||
const identifier: string = id
|
||||
const container: HTMLDivElement = $container
|
||||
imaPlayer.addEventListener('AdStarted', () => {})
|
||||
void [identifier, container]
|
||||
}
|
||||
const editorVastFactory: typeof artplayerPluginVast = (_callback) => (_art) => ({name: 'artplayerPluginVast'})
|
||||
`, 'typescript', api.Uri.parse('file:///consumer.ts'))
|
||||
const invalid = api.editor.createModel('new Artplayer({ container: 123, url: "" })', 'typescript', api.Uri.parse('file:///invalid.ts'))
|
||||
const vastInvalid = api.editor.createModel('artplayerPluginVast();\nartplayerPluginVast(({id}) => { const wrong: number = id })', 'typescript', api.Uri.parse('file:///vast-invalid.ts'))
|
||||
try {
|
||||
const getWorker = await types.getTypeScriptWorker()
|
||||
const worker = await getWorker(model.uri, invalid.uri)
|
||||
const worker = await getWorker(model.uri, invalid.uri, vastInvalid.uri)
|
||||
const syntax = await worker.getSyntacticDiagnostics(model.uri.toString())
|
||||
const semantic = await worker.getSemanticDiagnostics(model.uri.toString())
|
||||
const declaration = await worker.getSemanticDiagnostics(libraryUri)
|
||||
const vastDeclaration = await worker.getSemanticDiagnostics(vastLibraryUri)
|
||||
const vastBad = (await worker.getSemanticDiagnostics(vastInvalid.uri.toString())).map(item => item.code)
|
||||
const bad = await worker.getSemanticDiagnostics(invalid.uri.toString())
|
||||
const output = await worker.getEmitOutput(model.uri.toString())
|
||||
if (syntax.length || semantic.length || declaration.length)
|
||||
return { syntax, semantic, declaration, invalid: bad.map(item => item.code), ready: false }
|
||||
return { syntax, semantic, declaration, vastDeclaration, vastBad, vastSource, invalid: bad.map(item => item.code), ready: false }
|
||||
const script = output.outputFiles.find(file => file.name.endsWith('.js'))
|
||||
if (!script)
|
||||
throw new Error('Monaco did not emit the typed example')
|
||||
@@ -37,7 +50,7 @@ editorEvents.emit('value', 1)
|
||||
try {
|
||||
if (!art.isReady)
|
||||
await new Promise(resolve => art.on('ready', resolve))
|
||||
return { syntax, semantic, declaration, invalid: bad.map(item => item.code), ready: art.isReady && art.video.videoWidth > 0 }
|
||||
return { syntax, semantic, declaration, vastDeclaration, vastBad, vastSource, invalid: bad.map(item => item.code), ready: art.isReady && art.video.videoWidth > 0 }
|
||||
}
|
||||
finally {
|
||||
art.destroy()
|
||||
@@ -46,12 +59,17 @@ editorEvents.emit('value', 1)
|
||||
finally {
|
||||
model.dispose()
|
||||
invalid.dispose()
|
||||
vastInvalid.dispose()
|
||||
library.dispose()
|
||||
vastLibrary.dispose()
|
||||
}
|
||||
})
|
||||
expect(result.syntax).toEqual([])
|
||||
expect(result.semantic).toEqual([])
|
||||
expect(result.declaration).toEqual([])
|
||||
expect(result.vastDeclaration).toEqual([])
|
||||
expect(result.vastBad).toEqual([2554, 2322])
|
||||
await testInfo.attach('vast-editor-declaration', { contentType: 'text/plain', body: result.vastSource })
|
||||
expect(result.invalid.length).toBeGreaterThan(0)
|
||||
expect(result.ready).toBe(true)
|
||||
})
|
||||
@@ -4,6 +4,7 @@ import fs from 'node:fs'
|
||||
import { test } from 'node:test'
|
||||
import { ESLint } from 'eslint'
|
||||
import compat from 'typescript-compat'
|
||||
import { verifyVastContract } from '../refactor/scripts/vast-contract.mjs'
|
||||
import { vastSdkDeclarations } from '../scripts/editor-declarations/dependencies.ts'
|
||||
import { editorLibUris, generateEditorDeclarations } from '../scripts/editor-declarations/generate.ts'
|
||||
import { checkStandaloneDeclarations } from '../scripts/editor-declarations/validation.ts'
|
||||
@@ -24,11 +25,14 @@ test('editor declarations are reproducible, standalone and preserve constructor/
|
||||
assert.throws(() => asGlobalDeclaration('export { default } from "./missing"', 'Artplayer'), /unresolved exports/)
|
||||
})
|
||||
|
||||
test('Chapter and VAST editor consumers preserve SDK types, optional Window hook and named results', () => {
|
||||
test('Chapter and historical workspace VAST editor consumers preserve SDK types, optional Window hook and named results', async () => {
|
||||
const contract = await verifyVastContract()
|
||||
const core = fs.readFileSync('docs/assets/ts/artplayer.d.ts', 'utf8')
|
||||
const generated = new Map([['artplayer.d.ts', core]])
|
||||
for (const [suffix, global] of [['chapter', 'artplayerPluginChapter'], ['vast', 'artplayerPluginVast']]) {
|
||||
const source = fs.readFileSync(`packages/artplayer-plugin-${suffix}/types/artplayer-plugin-${suffix}.d.ts`, 'utf8')
|
||||
const source = suffix === 'vast'
|
||||
? contract.sources.get('packages/artplayer-plugin-vast/types/artplayer-plugin-vast.d.ts')
|
||||
: fs.readFileSync(`packages/artplayer-plugin-${suffix}/types/artplayer-plugin-${suffix}.d.ts`, 'utf8')
|
||||
const old = `${source.replace(/^import.*$/gim, '')}\nexport = ${global};\nexport as namespace ${global};\n`
|
||||
const diagnostics = checkPluginEditorDeclaration(old, core)
|
||||
assert(diagnostics.some(item => item.code === 2309))
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import type { google, ImaSdk } from '@alugha/ima'
|
||||
import type { Player, PlayerOptions } from '@glomex/vast-ima-player'
|
||||
import type Artplayer from 'artplayer'
|
||||
import type { ArtplayerPluginVastInstance, ArtplayerPluginVastOption, CompatibilityOptions, PublishedContext, RuntimeFactory, RuntimeResult, WorkspaceContext } from 'artplayer-plugin-vast/runtime'
|
||||
import vast from 'artplayer-plugin-vast/runtime'
|
||||
|
||||
declare const art: Artplayer
|
||||
declare const options: CompatibilityOptions
|
||||
|
||||
const registration = vast((context) => {
|
||||
const player: Player = context.imaPlayer
|
||||
const container: HTMLDivElement = context.$container
|
||||
const id: string = context.id
|
||||
const sdk: ImaSdk = context.ima
|
||||
const settings: google.ima.AdsRenderingSettings = context.adsRenderingSettings
|
||||
const playerOptions: PlayerOptions = context.playerOptions
|
||||
const self: PublishedContext = context
|
||||
context.id = id
|
||||
context.$container = container
|
||||
context.imaPlayer = player
|
||||
context.init()?.addEventListener('AdStarted', () => {})
|
||||
const urlResult: void = context.playUrl('/ad.xml', { adTagUrl: '/override.xml', custom: true })
|
||||
const responseResult: void = context.playRes('<VAST/>')
|
||||
// @ts-expect-error SDK methods retain actual vendor signatures.
|
||||
context.imaPlayer.playAds(42)
|
||||
// @ts-expect-error SDK settings are typed.
|
||||
context.adsRenderingSettings.enablePreloading = 'yes'
|
||||
// @ts-expect-error The original media element must remain an element.
|
||||
context.$container = 'container'
|
||||
// @ts-expect-error Live container is read-only in both modes.
|
||||
context.container = container
|
||||
// @ts-expect-error Terminal core destruction makes init return null.
|
||||
const initialized: Player = context.init()
|
||||
void [player, container, id, sdk, settings, playerOptions, self, urlResult, responseResult, initialized]
|
||||
})
|
||||
|
||||
const pending: Promise<RuntimeResult> = registration(art)
|
||||
// @ts-expect-error Registration is asynchronous.
|
||||
const synchronous: RuntimeResult = registration(art)
|
||||
pending.then((result) => {
|
||||
const name: 'artplayerPluginVast' = result.name
|
||||
const disposed: void = result.destroy()
|
||||
const migrated: ArtplayerPluginVastInstance = result
|
||||
void [name, disposed, migrated]
|
||||
})
|
||||
vast()
|
||||
vast.default()
|
||||
vast(undefined, { compatibility: 'workspace-1.2' })
|
||||
|
||||
vast(async (context) => {
|
||||
const self: WorkspaceContext = context
|
||||
const player: Player | null = context.imaPlayer
|
||||
const container: HTMLDivElement | null = context.$container
|
||||
const id: string | null = context.id
|
||||
context.playerOptions.autoResize = false
|
||||
context.init()?.addEventListener('AdStarted', () => {})
|
||||
// @ts-expect-error Workspace resource getters may be null.
|
||||
const nonNull: Player = context.imaPlayer
|
||||
// @ts-expect-error Workspace fields are getters without setters.
|
||||
context.imaPlayer = player
|
||||
// @ts-expect-error Workspace identifiers are getters without setters.
|
||||
context.id = 'new-id'
|
||||
// @ts-expect-error Request input remains a string.
|
||||
context.playUrl(123)
|
||||
void [self, player, container, id, nonNull]
|
||||
}, { compatibility: 'workspace-1.2' })
|
||||
|
||||
vast((context) => {
|
||||
const player: Player | null = context.imaPlayer
|
||||
// @ts-expect-error Dynamic mode cannot promise eager allocation.
|
||||
const eager: Player = context.imaPlayer
|
||||
void [player, eager]
|
||||
}, options)
|
||||
const callback: ArtplayerPluginVastOption = context => context.init()
|
||||
vast(callback, { compatibility: 'workspace-1.2' })
|
||||
const factory: RuntimeFactory = vast.default
|
||||
// @ts-expect-error Unknown compatibility mode is rejected at runtime.
|
||||
vast(undefined, { compatibility: 'wrong' })
|
||||
// @ts-expect-error Callback must be callable when supplied.
|
||||
vast(1)
|
||||
// @ts-expect-error A known workspace option cannot provide eager-only context.
|
||||
vast((context: PublishedContext) => context.id, { compatibility: 'workspace-1.2' })
|
||||
void [factory, synchronous]
|
||||
Reference in new issue
Block a user