Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/remote/shared/webdriver/test/xpcshell/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 22 kB image not shown  

Quelle  test_Actions.js   Sprache: JAVA

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


"use strict";

const { actions, CLICK_INTERVAL, ClickTracker } = ChromeUtils.importESModule(
  "chrome://remote/content/shared/webdriver/Actions.sys.mjs"
);

const { setTimeout } = ChromeUtils.importESModule(
  "resource://gre/modules/Timer.sys.mjs"
);

const XHTMLNS = "http://www.w3.org/1999/xhtml";

const domEl = {
  nodeType: 1,
  ELEMENT_NODE: 1,
  namespaceURI: XHTMLNS,
};

add_task(function test_createInputState() {
  for (let type of ["none""key""pointer" /*"wheel"*/]) {
    const state = new actions.State();
    const id = "device";
    const actionSequence = {
      type,
      id,
      actions: [],
    };
    actions.Chain.fromJSON(state, [actionSequence]);
    equal(state.inputStateMap.size, 1);
    equal(state.inputStateMap.get(id).constructor.type, type);
  }
});

add_task(async function test_defaultPointerParameters() {
  let state = new actions.State();
  const inputTickActions = [
    { type: "pointer", subtype: "pointerDown", button: 0 },
  ];
  const chain = await actions.Chain.fromJSON(
    state,
    chainForTick(inputTickActions)
  );
  const pointerAction = chain[0][0];
  equal(
    state.getInputSource(pointerAction.id).pointer.constructor.type,
    "mouse"
  );
});

