How to use callModelHook method in Playwright Internal

Best JavaScript code snippet using playwright-internal

Run Playwright Internal automation tests on LambdaTest cloud grid

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

route-test.js

Source: route-test.js Github

copy
1import { A } from '@ember/array';
2import ArrayProxy from '@ember/array/proxy';
3import { assign } from '@ember/polyfills';
4import Route from '@ember/routing/route';
5import RSVP from 'rsvp';
6import { run } from '@ember/runloop';
7import EmberObject, { get } from '@ember/object';
8import { module, test } from 'qunit';
9import InfinityModel from 'ember-infinity/lib/infinity-model';
10import { setupTest } from 'ember-qunit';
11
12module('Unit | RouteMixin', function(hooks) {
13  setupTest(hooks);
14
15  hooks.beforeEach(function() {
16    this.EA = (content, meta={}) => {
17      return ArrayProxy.create(assign({ content: A(content) }, meta));
18    };
19
20    // create mock store first
21    this.createMockStore = (resolution, assertion) => {
22      return {
23        query() {
24          if (assertion) {
25            assertion.apply(this, arguments);
26          }
27
28          return RSVP.resolve(resolution);
29        }
30      };
31    }
32
33    // then create the route with the infinity service patched store
34    this.createRoute = (infinityModelArgs = [null], store = null) => {
35      if (store) {
36        infinityModelArgs[1] = assign({}, infinityModelArgs[1], store);
37      }
38      store = store || { store: this.createMockStore() };
39      this.infinity = this.owner.factoryFor('service:infinity').create(store);
40
41      let RouteObject = Route.extend({
42        infinity: this.infinity,
43        model() {
44          return this.infinity.model(...infinityModelArgs);
45        }
46      });
47
48      return RouteObject.create();
49    }
50
51    this.callModelHook = (route) => {
52      let model;
53      run(() => {
54        route.model().then(result => {
55          model = result;
56        });
57      });
58
59      route.set('controller', EmberObject.create({ model }));
60
61      return model;
62    }
63  });
64
65  module('basics', function() {
66    test('it works', function(assert) {
67      let RouteObject = Route.extend();
68      let route = RouteObject.create();
69      assert.ok(route);
70    });
71
72    test('it can not use infinityModel that is not an instance of InfinityModel', function (assert) {
73      assert.expect(1);
74
75      const ExtendedEmberObject = EmberObject.extend({
76        customId: 2,
77        buildParams() {
78          let params = this._super(...arguments);
79          params['custom_id'] = get(this, 'customId');
80          return params;
81        }
82      });
83
84      let item = { id: 1, title: 'The Great Gatsby' };
85      let route = this.createRoute(['post', { store: this.createMockStore(this.EA([item])) }, ExtendedEmberObject]);
86
87      try {
88        route.model();
89      } catch(e) {
90        assert.equal(e.message, 'Ember Infinity: You must pass an Infinity Model instance as the third argument', "wat");
91      }
92    });
93
94    test('it can use infinityModel with a custom data store', function(assert) {
95      let item = this.EA({ id: 1, title: 'The Great Gatsby' });
96      let mockStore = {
97        query() {
98          return RSVP.resolve(item);
99        }
100      };
101      let route = this.createRoute(['post'], {
102        store: mockStore
103      });
104
105      try {
106        route.model();
107        assert.ok(route.get('infinity.store').query, 'custom store works');
108      } catch(e) {
109        assert.ok(false, 'something failed');
110      }
111    });
112
113    test('custom data store can specify custom query method', function(assert) {
114      let EA = this.EA;
115      let mockStore =
116        {
117          findAll() {
118            let item = { id: 1, title: 'The Great Gatsby' };
119            return RSVP.resolve(EA([item]));
120          }
121        };
122      let route = this.createRoute(['post'], { store: mockStore, storeFindMethod: 'findAll' });
123
124      try {
125        route.model();
126        assert.ok(true, 'custom store with specified query method works');
127      } catch(e) {
128        assert.ok(false, 'something failed');
129      }
130    });
131
132    test('custom data store must specify custom query method', function(assert) {
133      let simpleStore = {
134        findAll() {
135          return RSVP.resolve();
136        }
137      };
138      let route = this.createRoute(['post'], { store: simpleStore });
139
140      try {
141        route.model();
142      } catch(e) {
143        assert.equal(e.message, 'Ember Infinity: Custom data store must specify query method');
144      }
145    });
146
147    test('it can not use infinityModel without passing a string for custom data store', function(assert) {
148      let route = this.createRoute(['post'], { store: 234 });
149
150      try {
151        route.model();
152      } catch(e) {
153        assert.equal(e.message, 'Ember Infinity: Custom data store must specify query method');
154      }
155    });
156
157    test('it can not use infinityModel without a Model Name', function(assert) {
158      let route = this.createRoute();
159
160      try {
161        route.model();
162      } catch(e) {
163        assert.equal(e.message, 'Ember Infinity: You must pass a Model Name to infinityModel');
164      }
165    });
166
167    test('it sets state before it reaches the end', function(assert) {
168      let store = this.createMockStore(this.EA([{id: 1, name: 'Test'}], { meta: { total_pages: 31 } } ));
169      let route = this.createRoute(['item'], { store });
170
171      let model = this.callModelHook(route);
172
173      assert.equal(model.get('_totalPages'), 31, '_totalPages');
174      assert.equal(model.get('currentPage'), 1, 'currentPage');
175      assert.equal(model.get('canLoadMore'), true, 'canLoadMore');
176      assert.notOk(route.get('_extraParams'), 'extra params are empty');
177      assert.ok(!model.get('reachedInfinity'), 'Should not reach infinity');
178    });
179
180    test('it sets count state before it reaches the end', function(assert) {
181      let store = this.createMockStore(this.EA([{id: 1, name: 'Test'}], { meta: { count: 31 } } ));
182      let route = this.createRoute(['item'], { store });
183
184      let model = this.callModelHook(route);
185
186      assert.equal(model.get('_count'), 31, '_count');
187      assert.equal(model.get('currentPage'), 1, 'currentPage');
188      assert.equal(model.get('canLoadMore'), true, 'canLoadMore');
189      assert.notOk(route.get('_extraParams'), 'extra params are empty');
190      assert.ok(!model.get('reachedInfinity'), 'Should not reach infinity');
191    });
192
193    test('it allows customizations of request params', function(assert) {
194      let store = this.createMockStore(
195        this.EA([]),
196        (modelType, findQuery) => {
197          assert.deepEqual(findQuery, { per: 25, p: 1 }, 'findQuery');
198        }
199      );
200
201      let route = this.createRoute(
202        ['item', {
203          perPageParam: 'per', pageParam: 'p'
204        }],
205        { store }
206      );
207
208      this.callModelHook(route);
209    });
210
211    test('It allows to set startingPage as 0', function(assert) {
212      let store = this.createMockStore( this.EA([{id: 1, name: 'Test'}], { total_pages: 1 }) );
213      let route = this.createRoute(
214        ['item', {
215          startingPage: 0
216        }],
217        { store }
218      );
219
220      let model = this.callModelHook(route);
221
222      assert.equal(model.get('currentPage'), 0);
223      assert.equal(model.get('canLoadMore'), false);
224    });
225
226    test('it skips request params when set to null', function(assert) {
227      let store = this.createMockStore(
228        this.EA([]),
229        (modelType, findQuery) => {
230          assert.deepEqual(findQuery, {}, 'findQuery');
231      });
232
233      let route = this.createRoute(
234        ['item', {
235          perPageParam: null, pageParam: null
236        }],
237        { store }
238      );
239
240      this.callModelHook(route);
241    });
242
243    test('it allows customizations of meta parsing params', function(assert) {
244      let store = this.createMockStore(
245        this.EA([{id: 1, name: 'Walter White'}], { pagination: { total: 22 } })
246      );
247
248      let route = this.createRoute(
249        ['item', {
250          totalPagesParam: 'pagination.total',
251        }],
252        { store }
253      );
254
255      let model = this.callModelHook(route);
256
257      assert.equal(model.get('totalPagesParam'), 'pagination.total', 'totalPagesParam');
258      assert.equal(model.get('_totalPages'), 22, '_totalPages');
259    });
260
261    test('it allows customizations of meta count params', function(assert) {
262      let store = this.createMockStore(
263        this.EA([{id: 1, name: 'Walter White'}], { pagination: { records: 22 } })
264      );
265
266      let route = this.createRoute(
267        ['item', { countParam: 'pagination.records', }],
268        { store }
269      );
270
271      let model = this.callModelHook(route);
272
273      assert.equal(model.get('countParam'), 'pagination.records', 'countParam');
274      assert.equal(model.get('_count'), 22, '_count');
275    });
276
277    test('it copies arbitrary model hook meta from route request to the infinityModel', function(assert) {
278      let store = this.createMockStore(
279        this.EA([{id: 1, name: 'Walter White'}], { meta: { meaningOfLife: 42 }})
280      );
281
282      let route = this.createRoute(['item', {}], { store });
283
284      let model = this.callModelHook(route);
285
286      assert.equal(model.get('meta.meaningOfLife'), 42, 'meta');
287    });
288  });
289
290  module('RouteMixin - reaching the end', function(hooks) {
291    hooks.beforeEach(function() {
292
293      this.createRouteWithStore = (extras, boundParamsOrInfinityModel) => {
294        let store = this.createMockStore(this.EA([{id: 1, name: 'Test'}], { meta: { total_pages: 2 } }));
295        this.route = this.createRoute(['item', extras, boundParamsOrInfinityModel], { store });
296
297        this.callModelHookWithStore();
298      };
299
300      this.callModelHookWithStore = () => {
301        this.model = this.callModelHook(this.route);
302      };
303
304      this.loadMore = () => {
305        run(() => {
306          this.route.infinity.infinityLoad(this.model);
307        });
308      };
309    });
310
311    test('it sets state when it reaches the end', function (assert) {
312      assert.expect(4);
313
314      this.createRouteWithStore({ startingPage: 2 });
315
316      assert.equal(this.model.get('_totalPages'), 2, '_totalPages');
317      assert.equal(this.model.get('currentPage'), 2, 'currentPage');
318      assert.equal(this.model.get('canLoadMore'), false, 'canLoadMore');
319      assert.ok(this.model.get('reachedInfinity'), 'Should reach infinity');
320    });
321
322    test('it uses extra params when loading more data', function (assert) {
323      assert.expect(4);
324
325      this.createRouteWithStore({ extra: 'param' });
326
327      // assert.equal(this.model.get('_extraParams.extra'), 'param', '_extraParams.extra');
328      assert.equal(this.model.get('canLoadMore'), true, 'canLoadMore');
329
330      this.loadMore();
331
332      // assert.equal(this.model.get('_extraParams.extra'), 'param', '_extraParams.extra');
333      assert.equal(this.model.get('canLoadMore'), false, 'canLoadMore');
334      assert.equal(this.model.get('currentPage'), 2, 'currentPage');
335      assert.ok(this.model.get('reachedInfinity'), 'Should reach infinity');
336    });
337
338    test('route accepts an instance of InfinityModel as the third argument', function (assert) {
339      assert.expect(3);
340
341      let ExtendedInfinityModel = InfinityModel.extend({
342        customId: 2,
343        buildParams() {
344          let params = this._super(...arguments);
345          params['custom_id'] = get(this, 'customId');
346          return params;
347        }
348      });
349      this.createRouteWithStore({ extra: 'param' }, ExtendedInfinityModel);
350
351      assert.equal(this.model instanceof InfinityModel, true, 'model is instance of extended infinity model');
352
353      this.loadMore();
354
355      assert.equal(this.model instanceof InfinityModel, true, 'model is instance of extended infinity model');
356      assert.ok(this.model.get('reachedInfinity'), 'Should reach infinity');
357    });
358
359    test('route accepts an instance of InfinityModel as the third argument with passed in param', function (assert) {
360      assert.expect(2);
361
362      let ExtendedInfinityModel = InfinityModel.extend({
363        buildParams() {
364          let params = this._super(...arguments);
365          params['custom_id'] = get(this, 'custom.id');
366          assert.equal(params['custom_id'], 2);
367          return params;
368        }
369      });
370      // imagine 'custom' being some type of service that holds state
371      this.createRouteWithStore({ extra: 'param' }, ExtendedInfinityModel.extend({ custom: { id : 2 } }));
372
373      this.loadMore();
374    });
375
376    test('route does not detect boundParams when no boundParams passed', function (assert) {
377      assert.expect(1);
378
379      this.createRouteWithStore({ extra: 'param' });
380
381      assert.equal(this.model.get('_deprecatedBoundParams'), undefined, 'bound params is not detected');
382    });
383
384    test("It doesn't request more pages once canLoadMore is false", function (assert) {
385      assert.expect(6);
386
387      this.createRouteWithStore();
388
389      assert.ok(this.model.get('canLoadMore'), 'can load more');
390      assert.equal(this.model.get('currentPage'), 1, 'currentPage');
391
392      this.loadMore();
393
394      assert.notOk(this.model.get('canLoadMore'), 'can load more');
395      assert.equal(this.model.get('currentPage'), 2, 'currentPage');
396
397      this.loadMore();
398
399      assert.notOk(this.model.get('canLoadMore'), 'can load more');
400      assert.equal(this.model.get('currentPage'), 2, 'currentPage');
401    });
402
403    test("It resets the currentPage when the model hook is called again", function (assert) {
404      assert.expect(5);
405
406      this.createRouteWithStore();
407
408      assert.ok(this.model.get('canLoadMore'), 'can load more');
409      assert.equal(this.model.get('currentPage'), 1, 'currentPage');
410
411      this.callModelHookWithStore();
412      assert.equal(this.model.get('currentPage'), 1, 'currentPage');
413
414      this.loadMore();
415
416      assert.equal(this.model.get('currentPage'), 2, 'currentPage');
417
418      this.callModelHookWithStore();
419
420      assert.equal(this.model.get('currentPage'), 1, 'currentPage');
421    });
422  });
423
424  module('RouteMixin - loading more data', function(hooks) {
425    hooks.beforeEach(function(assert) {
426      let store = this.createMockStore(
427        // return response for model hook
428        this.EA([{id: 1, name: 'Test'}, {id: 2, name: 'Test 2'}], { meta: { testTotalPages: 3 } }),
429        // for query method in model hook
430        (modelType, findQuery) => {
431          assert.equal(findQuery.testPerPage, 1);
432          assert.equal(findQuery.testPage, this.expectedPageNumber);
433        }
434      );
435
436      this.route = this.createRoute(
437        ['item', {
438          // explicit params passed to infinityModel hook
439          perPage: 1, startingPage: 2,
440          totalPagesParam: 'meta.testTotalPages', perPageParam: 'testPerPage', pageParam: 'testPage'
441        }],
442        { store: store }
443      );
444
445      this.expectedPageNumber = 2;
446
447      this.model = this.callModelHook(this.route);
448    });
449
450    test('it uses overridden params when loading more data', function (assert) {
451      assert.expect(4);
452
453      this.expectedPageNumber = 2;
454
455      assert.equal(this.model.get('canLoadMore'), true, 'canLoadMore');
456      assert.equal(this.model.get('currentPage'), 2, 'currentPage');
457    });
458
459    test('it uses overridden params when reaching the end', function (assert) {
460      assert.expect(7);
461
462      this.expectedPageNumber = 3;
463
464      const infinityModel = this.route.get('infinity.infinityModels').objectAt(0);
465      run(() => {
466        this.route.infinity.infinityLoad(infinityModel);
467      });
468
469      assert.equal(this.model.get('canLoadMore'), false, 'canLoadMore');
470      assert.equal(this.model.get('currentPage'), 3, 'currentPage');
471      assert.ok(this.model.get('reachedInfinity'), 'Should reach infinity');
472    });
473  });
474});
475
476
Full Screen

