import { CONTENT_MESSAGE_TYPE, MAIN_MESSAGE_TYPE } from "common/Actions.mjs"; import Joi from "joi-browser"; export const baseKeys = { client_id: Joi.string().optional(), addon_version: Joi.string().required(), locale: Joi.string().required(), session_id: Joi.string(), page: Joi.valid([ "about:home", "about:newtab", "about:welcome", "both", "unknown", ]), user_prefs: Joi.number().integer().required(), }; export const eventsTelemetryExtraKeys = Joi.object() .keys({ session_id: baseKeys.session_id.required(), page: baseKeys.page.required(), addon_version: baseKeys.addon_version.required(), user_prefs: baseKeys.user_prefs.required(), action_position: Joi.string().optional(), }) .options({ allowUnknown: false }); export const UTUserEventPing = Joi.array().items( Joi.string().required().valid("activity_stream"), Joi.string().required().valid("event"), Joi.string() .required() .valid([ "CLICK", "SEARCH", "BLOCK", "DELETE", "DELETE_CONFIRM", "DIALOG_CANCEL", "DIALOG_OPEN", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "OPEN_NEWTAB_PREFS", "CLOSE_NEWTAB_PREFS", "BOOKMARK_DELETE", "BOOKMARK_ADD", "PIN", "UNPIN", "SAVE_TO_POCKET", ]), Joi.string().required(), eventsTelemetryExtraKeys ); // Use this to validate actions generated from Redux export const UserEventAction = Joi.object().keys({ type: Joi.string().required(), data: Joi.object() .keys({ event: Joi.valid([ "CLICK", "SEARCH", "SEARCH_HANDOFF", "BLOCK", "DELETE", "DELETE_CONFIRM", "DIALOG_CANCEL", "DIALOG_OPEN", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "OPEN_NEWTAB_PREFS", "CLOSE_NEWTAB_PREFS", "BOOKMARK_DELETE", "BOOKMARK_ADD", "PIN", "PREVIEW_REQUEST", "UNPIN", "SAVE_TO_POCKET", "MENU_MOVE_UP", "MENU_MOVE_DOWN", "SCREENSHOT_REQUEST", "MENU_REMOVE", "MENU_COLLAPSE", "MENU_EXPAND", "MENU_MANAGE", "MENU_ADD_TOPSITE", "MENU_PRIVACY_NOTICE", "DELETE_FROM_POCKET", "ARCHIVE_FROM_POCKET", "SKIPPED_SIGNIN", "SUBMIT_EMAIL", "SUBMIT_SIGNIN", "SHOW_PRIVACY_INFO", "CLICK_PRIVACY_INFO", ]).required(), source: Joi.valid(["TOP_SITES", "TOP_STORIES", "HIGHLIGHTS"]), action_position: Joi.number().integer(), value: Joi.object().keys({ icon_type: Joi.valid([ "tippytop", "rich_icon", "screenshot_with_icon", "screenshot", "no_image", "custom_screenshot", ]), card_type: Joi.valid([ "bookmark", "trending", "pinned", "pocket", "search", "spoc", "organic", ]), search_vendor: Joi.valid(["google", "amazon"]), has_flow_params: Joi.bool(), }), }) .required(), meta: Joi.object() .keys({ to: Joi.valid(MAIN_MESSAGE_TYPE).required(), from: Joi.valid(CONTENT_MESSAGE_TYPE).required(), }) .required(), }); export const TileSchema = Joi.object().keys({ id: Joi.number().integer().required(), pos: Joi.number().integer(), }); export const UTSessionPing = Joi.array().items( Joi.string().required().valid("activity_stream"), Joi.string().required().valid("end"), Joi.string().required().valid("session"), Joi.string().required(), eventsTelemetryExtraKeys ); export function chaiAssertions(_chai) { const { Assertion } = _chai; Assertion.addMethod("validate", function (schema, schemaName) { const { error } = Joi.validate(this._obj, schema, { allowUnknown: false }); this.assert( !error, `Expected to be ${ schemaName ? `a valid ${schemaName}` : "valid" } but there were errors: ${error}` ); }); const assertions = { /** * assert.validate - Validates an item given a Joi schema * * @param {any} actual The item to validate * @param {obj} schema A Joi schema */ validate(actual, schema, schemaName) { new Assertion(actual).validate(schema, schemaName); }, /** * isUserEventAction - Passes if the item is a valid UserEvent action * * @param {any} actual The item to validate */ isUserEventAction(actual) { new Assertion(actual).validate(UserEventAction, "UserEventAction"); }, }; Object.assign(_chai.assert, assertions); }