feat: add desktop repo (#1071)
This commit is contained in:
158
packages/desktop/test/packageManager.spec.ts
Normal file
158
packages/desktop/test/packageManager.spec.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
import test from 'ava'
|
||||
import { promises as fs } from 'fs'
|
||||
import path from 'path'
|
||||
import proxyquire from 'proxyquire'
|
||||
import { ensureDirectoryExists, readJSONFile } from '../app/javascripts/Main/Utils/FileUtils'
|
||||
import { createTmpDir } from './testUtils'
|
||||
import { AppName } from '../app/javascripts/Main/strings'
|
||||
import makeFakePaths from './fakePaths'
|
||||
import { PackageManagerInterface } from '../app/javascripts/Main/Packages/PackageManagerInterface'
|
||||
|
||||
const tmpDir = createTmpDir(__filename)
|
||||
const FakePaths = makeFakePaths(tmpDir.path)
|
||||
|
||||
const contentDir = path.join(tmpDir.path, 'Extensions')
|
||||
let downloadFileCallCount = 0
|
||||
|
||||
const { initializePackageManager } = proxyquire('../app/javascripts/Main/Packages/PackageManager', {
|
||||
'./paths': {
|
||||
Paths: FakePaths,
|
||||
'@noCallThru': true,
|
||||
},
|
||||
'./networking': {
|
||||
/** Download a fake component file */
|
||||
async downloadFile(_src: string, dest: string) {
|
||||
downloadFileCallCount += 1
|
||||
if (!path.normalize(dest).startsWith(tmpDir.path)) {
|
||||
throw new Error(`Bad download destination: ${dest}`)
|
||||
}
|
||||
await ensureDirectoryExists(path.dirname(dest))
|
||||
await fs.copyFile(path.join(__dirname, 'data', 'zip-file.zip'), path.join(dest))
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const fakeWebContents = {
|
||||
send(_eventName: string, { error }) {
|
||||
if (error) throw error
|
||||
},
|
||||
}
|
||||
|
||||
const name = 'Fake Component'
|
||||
const identifier = 'fake.component'
|
||||
const uuid = 'fake-component'
|
||||
const version = '1.0.0'
|
||||
const modifiers = Array(20)
|
||||
.fill(0)
|
||||
.map((_, i) => String(i).padStart(2, '0'))
|
||||
|
||||
function fakeComponent({ deleted = false, modifier = '' } = {}) {
|
||||
return {
|
||||
uuid: uuid + modifier,
|
||||
deleted,
|
||||
content: {
|
||||
name: name + modifier,
|
||||
autoupdateDisabled: false,
|
||||
package_info: {
|
||||
version,
|
||||
identifier: identifier + modifier,
|
||||
download_url: 'https://standardnotes.com',
|
||||
url: 'https://standardnotes.com',
|
||||
latest_url: 'https://standardnotes.com',
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
let packageManager: PackageManagerInterface
|
||||
|
||||
const log = console.log
|
||||
const error = console.error
|
||||
|
||||
test.before(async function () {
|
||||
/** Silence the package manager's output. */
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
console.log = () => {}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
console.error = () => {}
|
||||
await ensureDirectoryExists(contentDir)
|
||||
packageManager = await initializePackageManager(fakeWebContents)
|
||||
})
|
||||
|
||||
test.after.always(async function () {
|
||||
console.log = log
|
||||
console.error = error
|
||||
await tmpDir.clean()
|
||||
})
|
||||
|
||||
test.beforeEach(function () {
|
||||
downloadFileCallCount = 0
|
||||
})
|
||||
|
||||
test('installs multiple components', async (t) => {
|
||||
await packageManager.syncComponents(modifiers.map((modifier) => fakeComponent({ modifier })))
|
||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||
|
||||
const files = await fs.readdir(contentDir)
|
||||
t.is(files.length, 1 + modifiers.length)
|
||||
for (const modifier of modifiers) {
|
||||
t.true(files.includes(identifier + modifier))
|
||||
}
|
||||
t.true(files.includes('mapping.json'))
|
||||
const mappingContents = await fs.readFile(path.join(contentDir, 'mapping.json'), 'utf8')
|
||||
|
||||
t.deepEqual(
|
||||
JSON.parse(mappingContents),
|
||||
modifiers.reduce((acc, modifier) => {
|
||||
acc[uuid + modifier] = {
|
||||
location: path.join('Extensions', identifier + modifier),
|
||||
version,
|
||||
}
|
||||
return acc
|
||||
}, {}),
|
||||
)
|
||||
|
||||
const downloads = await fs.readdir(path.join(tmpDir.path, AppName, 'downloads'))
|
||||
t.is(downloads.length, modifiers.length)
|
||||
for (const modifier of modifiers) {
|
||||
t.true(downloads.includes(`${name + modifier}.zip`))
|
||||
}
|
||||
|
||||
for (const modifier of modifiers) {
|
||||
const componentFiles = await fs.readdir(path.join(contentDir, identifier + modifier))
|
||||
t.is(componentFiles.length, 2)
|
||||
}
|
||||
})
|
||||
|
||||
test('uninstalls multiple components', async (t) => {
|
||||
await packageManager.syncComponents(modifiers.map((modifier) => fakeComponent({ deleted: true, modifier })))
|
||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||
|
||||
const files = await fs.readdir(contentDir)
|
||||
t.deepEqual(files, ['mapping.json'])
|
||||
|
||||
t.deepEqual(await readJSONFile(path.join(contentDir, 'mapping.json')), {})
|
||||
})
|
||||
|
||||
test("doesn't download anything when two install/uninstall tasks are queued", async (t) => {
|
||||
await Promise.all([
|
||||
packageManager.syncComponents([fakeComponent({ deleted: false })]),
|
||||
packageManager.syncComponents([fakeComponent({ deleted: false })]),
|
||||
packageManager.syncComponents([fakeComponent({ deleted: true })]),
|
||||
])
|
||||
t.is(downloadFileCallCount, 1)
|
||||
})
|
||||
|
||||
test("Relies on download_url's version field to store the version number", async (t) => {
|
||||
await packageManager.syncComponents([fakeComponent()])
|
||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||
|
||||
const mappingFileVersion = JSON.parse(await fs.readFile(path.join(contentDir, 'mapping.json'), 'utf8'))[uuid].version
|
||||
|
||||
const packageJsonVersion = JSON.parse(
|
||||
await fs.readFile(path.join(contentDir, identifier, 'package.json'), 'utf-8'),
|
||||
).version
|
||||
|
||||
t.not(mappingFileVersion, packageJsonVersion)
|
||||
t.is(mappingFileVersion, version)
|
||||
})
|
||||
Reference in New Issue
Block a user