Skip to content

Commit 98b8e68

Browse files
committed
fix: prevent infinite loop with setProps with immediate watchers
* prevent `setProps` from being called on non-top level wrappers * remove useless `silent` option from config
1 parent d2add54 commit 98b8e68

File tree

19 files changed

+143
-202
lines changed

19 files changed

+143
-202
lines changed

Diff for: docs/api/config.md

+1-16
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ config.deprecationWarningHandler = (method, message) => {
4747
- type: `{ [name: string]: Component | boolean | string }`
4848
- default: `{}`
4949

50-
The stub stored in `config.stubs` is used by default.
50+
The stub stored in `config.stubs` is used by default.
5151
Stubs to use in components. These are overwritten by `stubs` passed in the mounting options.
5252

5353
When passing `stubs` as an array in the mounting options, `config.stubs` are converted to an array, and will stub components with a basic component that returns `<${component name}-stub>`.
@@ -112,18 +112,3 @@ config.provide['$logger'] = {
112112
}
113113
}
114114
```
115-
116-
### `silent`
117-
118-
- type: `Boolean`
119-
- default: `true`
120-
121-
It suppresses warnings triggered by Vue while mutating component's observables (e.g. props). When set to `false`, all warnings are visible in the console. This is a configurable way which relies on `Vue.config.silent`.
122-
123-
Example:
124-
125-
```js
126-
import { config } from '@vue/test-utils'
127-
128-
config.silent = false
129-
```

Diff for: docs/api/wrapper/setProps.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88

99
Sets `Wrapper` `vm` props and forces update.
1010

11-
**Note the Wrapper must contain a Vue instance.**
11+
::: warning
12+
`setProps` could be called only for top-level component, mounted by `mount` or `shallowMount`
13+
:::
1214

1315
```js
1416
import { mount } from '@vue/test-utils'

Diff for: docs/ja/api/config.md

-15
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,3 @@ config.provide['$logger'] = {
7373
}
7474
}
7575
```
76-
77-
### `silent`
78-
79-
- 型: `Boolean`
80-
- デフォルト: `true`
81-
82-
Vue がコンポーネントの変更を感知するプロパティ(例えば props )が変更される時に出す警告を出力しません。`false` をセットするとすべての警告はコンソールに表示されません。この機能は `Vue.config.silent` を使って実現しています。
83-
84-
例:
85-
86-
```js
87-
import { config } from '@vue/test-utils'
88-
89-
config.silent = false
90-
```

Diff for: docs/ru/api/config.md

-15
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,3 @@ config.provide['$logger'] = {
7474
}
7575
}
7676
```
77-
78-
### `silent`
79-
80-
- Тип: `Boolean`
81-
- По умолчанию: `true`
82-
83-
Подавляет предупреждения, вызванные Vue во время изменения наблюдаемых компонентов (например, входных параметров). Если установлено значение `false`, все предупреждения показываются в консоли. Это настраиваемый способ, который основывается на `Vue.config.silent`.
84-
85-
Пример:
86-
87-
```js
88-
import { config } from '@vue/test-utils'
89-
90-
config.silent = false
91-
```

Diff for: docs/ru/api/wrapper/setProps.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88

99
Устанавливает входные параметры `Wrapper` `vm` и выполняет принудительное обновление.
1010

11-
**Обратите внимание, что `Wrapper` должен содержать экземпляр Vue.**
11+
::: warning Обратите внимание!
12+
`setProps` может быть вызван только на `wrapper` верхнего уровня, который был создан с помощью `mount` или `shallowMount`
13+
:::
1214

1315
```js
1416
import { mount } from '@vue/test-utils'

Diff for: docs/zh/api/config.md

+1-16
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ config.showDeprecationWarnings = false
2424
- 类型:`{ [name: string]: Component | boolean | string }`
2525
- 默认值:`{}`
2626

27-
存储在 `config.stubs` 中的存根会被默认使用。
27+
存储在 `config.stubs` 中的存根会被默认使用。
2828
用到的组件存根。它们会被传入挂载选项的 `stubs` 覆写。
2929

3030
当把 `stubs` 作为一个数组传入挂载选项时,`config.stubs` 会被转换为一个数组,然后用只返回一个 `<${component name}-stub>` 的基础组件进行存根。
@@ -89,18 +89,3 @@ config.provide['$logger'] = {
8989
}
9090
}
9191
```
92-
93-
### `silent`
94-
95-
- 类型:`Boolean`
96-
- 默认值:`true`
97-
98-
在组件的可观察内容 (如 props) 发生突变时,警告会被 Vue 阻止。当设置为 `false` 时,所有的警告都会出现在控制台中。这是一个 `Vue.config.silent` 的配置方式。
99-
100-
示例;
101-
102-
```js
103-
import { config } from '@vue/test-utils'
104-
105-
config.silent = false
106-
```

Diff for: flow/config.flow.js

