How to use act method in stryker-parent

Best JavaScript code snippet using stryker-parent

bso.ts

Source:bso.ts Github

copy

Full Screen

...14}15function Tmp<T extends HTMLElement>(tag: string, act?: (t: T) => any | T, ...content: ElementCreator[]): T { 16 var el = document.createElement(tag) as T; 17 if (act)18 act(el);19 for (var e in content) {20 var em = content[e];21 if (Array.isArray(em)) {22 var tmp1 = em as Array<HTMLElement>;23 for (var x in tmp1) {24 el.appendChild(tmp1[x]);25 }26 }27 else {28 var tmp2 = em as Creator;29 el.appendChild(tmp2());30 }31 }32 return el;...

Full Screen

Full Screen

ReactAct.js

Source:ReactAct.js Github

copy

Full Screen

...89 .then(() => {90 if (!wasAwaited) {91 didWarnNoAwaitAct = true;92 console.error(93 'You called act(async () => ...) without await. ' +94 'This could lead to unexpected testing behaviour, ' +95 'interleaving multiple act calls and mixing their ' +96 'scopes. ' +97 'You should - await act(async () => ...);',98 );99 }100 });101 }102 }103 return thenable;104 } else {105 const returnValue: T = (result: any);106 // The callback is not an async function. Exit the current scope107 // immediately, without awaiting.108 popActScope(prevActScopeDepth);109 if (actScopeDepth === 0) {110 // Exiting the outermost act scope. Flush the queue.111 const queue = ReactCurrentActQueue.current;112 if (queue !== null) {113 flushActQueue(queue);114 ReactCurrentActQueue.current = null;115 }116 // Return a thenable. If the user awaits it, we'll flush again in117 // case additional work was scheduled by a microtask.118 const thenable: Thenable<T> = {119 then(resolve, reject) {120 // Confirm we haven't re-entered another `act` scope, in case121 // the user does something weird like await the thenable122 // multiple times.123 if (ReactCurrentActQueue.current === null) {124 // Recursively flush the queue until there's no remaining work.125 ReactCurrentActQueue.current = [];126 recursivelyFlushAsyncActWork(returnValue, resolve, reject);127 } else {128 resolve(returnValue);129 }130 },131 };132 return thenable;133 } else {134 // Since we're inside a nested `act` scope, the returned thenable135 // immediately resolves. The outer scope will flush the queue.136 const thenable: Thenable<T> = {137 then(resolve, reject) {138 resolve(returnValue);139 },140 };141 return thenable;142 }143 }144 } else {145 throw new Error('act(...) is not supported in production builds of React.');146 }147}148function popActScope(prevActScopeDepth) {149 if (__DEV__) {150 if (prevActScopeDepth !== actScopeDepth - 1) {151 console.error(152 'You seem to have overlapping act() calls, this is not supported. ' +153 'Be sure to await previous act() calls before making a new one. ',154 );155 }156 actScopeDepth = prevActScopeDepth;157 }158}159function recursivelyFlushAsyncActWork<T>(160 returnValue: T,161 resolve: T => mixed,162 reject: mixed => mixed,163) {164 if (__DEV__) {165 const queue = ReactCurrentActQueue.current;166 if (queue !== null) {167 try {...

Full Screen

Full Screen

jsx-fragments.js

Source:jsx-fragments.js Github

copy

Full Screen

1/**2 * @fileoverview Tests for jsx-fragments3 * @author Alex Zherdev4 */5'use strict';6// ------------------------------------------------------------------------------7// Requirements8// ------------------------------------------------------------------------------9const RuleTester = require('eslint').RuleTester;10const rule = require('../../../lib/rules/jsx-fragments');11const parsers = require('../../helpers/parsers');12const parserOptions = {13 ecmaVersion: 2018,14 sourceType: 'module',15 ecmaFeatures: {16 jsx: true,17 },18};19const settings = {20 react: {21 version: '16.2',22 pragma: 'Act',23 fragment: 'Frag',24 },25};26const settingsOld = {27 react: {28 version: '16.1',29 pragma: 'Act',30 fragment: 'Frag',31 },32};33// ------------------------------------------------------------------------------34// Tests35// ------------------------------------------------------------------------------36const ruleTester = new RuleTester({ parserOptions });37ruleTester.run('jsx-fragments', rule, {38 valid: parsers.all([39 {40 code: '<><Foo /></>',41 features: ['fragment', 'no-ts-old'],42 settings,43 },44 {45 code: '<Act.Frag><Foo /></Act.Frag>',46 options: ['element'],47 settings,48 },49 {50 code: '<Act.Frag />',51 options: ['element'],52 settings,53 },54 {55 code: `56 import Act, { Frag as F } from 'react';57 <F><Foo /></F>;58 `,59 options: ['element'],60 settings,61 },62 {63 code: `64 const F = Act.Frag;65 <F><Foo /></F>;66 `,67 options: ['element'],68 settings,69 },70 {71 code: `72 const { Frag } = Act;73 <Frag><Foo /></Frag>;74 `,75 options: ['element'],76 settings,77 },78 {79 code: `80 const { Frag } = require('react');81 <Frag><Foo /></Frag>;82 `,83 options: ['element'],84 settings,85 },86 {87 code: '<Act.Frag key="key"><Foo /></Act.Frag>',88 options: ['syntax'],89 settings,90 },91 {92 code: '<Act.Frag key="key" />',93 options: ['syntax'],94 settings,95 },96 ]),97 invalid: parsers.all([98 {99 code: '<><Foo /></>',100 features: ['fragment', 'no-ts-old'],101 settings: settingsOld,102 errors: [103 { messageId: 'fragmentsNotSupported' },104 ],105 },106 {107 code: '<Act.Frag><Foo /></Act.Frag>',108 settings: settingsOld,109 errors: [110 { messageId: 'fragmentsNotSupported' },111 ],112 },113 {114 code: '<Act.Frag />',115 settings: settingsOld,116 errors: [117 { messageId: 'fragmentsNotSupported' },118 ],119 },120 {121 code: '<><Foo /></>',122 output: '<Act.Frag><Foo /></Act.Frag>',123 features: ['fragment', 'no-ts-old'],124 options: ['element'],125 settings,126 errors: [127 {128 messageId: 'preferPragma',129 data: { react: 'Act', fragment: 'Frag' },130 },131 ],132 },133 {134 code: '<><Foo /></>',135 output: '<><Foo /></>', // should get '<Act.Frag><Foo /></Act.Frag>', but the old TS parser lacks opening/closing Fragment info136 features: ['fragment', 'no-babel', 'ts', 'no-ts-new'],137 options: ['element'],138 settings,139 errors: [140 {141 messageId: 'preferPragma',142 data: { react: 'Act', fragment: 'Frag' },143 },144 ],145 },146 {147 code: '<Act.Frag><Foo /></Act.Frag>',148 output: '<><Foo /></>',149 options: ['syntax'],150 settings,151 errors: [152 {153 messageId: 'preferFragment',154 data: { react: 'Act', fragment: 'Frag' },155 },156 ],157 },158 {159 code: '<Act.Frag />',160 output: '<></>',161 options: ['syntax'],162 settings,163 errors: [164 {165 messageId: 'preferFragment',166 data: { react: 'Act', fragment: 'Frag' },167 },168 ],169 },170 {171 code: `172 import Act, { Frag as F } from 'react';173 <F />;174 `,175 output: `176 import Act, { Frag as F } from 'react';177 <></>;178 `,179 options: ['syntax'],180 settings,181 errors: [182 {183 messageId: 'preferFragment',184 data: { react: 'Act', fragment: 'Frag' },185 },186 ],187 },188 {189 code: `190 import Act, { Frag as F } from 'react';191 <F><Foo /></F>;192 `,193 output: `194 import Act, { Frag as F } from 'react';195 <><Foo /></>;196 `,197 options: ['syntax'],198 settings,199 errors: [200 {201 messageId: 'preferFragment',202 data: { react: 'Act', fragment: 'Frag' },203 },204 ],205 },206 {207 code: `208 import Act, { Frag } from 'react';209 <Frag><Foo /></Frag>;210 `,211 output: `212 import Act, { Frag } from 'react';213 <><Foo /></>;214 `,215 options: ['syntax'],216 settings,217 errors: [218 {219 messageId: 'preferFragment',220 data: { react: 'Act', fragment: 'Frag' },221 },222 ],223 },224 {225 code: `226 const F = Act.Frag;227 <F><Foo /></F>;228 `,229 output: `230 const F = Act.Frag;231 <><Foo /></>;232 `,233 options: ['syntax'],234 settings,235 errors: [236 {237 messageId: 'preferFragment',238 data: { react: 'Act', fragment: 'Frag' },239 },240 ],241 },242 {243 code: `244 const { Frag } = Act;245 <Frag><Foo /></Frag>;246 `,247 output: `248 const { Frag } = Act;249 <><Foo /></>;250 `,251 options: ['syntax'],252 settings,253 errors: [254 {255 messageId: 'preferFragment',256 data: { react: 'Act', fragment: 'Frag' },257 },258 ],259 },260 {261 code: `262 const { Frag } = require('react');263 <Frag><Foo /></Frag>;264 `,265 output: `266 const { Frag } = require('react');267 <><Foo /></>;268 `,269 options: ['syntax'],270 settings,271 errors: [272 {273 messageId: 'preferFragment',274 data: { react: 'Act', fragment: 'Frag' },275 },276 ],277 },278 ]),...

Full Screen

Full Screen

Match.js

Source:Match.js Github

copy

Full Screen

1// |reftest| skip2// A little pattern-matching library.3var Match =4(function() {5 function Pattern(template) {6 // act like a constructor even as a function7 if (!(this instanceof Pattern))8 return new Pattern(template);9 this.template = template;10 }11 Pattern.prototype = {12 match: function(act) {13 return match(act, this.template);14 },15 matches: function(act) {16 try {17 return this.match(act);18 }19 catch (e if e instanceof MatchError) {20 return false;21 }22 },23 assert: function(act, message) {24 try {25 return this.match(act);26 }27 catch (e if e instanceof MatchError) {28 throw new Error((message || "failed match") + ": " + e.message);29 }30 },31 toString: () => "[object Pattern]"32 };33 Pattern.ANY = new Pattern;34 Pattern.ANY.template = Pattern.ANY;35 Pattern.NUMBER = new Pattern;36 Pattern.NUMBER.match = function (act) {37 if (typeof act !== 'number') {38 throw new MatchError("Expected number, got: " + quote(act));39 }40 }41 Pattern.NATURAL = new Pattern42 Pattern.NATURAL.match = function (act) {43 if (typeof act !== 'number' || act !== Math.floor(act) || act < 0) {44 throw new MatchError("Expected natural number, got: " + quote(act));45 }46 }47 var quote = uneval;48 function MatchError(msg) {49 this.message = msg;50 }51 MatchError.prototype = {52 toString: function() {53 return "match error: " + this.message;54 }55 };56 function isAtom(x) {57 return (typeof x === "number") ||58 (typeof x === "string") ||59 (typeof x === "boolean") ||60 (x === null) ||61 (typeof x === "object" && x instanceof RegExp);62 }63 function isObject(x) {64 return (x !== null) && (typeof x === "object");65 }66 function isFunction(x) {67 return typeof x === "function";68 }69 function isArrayLike(x) {70 return isObject(x) && ("length" in x);71 }72 function matchAtom(act, exp) {73 if ((typeof exp) === "number" && isNaN(exp)) {74 if ((typeof act) !== "number" || !isNaN(act))75 throw new MatchError("expected NaN, got: " + quote(act));76 return true;77 }78 if (exp === null) {79 if (act !== null)80 throw new MatchError("expected null, got: " + quote(act));81 return true;82 }83 if (exp instanceof RegExp) {84 if (!(act instanceof RegExp) || exp.source !== act.source)85 throw new MatchError("expected " + quote(exp) + ", got: " + quote(act));86 return true;87 }88 switch (typeof exp) {89 case "string":90 if (act !== exp)91 throw new MatchError("expected " + quote(exp) + ", got " + quote(act));92 return true;93 case "boolean":94 case "number":95 if (exp !== act)96 throw new MatchError("expected " + exp + ", got " + quote(act));97 return true;98 }99 throw new Error("bad pattern: " + exp.toSource());100 }101 function matchObject(act, exp) {102 if (!isObject(act))103 throw new MatchError("expected object, got " + quote(act));104 for (var key in exp) {105 if (!(key in act))106 throw new MatchError("expected property " + quote(key) + " not found in " + quote(act));107 match(act[key], exp[key]);108 }109 return true;110 }111 function matchFunction(act, exp) {112 if (!isFunction(act))113 throw new MatchError("expected function, got " + quote(act));114 if (act !== exp)115 throw new MatchError("expected function: " + exp +116 "\nbut got different function: " + act);117 }118 function matchArray(act, exp) {119 if (!isObject(act) || !("length" in act))120 throw new MatchError("expected array-like object, got " + quote(act));121 var length = exp.length;122 if (act.length !== exp.length)123 throw new MatchError("expected array-like object of length " + length + ", got " + quote(act));124 for (var i = 0; i < length; i++) {125 if (i in exp) {126 if (!(i in act))127 throw new MatchError("expected array property " + i + " not found in " + quote(act));128 match(act[i], exp[i]);129 }130 }131 return true;132 }133 function match(act, exp) {134 if (exp === Pattern.ANY)135 return true;136 if (exp instanceof Pattern)137 return exp.match(act);138 if (isAtom(exp))139 return matchAtom(act, exp);140 if (isArrayLike(exp))141 return matchArray(act, exp);142 if (isFunction(exp))143 return matchFunction(act, exp);144 return matchObject(act, exp);145 }146 return { Pattern: Pattern,147 MatchError: MatchError };...

Full Screen

Full Screen

act-compat.js

Source:act-compat.js Github

copy

Full Screen

...33 const firstArgIsString = typeof args[0] === 'string';34 if (firstArgIsString && args[0].indexOf('Warning: Do not await the result of calling ReactTestUtils.act') === 0) {35 // v16.8.636 isAsyncActSupported = false;37 } else if (!(firstArgIsString && args[0].indexOf('Warning: The callback passed to ReactTestUtils.act(...) function must not return anything') === 0)) {38 originalConsoleError.apply(console, args);39 }40 };41 let cbReturn, result;42 try {43 result = reactAct(() => {44 cbReturn = cb();45 return cbReturn;46 });47 } catch (err) {48 console.error = originalConsoleError;49 reject(err);50 return;51 }52 result.then(() => {53 console.error = originalConsoleError; // if it got here, it means async act is supported54 isAsyncActSupported = true;55 resolve();56 }, err => {57 console.error = originalConsoleError;58 isAsyncActSupported = true;59 reject(err);60 }); // 16.8.6's act().then() doesn't call a resolve handler, so we need to manually flush here, sigh61 if (isAsyncActSupported === false) {62 console.error = originalConsoleError;63 /* istanbul ignore next */64 if (!youHaveBeenWarned) {65 // if act is supported and async act isn't and they're trying to use async66 // act, then they need to upgrade from 16.8 to 16.9.67 // This is a seemless upgrade, so we'll add a warning68 console.error(`It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.`);69 youHaveBeenWarned = true;70 }71 cbReturn.then(() => {72 // a faux-version.73 // todo - copy https://github.com/facebook/react/blob/master/packages/shared/enqueueTask.js74 Promise.resolve().then(() => {75 // use sync act to flush effects76 act(() => {});77 resolve();78 });79 }, reject);80 }81 });82 } else if (isAsyncActSupported === false) {83 // use the polyfill directly84 let result;85 act(() => {86 result = cb();87 });88 return result.then(() => {89 return Promise.resolve().then(() => {90 // use sync act to flush effects91 act(() => {});92 });93 });94 } // all good! regular act95 return act(cb);96 } // use the polyfill97 let result;98 act(() => {99 result = cb();100 });101 return result.then(() => {102 return Promise.resolve().then(() => {103 // use sync act to flush effects104 act(() => {});105 });106 });107}108var _default = act;109/* eslint no-console:0 */...

Full Screen

Full Screen

pickResponse.ts

Source:pickResponse.ts Github

copy

Full Screen

1import type { IPet, ID } from 'common/types';2import type { ActAction } from 'redux/types';3import type { AttackAct, BullyAct, HealAct, CaressAct } from 'common/types/act';4import {5 attackPanic,6 attackCounter,7 attackAvenge,8 attackJoin,9 bullyCounter,10 bullyAvenge,11 bullyJoin,12 healDelight,13 caressCounter,14 caressJoin,15} from 'redux/actions';16import { selectPet } from 'common/utils';17import { actValue } from 'common/utils/rolls';18import {19 responseChoice,20 attackResponseTypes,21 bullyResponseTypes,22 healResponseTypes,23 caressResponseTypes,24} from './responseChoice';25import { selectBestChoice } from './selectBestChoice';26const pickAttackResponse = (actor: IPet, act: AttackAct, pets: IPet[]) => {27 const choices = attackResponseTypes.map((type) =>28 responseChoice(actor, type, act)29 );30 const bestChoice = selectBestChoice(choices);31 if (!bestChoice) return null;32 const actActor = selectPet(pets, act.actor);33 const actTarget = selectPet(pets, act.target);34 if (!actActor) return null;35 switch (bestChoice.type) {36 case 'pets/attackPanic':37 return attackPanic({38 actor: actor.id,39 act,40 });41 case 'pets/attackCounter':42 return attackCounter({43 actor: actor.id,44 act,45 value: actValue(actor, 'attack', actActor),46 });47 case 'pets/attackAvenge':48 // unsafe49 return attackAvenge({50 actor: actor.id,51 act,52 value: actValue(actor, 'attack', actActor),53 });54 case 'pets/attackJoin':55 if (!actTarget) return null;56 return attackJoin({57 actor: actor.id,58 act,59 value: actValue(actor, 'attack', actTarget),60 });61 }62};63const pickBullyResponse = (actor: IPet, act: BullyAct, pets: IPet[]) => {64 const choices = bullyResponseTypes.map((type) =>65 responseChoice(actor, type, act)66 );67 const bestChoice = selectBestChoice(choices);68 if (!bestChoice) return null;69 const actActor = selectPet(pets, act.actor);70 const actTarget = selectPet(pets, act.target);71 if (!actActor || !actTarget) return null;72 switch (bestChoice.type) {73 case 'pets/bullyCounter':74 return bullyCounter({75 actor: actor.id,76 act,77 value: actValue(actor, 'bully', actActor),78 });79 case 'pets/bullyAvenge':80 return bullyAvenge({81 actor: actor.id,82 act,83 value: actValue(actor, 'bully', actActor),84 });85 case 'pets/bullyJoin':86 return bullyJoin({87 actor: actor.id,88 act,89 value: actValue(actor, 'bully', actTarget),90 });91 }92};93const pickHealResponse = (actor: IPet, act: HealAct, pets: IPet[]) => {94 const choices = healResponseTypes.map((type) =>95 responseChoice(actor, type, act)96 );97 const bestChoice = selectBestChoice(choices);98 if (!bestChoice) return null;99 const actActor = selectPet(pets, act.actor);100 const actTarget = selectPet(pets, act.target);101 if (!actActor || !actTarget) return null;102 return healDelight({103 actor: actor.id,104 act,105 });106};107const pickCaressResponse = (actor: IPet, act: CaressAct, pets: IPet[]) => {108 const choices = caressResponseTypes.map((type) =>109 responseChoice(actor, type, act)110 );111 const bestChoice = selectBestChoice(choices);112 if (!bestChoice) return null;113 const actActor = selectPet(pets, act.actor);114 const actTarget = selectPet(pets, act.target);115 if (!actActor || !actTarget) return null;116 switch (bestChoice.type) {117 case 'pets/caressCounter':118 return caressCounter({119 actor: actor.id,120 act,121 value: actValue(actor, 'caress', actActor),122 });123 case 'pets/caressJoin':124 return caressJoin({125 actor: actor.id,126 act,127 value: actValue(actor, 'caress', actTarget),128 });129 }130};131const pickResponse = (132 actorID: ID,133 { type, payload: act }: ActAction,134 pets: IPet[]135) => {136 const actor = selectPet(pets, actorID);137 if (!actor) return null;138 switch (type) {139 case 'pets/attack':140 return pickAttackResponse(actor, act, pets);141 case 'pets/bully':142 return pickBullyResponse(actor, act, pets);143 case 'pets/heal':144 return pickHealResponse(actor, act, pets);145 case 'pets/caress':146 return pickCaressResponse(actor, act, pets);147 default:148 return null;149 }150};...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { act } = require('stryker-parent');2const { act } = require('stryker-parent');3const { act } = require('stryker-parent');4const { act } = require('stryker-parent');5const { act } = require('stryker-parent');6const { act } = require('stryker-parent');7const { act } = require('stryker-parent');8const { act } = require('stryker-parent');9const { act } = require('stryker-parent');10const { act } = require('stryker-parent');11const { act } = require('stryker-parent');12const { act } = require('stryker-parent');13const { act } = require('stryker-parent');14const { act } = require('stryker-parent');15const { act } = require('stryker-parent');16const { act } = require('stryker-parent');17const { act } = require('stryker-parent');18const { act } = require('stryker-parent');19const { act } = require('stryker-parent');20const { act } = require('stry

Full Screen

Using AI Code Generation

copy

Full Screen

1var stryker = require('stryker-parent');2stryker.act(strykerConfig, strykerOptions);3var stryker = require('stryker-parent');4stryker.act(strykerConfig, strykerOptions)5 .then(function () {6 })7 .catch(function (error) {8 });

Full Screen

Using AI Code Generation

copy

Full Screen

1function act(){2 console.log("I am in stryker-parent");3}4function act(){5 console.log("I am in stryker-child");6}7module.exports = {8}9var strykerChild = require('./stryker-child.js');10function act(){11 console.log("I am in stryker-parent");12 strykerChild.act();13}14module.exports = {15}16var strykerChild = require('./stryker-child.js');17function act(){18 console.log("I am in stryker-parent");19 strykerChild.act();20}21module.exports = {22}23function act(){24 console.log("I am in stryker-child");25}26module.exports = {27}28var strykerChild = require('./stryker-child.js');29function act(){30 console.log("I am in stryker-parent");31 strykerChild.act();32}33module.exports = {34}35var strykerParent = require('./stryker-parent.js');36function act(){37 console.log("I am in stryker-child");38 strykerParent.act();39}40module.exports = {41}42var strykerChild = require('./stryker-child.js');43function act(){44 console.log("I am in stry

Full Screen

Using AI Code Generation

copy

Full Screen

1var stryker = require('stryker-parent');2stryker.act('test', function (err, result) {3});4var stryker = require('stryker');5module.exports = {6 act: function (action, callback) {7 stryker.act(action, callback);8 }9};10module.exports = {11 act: function (action, callback) {12 callback(null, result);13 }14};15Note: If you want to use the act method of stryker-parent, you can do it by calling require('stryker-parent') and then calling the act method of the returned object. The act method of stryker-parent will then call the

Full Screen

Using AI Code Generation

copy

Full Screen

1const Parent = require('stryker-parent');2const parent = new Parent();3parent.act('test', 'test message', (err, response) => {4});5const Child = require('stryker-child');6const child = new Child();7child.act('test', 'test message', (err, response) => {8});9const Child = require('stryker-child');10const child = new Child();11child.act('test', 'test message', (err, response) => {12});13const Child = require('stryker-child');14const child = new Child();15child.act('test', 'test message', (err, response) => {16});17const Child = require('stryker-child');18const child = new Child();19child.act('test', 'test message', (err, response) => {20});21const Child = require('stryker-child');22const child = new Child();23child.act('test', 'test message', (err, response) => {24});25const Child = require('stryker-child');26const child = new Child();27child.act('test', 'test message', (err, response) => {28});29const Child = require('stryker-child');30const child = new Child();31child.act('test', 'test message', (err, response) => {32});33const Child = require('stryker-child');34const child = new Child();35child.act('test', 'test message', (err, response) => {

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run stryker-parent automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful