Skip to content

Commit

Permalink
Merge pull request #4907 from owncloud/tests_and_optimize
Browse files Browse the repository at this point in the history
Tests and optimize
  • Loading branch information
fschade authored Apr 6, 2021
2 parents eb821de + 183f838 commit 8e129ff
Show file tree
Hide file tree
Showing 28 changed files with 194 additions and 42 deletions.
6 changes: 6 additions & 0 deletions changelog/unreleased/change-introduce-web-pkg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Change: Add web-pkg package

We added web-pkg as a new package.
It is supposed to be the central location for reuse of generic functionality.

https://github.com/owncloud/web/pull/4907
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"packages/web-app-files",
"packages/web-app-markdown-editor",
"packages/web-app-media-viewer",
"packages/web-pkg",
"packages/web-runtime"
],
"scripts": {
Expand Down Expand Up @@ -45,7 +46,7 @@
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"chromedriver": "^89.0.0",
"core-js": "3",
"core-js": "^3.10.0",
"cucumber": ">=6.0.5",
"cucumber-pretty": ">=6.0.0",
"depcheck": "^1.3.1",
Expand Down Expand Up @@ -80,13 +81,13 @@
"rollup-plugin-copy-watch": "^0.0.1",
"rollup-plugin-delete": "^2.0.0",
"rollup-plugin-gzip": "^2.5.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-modify": "^3.0.0",
"rollup-plugin-node-globals": "^1.4.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-postcss": "^4.0.0",
"rollup-plugin-progress": "^1.1.2",
"rollup-plugin-serve": "^1.1.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-visualizer": "^4.2.0",
"rollup-plugin-vue": "^5.1.4",
Expand Down
9 changes: 9 additions & 0 deletions packages/web-pkg/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "web-pkg",
"version": "0.0.0",
"description": "ownCloud web pkg",
"license": "AGPL-3.0",
"devDependencies": {
"lodash-es": "^4.17.20"
}
}
17 changes: 17 additions & 0 deletions packages/web-pkg/src/utils/object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { isPlainObject } from 'lodash'

export const keysDeep = obj => {
const paths = []

const walk = (o, p = '') =>
Object.keys(o).forEach(key => {
if (isPlainObject(o[key])) {
walk(o[key], `${p}${key}.`)
} else {
paths.push(`${p}${key}`)
}
})

walk(obj)
return paths
}
19 changes: 19 additions & 0 deletions packages/web-pkg/tests/utils/object.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { keysDeep } from 'web-pkg/src/utils/object'

describe('keysDeep', () => {
it('should return the correct keys', () => {
expect(
keysDeep({
foo1: { bar1: { baz1: 1, baz2: 1 }, bar2: { baz1: 1, baz2: 1 }, bar3: 1 },
foo2: 1
})
).toMatchObject([
'foo1.bar1.baz1',
'foo1.bar1.baz2',
'foo1.bar2.baz1',
'foo1.bar2.baz2',
'foo1.bar3',
'foo2'
])
})
})
2 changes: 2 additions & 0 deletions packages/web-runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
"vue-scrollto": "^2.15.0",
"vue2-touch-events": "^2.2.1",
"vuex": "^3.1.1",
"vuex-extensions": "^1.1.5",
"vuex-persist": "2.0.1",
"vuex-router-sync": "^5.0.0",
"web-pkg": "*",
"wicked-good-xpath": "^1.3.0"
}
}
2 changes: 1 addition & 1 deletion packages/web-runtime/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
<script>
import 'inert-polyfill'
import { mapGetters, mapState, mapActions } from 'vuex'
import TopBar from './components/Top-Bar.vue'
import TopBar from './components/TopBar.vue'
import MessageBar from './components/MessageBar.vue'
import SkipTo from './components/SkipTo.vue'
import moment from 'moment'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,3 @@ export const loadConfig = async () => {
}
return config
}

export default {
loadConfig: loadConfig
}
22 changes: 22 additions & 0 deletions packages/web-runtime/src/helpers/theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import defaultTheme from 'web-runtime/themes/owncloud.json'
export const loadTheme = async (name = '') => {
const defaults = { theme: defaultTheme, name: 'themes/owncloud/theme.json' }

if (name === '' || name === defaults.name) {
return defaults
}

let response
try {
response = await fetch(name)
} catch (e) {
return defaults
}

if (!response.ok) {
return defaults
}

const customTheme = await response.json()
return { theme: customTheme, name }
}
8 changes: 4 additions & 4 deletions packages/web-runtime/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ import wgxpath from 'wicked-good-xpath'

import { registerClient } from './services/clientRegistration'