-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@ declare type Config = {
33
mocks?: Object,
44
methods?: { [name: string]: Function },
55
provide?: Object,
6-
silent?: boolean,
76
showDeprecationWarnings?: boolean
87
}

Diff for: packages/create-instance/create-instance.js

+14-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import createScopedSlots from './create-scoped-slots'
1111
import { createStubsFromStubsObject } from './create-component-stubs'
1212
import { patchCreateElement } from './patch-create-element'
1313

14-
function createContext(options, scopedSlots) {
14+
function createContext(options, scopedSlots, currentProps) {
1515
const on = {
1616
...(options.context && options.context.on),
1717
...options.listeners
@@ -20,8 +20,8 @@ function createContext(options, scopedSlots) {
2020
attrs: {
2121
...options.attrs,
2222
// pass as attrs so that inheritAttrs works correctly
23-
// propsData should take precedence over attrs
24-
...options.propsData
23+
// props should take precedence over attrs
24+
...currentProps
2525
},
2626
...(options.context || {}),
2727
on,
@@ -110,16 +110,26 @@ export default function createInstance(
110110
parentComponentOptions.provide = function() {
111111
return {
112112
...getValuesFromCallableOption.call(this, originalParentComponentProvide),
113+
// $FlowIgnore
113114
...getValuesFromCallableOption.call(this, options.provide)
114115
}
115116
}
116117

118+
const originalParentComponentData = parentComponentOptions.data
119+
parentComponentOptions.data = function() {
120+
return {
121+
...getValuesFromCallableOption.call(this, originalParentComponentData),
122+
vueTestUtils_childProps: { ...options.propsData }
123+
}
124+
}
125+
117126
parentComponentOptions.$_doNotStubChildren = true
127+
parentComponentOptions.$_isWrapperParent = true
118128
parentComponentOptions._isFunctionalContainer = componentOptions.functional
119129
parentComponentOptions.render = function(h) {
120130
return h(
121131
Constructor,
122-
createContext(options, scopedSlots),
132+
createContext(options, scopedSlots, this.vueTestUtils_childProps),
123133
createChildren(this, h, options)
124134
)
125135
}

Diff for: packages/server-test-utils/dist/vue-server-test-utils.js

+23-24
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
1313
var Vue__default = /*#__PURE__*/_interopDefaultLegacy(Vue);
1414
var cheerio__default = /*#__PURE__*/_interopDefaultLegacy(cheerio);
1515

16-
//
16+
//
1717

1818
function createVNodes(vm, slotValue, name) {
1919
var el = vueTemplateCompiler.compileToFunctions(
@@ -1698,7 +1698,7 @@ var CREATE_ELEMENT_ALIAS = semver.gt(Vue__default['default'].version, '2.1.5')
16981698
? '_c'
16991699
: '_h';
17001700

1701-
//
1701+
//
17021702

17031703
function findDOMNodes(
17041704
element,
@@ -1716,7 +1716,7 @@ function findDOMNodes(
17161716
return nodes.concat([].slice.call(element.querySelectorAll(selector)))
17171717
}
17181718

1719-
//
1719+
//
17201720

17211721
function isDomSelector(selector) {
17221722
if (typeof selector !== 'string') {
@@ -1956,7 +1956,7 @@ function matches(node, selector) {
19561956
return vmMatchesName(componentInstance, nameSelector)
19571957
}
19581958

1959-
//
1959+
//
19601960

19611961
function findAllInstances(rootVm) {
19621962
var instances = [rootVm];
@@ -2094,7 +2094,7 @@ function normalizeProvide(provide) {
20942094
return provide
20952095
}
20962096

2097-
//
2097+
//
20982098

20992099
function getOption(option, config) {
21002100
if (option === false) {
@@ -2149,7 +2149,6 @@ var config = {
21492149
mocks: {},
21502150
methods: {},
21512151
provide: {},
2152-
silent: true,
21532152
showDeprecationWarnings:
21542153
typeof process.env.SHOW_DEPRECATIONS !== 'undefined'
21552154
? process.env.SHOW_DEPRECATIONS
@@ -7541,7 +7540,7 @@ function ocd(str, options) {
75417540
.replace(/>(\s*)(?=<!--\s*\/)/g, '> ');
75427541
}
75437542

7544-
//
7543+
//
75457544

75467545
function getSelectorType(selector) {
75477546
if (isDomSelector(selector)) { return DOM_SELECTOR }
@@ -7569,7 +7568,7 @@ function getSelector(
75697568
}
75707569
}
75717570

7572-
//
7571+
//
75737572

75747573
var WrapperArray = function WrapperArray(wrappers) {
75757574
var length = wrappers.length;
@@ -7795,7 +7794,7 @@ WrapperArray.prototype.destroy = function destroy () {
77957794
this.wrappers.forEach(function (wrapper) { return wrapper.destroy(); });
77967795
};
77977796

7798-
//
7797+
//
77997798

78007799
var buildSelectorString = function (selector) {
78017800
if (getSelectorType(selector) === REF_SELECTOR) {
@@ -9439,7 +9438,7 @@ function createDOMEvent(type, options) {
94399438
return event
94409439
}
94419440

9442-
//
9441+
//
94439442

94449443
var Wrapper = function Wrapper(
94459444
node,
@@ -10321,7 +10320,7 @@ Wrapper.prototype.trigger = function trigger (type, options) {
1032110320
return nextTick()
1032210321
};
1032310322

10324-
//
10323+
//
1032510324

1032610325
var VueWrapper = /*@__PURE__*/(function (Wrapper) {
1032710326
function VueWrapper(vm, options) {
@@ -10360,7 +10359,7 @@ var VueWrapper = /*@__PURE__*/(function (Wrapper) {
1036010359
return VueWrapper;
1036110360
}(Wrapper));
1036210361

10363-
//
10362+
//
1036410363

1036510364
function createWrapper(
1036610365
node,
@@ -12862,7 +12861,7 @@ function cloneDeep(value) {
1286212861

1286312862
var cloneDeep_1 = cloneDeep;
1286412863

12865-
//
12864+
//
1286612865

1286712866
/**
1286812867
* Used internally by vue-server-test-utils and test-utils to propagate/create vue instances.
@@ -12931,7 +12930,7 @@ function _createLocalVue(
1293112930
return instance
1293212931
}
1293312932

12934-
//
12933+
//
1293512934

1293612935
function compileTemplate(component) {
1293712936
if (component.template) {
@@ -12986,7 +12985,7 @@ function compileTemplateForSlots(slots) {
1298612985
});
1298712986
}
1298812987

12989-
//
12988+
//
1299012989

1299112990
function isValidSlot(slot) {
1299212991
return isVueComponent(slot) || typeof slot === 'string'
@@ -13083,7 +13082,7 @@ function validateOptions(options, component) {
1308313082
Vue__default['default'].config.productionTip = false;
1308413083
Vue__default['default'].config.devtools = false;
1308513084

13086-
//
13085+
//
1308713086

1308813087
function throwError(msg) {
1308913088
throw new Error(("[vue-test-utils]: " + msg))
@@ -13192,7 +13191,7 @@ function warnDeprecated(method, fallback) {
1319213191
}
1319313192
}
1319413193

13195-
//
13194+
//
1319613195

1319713196
function addMocks(
1319813197
_Vue,
@@ -13219,7 +13218,7 @@ function addMocks(
1321913218
});
1322013219
}
1322113220

13222-
//
13221+
//
1322313222

1322413223
function logEvents(
1322513224
vm,
@@ -13256,7 +13255,7 @@ function addStubs(_Vue, stubComponents) {
1325613255
_Vue.mixin(( obj = {}, obj[BEFORE_RENDER_LIFECYCLE_HOOK] = addStubComponentsMixin, obj ));
1325713256
}
1325813257

13259-
//
13258+
//
1326013259

1326113260
var MOUNTING_OPTIONS = [
1326213261
'attachToDocument',
@@ -13280,7 +13279,7 @@ function extractInstanceOptions(options) {
1328013279
return instanceOptions
1328113280
}
1328213281

13283-
//
13282+
//
1328413283

1328513284
function isDestructuringSlotScope(slotScope) {
1328613285
return /^{.*}$/.test(slotScope)
@@ -13409,7 +13408,7 @@ function createScopedSlots(
1340913408
return scopedSlots
1341013409
}
1341113410

13412-
//
13411+
//
1341313412

1341413413
function isVueComponentStub(comp) {
1341513414
return (comp && comp.template) || isVueComponent(comp)
@@ -13725,7 +13724,7 @@ function patchCreateElement(_Vue, stubs, stubAllComponents) {
1372513724
_Vue.mixin(( obj = {}, obj[BEFORE_RENDER_LIFECYCLE_HOOK] = patchCreateElementMixin, obj ));
1372613725
}
1372713726

13728-
//
13727+
//
1372913728

1373013729
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
1373113730

@@ -13849,7 +13848,7 @@ function createInstance(
1384913848

1385013849
var config$1 = testUtils.config;
1385113850

13852-
//
13851+
//
1385313852

1385413853
Vue__default['default'].config.productionTip = false;
1385513854
Vue__default['default'].config.devtools = false;
@@ -13884,7 +13883,7 @@ function renderToString(
1388413883
return renderer.renderToString(vm)
1388513884
}
1388613885

13887-
//
13886+
//
1388813887

1388913888
function render(
1389013889
component,

Diff for: packages/server-test-utils/types/index.d.ts

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ interface VueTestUtilsConfigOptions {
4545
mocks?: object
4646
methods?: Record<string, Function>
4747
provide?: object,
48-
silent?: Boolean
4948
}
5049

5150
export declare let config: VueTestUtilsConfigOptions

Diff for: packages/server-test-utils/types/test/renderToString.ts

-1
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,3 @@ config.methods = {
6666
config.provide = {
6767
foo: {}
6868
}
69-
config.silent = true

0 commit comments

Comments
 (0)