vModel.js

Source: vModel.js Github

copy
1import { addEventListener } from '../modules/events.js'
2import {
3  isArray,
4  looseEqual,
5  looseIndexOf,
6  invokeArrayFns,
7  toNumber,
8  isSet
9} from '../../shared/index.js'
10
11const getModelAssigner = vnode => {
12  const fn = vnode.props['onUpdate:modelValue']
13  return isArray(fn) ? value => invokeArrayFns(fn, value) : fn
14}
15
16function onCompositionStart (e) {
17  e.target.composing = true
18}
19function onCompositionEnd (e) {
20  const target = e.target
21  if (target.composing) {
22    target.composing = false
23    trigger(target, 'input')
24  }
25}
26function trigger (el, type) {
27  const e = document.createEvent('HTMLEvents')
28  e.initEvent(type, true, true)
29  el.dispatchEvent(e)
30}
31
32// We are exporting the v-model runtime directly as vnode hooks so that it can
33// be tree-shaken in case v-model is never used.
34export const vModelText = {
35  created (el, { modifiers: { lazy, trim, number } }, vnode) {
36    el._assign = getModelAssigner(vnode)
37    const castToNumber =
38      number || (vnode.props && vnode.props.type === 'number')
39    addEventListener(el, lazy ? 'change' : 'input', e => {
40      if (e.target.composing) return
41      let domValue = el.value
42      if (trim) {
43        domValue = domValue.trim()
44      } else if (castToNumber) {
45        domValue = toNumber(domValue)
46      }
47      el._assign(domValue)
48    })
49    if (trim) {
50      addEventListener(el, 'change', () => {
51        el.value = el.value.trim()
52      })
53    }
54    if (!lazy) {
55      addEventListener(el, 'compositionstart', onCompositionStart)
56      addEventListener(el, 'compositionend', onCompositionEnd)
57      // Safari < 10.2 & UIWebView doesn't fire compositionend when
58      // switching focus before confirming composition choice
59      // this also fixes the issue where some browsers e.g. iOS Chrome
60      // fires "change" instead of "input" on autocomplete.
61      addEventListener(el, 'change', onCompositionEnd)
62    }
63  },
64  // set value on mounted so it's after min/max for type="range"
65  mounted (el, { value }) {
66    el.value = value == null ? '' : value
67  },
68  beforeUpdate (el, { value, modifiers: { lazy, trim, number } }, vnode) {
69    el._assign = getModelAssigner(vnode)
70    // avoid clearing unresolved text. #2302
71    if (el.composing) return
72    if (document.activeElement === el) {
73      if (lazy) {
74        return
75      }
76      if (trim && el.value.trim() === value) {
77        return
78      }
79      if ((number || el.type === 'number') && toNumber(el.value) === value) {
80        return
81      }
82    }
83    const newValue = value == null ? '' : value
84    if (el.value !== newValue) {
85      el.value = newValue
86    }
87  }
88}
89export const vModelCheckbox = {
90  // #4096 array checkboxes need to be deep traversed
91  deep: true,
92  created (el, _, vnode) {
93    el._assign = getModelAssigner(vnode)
94    addEventListener(el, 'change', () => {
95      const modelValue = el._modelValue
96      const elementValue = getValue(el)
97      const checked = el.checked
98      const assign = el._assign
99      if (isArray(modelValue)) {
100        const index = looseIndexOf(modelValue, elementValue)
101        const found = index !== -1
102        if (checked && !found) {
103          assign(modelValue.concat(elementValue))
104        } else if (!checked && found) {
105          const filtered = [...modelValue]
106          filtered.splice(index, 1)
107          assign(filtered)
108        }
109      } else if (isSet(modelValue)) {
110        const cloned = new Set(modelValue)
111        if (checked) {
112          cloned.add(elementValue)
113        } else {
114          cloned.delete(elementValue)
115        }
116        assign(cloned)
117      } else {
118        assign(getCheckboxValue(el, checked))
119      }
120    })
121  },
122  // set initial checked on mount to wait for true-value/false-value
123  mounted: setChecked,
124  beforeUpdate (el, binding, vnode) {
125    el._assign = getModelAssigner(vnode)
126    setChecked(el, binding, vnode)
127  }
128}
129
130function setChecked (el, { value, oldValue }, vnode) {
131  el._modelValue = value
132  if (isArray(value)) {
133    el.checked = looseIndexOf(value, vnode.props.value) > -1
134  } else if (isSet(value)) {
135    el.checked = value.has(vnode.props.value)
136  } else if (value !== oldValue) {
137    el.checked = looseEqual(value, getCheckboxValue(el, true))
138  }
139}
140
141export const vModelRadio = {
142  created (el, { value }, vnode) {
143    el.checked = looseEqual(value, vnode.props.value)
144    el._assign = getModelAssigner(vnode)
145    addEventListener(el, 'change', () => {
146      el._assign(getValue(el))
147    })
148  },
149  beforeUpdate (el, { value, oldValue }, vnode) {
150    el._assign = getModelAssigner(vnode)
151    if (value !== oldValue) {
152      el.checked = looseEqual(value, vnode.props.value)
153    }
154  }
155}
156
157export const vModelSelect = {
158  // <select multiple> value need to be deep traversed
159  deep: true,
160  created (el, { value, modifiers: { number } }, vnode) {
161    const isSetModel = isSet(value)
162    addEventListener(el, 'change', () => {
163      const selectedVal = Array.prototype.filter
164        .call(el.options, o => o.selected)
165        .map(o => (number ? toNumber(getValue(o)) : getValue(o)))
166      el._assign(
167        el.multiple
168          ? isSetModel
169            ? new Set(selectedVal)
170            : selectedVal
171          : selectedVal[0]
172      )
173    })
174    el._assign = getModelAssigner(vnode)
175  },
176  // set value in mounted & updated because <select> relies on its children
177  // <option>s.
178  mounted (el, { value }) {
179    setSelected(el, value)
180  },
181  beforeUpdate (el, _binding, vnode) {
182    el._assign = getModelAssigner(vnode)
183  },
184  updated (el, { value }) {
185    setSelected(el, value)
186  }
187}
188
189function setSelected (el, value) {
190  const isMultiple = el.multiple
191  for (let i = 0, l = el.options.length; i < l; i++) {
192    const option = el.options[i]
193    const optionValue = getValue(option)
194    if (isMultiple) {
195      if (isArray(value)) {
196        option.selected = looseIndexOf(value, optionValue) > -1
197      } else {
198        option.selected = value.has(optionValue)
199      }
200    } else {
201      if (looseEqual(getValue(option), value)) {
202        if (el.selectedIndex !== i) el.selectedIndex = i
203        return
204      }
205    }
206  }
207  if (!isMultiple && el.selectedIndex !== -1) {
208    el.selectedIndex = -1
209  }
210}
211// retrieve raw value set via :value bindings
212function getValue (el) {
213  return '_value' in el ? el._value : el.value
214}
215// retrieve raw value for true-value and false-value set via :true-value or :false-value bindings
216function getCheckboxValue (el, checked) {
217  const key = checked ? '_trueValue' : '_falseValue'
218  return key in el ? el[key] : checked
219}
220
221export const vModelDynamic = {
222  created (el, binding, vnode) {
223    callModelHook(el, binding, vnode, null, 'created')
224  },
225  mounted (el, binding, vnode) {
226    callModelHook(el, binding, vnode, null, 'mounted')
227  },
228  beforeUpdate (el, binding, vnode, prevVNode) {
229    callModelHook(el, binding, vnode, prevVNode, 'beforeUpdate')
230  },
231  updated (el, binding, vnode, prevVNode) {
232    callModelHook(el, binding, vnode, prevVNode, 'updated')
233  }
234}
235
236function callModelHook (el, binding, vnode, prevVNode, hook) {
237  let modelToUse
238  switch (el.tagName) {
239    case 'SELECT':
240      modelToUse = vModelSelect
241      break
242    case 'TEXTAREA':
243      modelToUse = vModelText
244      break
245    default:
246      switch (vnode.props && vnode.props.type) {
247        case 'checkbox':
248          modelToUse = vModelCheckbox
249          break
250        case 'radio':
251          modelToUse = vModelRadio
252          break
253        default:
254          modelToUse = vModelText
255      }
256  }
257  const fn = modelToUse[hook]
258  fn && fn(el, binding, vnode, prevVNode)
259}
260
Full Screen