add_task(async function test_processPointerParameters() {
  for (let subtype of ["pointerDown""pointerUp"]) {
    for (let pointerType of [2, true, {}, []]) {
      const inputTickActions = [
        {
          type: "pointer",
          parameters: { pointerType },
          subtype,
          button: 0,
        },
      ];
      let message = `Action sequence with parameters: {pointerType: ${pointerType} subtype: ${subtype}}`;
      await checkFromJSONErrors(
        inputTickActions,
        /Expected "pointerType" to be a string/,
        message
      );
    }

    for (let pointerType of ["""foo"]) {
      const inputTickActions = [
        {
          type: "pointer",
          parameters: { pointerType },
          subtype,
          button: 0,
        },
      ];
      let message = `Action sequence with parameters: {pointerType: ${pointerType} subtype: ${subtype}}`;
      await checkFromJSONErrors(
        inputTickActions,
        /Expected "pointerType" to be one of/,
        message
      );
    }
  }

  for (let pointerType of ["mouse" /*"touch"*/]) {
    let state = new actions.State();
    const inputTickActions = [
      {
        type: "pointer",
        parameters: { pointerType },
        subtype: "pointerDown",
        button: 0,
      },
    ];
    const chain = await actions.Chain.fromJSON(
      state,
      chainForTick(inputTickActions)
    );
    const pointerAction = chain[0][0];
    equal(
      state.getInputSource(pointerAction.id).pointer.constructor.type,
      pointerType
    );
  }
});

add_task(async function test_processPointerDownAction() {
  for (let button of [-1, "a"]) {
    const inputTickActions = [
      { type: "pointer", subtype: "pointerDown", button },
    ];
    await checkFromJSONErrors(
      inputTickActions,
      /Expected "button" to be a positive integer/,
      `pointerDown with {button: ${button}}`
    );
  }
  let state = new actions.State();
  const inputTickActions = [
    { type: "pointer", subtype: "pointerDown", button: 5 },
  ];
  const chain = await actions.Chain.fromJSON(
    state,
    chainForTick(inputTickActions)
  );
  equal(chain[0][0].button, 5);
});

add_task(async function test_validateActionDurationAndCoordinates() {
  for (let [type, subtype] of [
    ["none""pause"],
    ["pointer""pointerMove"],
  ]) {
    for (let duration of [-1, "a"]) {
      const inputTickActions = [{ type, subtype, duration }];
      await checkFromJSONErrors(
        inputTickActions,
        /Expected "duration" to be a positive integer/,
        `{subtype} with {duration: ${duration}}`
      );
    }
  }
  for (let name of ["x""y"]) {
    const actionItem = {
      type: "pointer",
      subtype: "pointerMove",
      duration: 5000,
    };
    actionItem[name] = "a";
    await checkFromJSONErrors(
      [actionItem],
      /Expected ".*" to be an integer/,
      `${name}: "a", subtype: pointerMove`
    );
  }
});

add_task(async function test_processPointerMoveActionOriginStringValidation() {
  for (let origin of ["""viewports""pointers"]) {
    const inputTickActions = [
      {
        type: "pointer",
        x: 0,
        y: 0,
        duration: 5000,
        subtype: "pointerMove",
        origin,
      },
    ];
    await checkFromJSONErrors(
      inputTickActions,
      /Expected "origin" to be undefined, "viewport""pointer", or an element/,
      `actionItem.origin: ${origin}`,
      { isElementOrigin: () => false }
    );
  }
});

add_task(async function test_processPointerMoveActionOriginElementValidation() {
  const element = { foo: "bar" };
  const inputTickActions = [
    {
      type: "pointer",
      x: 0,
      y: 0,
      duration: 5000,
      subtype: "pointerMove",
      origin: element,
    },
  ];

  // invalid element origin
  await checkFromJSONErrors(
    inputTickActions,
    /Expected "origin" to be undefined, "viewport""pointer", or an element/,
    `actionItem.origin: (${getTypeString(element)})`,
    { isElementOrigin: elem => "foo1" in elem }
  );

  let state = new actions.State();
  const actionsOptions = {
    isElementOrigin: elem => "foo" in elem,
    getElementOrigin: elem => elem,
  };

  // valid element origin
  const chain = await actions.Chain.fromJSON(
    state,
    chainForTick(inputTickActions),
    actionsOptions
  );
  deepEqual(chain[0][0].origin, { element });
});

add_task(async function test_processPointerMoveActionDefaultOrigin() {
  let state = new actions.State();
  const inputTickActions = [
    { type: "pointer", x: 0, y: 0, duration: 5000, subtype: "pointerMove" },
  ];
  const chain = await actions.Chain.fromJSON(
    state,
    chainForTick(inputTickActions),
    {}
  );
  // The default is viewport coordinates which have an origin at [0,0] and don't depend on inputSource
  deepEqual(chain[0][0].origin.getOriginCoordinates(nullnull), {
    x: 0,
    y: 0,
  });
});

add_task(async function test_processPointerMoveAction() {
  let state = new actions.State();
  const actionItems = [
    {
      duration: 5000,
      type: "pointerMove",
      origin: undefined,
      x: 0,
      y: 0,
    },
    {
      duration: undefined,
      type: "pointerMove",
      origin: domEl,
      x: 0,
      y: 0,
    },
    {
      duration: 5000,
      type: "pointerMove",
      x: 1,
      y: 2,
      origin: undefined,
    },
  ];
  const actionSequence = {
    id: "some_id",
    type: "pointer",
    actions: actionItems,
  };
  let actionsOptions = {
    isElementOrigin: elem => elem == domEl,
    getElementOrigin: elem => elem,
  };

  let chain = await actions.Chain.fromJSON(
    state,
    [actionSequence],
    actionsOptions
  );
  equal(chain.length, actionItems.length);
  for (let i = 0; i < actionItems.length; i++) {
    let actual = chain[i][0];
    let expected = actionItems[i];
    equal(actual.duration, expected.duration);
    equal(actual.x, expected.x);
    equal(actual.y, expected.y);

    let originClass;
    if (expected.origin === undefined || expected.origin == "viewport") {
      originClass = "ViewportOrigin";
    } else if (expected.origin === "pointer") {
      originClass = "PointerOrigin";
    } else {
      originClass = "ElementOrigin";
    }
    deepEqual(actual.origin.constructor.name, originClass);
  }
});

add_task(async function test_computePointerDestinationViewport() {
  const state = new actions.State();
  const inputTickActions = [
    {
      type: "pointer",
      subtype: "pointerMove",
      x: 100,
      y: 200,
      origin: "viewport",
    },
  ];
  const chain = await actions.Chain.fromJSON(
    state,
    chainForTick(inputTickActions),
    {}
  );
  const actionItem = chain[0][0];
  const inputSource = state.getInputSource(actionItem.id);
  // these values should not affect the outcome
  inputSource.x = "99";
  inputSource.y = "10";
  const target = await actionItem.origin.getTargetCoordinates(
    inputSource,
    [actionItem.x, actionItem.y],
    null
  );
  equal(actionItem.x, target[0]);
  equal(actionItem.y, target[1]);
});

add_task(async function test_computePointerDestinationPointer() {
  const state = new actions.State();
  const inputTickActions = [
    {
      type: "pointer",
      subtype: "pointerMove",
      x: 100,
      y: 200,
      origin: "pointer",
    },
  ];
  const chain = await actions.Chain.fromJSON(
    state,
    chainForTick(inputTickActions),
    {}
  );
  const actionItem = chain[0][0];
  const inputSource = state.getInputSource(actionItem.id);
  inputSource.x = 10;
  inputSource.y = 99;
  const target = await actionItem.origin.getTargetCoordinates(
    inputSource,
    [actionItem.x, actionItem.y],
    null
  );
  equal(actionItem.x + inputSource.x, target[0]);
  equal(actionItem.y + inputSource.y, target[1]);
});

add_task(async function test_processPointerAction() {
  for (let pointerType of ["mouse""touch"]) {
    const actionItems = [
      {
        duration: 2000,
        type: "pause",
      },
      {
        type: "pointerMove",
        duration: 2000,
        x: 0,
        y: 0,
      },
      {
        type: "pointerUp",
        button: 1,
      },
    ];
    let actionSequence = {
      type: "pointer",
      id: "some_id",
      parameters: {
        pointerType,
      },
      actions: actionItems,
    };
    const state = new actions.State();
    const chain = await actions.Chain.fromJSON(state, [actionSequence], {});
    equal(chain.length, actionItems.length);
    for (let i = 0; i < actionItems.length; i++) {
      const actual = chain[i][0];
      const expected = actionItems[i];
      equal(actual.type, expected.type === "pause" ? "none" : "pointer");
      equal(actual.subtype, expected.type);
      equal(actual.id, actionSequence.id);
      if (expected.type === "pointerUp") {
        equal(actual.button, expected.button);
      } else {
        equal(actual.duration, expected.duration);
      }
      if (expected.type !== "pause") {
        equal(
          state.getInputSource(actual.id).pointer.constructor.type,
          pointerType
        );
      }
    }
  }
});

add_task(async function test_processPauseAction() {
  for (let type of ["none""key""pointer"]) {
    const state = new actions.State();
    const actionSequence = {
      type,
      id: "some_id",
      actions: [{ type: "pause", duration: 5000 }],
    };
    const chain = await actions.Chain.fromJSON(state, [actionSequence], {});
    const actionItem = chain[0][0];
    equal(actionItem.type, "none");
    equal(actionItem.subtype, "pause");
    equal(actionItem.id, "some_id");
    equal(actionItem.duration, 5000);
  }
  const state = new actions.State();
  const actionSequence = {
    type: "none",
    id: "some_id",
    actions: [{ type: "pause" }],
  };
  const chain = await actions.Chain.fromJSON(state, [actionSequence], {});
  const actionItem = chain[0][0];
  equal(actionItem.duration, undefined);
});

add_task(async function test_processActionSubtypeValidation() {
  for (let type of ["none""key""pointer"]) {
    const message = `type: ${type}, subtype: dancing`;
    const inputTickActions = [{ type, subtype: "dancing" }];
    await checkFromJSONErrors(
      inputTickActions,
      new RegExp(`Expected known subtype for type`),
      message
    );
  }
});

add_task(async function test_processKeyActionDown() {
  for (let value of [-1, undefined, [], ["a"], { length: 1 }, null]) {
    const inputTickActions = [{ type: "key", subtype: "keyDown", value }];
    const message = `actionItem.value: (${getTypeString(value)})`;
    await checkFromJSONErrors(
      inputTickActions,
      /Expected "value" to be a string that represents single code point/,
      message
    );
  }

  const state = new actions.State();
  const actionSequence = {
    type: "key",
    id: "keyboard",
    actions: [{ type: "keyDown", value: "\uE004" }],
  };
  const chain = await actions.Chain.fromJSON(state, [actionSequence], {});
  const actionItem = chain[0][0];

  equal(actionItem.type, "key");
  equal(actionItem.id, "keyboard");
  equal(actionItem.subtype, "keyDown");
  equal(actionItem.value, "\ue004");
});

add_task(async function test_processInputSourceActionSequenceValidation() {
  await checkFromJSONErrors(
    [{ type: "swim", subtype: "pause", id: "some id" }],
    /Expected known action type/,
    "actionSequence type: swim"
  );

  await checkFromJSONErrors(
    [{ type: "none", subtype: "pause", id: -1 }],
    /Expected "id" to be a string/,
    "actionSequence id: -1"
  );

  await checkFromJSONErrors(
    [{ type: "none", subtype: "pause", id: undefined }],
    /Expected "id" to be a string/,
    "actionSequence id: undefined"
  );

  const state = new actions.State();
  const actionSequence = [
    { type: "none", subtype: "pause", id: "some_id", actions: -1 },
  ];
  const errorRegex = /Expected "actionSequence.actions" to be an array/;
  const message = "actionSequence actions: -1";

  await Assert.rejects(
    actions.Chain.fromJSON(state, actionSequence, {}),
    /InvalidArgumentError/,
    message
  );
  await Assert.rejects(
    actions.Chain.fromJSON(state, actionSequence, {}),
    errorRegex,
    message
  );
});

add_task(async function test_processInputSourceActionSequence() {
  const state = new actions.State();
  const actionItem = { type: "pause", duration: 5 };
  const actionSequence = {
    type: "none",
    id: "some id",
    actions: [actionItem],
  };
  const chain = await actions.Chain.fromJSON(state, [actionSequence], {});
  equal(chain.length, 1);
  const tickActions = chain[0];
  equal(tickActions.length, 1);
  equal(tickActions[0].type, "none");
  equal(tickActions[0].subtype, "pause");
  equal(tickActions[0].duration, 5);
  equal(tickActions[0].id, "some id");
});

add_task(async function test_processInputSourceActionSequencePointer() {
  const state = new actions.State();
  const actionItem = { type: "pointerDown", button: 1 };
  const actionSequence = {
    type: "pointer",
    id: "9",
    actions: [actionItem],
    parameters: {
      pointerType: "mouse"// TODO "pen"
    },
  };
  const chain = await actions.Chain.fromJSON(state, [actionSequence], {});
  equal(chain.length, 1);
  const tickActions = chain[0];
  equal(tickActions.length, 1);
  equal(tickActions[0].type, "pointer");
  equal(tickActions[0].subtype, "pointerDown");
  equal(tickActions[0].button, 1);
  equal(tickActions[0].id, "9");
  const inputSource = state.getInputSource(tickActions[0].id);
  equal(inputSource.constructor.type, "pointer");
  equal(inputSource.pointer.constructor.type, "mouse");
});

add_task(async function test_processInputSourceActionSequenceKey() {
  const state = new actions.State();
  const actionItem = { type: "keyUp", value: "a" };
  const actionSequence = {
    type: "key",
    id: "9",
    actions: [actionItem],
  };
  const chain = await actions.Chain.fromJSON(state, [actionSequence], {});
  equal(chain.length, 1);
  const tickActions = chain[0];
  equal(tickActions.length, 1);
  equal(tickActions[0].type, "key");
  equal(tickActions[0].subtype, "keyUp");
  equal(tickActions[0].value, "a");
  equal(tickActions[0].id, "9");
});

add_task(async function test_processInputSourceActionSequenceInputStateMap() {
  const state = new actions.State();
  const id = "1";
  const actionItem = { type: "pause", duration: 5000 };
  const actionSequence = {
    type: "key",
    id,
    actions: [actionItem],
  };
  await actions.Chain.fromJSON(state, [actionSequence], {});
  equal(state.inputStateMap.size, 1);
  equal(state.inputStateMap.get(id).constructor.type, "key");

  // Construct a different state with the same input id
  const state1 = new actions.State();
  const actionItem1 = { type: "pointerDown", button: 0 };
  const actionSequence1 = {
    type: "pointer",
    id,
    actions: [actionItem1],
  };
  await actions.Chain.fromJSON(state1, [actionSequence1], {});
  equal(state1.inputStateMap.size, 1);

  // Overwrite the state in the initial map with one of a different type
  state.inputStateMap.set(id, state1.inputStateMap.get(id));
  equal(state.inputStateMap.get(id).constructor.type, "pointer");

  const message = "Wrong state for input id type";
  await Assert.rejects(
    actions.Chain.fromJSON(state, [actionSequence]),
    /InvalidArgumentError/,
    message
  );
  await Assert.rejects(
    actions.Chain.fromJSON(state, [actionSequence]),
    /Expected input source \[object String\] "1" to be type pointer/,
    message
  );
});

add_task(async function test_extractActionChainValidation() {
  for (let action of [-1, "a", undefined, null]) {
    const state = new actions.State();
    let message = `actions: ${getTypeString(action)}`;
    await Assert.rejects(
      actions.Chain.fromJSON(state, action),
      /InvalidArgumentError/,
      message
    );
    await Assert.rejects(
      actions.Chain.fromJSON(state, action),
      /Expected "actions" to be an array/,
      message
    );
  }
});

add_task(async function test_extractActionChainEmpty() {
  const state = new actions.State();
  deepEqual(await actions.Chain.fromJSON(state, [], {}), []);
});

add_task(async function test_extractActionChain_oneTickOneInput() {
  const state = new actions.State();
  const actionItem = { type: "pause", duration: 5000 };
  const actionSequence = {
    type: "none",
    id: "some id",
    actions: [actionItem],
  };
  const actionsByTick = await actions.Chain.fromJSON(
    state,
    [actionSequence],
    {}
  );
  equal(1, actionsByTick.length);
  equal(1, actionsByTick[0].length);
  equal(actionsByTick[0][0].id, actionSequence.id);
  equal(actionsByTick[0][0].type, "none");
  equal(actionsByTick[0][0].subtype, "pause");
  equal(actionsByTick[0][0].duration, actionItem.duration);
});

add_task(async function test_extractActionChain_twoAndThreeTicks() {
  const state = new actions.State();
  const mouseActionItems = [
    {
      type: "pointerDown",
      button: 2,
    },
    {
      type: "pointerUp",
      button: 2,
    },
  ];
  const mouseActionSequence = {
    type: "pointer",
    id: "7",
    actions: mouseActionItems,
    parameters: {
      pointerType: "mouse",
    },
  };
  const keyActionItems = [
    {
      type: "keyDown",
      value: "a",
    },
    {
      type: "pause",
      duration: 4,
    },
    {
      type: "keyUp",
      value: "a",
    },
  ];
  let keyActionSequence = {
    type: "key",
    id: "1",
    actions: keyActionItems,
  };
  let actionsByTick = await actions.Chain.fromJSON(
    state,
    [keyActionSequence, mouseActionSequence],
    {}
  );
  // number of ticks is same as longest action sequence
  equal(keyActionItems.length, actionsByTick.length);
  equal(2, actionsByTick[0].length);
  equal(2, actionsByTick[1].length);
  equal(1, actionsByTick[2].length);

  equal(actionsByTick[2][0].id, keyActionSequence.id);
  equal(actionsByTick[2][0].type, "key");
  equal(actionsByTick[2][0].subtype, "keyUp");
});

add_task(async function test_computeTickDuration() {
  const state = new actions.State();
  const expected = 8000;
  const inputTickActions = [
    { type: "none", subtype: "pause", duration: 5000 },
    { type: "key", subtype: "pause", duration: 1000 },
    { type: "pointer", subtype: "pointerMove", duration: 6000, x: 0, y: 0 },
    // invalid because keyDown should not have duration, so duration should be ignored.
    { type: "key", subtype: "keyDown", duration: 100000, value: "a" },
    { type: "pointer", subtype: "pause", duration: expected },
    { type: "pointer", subtype: "pointerUp", button: 0 },
  ];
  const chain = await actions.Chain.fromJSON(
    state,
    chainForTick(inputTickActions),
    {}
  );
  equal(1, chain.length);
  const tickActions = chain[0];
  equal(expected, tickActions.getDuration());
});

add_task(async function test_computeTickDuration_noDurations() {
  const state = new actions.State();
  const inputTickActions = [
    // invalid because keyDown should not have duration, so duration should be ignored.
    { type: "key", subtype: "keyDown", duration: 100000, value: "a" },
    // undefined duration permitted
    { type: "none", subtype: "pause" },
    { type: "pointer", subtype: "pointerMove", button: 0, x: 0, y: 0 },
    { type: "pointer", subtype: "pointerDown", button: 0 },
    { type: "key", subtype: "keyUp", value: "a" },
  ];
  const chain = await actions.Chain.fromJSON(
    state,
    chainForTick(inputTickActions),
    {}
  );
  equal(0, chain[0].getDuration());
});

add_task(function test_ClickTracker_setClick() {
  const clickTracker = new ClickTracker();
  const button1 = 1;
  const button2 = 2;

  clickTracker.setClick(button1);
  equal(1, clickTracker.count);

  // Make sure that clicking different mouse buttons doesn't increase the count.
  clickTracker.setClick(button2);
  equal(1, clickTracker.count);

  clickTracker.setClick(button2);
  equal(2, clickTracker.count);

  clickTracker.reset();
  equal(0, clickTracker.count);
});

add_task(function test_ClickTracker_reset_after_timeout() {
  const clickTracker = new ClickTracker();

  clickTracker.setClick(1);
  equal(1, clickTracker.count);

  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
  setTimeout(() => equal(0, clickTracker.count), CLICK_INTERVAL + 10);
});

// helpers
function getTypeString(obj) {
  return Object.prototype.toString.call(obj);
}

async function checkFromJSONErrors(
  inputTickActions,
  regex,
  message,
  options = {}
) {
  const { isElementOrigin = () => true, getElementOrigin = elem => elem } =
    options;

  const state = new actions.State();
  const actionsOptions = { isElementOrigin, getElementOrigin };

  if (typeof message == "undefined") {
    message = `fromJSON`;
  }

  await Assert.rejects(
    actions.Chain.fromJSON(
      state,
      chainForTick(inputTickActions),
      actionsOptions
    ),
    /InvalidArgumentError/,
    message
  );
  await Assert.rejects(
    actions.Chain.fromJSON(
      state,
      chainForTick(inputTickActions),
      actionsOptions
    ),
    regex,
    message
  );
}

function chainForTick(tickActions) {
  const actions = [];
  let lastId = 0;
  for (let { type, subtype, parameters, ...props } of tickActions) {
    let id;
    if (!props.hasOwnProperty("id")) {
      id = `${type}_${lastId++}`;
    } else {
      id = props.id;
      delete props.id;
    }
    const inputAction = { type, id, actions: [{ type: subtype, ...props }] };
    if (parameters !== undefined) {
      inputAction.parameters = parameters;
    }
    actions.push(inputAction);
  }
  return actions;
}

Messung V0.5
C=94 H=91 G=92

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.