Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f66ac8a
ci(code-coverage): add code coverage reporting to edge app workflow
nicomiguelino Jan 29, 2026
d37d2f9
fix(ci): simplify coverage workflow to run tests only
nicomiguelino Jan 29, 2026
925768b
feat(ci): enable automatic coverage checks with 90% threshold
nicomiguelino Jan 29, 2026
060f439
test(edge-apps-library): improve test coverage
nicomiguelino Jan 29, 2026
5bee791
Update edge-apps/edge-apps-library/package.json
nicomiguelino Jan 29, 2026
13dce38
test(edge-apps-library): update `JPEG_MAGIC_BYTES` to have only three…
nicomiguelino Jan 29, 2026
ae528e6
fix(edge-apps-library): correct cors_proxy_url parameter handling in …
nicomiguelino Jan 29, 2026
86ab278
test(edge-apps-library): make the assertion for the error message les…
nicomiguelino Jan 29, 2026
ead3f2a
Update edge-apps/edge-apps-library/src/utils/theme.test.ts
nicomiguelino Jan 29, 2026
1ef9018
refactor(edge-apps-library): simplify getPrimaryColor test descriptions
nicomiguelino Jan 29, 2026
9e6416b
refactor(edge-apps-library): simplify getSecondaryColor test descript…
nicomiguelino Jan 29, 2026
2780971
feat(ci): add coverage summary to GitHub Actions step summary
nicomiguelino Jan 29, 2026
fbe8a69
feat(ci): add per-file coverage details to summary
nicomiguelino Jan 29, 2026
f17e9ee
fix(ci): parse Bun test output for accurate coverage numbers
nicomiguelino Jan 29, 2026
0602541
style(ci): right-align percentage columns in coverage table
nicomiguelino Jan 29, 2026
3085098
fix(ci): use grouped commands for shellcheck compliance
nicomiguelino Jan 29, 2026
6bdc932
temporary: check if the code coverage pipeline will not break existin…
nicomiguelino Jan 29, 2026
3cddaf4
Update .github/workflows/edge-app-checks.yml
nicomiguelino Jan 30, 2026
faf37b0
chore: revert temporary changes
nicomiguelino Jan 30, 2026
31f3256
Update .github/workflows/edge-app-checks.yml
nicomiguelino Jan 30, 2026
f80d376
Update .github/workflows/edge-app-checks.yml
nicomiguelino Jan 30, 2026
e3dfc59
docs(test): document expectProperty helper limitation
nicomiguelino Jan 30, 2026
d4de69a
test(theme): strengthen logoUrl assertion in branding test
nicomiguelino Jan 30, 2026
10cee9e
test(theme): verify empty string to undefined conversion in branding
nicomiguelino Jan 30, 2026
a6521be
docs(test): explain jsdom Blob workaround for SVG test
nicomiguelino Jan 30, 2026
be6e28f
Merge branch 'master' into add-code-coverage-reports
nicomiguelino Jan 30, 2026
28e2fcc
Merge branch 'master' into add-code-coverage-reports
nicomiguelino Jan 31, 2026
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
2 changes: 2 additions & 0 deletions edge-apps/edge-apps-library/bunfig.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[test]
preload = ["./src/test/setup.ts"]
coverage = true
coverageThreshold = 0.9