runtime-dom.cjs.prod.js

Source: runtime-dom.cjs.prod.js Github

copy
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var runtimeCore = require('@vue/runtime-core');
6require('@vue/compiler-dom');
7
8const doc = document;
9const svgNS = 'http://www.w3.org/2000/svg';
10const nodeOps = {
11    insert: (child, parent, anchor) => {
12        if (anchor != null) {
13            parent.insertBefore(child, anchor);
14        }
15        else {
16            parent.appendChild(child);
17        }
18    },
19    remove: (child) => {
20        const parent = child.parentNode;
21        if (parent != null) {
22            parent.removeChild(child);
23        }
24    },
25    createElement: (tag, isSVG) => isSVG ? doc.createElementNS(svgNS, tag) : doc.createElement(tag),
26    createText: (text) => doc.createTextNode(text),
27    createComment: (text) => doc.createComment(text),
28    setText: (node, text) => {
29        node.nodeValue = text;
30    },
31    setElementText: (el, text) => {
32        el.textContent = text;
33    },
34    parentNode: (node) => node.parentNode,
35    nextSibling: (node) => node.nextSibling,
36    querySelector: (selector) => doc.querySelector(selector)
37};
38
39// compiler should normalize class + :class bindings on the same element
40// into a single binding ['staticClass', dynamic]
41function patchClass(el, value, isSVG) {
42    // directly setting className should be faster than setAttribute in theory
43    if (isSVG) {
44        el.setAttribute('class', value);
45    }
46    else {
47        el.className = value;
48    }
49}
50
51const EMPTY_OBJ =  {};
52const isOn = (key) => key[0] === 'o' && key[1] === 'n';
53const isArray = Array.isArray;
54const isString = (val) => typeof val === 'string';
55const isObject = (val) => val !== null && typeof val === 'object';
56
57function patchStyle(el, prev, next) {
58    const style = el.style;
59    if (!next) {
60        el.removeAttribute('style');
61    }
62    else if (isString(next)) {
63        style.cssText = next;
64    }
65    else {
66        for (const key in next) {
67            style[key] = next[key];
68        }
69        if (prev && !isString(prev)) {
70            for (const key in prev) {
71                if (!next[key]) {
72                    style[key] = '';
73                }
74            }
75        }
76    }
77}
78
79function patchAttr(el, key, value) {
80    if (value == null) {
81        el.removeAttribute(key);
82    }
83    else {
84        el.setAttribute(key, value);
85    }
86}
87
88function patchDOMProp(el, key, value, 
89// the following args are passed only due to potential innerHTML/textContent
90// overriding existing VNodes, in which case the old tree must be properly
91// unmounted.
92prevChildren, parentComponent, parentSuspense, unmountChildren) {
93    if ((key === 'innerHTML' || key === 'textContent') && prevChildren != null) {
94        unmountChildren(prevChildren, parentComponent, parentSuspense);
95    }
96    if (key === 'value' && el.tagName !== 'PROGRESS') {
97        // store value as _value as well since
98        // non-string values will be stringified.
99        el._value = value;
100    }
101    if (value === '' && typeof el[key] === 'boolean') {
102        // e.g. <select multiple> compiles to { multiple: '' }
103        el[key] = true;
104    }
105    else {
106        el[key] = value == null ? '' : value;
107    }
108}
109
110// Async edge case fix requires storing an event listener's attach timestamp.
111let _getNow = Date.now;
112// Determine what event timestamp the browser is using. Annoyingly, the
113// timestamp can either be hi-res ( relative to page load) or low-res
114// (relative to UNIX epoch), so in order to compare time we have to use the
115// same timestamp type when saving the flush timestamp.
116if (typeof document !== 'undefined' &&
117    _getNow() > document.createEvent('Event').timeStamp) {
118    // if the low-res timestamp which is bigger than the event timestamp
119    // (which is evaluated AFTER) it means the event is using a hi-res timestamp,
120    // and we need to use the hi-res version for event listeners as well.
121    _getNow = () => performance.now();
122}
123// To avoid the overhead of repeatedly calling performance.now(), we cache
124// and use the same timestamp for all event listeners attached in the same tick.
125let cachedNow = 0;
126const p = Promise.resolve();
127const reset = () => {
128    cachedNow = 0;
129};
130const getNow = () => cachedNow || (p.then(reset), (cachedNow = _getNow()));
131function addEventListener(el, event, handler, options) {
132    el.addEventListener(event, handler, options);
133}
134function removeEventListener(el, event, handler, options) {
135    el.removeEventListener(event, handler, options);
136}
137function patchEvent(el, name, prevValue, nextValue, instance = null) {
138    const prevOptions = prevValue && 'options' in prevValue && prevValue.options;
139    const nextOptions = nextValue && 'options' in nextValue && nextValue.options;
140    const invoker = prevValue && prevValue.invoker;
141    const value = nextValue && 'handler' in nextValue ? nextValue.handler : nextValue;
142    if (prevOptions || nextOptions) {
143        const prev = prevOptions || EMPTY_OBJ;
144        const next = nextOptions || EMPTY_OBJ;
145        if (prev.capture !== next.capture ||
146            prev.passive !== next.passive ||
147            prev.once !== next.once) {
148            if (invoker) {
149                removeEventListener(el, name, invoker, prev);
150            }
151            if (nextValue && value) {
152                const invoker = createInvoker(value, instance);
153                nextValue.invoker = invoker;
154                addEventListener(el, name, invoker, next);
155            }
156            return;
157        }
158    }
159    if (nextValue && value) {
160        if (invoker) {
161            prevValue.invoker = null;
162            invoker.value = value;
163            nextValue.invoker = invoker;
164            invoker.lastUpdated = getNow();
165        }
166        else {
167            addEventListener(el, name, createInvoker(value, instance), nextOptions || void 0);
168        }
169    }
170    else if (invoker) {
171        removeEventListener(el, name, invoker, prevOptions || void 0);
172    }
173}
174function createInvoker(initialValue, instance) {
175    const invoker = (e) => {
176        // async edge case #6566: inner click event triggers patch, event handler
177        // attached to outer element during patch, and triggered again. This
178        // happens because browsers fire microtask ticks between event propagation.
179        // the solution is simple: we save the timestamp when a handler is attached,
180        // and the handler would only fire if the event passed to it was fired
181        // AFTER it was attached.
182        if (e.timeStamp >= invoker.lastUpdated - 1) {
183            runtimeCore.callWithAsyncErrorHandling(invoker.value, instance, 5 /* NATIVE_EVENT_HANDLER */, [e]);
184        }
185    };
186    invoker.value = initialValue;
187    initialValue.invoker = invoker;
188    invoker.lastUpdated = getNow();
189    return invoker;
190}
191
192function patchProp(el, key, nextValue, prevValue, isSVG, prevChildren, parentComponent, parentSuspense, unmountChildren) {
193    switch (key) {
194        // special
195        case 'class':
196            patchClass(el, nextValue, isSVG);
197            break;
198        case 'style':
199            patchStyle(el, prevValue, nextValue);
200            break;
201        case 'modelValue':
202        case 'onUpdate:modelValue':
203            // Do nothing. This is handled by v-model directives.
204            break;
205        default:
206            if (isOn(key)) {
207                patchEvent(el, key.slice(2).toLowerCase(), prevValue, nextValue, parentComponent);
208            }
209            else if (!isSVG && key in el) {
210                patchDOMProp(el, key, nextValue, prevChildren, parentComponent, parentSuspense, unmountChildren);
211            }
212            else {
213                patchAttr(el, key, nextValue);
214            }
215            break;
216    }
217}
218
219const getModelAssigner = (vnode) => vnode.props['onUpdate:modelValue'];
220function onCompositionStart(e) {
221    e.target.composing = true;
222}
223function onCompositionEnd(e) {
224    const target = e.target;
225    if (target.composing) {
226        target.composing = false;
227        trigger(target, 'input');
228    }
229}
230function trigger(el, type) {
231    const e = document.createEvent('HTMLEvents');
232    e.initEvent(type, true, true);
233    el.dispatchEvent(e);
234}
235function toNumber(val) {
236    const n = parseFloat(val);
237    return isNaN(n) ? val : n;
238}
239// We are exporting the v-model runtime directly as vnode hooks so that it can
240// be tree-shaken in case v-model is never used.
241const vModelText = {
242    beforeMount(el, { value, modifiers: { lazy, trim, number } }, vnode) {
243        el.value = value;
244        const assign = getModelAssigner(vnode);
245        const castToNumber = number || el.type === 'number';
246        addEventListener(el, lazy ? 'change' : 'input', () => {
247            let domValue = el.value;
248            if (trim) {
249                domValue = domValue.trim();
250            }
251            else if (castToNumber) {
252                domValue = toNumber(domValue);
253            }
254            assign(domValue);
255        });
256        if (trim) {
257            addEventListener(el, 'change', () => {
258                el.value = el.value.trim();
259            });
260        }
261        if (!lazy) {
262            addEventListener(el, 'compositionstart', onCompositionStart);
263            addEventListener(el, 'compositionend', onCompositionEnd);
264            // Safari < 10.2 & UIWebView doesn't fire compositionend when
265            // switching focus before confirming composition choice
266            // this also fixes the issue where some browsers e.g. iOS Chrome
267            // fires "change" instead of "input" on autocomplete.
268            addEventListener(el, 'change', onCompositionEnd);
269        }
270    },
271    beforeUpdate(el, { value, modifiers: { trim, number } }) {
272        if (document.activeElement === el) {
273            if (trim && el.value.trim() === value) {
274                return;
275            }
276            if ((number || el.type === 'number') && toNumber(el.value) === value) {
277                return;
278            }
279        }
280        el.value = value;
281    }
282};
283const vModelCheckbox = {
284    beforeMount(el, binding, vnode) {
285        setChecked(el, binding, vnode);
286        const assign = getModelAssigner(vnode);
287        addEventListener(el, 'change', () => {
288            const modelValue = el._modelValue;
289            const elementValue = getValue(el);
290            const checked = el.checked;
291            if (isArray(modelValue)) {
292                const index = looseIndexOf(modelValue, elementValue);
293                const found = index !== -1;
294                if (checked && !found) {
295                    assign(modelValue.concat(elementValue));
296                }
297                else if (!checked && found) {
298                    const filtered = [...modelValue];
299                    filtered.splice(index, 1);
300                    assign(filtered);
301                }
302            }
303            else {
304                assign(checked);
305            }
306        });
307    },
308    beforeUpdate: setChecked
309};
310function setChecked(el, { value }, vnode) {
311    el._modelValue = value;
312    el.checked = isArray(value)
313        ? looseIndexOf(value, vnode.props.value) > -1
314        : !!value;
315}
316const vModelRadio = {
317    beforeMount(el, { value }, vnode) {
318        el.checked = looseEqual(value, vnode.props.value);
319        const assign = getModelAssigner(vnode);
320        addEventListener(el, 'change', () => {
321            assign(getValue(el));
322        });
323    },
324    beforeUpdate(el, { value }, vnode) {
325        el.checked = looseEqual(value, vnode.props.value);
326    }
327};
328const vModelSelect = {
329    // use mounted & updated because <select> relies on its children <option>s.
330    mounted(el, { value }, vnode) {
331        setSelected(el, value);
332        const assign = getModelAssigner(vnode);
333        addEventListener(el, 'change', () => {
334            const selectedVal = Array.prototype.filter
335                .call(el.options, (o) => o.selected)
336                .map(getValue);
337            assign(el.multiple ? selectedVal : selectedVal[0]);
338        });
339    },
340    updated(el, { value }) {
341        setSelected(el, value);
342    }
343};
344function setSelected(el, value) {
345    const isMultiple = el.multiple;
346    if (isMultiple && !isArray(value)) {
347        return;
348    }
349    for (let i = 0, l = el.options.length; i < l; i++) {
350        const option = el.options[i];
351        const optionValue = getValue(option);
352        if (isMultiple) {
353            option.selected = looseIndexOf(value, optionValue) > -1;
354        }
355        else {
356            if (looseEqual(getValue(option), value)) {
357                el.selectedIndex = i;
358                return;
359            }
360        }
361    }
362    if (!isMultiple) {
363        el.selectedIndex = -1;
364    }
365}
366function looseEqual(a, b) {
367    if (a === b)
368        return true;
369    const isObjectA = isObject(a);
370    const isObjectB = isObject(b);
371    if (isObjectA && isObjectB) {
372        try {
373            const isArrayA = isArray(a);
374            const isArrayB = isArray(b);
375            if (isArrayA && isArrayB) {
376                return (a.length === b.length &&
377                    a.every((e, i) => looseEqual(e, b[i])));
378            }
379            else if (a instanceof Date && b instanceof Date) {
380                return a.getTime() === b.getTime();
381            }
382            else if (!isArrayA && !isArrayB) {
383                const keysA = Object.keys(a);
384                const keysB = Object.keys(b);
385                return (keysA.length === keysB.length &&
386                    keysA.every(key => looseEqual(a[key], b[key])));
387            }
388            else {
389                /* istanbul ignore next */
390                return false;
391            }
392        }
393        catch (e) {
394            /* istanbul ignore next */
395            return false;
396        }
397    }
398    else if (!isObjectA && !isObjectB) {
399        return String(a) === String(b);
400    }
401    else {
402        return false;
403    }
404}
405function looseIndexOf(arr, val) {
406    return arr.findIndex(item => looseEqual(item, val));
407}
408// retrieve raw value set via :value bindings
409function getValue(el) {
410    return '_value' in el ? el._value : el.value;
411}
412const vModelDynamic = {
413    beforeMount(el, binding, vnode) {
414        callModelHook(el, binding, vnode, null, 'beforeMount');
415    },
416    mounted(el, binding, vnode) {
417        callModelHook(el, binding, vnode, null, 'mounted');
418    },
419    beforeUpdate(el, binding, vnode, prevVNode) {
420        callModelHook(el, binding, vnode, prevVNode, 'beforeUpdate');
421    },
422    updated(el, binding, vnode, prevVNode) {
423        callModelHook(el, binding, vnode, prevVNode, 'updated');
424    }
425};
426function callModelHook(el, binding, vnode, prevVNode, hook) {
427    let modelToUse;
428    switch (el.tagName) {
429        case 'SELECT':
430            modelToUse = vModelSelect;
431            break;
432        case 'TEXTAREA':
433            modelToUse = vModelText;
434            break;
435        default:
436            switch (el.type) {
437                case 'checkbox':
438                    modelToUse = vModelCheckbox;
439                    break;
440                case 'radio':
441                    modelToUse = vModelRadio;
442                    break;
443                default:
444                    modelToUse = vModelText;
445            }
446    }
447    const fn = modelToUse[hook];
448    fn && fn(el, binding, vnode, prevVNode);
449}
450
451const systemModifiers = ['ctrl', 'shift', 'alt', 'meta'];
452const modifierGuards = {
453    stop: e => e.stopPropagation(),
454    prevent: e => e.preventDefault(),
455    self: e => e.target !== e.currentTarget,
456    ctrl: e => !e.ctrlKey,
457    shift: e => !e.shiftKey,
458    alt: e => !e.altKey,
459    meta: e => !e.metaKey,
460    left: e => 'button' in e && e.button !== 0,
461    middle: e => 'button' in e && e.button !== 1,
462    right: e => 'button' in e && e.button !== 2,
463    exact: (e, modifiers) => systemModifiers.some(m => e[`${m}Key`] && !modifiers.includes(m))
464};
465const withModifiers = (fn, modifiers) => {
466    return (event) => {
467        for (let i = 0; i < modifiers.length; i++) {
468            const guard = modifierGuards[modifiers[i]];
469            if (guard && guard(event, modifiers))
470                return;
471        }
472        return fn(event);
473    };
474};
475// Kept for 2.x compat.
476// Note: IE11 compat for `spacebar` and `del` is removed for now.
477const keyNames = {
478    esc: 'escape',
479    space: ' ',
480    up: 'arrowup',
481    left: 'arrowleft',
482    right: 'arrowright',
483    down: 'arrowdown',
484    delete: 'backspace'
485};
486const withKeys = (fn, modifiers) => {
487    return (event) => {
488        if (!('key' in event))
489            return;
490        const eventKey = event.key.toLowerCase();
491        if (
492        // None of the provided key modifiers match the current event key
493        !modifiers.some(k => k === eventKey || keyNames[k] === eventKey)) {
494            return;
495        }
496        return fn(event);
497    };
498};
499
500const { render, createApp } = runtimeCore.createRenderer({
501    patchProp,
502    ...nodeOps
503});
504const exportedCreateApp =  createApp;
505
506Object.keys(runtimeCore).forEach(function (k) {
507  if (k !== 'default') Object.defineProperty(exports, k, {
508    enumerable: true,
509    get: function () {
510      return runtimeCore[k];
511    }
512  });
513});
514exports.createApp = exportedCreateApp;
515exports.render = render;
516exports.vModelCheckbox = vModelCheckbox;
517exports.vModelDynamic = vModelDynamic;
518exports.vModelRadio = vModelRadio;
519exports.vModelSelect = vModelSelect;
520exports.vModelText = vModelText;
521exports.withKeys = withKeys;
522exports.withModifiers = withModifiers;
523
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Internal on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)