test_manifest_reducer.js (5363B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { 7 FETCH_MANIFEST_FAILURE, 8 FETCH_MANIFEST_START, 9 FETCH_MANIFEST_SUCCESS, 10 RESET_MANIFEST, 11 MANIFEST_MEMBER_VALUE_TYPES, 12 } = require("resource://devtools/client/application/src/constants.js"); 13 14 const { ICON, COLOR, STRING, URL } = MANIFEST_MEMBER_VALUE_TYPES; 15 16 const { 17 manifestReducer, 18 ManifestState, 19 } = require("resource://devtools/client/application/src/reducers/manifest-state.js"); 20 21 const MANIFEST_PROCESSING = [ 22 // empty manifest 23 { 24 source: {}, 25 processed: {}, 26 }, 27 // manifest with just one member 28 { 29 source: { name: "Foo" }, 30 processed: { 31 identity: [{ key: "name", value: "Foo", type: STRING }], 32 }, 33 }, 34 // manifest with two members from the same category 35 { 36 source: { 37 short_name: "Short Foo", 38 name: "Long Foo", 39 }, 40 processed: { 41 identity: [ 42 { key: "short_name", value: "Short Foo", type: STRING }, 43 { key: "name", value: "Long Foo", type: STRING }, 44 ], 45 }, 46 }, 47 // manifest with members from two different categories 48 { 49 source: { 50 name: "Foo", 51 background_color: "#FF0000", 52 start_url: "https://example.com/?q=foo", 53 scope: "https://example.com", 54 }, 55 processed: { 56 identity: [{ key: "name", value: "Foo", type: STRING }], 57 presentation: [ 58 { key: "background_color", value: "#FF0000", type: COLOR }, 59 { key: "start_url", value: "https://example.com/?q=foo", type: URL }, 60 { key: "scope", value: "https://example.com", type: URL }, 61 ], 62 }, 63 }, 64 // manifest with icons 65 { 66 source: { 67 icons: [ 68 { 69 src: "something.png", 70 type: "image/png", 71 sizes: ["16x16", "32x32"], 72 purpose: ["any"], 73 }, 74 { 75 src: "another.svg", 76 type: "image/svg", 77 sizes: ["any"], 78 purpose: ["any maskable"], 79 }, 80 { 81 src: "something.png", 82 type: undefined, 83 sizes: undefined, 84 purpose: ["any"], 85 }, 86 ], 87 }, 88 processed: { 89 icons: [ 90 { 91 key: { sizes: "16x16 32x32", contentType: "image/png" }, 92 value: { src: "something.png", purpose: "any" }, 93 type: ICON, 94 }, 95 { 96 key: { sizes: "any", contentType: "image/svg" }, 97 value: { src: "another.svg", purpose: "any maskable" }, 98 type: ICON, 99 }, 100 { 101 key: { sizes: undefined, contentType: undefined }, 102 value: { src: "something.png", purpose: "any" }, 103 type: ICON, 104 }, 105 ], 106 }, 107 }, 108 // manifest with issues 109 { 110 source: { 111 moz_validation: [ 112 { warn: "A warning" }, 113 { error: "An error", type: "json" }, 114 ], 115 }, 116 processed: { 117 validation: [ 118 { level: "warning", message: "A warning", type: null }, 119 { level: "error", message: "An error", type: "json" }, 120 ], 121 }, 122 }, 123 // manifest with URL 124 { 125 source: { 126 moz_manifest_url: "https://example.com/manifest.json", 127 }, 128 processed: { 129 url: "https://example.com/manifest.json", 130 }, 131 }, 132 ]; 133 134 add_task(async function () { 135 info("Test manifest reducer: FETCH_MANIFEST_START action"); 136 137 const state = ManifestState(); 138 const action = { type: FETCH_MANIFEST_START }; 139 const newState = manifestReducer(state, action); 140 141 equal(newState.isLoading, true, "Loading flag is true"); 142 }); 143 144 add_task(async function () { 145 info("Test manifest reducer: FETCH_MANIFEST_FAILURE action"); 146 147 const state = Object.assign(ManifestState(), { isLoading: true }); 148 const action = { type: FETCH_MANIFEST_FAILURE, error: "some error" }; 149 const newState = manifestReducer(state, action); 150 151 equal(newState.errorMessage, "some error", "Error message is as expected"); 152 equal(newState.isLoading, false, "Loading flag is false"); 153 equal(newState.manifest, null, "Manifest is null"); 154 }); 155 156 add_task(async function () { 157 info("Test manifest reducer: FETCH_MANIFEST_SUCCESS action"); 158 159 // test manifest processing 160 MANIFEST_PROCESSING.forEach(({ source, processed }) => { 161 test_manifest_processing(source, processed); 162 }); 163 }); 164 165 add_task(async function () { 166 info("Test manifest reducer: RESET_MANIFEST action"); 167 168 const state = Object.assign(ManifestState(), { 169 isLoading: true, 170 manifest: { identity: [{ key: "name", value: "Foo" }] }, 171 errorMessage: "some error", 172 }); 173 const action = { type: RESET_MANIFEST }; 174 const newState = manifestReducer(state, action); 175 176 deepEqual(newState, ManifestState(), "Manifest has been reset to defaults"); 177 }); 178 179 function test_manifest_processing(source, processed) { 180 const state = ManifestState(); 181 state.isLoading = true; 182 183 const action = { type: FETCH_MANIFEST_SUCCESS, manifest: source }; 184 const newState = manifestReducer(state, action); 185 186 // merge the expected processed manifst with some default values 187 const expected = Object.assign( 188 { 189 icons: [], 190 identity: [], 191 presentation: [], 192 url: undefined, 193 validation: [], 194 }, 195 processed 196 ); 197 198 deepEqual(newState.manifest, expected, "Processed manifest as expected"); 199 equal(newState.errorMessage, "", "Error message is empty"); 200 equal(newState.isLoading, false, "Loading flag is false"); 201 }