90 changes: 60 additions & 30 deletions edge-apps/edge-apps-library/src/test/mock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ import {

const global = globalThis as Record<string, unknown>

// Helper function to check property
function expectProperty(obj: unknown, key: string, value?: unknown) {
if (value !== undefined) {
expect(obj).toHaveProperty(key, value)
} else {
expect(obj).toHaveProperty(key)
}
}

// eslint-disable-next-line max-lines-per-function
describe('mock utilities', () => {
afterEach(() => {
Expand All @@ -17,22 +26,36 @@ describe('mock utilities', () => {

describe('mockMetadata', () => {
test('should have default metadata values', () => {
expect(mockMetadata).toHaveProperty('coordinates')
expect(mockMetadata).toHaveProperty('hostname', 'test-hostname')
expect(mockMetadata).toHaveProperty('location', 'Test Location')
expect(mockMetadata).toHaveProperty('hardware', 'test-hardware')
expect(mockMetadata).toHaveProperty('screenly_version', '1.0.0-test')
expect(mockMetadata).toHaveProperty('screen_name', 'Test Screen')
expect(mockMetadata).toHaveProperty('tags')
const expectedProperties = [
{ key: 'coordinates' },
{ key: 'hostname', value: 'test-hostname' },
{ key: 'location', value: 'Test Location' },
{ key: 'hardware', value: 'test-hardware' },
{ key: 'screenly_version', value: '1.0.0-test' },
{ key: 'screen_name', value: 'Test Screen' },
{ key: 'tags' },
]

expectedProperties.forEach(({ key, value }) => {
expectProperty(mockMetadata, key, value)
})

expect(Array.isArray(mockMetadata.tags)).toBe(true)
})
})

describe('mockSettings', () => {
test('should have default settings values', () => {
expect(mockSettings).toHaveProperty('screenly_color_accent', '#972EFF')
expect(mockSettings).toHaveProperty('screenly_color_light', '#ADAFBE')
expect(mockSettings).toHaveProperty('screenly_color_dark', '#454BD2')
const expectedProperties = [
{ key: 'screenly_color_accent', value: '#972EFF' },
{ key: 'screenly_color_light', value: '#ADAFBE' },
{ key: 'screenly_color_dark', value: '#454BD2' },
]

expectedProperties.forEach(({ key, value }) => {
expectProperty(mockSettings, key, value)
})

expect(mockSettings).not.toHaveProperty('theme')
})
})
Expand All @@ -41,36 +64,44 @@ describe('mock utilities', () => {
test('should create mock with default values', () => {
const mock = createMockScreenly()

expect(mock).toHaveProperty('signalReadyForRendering')
expect(mock).toHaveProperty('metadata')
expect(mock).toHaveProperty('settings')
expect(mock).toHaveProperty('cors_proxy_url', 'http://localhost:8080')
const expectedProperties = [
'signalReadyForRendering',
'metadata',
'settings',
]
expectedProperties.forEach((key) => expectProperty(mock, key))

expectProperty(mock, 'cors_proxy_url', 'http://localhost:8080')
expect(typeof mock.signalReadyForRendering).toBe('function')
})

test('should have a callable signalReadyForRendering function', () => {
const mock = createMockScreenly()
expect(() => mock.signalReadyForRendering()).not.toThrow()
})

test('should merge custom metadata', () => {
const mock = createMockScreenly({
const customMetadata = {
hostname: 'custom-hostname',
location: 'Custom Location',
})
}
const mock = createMockScreenly(customMetadata)

expect(mock.metadata.hostname).toBe('custom-hostname')
expect(mock.metadata.location).toBe('Custom Location')
expect(mock.metadata.hardware).toBe('test-hardware') // default value preserved
expect(mock.metadata.hardware).toBe('test-hardware')
})

test('should merge custom settings', () => {
const mock = createMockScreenly(
{},
{
theme: 'dark',
custom_setting: 'custom_value',
},
)
const customSettings = {
theme: 'dark',
custom_setting: 'custom_value',
}
const mock = createMockScreenly({}, customSettings)

expect(mock.settings.theme).toBe('dark')
expect(mock.settings.custom_setting).toBe('custom_value')
expect(mock.settings.screenly_color_accent).toBe('#972EFF') // default value preserved
expect(mock.settings.screenly_color_accent).toBe('#972EFF')
})
})

Expand All @@ -79,21 +110,20 @@ describe('mock utilities', () => {
setupScreenlyMock()

expect(global.screenly).toBeDefined()
expect(global.screenly).toHaveProperty('metadata')
expect(global.screenly).toHaveProperty('settings')
expectProperty(global.screenly, 'metadata')
expectProperty(global.screenly, 'settings')
})

test('should setup with custom values', () => {
setupScreenlyMock({ hostname: 'custom-host' }, { theme: 'dark' })

const screenly = global.screenly as Record<string, unknown>
expect(screenly.metadata).toHaveProperty('hostname', 'custom-host')
expect(screenly.settings).toHaveProperty('theme', 'dark')
expectProperty(screenly.metadata, 'hostname', 'custom-host')
expectProperty(screenly.settings, 'theme', 'dark')
})

test('should return the mock object', () => {
const mock = setupScreenlyMock()

expect(mock).toBe(global.screenly)
})
})
Expand Down
1 change: 1 addition & 0 deletions edge-apps/edge-apps-library/src/test/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ global.document = dom.window.document
global.window = dom.window as unknown as Window & typeof globalThis
global.navigator = dom.window.navigator
global.Node = dom.window.Node
global.FileReader = dom.window.FileReader
Loading
Loading