commit 97810c00b1c3383cb4c0a0c7229b19bb73a8775d Author: Felix Edel Date: Wed Sep 30 10:32:10 2020 +0200 Add redux integration tests for build actions This also moves the build "slice" of our redux state into an initialState variable that allow using the same state for testing. We should move the others slices to the initialState later on as well. Change-Id: Id1a476a3b82df530a859732f8dab9ef7c11939e5 diff --git a/web/src/actions/build.js b/web/src/actions/build.js index 488f330..510e018 100644 --- a/web/src/actions/build.js +++ b/web/src/actions/build.js @@ -140,7 +140,7 @@ export function taskPathMatches (ref, test) { } -const receiveBuildOutput = (buildId, output) => { +export const receiveBuildOutput = (buildId, output) => { const hosts = {} // Compute stats output.forEach(phase => { @@ -220,7 +220,7 @@ export const requestBuildManifest = () => ({ type: BUILD_MANIFEST_REQUEST }) -const receiveBuildManifest = (buildId, manifest) => { +export const receiveBuildManifest = (buildId, manifest) => { const index = {} const renderNode = (root, object) => { diff --git a/web/src/reducers/build.js b/web/src/reducers/build.js index ab33951..5306aa4 100644 --- a/web/src/reducers/build.js +++ b/web/src/reducers/build.js @@ -27,16 +27,9 @@ import { BUILD_MANIFEST_SUCCESS, } from '../actions/build' -export default ( - state = { - isFetching: false, - isFetchingOutput: false, - isFetchingManifest: false, - builds: {}, - buildsets: {}, - }, - action -) => { +import initialState from './initialState' + +export default (state = initialState.build, action) => { switch (action.type) { case BUILD_FETCH_REQUEST: case BUILDSET_FETCH_REQUEST: diff --git a/web/src/reducers/initialState.js b/web/src/reducers/initialState.js new file mode 100644 index 0000000..382f309 --- /dev/null +++ b/web/src/reducers/initialState.js @@ -0,0 +1,9 @@ +export default { + build: { + builds: {}, + buildsets: {}, + isFetching: false, + isFetchingOutput: false, + isFetchingManifest: false, + }, +} diff --git a/web/src/store.test.js b/web/src/store.test.js new file mode 100644 index 0000000..20ce191 --- /dev/null +++ b/web/src/store.test.js @@ -0,0 +1,239 @@ +import { createStore } from 'redux' + +import rootReducer from './reducers' +import initialState from './reducers/initialState' +import * as buildActions from './actions/build' + +it('should fetch a build', () => { + const store = createStore(rootReducer, initialState) + const build = { + uuid: '1234', + job_name: 'run-tox', + } + + const action = buildActions.receiveBuild(build.uuid, build) + store.dispatch(action) + + const fetchedBuild = store.getState().build.builds[build.uuid] + expect(fetchedBuild).toEqual(build) +}) + +it('should fetch output and update the build in the store', () => { + const store = createStore(rootReducer, initialState) + const build = { + uuid: '1234', + job_name: 'run-tox', + } + const output = [ + { + branch: 'master', + index: '0', + phase: 'pre', + playbook: 'opendev.org/opendev/base-jobs/playbooks/base/pre.yaml', + plays: [ + { + play: { + duration: { + end: '2020-09-24T23:24:02.272988Z', + start: '2020-09-24T23:23:52.900231Z', + }, + id: 'bc764e04-8d26-889a-2270-000000000006', + name: 'localhost', + }, + tasks: [ + { + hosts: { + localhost: { + action: 'include_role', + changed: false, + include_args: { + name: 'set-zuul-log-path-fact', + }, + }, + }, + role: { + id: 'bc764e04-8d26-889a-2270-000000000009', + name: 'emit-job-header', + path: + '/var/lib/zuul/builds/79dea00ae4dd4943a09a8bb701488bb5/trusted/project_1/opendev.org/zuul/zuul-jobs/roles/emit-job-header', + }, + task: { + duration: { + end: '2020-09-24T23:23:55.818592Z', + start: '2020-09-24T23:23:55.724571Z', + }, + id: 'bc764e04-8d26-889a-2270-00000000000c', + name: 'Setup log path fact', + }, + }, + ], + }, + ], + stats: { + localhost: { + changed: 2, + failures: 0, + ignored: 0, + ok: 6, + rescued: 0, + skipped: 5, + unreachable: 0, + }, + 'ubuntu-bionic': { + changed: 22, + failures: 0, + ignored: 0, + ok: 47, + rescued: 0, + skipped: 7, + unreachable: 0, + }, + }, + trusted: true, + }, + ] + + // Fetch the build + store.dispatch(buildActions.receiveBuild(build.uuid, build)) + + // Fetch the output + store.dispatch(buildActions.receiveBuildOutput(build.uuid, output)) + + const newState = store.getState() + expect(Object.keys(newState.build.builds).length).toEqual(1) + + const expectedHosts = { + localhost: { + changed: 2, + failures: 0, + ignored: 0, + ok: 6, + rescued: 0, + skipped: 5, + unreachable: 0, + failed: [], + }, + 'ubuntu-bionic': { + changed: 22, + failures: 0, + ignored: 0, + ok: 47, + rescued: 0, + skipped: 7, + unreachable: 0, + failed: [], + }, + } + + const fetchedBuild = newState.build.builds[build.uuid] + expect(fetchedBuild.errorIds).toEqual(new Set()) + expect(fetchedBuild.hosts).toEqual(expectedHosts) + expect(fetchedBuild.output).toEqual(output) +}) + +it('should fetch manifest and update the build in the store', () => { + const store = createStore(rootReducer, initialState) + const build = { + uuid: '1234', + job_name: 'run-tox', + } + const manifest = { + tree: [ + { + name: 'zuul-info', + mimetype: 'application/directory', + encoding: null, + children: [ + { + name: 'host-info.ubuntu-bionic.yaml', + mimetype: 'text/plain', + encoding: null, + last_modified: 1600989879, + size: 12895, + }, + { + name: 'inventory.yaml', + mimetype: 'text/plain', + encoding: null, + last_modified: 1600989840, + size: 3734, + }, + { + name: 'zuul-info.ubuntu-bionic.txt', + mimetype: 'text/plain', + encoding: null, + last_modified: 1600989881, + size: 2584, + }, + ], + }, + { + name: 'job-output.json', + mimetype: 'application/json', + encoding: null, + last_modified: 1600990084, + size: 612933, + }, + { + name: 'job-output.txt', + mimetype: 'text/plain', + encoding: null, + last_modified: 1600990088, + size: 84764, + }, + ], + } + + // Fetch the build + store.dispatch(buildActions.receiveBuild(build.uuid, build)) + + // Fetch the manifest + store.dispatch(buildActions.receiveBuildManifest(build.uuid, manifest)) + + const newState = store.getState() + expect(Object.keys(newState.build.builds).length).toEqual(1) + + const expectedManifestIndex = { + '/zuul-info/host-info.ubuntu-bionic.yaml': { + name: 'host-info.ubuntu-bionic.yaml', + mimetype: 'text/plain', + encoding: null, + last_modified: 1600989879, + size: 12895, + }, + '/zuul-info/inventory.yaml': { + name: 'inventory.yaml', + mimetype: 'text/plain', + encoding: null, + last_modified: 1600989840, + size: 3734, + }, + '/zuul-info/zuul-info.ubuntu-bionic.txt': { + name: 'zuul-info.ubuntu-bionic.txt', + mimetype: 'text/plain', + encoding: null, + last_modified: 1600989881, + size: 2584, + }, + '/job-output.json': { + name: 'job-output.json', + mimetype: 'application/json', + encoding: null, + last_modified: 1600990084, + size: 612933, + }, + '/job-output.txt': { + name: 'job-output.txt', + mimetype: 'text/plain', + encoding: null, + last_modified: 1600990088, + size: 84764, + }, + } + + const fetchedBuild = newState.build.builds[build.uuid] + expect(fetchedBuild.manifest).toEqual({ + index: expectedManifestIndex, + tree: manifest.tree, + }) +})