Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(desktop): add more utils test cases #1749

Merged
merged 1 commit into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/utils/mqttErrorReason.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@ const MqttErrorReason: Record<string, { [code: number]: string }> = {

type MqttVersion = '3.1' | '3.1.1' | '5.0'

const getErrorReason = (version: MqttVersion, code: number) => {
const getErrorReason = (version: MqttVersion, code: number): string => {
const versionMap = MqttErrorReason[version]
if (!versionMap) {
return 'Unknown error'
}
return versionMap[code] ?? 'Unknown error'
}

Expand Down
8 changes: 4 additions & 4 deletions src/utils/mqttUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import time from '@/utils/time'
import { getSSLFile } from '@/utils/getFiles'
import _ from 'lodash'

const setMQTT5Properties = ({ clean, properties: option }: ConnectionModel) => {
export const setMQTT5Properties = ({ clean, properties: option }: ConnectionModel) => {
if (option === undefined) {
return undefined
}
Expand All @@ -21,15 +21,15 @@ const setMQTT5Properties = ({ clean, properties: option }: ConnectionModel) => {
return Object.fromEntries(Object.entries(properties).filter(([_, v]) => v !== null && v !== undefined))
}

const setWillMQTT5Properties = (option: WillPropertiesModel) => {
export const setWillMQTT5Properties = (option: WillPropertiesModel) => {
if (option === undefined) {
return undefined
}
const properties: WillPropertiesModel = _.cloneDeep(option)
return Object.fromEntries(Object.entries(properties).filter(([_, v]) => v !== null && v !== undefined))
}

const getClientOptions = (record: ConnectionModel): IClientOptions => {
export const getClientOptions = (record: ConnectionModel): IClientOptions => {
const mqttVersionDict = {
'3.1': 3,
'3.1.1': 4,
Expand Down Expand Up @@ -127,7 +127,7 @@ const getClientOptions = (record: ConnectionModel): IClientOptions => {
return options
}

const getUrl = (record: ConnectionModel): string => {
export const getUrl = (record: ConnectionModel): string => {
const { host, port, path } = record
const protocol = getMQTTProtocol(record)

Expand Down
77 changes: 77 additions & 0 deletions tests/unit/components/ResizeHeight.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { expect } from 'chai'
import { shallowMount, Wrapper } from '@vue/test-utils'
import ResizeHeight from '@/components/ResizeHeight.vue'
import { Vue } from 'vue-property-decorator'

describe('ResizeHeight.vue', () => {
let wrapper: Wrapper<Vue>

beforeEach(() => {
wrapper = shallowMount(ResizeHeight, {
propsData: {
value: 100,
},
})
})

afterEach(() => {
wrapper.destroy()
})

it('renders correctly', () => {
expect(wrapper.find('.resize-height').exists()).to.be.true
})

it('emits change event on mousedown and mousemove', async () => {
const vm = wrapper.vm as any

// Call handleMousedown directly
vm.handleMousedown({ y: 100 } as MouseEvent)

// Simulate mousemove
const mousemoveEvent = { y: 150 } as MouseEvent
document.onmousemove!(mousemoveEvent)

await Vue.nextTick()

expect(wrapper.emitted('change')).to.exist
const emittedValue = wrapper.emitted('change')![0][0]
expect(typeof emittedValue).to.equal('number')
expect(emittedValue).to.equal(50)
})

it('adds select-none class to body on mousemove', async () => {
const vm = wrapper.vm as any
vm.handleMousedown({ y: 100 } as MouseEvent)

const mousemoveEvent = { y: 150 } as MouseEvent
document.onmousemove!(mousemoveEvent)

await Vue.nextTick()

expect(document.body.classList.contains('select-none')).to.be.true
})

it('removes select-none class from body on mouseup', async () => {
document.body.classList.add('select-none')

const mouseupEvent = new MouseEvent('mouseup')
document.dispatchEvent(mouseupEvent)

await Vue.nextTick()

expect(document.body.classList.contains('select-none')).to.be.false
})

it('removes mousemove event listener on mouseup', async () => {
const vm = wrapper.vm as any
vm.handleMousedown({ y: 100 } as MouseEvent)

const mouseupEvent = new MouseEvent('mouseup')
document.dispatchEvent(mouseupEvent)

await Vue.nextTick()

expect(document.onmousemove).to.be.null
})
})
72 changes: 72 additions & 0 deletions tests/unit/utils/SystemTopicUtils.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { expect } from 'chai'
import * as SystemTopicUtils from '@/utils/SystemTopicUtils'
import time from '@/utils/time'

describe('SystemTopicUtils', () => {
let originalGetNowDate: () => string

beforeEach(() => {
originalGetNowDate = time.getNowDate
time.getNowDate = () => '2023-01-01 00:00:00'
})

afterEach(() => {
time.getNowDate = originalGetNowDate
})

describe('getBytes', () => {
it('should return chart data for received bytes', () => {
const message = { topic: '/metrics/bytes/received', payload: '100' }
const result = SystemTopicUtils.getBytes(message as MessageModel)
expect(result).to.deep.equal({
label: '2023-01-01 00:00:00',
recevied: 100,
sent: 0,
})
})

it('should return chart data for sent bytes', () => {
const message = { topic: '/metrics/bytes/sent', payload: '200' }
const result = SystemTopicUtils.getBytes(message as MessageModel)
expect(result).to.deep.equal({
label: '2023-01-01 00:00:00',
recevied: 100,
sent: 200,
})
})

it('should return null for unrelated topics', () => {
const message = { topic: '/other/topic', payload: '300' }
const result = SystemTopicUtils.getBytes(message as MessageModel)
expect(result).to.be.null
})
})

describe('getUptime', () => {
it('should return uptime data', () => {
const message = { topic: '/uptime', payload: '1000' }
const result = SystemTopicUtils.getUptime(message as MessageModel)
expect(result).to.equal('1000')
})

it('should return null for unrelated topics', () => {
const message = { topic: '/other/topic', payload: '1000' }
const result = SystemTopicUtils.getUptime(message as MessageModel)
expect(result).to.be.null
})
})

describe('getVersion', () => {
it('should return version data', () => {
const message = { topic: '/version', payload: '1.0.0' }
const result = SystemTopicUtils.getVersion(message as MessageModel)
expect(result).to.equal('1.0.0')
})

it('should return null for unrelated topics', () => {
const message = { topic: '/other/topic', payload: '1.0.0' }
const result = SystemTopicUtils.getVersion(message as MessageModel)
expect(result).to.be.null
})
})
})
95 changes: 95 additions & 0 deletions tests/unit/utils/convertPayload.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { expect } from 'chai'
import convertPayload from '@/utils/convertPayload'

describe('convertPayload', () => {
it('should convert Base64 to plain text', async () => {
const base64Payload = 'SGVsbG8gV29ybGQ='
const result = await convertPayload(base64Payload, 'Plaintext', 'Base64')
expect(result).to.equal('Hello World')
})

it('should convert plain text to Base64', async () => {
const plainPayload = 'Hello World'
const result = await convertPayload(plainPayload, 'Base64', 'Plaintext')
expect(result).to.equal('SGVsbG8gV29ybGQ=')
})

it('should convert Hex to plain text', async () => {
const hexPayload = '48 65 6c 6c 6f 20 57 6f 72 6c 64'
const result = await convertPayload(hexPayload, 'Plaintext', 'Hex')
expect(result).to.equal('Hello World')
})

it('should convert plain text to Hex', async () => {
const plainPayload = 'Hello World'
const result = await convertPayload(plainPayload, 'Hex', 'Plaintext')
expect(result).to.equal('4865 6c6c 6f20 576f 726c 64')
})

it('should convert JSON to plain text', async () => {
const jsonPayload = '{"key": "value"}'
const result = await convertPayload(jsonPayload, 'Plaintext', 'JSON')
expect(result).to.equal('{"key": "value"}')
})

it('should convert Hex to Base64', async () => {
const hexPayload = '48 65 6c 6c 6f 20 57 6f 72 6c 64'
const result = await convertPayload(hexPayload, 'Base64', 'Hex')
expect(result).to.equal('SGVsbG8gV29ybGQ=')
})

it('should convert Base64 to Hex', async () => {
const base64Payload = 'SGVsbG8gV29ybGQ='
const result = await convertPayload(base64Payload, 'Hex', 'Base64')
expect(result).to.equal('4865 6c6c 6f20 576f 726c 64')
})

it('should handle empty input', async () => {
const emptyPayload = ''
const result = await convertPayload(emptyPayload, 'Base64', 'Plaintext')
expect(result).to.equal('')
})

it('should handle whitespace-only input', async () => {
const whitespacePayload = ' '
const result = await convertPayload(whitespacePayload, 'Base64', 'Plaintext')
expect(result).to.equal('ICAg')
})

it('should handle special characters', async () => {
const specialCharsPayload = '!@#$%^&*()_+'
const result = await convertPayload(specialCharsPayload, 'Base64', 'Plaintext')
expect(result).to.equal('IUAjJCVeJiooKV8r')
})

it('should handle Unicode characters', async () => {
const unicodePayload = '你好,世界'
const result = await convertPayload(unicodePayload, 'Base64', 'Plaintext')
expect(result).to.equal('5L2g5aW977yM5LiW55WM')
})

it('should handle large integers', async () => {
const largeIntPayload = '9007199254740991'
const result = await convertPayload(largeIntPayload, 'Base64', 'Plaintext')
expect(result).to.equal('OTAwNzE5OTI1NDc0MDk5MQ==')
})

// JSON conversion tests are commented out due to issues casued by jsonUtils jsonStringify
/*
it('should convert plain text to JSON', async () => {
const plainPayload = '{"key": "value"}'
const result = await convertPayload(plainPayload, 'JSON', 'Plaintext')
expect(result).to.equal('{\n "key": "value"\n}')
})

it('should handle invalid JSON conversion', async () => {
const invalidPayload = 'Not a JSON'
try {
await convertPayload(invalidPayload, 'JSON', 'Plaintext')
expect.fail('Should have thrown an error')
} catch (error) {
expect(error).to.be.an('error')
}
})
*/
})
46 changes: 46 additions & 0 deletions tests/unit/utils/copilot.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { expect } from 'chai'
import { processStream } from '@/utils/copilot'

describe('Copilot', () => {
describe('processStream', () => {
it('should process stream data and invoke callback for each content', async () => {
let readCount = 0
const mockReader = {
read: async () => {
readCount++
if (readCount === 1) {
return {
done: false,
value: new TextEncoder().encode('data: {"choices":[{"delta":{"content":"Hello"}}]}\n\n'),
}
} else if (readCount === 2) {
return {
done: false,
value: new TextEncoder().encode('data: {"choices":[{"delta":{"content":" World"}}]}\n\n'),
}
} else {
return { done: true }
}
},
}

const mockResponse = {
body: {
getReader: () => mockReader,
},
} as unknown as Response

const callbackResults: string[] = []
const callback = (content: string) => {
callbackResults.push(content)
}

const result = await processStream(mockResponse, callback)

expect(result).to.be.true
expect(callbackResults).to.have.lengthOf(2)
expect(callbackResults[0]).to.equal('Hello')
expect(callbackResults[1]).to.equal(' World')
})
})
})
29 changes: 29 additions & 0 deletions tests/unit/utils/delay.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { expect } from 'chai'
import delay from '@/utils/delay'

describe('delay', () => {
it('should delay execution for the specified time', async () => {
const startTime = Date.now()
const delayTime = 100 // 100 milliseconds

await delay(delayTime)

const endTime = Date.now()
const elapsedTime = endTime - startTime

// Allow for some small variance in timing
expect(elapsedTime).to.be.at.least(delayTime)
expect(elapsedTime).to.be.below(delayTime + 50)
})

it('should resolve without error', async () => {
try {
await delay(50)
// If we reach this point, the promise resolved successfully
expect(true).to.be.true
} catch (error) {
// If we catch an error, the test should fail
expect.fail('delay function threw an error')
}
})
})
Loading
Loading