From 97810c00b1c3383cb4c0a0c7229b19bb73a8775d Mon Sep 17 00:00:00 2001 From: Felix Edel Date: Wed, 30 Sep 2020 10:32:10 +0200 Subject: [PATCH] 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 --- web/src/actions/build.js | 4 +- web/src/reducers/build.js | 13 +- web/src/reducers/initialState.js | 9 ++ web/src/store.test.js | 239 +++++++++++++++++++++++++++++++ 4 files changed, 253 insertions(+), 12 deletions(-) create mode 100644 web/src/reducers/initialState.js create mode 100644 web/src/store.test.js diff --git a/web/src/actions/build.js b/web/src/actions/build.js index 488f330360..510e018f2f 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 ab339517cf..5306aa4e0b 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 0000000000..382f30975e --- /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 0000000000..20ce1916f4 --- /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, + }) +})