import { loadConfig } from './configHelper'
import { loadConfig } from './helpers/config'
import { loadTheme } from './helpers/theme'

wgxpath.install()

Expand Down Expand Up @@ -184,10 +185,9 @@ const finalizeInit = async () => {
}

const fetchTheme = async (themeName = 'owncloud') => {
const response = await fetch(`themes/${themeName}.json`)
const theme = await response.json()
const { theme, name } = await loadTheme(`themes/${themeName}.json`)

await store.dispatch('loadTheme', { theme, name: themeName })
await store.dispatch('loadTheme', { theme, name })
}

const missingOrInvalidConfig = async () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/web-runtime/src/store/config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import isEmpty from 'lodash-es/isEmpty'
import merge from 'lodash-es/merge'

const state = {
state: null,
Expand Down Expand Up @@ -84,7 +85,7 @@ const mutations = {
}
},
LOAD_THEME(state, theme) {
state.theme = { ...state.theme, ...theme }
state.theme = merge({}, state.theme, theme)
}
}

Expand Down
3 changes: 2 additions & 1 deletion packages/web-runtime/src/store/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Vue from 'vue'
import Vuex from 'vuex'
import VuexPersistence from 'vuex-persist'
import { createStore } from 'vuex-extensions'

/* STORE MODULES
*/
Expand Down Expand Up @@ -31,7 +32,7 @@ const vuexPersistInSession = new VuexPersistence({

const strict = process.env.NODE_ENV === 'development'

export const Store = new Vuex.Store({
export const Store = createStore(Vuex.Store, {
plugins: [vuexPersistInSession.plugin],
modules: {
app,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { shallowMount, createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'

import Stubs from '../config/stubs'

import TopBar from 'web-runtime/src/components/Top-Bar.vue'
import TopBar from 'web-runtime/src/components/TopBar.vue'
import stubs from '../../../../tests/unit/config/stubs'

const localVue = createLocalVue()
const search = enabled => ({
Expand All @@ -21,7 +19,7 @@ describe('Top Bar component', () => {
}
}),
localVue,
stubs: Stubs,
stubs,
propsData: {
userId: 'einstein',
userDisplayName: 'Albert Einstein'
Expand All @@ -40,7 +38,7 @@ describe('Top Bar component', () => {
}
}),
localVue,
stubs: Stubs,
stubs,
propsData: {
userId: 'einstein',
userDisplayName: 'Albert Einstein',
Expand All @@ -60,7 +58,7 @@ describe('Top Bar component', () => {
}
}),
localVue,
stubs: Stubs
stubs
})

wrapper.find('.oc-app-navigation-toggle').vm.$emit('click')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { loadConfig } from 'web-runtime/src/configHelper'
import fetchMock from 'jest-fetch-mock'

fetchMock.enableMocks()
import { loadConfig } from 'web-runtime/src/helpers/config'

const validConfig = `{
"server" : "http://localhost/owncloud-core",
Expand Down Expand Up @@ -31,14 +28,14 @@ const validConfig = `{

describe('config file loading and error reporting', () => {
it('should load and parse a valid config', function() {
fetchMock.mockOnce(validConfig)
fetch.mockResponseOnce(validConfig)
return loadConfig().then(async result => {
expect(await result).toMatchObject(JSON.parse(validConfig))
})
})
describe('empty config', () => {
it('should throw an exception', function() {
fetchMock.mockOnce('')
fetch.mockResponseOnce('')
return expect(loadConfig).rejects.toThrow(
'config could not be parsed. ' +
'FetchError: invalid json response body at ' +
Expand All @@ -48,7 +45,7 @@ describe('config file loading and error reporting', () => {
})
describe('config with an trailing comma', () => {
it('should throw an exception', function() {
fetchMock.mockOnce('"title": { "en": "Classic Design", "de": "Dateien", },')
fetch.mockResponseOnce('"title": { "en": "Classic Design", "de": "Dateien", },')
return expect(loadConfig).rejects.toThrow(
'config could not be parsed. ' +
'FetchError: invalid json response body at ' +
Expand All @@ -59,7 +56,7 @@ describe('config file loading and error reporting', () => {
})
describe('missing config', () => {
it('should throw an exception', function() {
fetchMock.mockOnce(
fetch.mockResponseOnce(
'<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">\n' +
'<html><head>\n' +
'<title>404 Not Found</title>\n' +
Expand Down
42 changes: 42 additions & 0 deletions packages/web-runtime/tests/helpers/theme.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { loadTheme } from 'web-runtime/src/helpers/theme'
import { merge } from 'lodash'
import defaultTheme from 'web-runtime/themes/owncloud.json'
const defaultName = 'themes/owncloud/theme.json'

describe('theme loading and error reporting', () => {
it('should load the default theme if no name is given', async () => {
const { theme, name } = await loadTheme()
expect(theme).toMatchObject(defaultTheme)
expect(name).toMatch(defaultName)
})

it('should load the default theme if default name is given', async () => {
const { theme, name } = await loadTheme(defaultName)
expect(theme).toMatchObject(defaultTheme)
expect(name).toMatch(defaultName)
})

it('should load the default theme if name is unknown', async () => {
fetch.mockResponseOnce(new Error(), { status: 404 })
const { theme, name } = await loadTheme('unknown.json')
expect(theme).toMatchObject(defaultTheme)
expect(name).toMatch(defaultName)
})

it('should load the default theme if server errors', async () => {
fetch.mockRejectOnce(new Error())
const { theme, name } = await loadTheme('something.json')
expect(theme).toMatchObject(defaultTheme)
expect(name).toMatch(defaultName)
})

it('should load the custom theme if a custom name is given', async () => {
const customTheme = merge({}, defaultTheme, { logo: { login: 'custom.svg' } })
const customName = 'themes/custom/theme.json'
fetch.mockResponseOnce(JSON.stringify(customTheme))

const { theme, name } = await loadTheme(customName)
expect(theme).toMatchObject(customTheme)
expect(name).toMatch(customName)
})
})
34 changes: 34 additions & 0 deletions packages/web-runtime/tests/store/config.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { loadTheme } from 'web-runtime/src/helpers/theme'
import store from 'web-runtime/src/store'
import { keysDeep } from 'web-pkg/src/utils/object'
import get from 'lodash-es/get'
import difference from 'lodash-es/difference'

describe('config theme bootstrap', () => {
const initialStoreTheme = { ...store.getters.configuration.theme }

beforeEach(() => {
store.reset()
})

it('should be able to loadTheme', async () => {
const { theme, name } = await loadTheme()

await store.dispatch('loadTheme', { theme, name })
keysDeep(theme).forEach(k => {
expect(get(store.getters.configuration.theme, k)).toBe(get(theme, k))
})
})

it('should not overwrite keys that are not part of theme', async () => {
const { theme, name } = await loadTheme()
const storeThemeKeys = keysDeep(store.getters.configuration.theme)
const loadedThemeKeys = keysDeep(theme)
const diffThemeKeys = difference(storeThemeKeys, loadedThemeKeys)
await store.dispatch('loadTheme', { theme, name })

diffThemeKeys.forEach(k => {
expect(get(store.getters.configuration.theme, k)).toBe(get(initialStoreTheme, k))
})
})
})
File renamed without changes.
10 changes: 6 additions & 4 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ const plugins = [
watch: !production && './config',
targets: [
{ src: './packages/web-container/img', dest: 'dist' },
{ src: './packages/web-container/themes', dest: 'dist' },
{ src: './packages/web-container/oidc-callback.html', dest: 'dist' },
{ src: './packages/web-container/oidc-silent-redirect.html', dest: 'dist' },
{ src: './packages/web-container/manifest.json', dest: 'dist' },
{ src: './packages/web-runtime/themes', dest: 'dist' },
{ src: `./config/${production ? 'config.dist.json' : 'config.json'}`, dest: 'dist' },
{ src: 'node_modules/requirejs/require.js', dest: 'dist/js' }
]
Expand Down Expand Up @@ -154,9 +154,11 @@ if (process.env.SERVER === 'true') {
port: process.env.PORT || 9100
})
)
plugins.push(livereload({
watch: 'dist',
}))
plugins.push(
livereload({
watch: 'dist'
})
)
}

if (process.env.REPORT === 'true') {
Expand Down
1 change: 1 addition & 0 deletions tests/unit/config/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
'.*\\.(vue)$': 'vue-jest',
'^.+\\.svg$': 'jest-svg-transformer'
},
transformIgnorePatterns: ['<rootDir>/node_modules/(?!lodash-es)'],
setupFiles: ['<rootDir>/tests/unit/config/jest.init.js'],
snapshotSerializers: ['jest-serializer-vue'],
coverageDirectory: '<rootDir>/coverage',
Expand Down
5 changes: 3 additions & 2 deletions tests/unit/config/jest.init.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { config } from '@vue/test-utils'
import fetchMock from 'jest-fetch-mock'

const $gettext = str => str
fetchMock.enableMocks()

config.mocks = {
$gettext
$gettext: str => str
}
Loading

0 comments on commit 8e129ff

Please sign in to comment.