Skip to content

Commit 1b6ef4b

Browse files
committed
Merge branch 'docs/migrationGuide' into v11
* docs/migrationGuide: Tweak a section heading. Mention the two additional deprecations on the release and migration pages Fix typos Add a separate releases page with an entry for 11.0.0 Stop generating a menu entry for the migration page Show the expect.it() function argument syntax. Add a function by value example. Convert all assertion references to links. Fix rendering the hyphen. Correct misspellings. Reorder the sections within the migration guide. Clarify the functions by value section. Swap "Use of" to "Using" to differentiate the intent. Tighten the examples and emphasise expect.it(). Minor copy edits to tighten the language. Add an initial migration guide.
2 parents 680d939 + 0eaf94d commit 1b6ef4b

File tree

3 files changed

+356
-100
lines changed

3 files changed

+356
-100
lines changed

documentation/index.md

Lines changed: 1 addition & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -141,106 +141,7 @@ The source for Unexpected can be found on
141141

142142
## Releases
143143

144-
See [changelog](https://github.com/unexpectedjs/unexpected/blob/master/CHANGELOG.md) for more details.
145-
146-
### 10.0.0
147-
148-
* Assertions are now declared with explicit type requirements for
149-
the arguments as part of the pattern. This is a breaking change
150-
that removes support for the old `addAssertion` syntax where the
151-
subject type(s) were passed as the first argument.
152-
See [addAssertion](./api/addAssertion/) for more
153-
information.
154-
* The `to be >`, `to be >=`, `to be <`, and `to be <=` assertions
155-
have been removed as they clashed with the new type syntax.
156-
Please use the fully spelled-out variants: `to be greater than`,
157-
`to be less than or equal to`, etc.
158-
* The `[not] to begin with`, `[not] to end with`, and
159-
`[not] to contain` assertions now require strings as the needle(s).
160-
Previously they supported any type, which would then be stringified.
161-
* Inside an assertion you can now access the `errorMode`, `shift`,
162-
`flags`, `alternations` properties etc. via the `expect` passed
163-
to the assertion. They can still be accessed via `this` as
164-
previously, but that is deprecated. (This change actually
165-
debuted in 9.12.0).
166-
* The `when passed as parameter(s) to`, `when called with`,
167-
`when decoded as` assertions can now be used standalone, ie. without delegating
168-
the result to another assertion in the same `expect` call.
169-
In that case they will provide the result as the fulfillment
170-
value of the promise.
171-
172-
### 9.0.0
173-
174-
* Build all error messages lazily. This is an internal refactoring
175-
that makes it possible to generate very different output in the
176-
text, Ansi, and HTML modes using the magicpen
177-
[raw](https://github.com/sunesimonsen/magicpen#raw) feature. This
178-
change mostly affects plugins, and we have updated all the official
179-
plugins accordingly, so please upgrade those to the latest version
180-
when you upgrade to Unexpected 9.
181-
* Made it possible to tweak the default error message when creating
182-
assertions. See [addAssertion](./api/addAssertion/) for more
183-
information.
184-
* Expanded the `to have message` assertion defined for `Error`
185-
instances to allow matching a serialization other than plain text:
186-
`to have ansi message`, `to have html message`.
187-
* The `to contain` assertion defined for strings: When the assertion fails,
188-
display a "diff" where partial matches are highlighted.
189-
190-
### 8.0.0
191-
192-
* All errors originating from assertions are now instances of
193-
[`UnexpectedError`](./api/UnexpectedError/), which can be manipulated before being
194-
serialized.
195-
* Error messages and diffs are now built lazily, improving
196-
performance.
197-
* Unexpected now detects created promises that were never returned and
198-
fails synchronously. This will uncover some extremely nasty bugs
199-
where the test suite succeeds when it should actually fail. This
200-
feature only works in [Mocha](https://mochajs.org/) and [Jasmine](https://jasmine.github.io/).
201-
* Deprecated error.output, please use error.getErrorMessage() instead.
202-
* Deprecated error.label, please use error.getLabel() instead.
203-
* `when decoded as`, `when called with`, `when passed as parameter to`, `when passed as parameters to`: Require the 4th argument to be
204-
a string specifying an assertion. Previously a function was also
205-
allowed, which turned out to be error prone. This also affects all
206-
plugins that use the internal function `Assertion.prototype.shift`
207-
to delegate to other assertions.
208-
* Nested error mode: Don't repeat the subject when it takes up
209-
multiple lines and is identical to the parent subject.
210-
* Added a new `bubbleThrough` error mode that will make the error
211-
bubble all the way to the top, mainly useful internally.
212-
* Added [`to error`](./assertions/function/to-error/) assertion.
213-
* Minor bugfixes and output tweaks.
214-
215-
### 7.0.0
216-
217-
* Support for
218-
[asynchronous assertions using promises](./api/addAssertion/#asynchronous-assertions).
219-
All built-in assertions that delegate to other assertions (such as `to satisfy`)
220-
have been rewritten to support this. The change is fully backwards compatible.
221-
* Removed support for the `to be an array of` and
222-
`to be an array of (strings|numbers|...)` assertions. There are better and
223-
more flexible alternatives.
224-
* Renamed assertions so that the subject type isn't mentioned in the assertion name.
225-
The old names are kept around as aliases for now. These assertions are affected:
226-
* `to be an array whose items satisfy` => `to have items satisfying`
227-
* `to be an (object|hash|map) whose keys satisfy` => `to have keys satisfying`
228-
* `to be an (object|hash|map) whose values satisfy` => `to have values satisfying`
229-
Also, these 3 assertions no longer pass for empty collections.
230-
* New `when passed as parameter to constructor` and `when passed as parameter to async` "adverbial" assertions.
231-
* New `when decoded as` "adverbial" assertion for `Buffer` instances.
232-
* New `to have message` assertion defined for `Error` instances.
233-
* A lot of output improvements and minor tweaks.
234-
235-
### 6.0.0
236-
237-
* New documentation and [corresponding site](https://unexpected.js.org/).
238-
* Use `Object.is`/the [SameValue algorithm](http://ecma-international.org/ecma-262/5.1/#sec-9.12) when checking equality of primitive values (the `to be` and `to equal` assertions).
239-
* Tweaked the output of numerous assertions.
240-
* Constrained `to be empty` and `to have length` to only work with strings and array-like objects.
241-
* Renamed the `arrayLike` type to `array-like`.
242-
* Changed style names and added theming support (mostly internal).
243-
* Removed grammatically incorrect assertions.
144+
See [the releases page](releases/).
244145

245146
## Configure the error output
246147

documentation/migration.md

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
---
2+
title: Migration
3+
template: default.ejs
4+
menuPage: false
5+
theme: light
6+
repository: https://github.com/unexpectedjs/unexpected
7+
---
8+
9+
# Migration
10+
11+
Unexpected has from its inception taken backwards compatibility very
12+
seriously. We think this is particularly important for a library
13+
intended for use in testing &ndash; we recognise that comprehensive test
14+
suites are often a large investment and play a central role in ongoing
15+
development of software. This sets a very high bar for any changes.
16+
17+
The project strictly adheres to semver. As such anything that carries
18+
a risk of breakage is carefully considered, must demonstrate significant
19+
benefit to be chosen for inclusion and would mean a new major version.
20+
21+
## Major revisions
22+
23+
### Migration to Unexpected 11
24+
25+
Version 11 is the first major release that makes some carefully
26+
calculated changes in the user facing API which may require test
27+
changes. We have made every effort to minimise the effects on end
28+
users and this extends to the plugin ecosystem which has seen the
29+
most commonly used being made compatible.
30+
31+
The changes are all focused on simplifying the mental model for users.
32+
A handful of constructs which proved themselves to be sources of
33+
confusion and to the best of our knowledge have not seen wide use
34+
have been replaced with **existing** alternatives. This means a safe
35+
upgrade path is available: tests can be updated against the current
36+
version of the library and the changes are forwards compatible.
37+
38+
#### Raise minimum node version to 6+
39+
40+
In our work to continue moving forward we have upgraded many of our
41+
dependencies. Many of these tools have themselves dropped node 4
42+
support and we have decided to do the same. This does not affect our
43+
browser compatibility which remains at the ES5 level and IE11.
44+
45+
#### Using extensions via the API requires calling .clone()
46+
47+
Previously once imported the entirety of the Unexpected API was
48+
immediately available to users which could lead to surprising
49+
results if types or assertions were added to it directly.
50+
51+
In version 11 the top-level of the library has been frozen and
52+
extending the functionality requires an expilcit `.clone()` call
53+
to be made:
54+
55+
```js#evaluate:false
56+
const unexpected = require('unexpected');
57+
58+
const expect = unexpected.clone();
59+
60+
expect.addAssertion(...);
61+
```
62+
63+
#### Use `expect.it()` for assertions on property values
64+
65+
Previously when used in conjunction with [to satisfy](../assertions/any/to-satisfy/)
66+
a property
67+
defined as a function on the right-hand side would be passed the
68+
value to allow further assertions:
69+
70+
```js#evaluate:false
71+
const obj = {
72+
version: 11,
73+
greeting: 'hello new major'
74+
};
75+
76+
expect(obj, 'to satisfy', {
77+
year: 2018,
78+
greeting: function(theValue) {
79+
expect(theValue, 'to start with', 'hello');
80+
}
81+
});
82+
```
83+
84+
> Note: this is no longer supported by Unexpected v11
85+
86+
For cases where the value of a property must conform to a more
87+
rigorous set of constraints, we replaced the earlier syntax with
88+
the `expect.it()`:
89+
90+
```js
91+
const obj = {
92+
version: 11,
93+
greeting: 'hello new major'
94+
};
95+
96+
expect(obj, 'to satisfy', {
97+
version: 11,
98+
greeting: expect.it(function(theValue) {
99+
expect(theValue, 'to start with', 'hello');
100+
})
101+
});
102+
```
103+
104+
We believe this is also much more versatile because of the powerful
105+
chaining support provided by `expect.it()`:
106+
107+
```js
108+
expect(obj, 'to satisfy', {
109+
version: 11,
110+
greeting: expect
111+
.it('to be a string')
112+
.and('to end with', 'major')
113+
.and(theValue => expect(theValue.split(' '), 'to have length', 3))
114+
});
115+
```
116+
117+
#### Functions are always compared by value
118+
119+
Building upon the `expect.it()` changes, all function comparisons
120+
will now be made using the identity of the function. This is unlike
121+
previous versions where they were treated specially and could lead
122+
to surprising results:
123+
124+
```js
125+
function createErrorIfRequired(message) {
126+
if (typeof message !== 'string') {
127+
return null;
128+
}
129+
return new Error(message);
130+
}
131+
132+
function somethingThatThrows() {
133+
throw new createErrorIfRequired('failure');
134+
}
135+
```
136+
137+
```js#evaluate:false
138+
expect(somethingThatThrows, 'to throw error', createErrorIfRequired);
139+
```
140+
141+
> Note: this is no longer supported by Unexpected v11
142+
143+
The code above is intended to check the error type, but passing a
144+
function directly on the right-hand side would cause it to succeed.
145+
In version 11 it immediately leads to an error and the assertion
146+
must be written more explicitly allowing the issue to be caught:
147+
148+
```js
149+
expect(
150+
somethingThatThrows,
151+
'to throw error',
152+
expect.it('to equal', createErrorIfRequired('failure'))
153+
);
154+
```
155+
156+
When interacting with object types this affects:
157+
158+
- [to satisfy](../assertions/any/to-satisfy/)
159+
- [to have keys satisfying](../assertions/object/to-have-keys-satisfying/)
160+
- [to have a value satisfying](../assertions/object/to-have-a-value-satisfying/)
161+
- [to have values satisfying](../assertions/object/to-have-values-satisfying/)
162+
163+
```js
164+
function myCallback() {}
165+
166+
const options = {
167+
data: null,
168+
callback: myCallback
169+
};
170+
171+
expect(options, 'to satisfy', {
172+
callback: myCallback
173+
});
174+
175+
expect(options, 'to have a value satisfying', myCallback);
176+
```
177+
178+
With array-like types it affects:
179+
180+
- [to satisfy](../assertions/any/to-satisfy/)
181+
- [to have an item satisfying](../assertions/array-like/to-have-an-item-satisfying/)
182+
- [to have items satisfying](../assertions/array-like/to-have-items-satisfying/)
183+
184+
```js
185+
const args = [myCallback];
186+
187+
expect(args, 'to have an item satisfying', myCallback);
188+
```
189+
190+
#### Support for `expect.async` has been removed
191+
192+
`expect.async` was a helper for asynchronous tests. It predates Unexpected's
193+
promise support and we expect that it's very unlikely to be used by anyone.
194+
195+
If you're using it, we recommend that you rewrite the given tests to a
196+
promise-driven flow as part of upgrading to Unexpected 11.
197+
198+
#### `this.errorMode` etc. no longer available in assertion handlers
199+
200+
This syntax has been deprecated since Unexpected 3:
201+
202+
```js#evaluate:false
203+
expect.addAssertion('<string> to be foo', (expect, subject) => {
204+
this.errorMode = 'nested';
205+
expect(subject, 'to equal', 'foo');
206+
});
207+
```
208+
209+
> Note: this is no longer supported by Unexpected v11
210+
211+
To fix code like this, access the property on `expect` instead:
212+
213+
```js
214+
expect.addAssertion('<string> to be foo', (expect, subject) => {
215+
expect.errorMode = 'nested';
216+
expect(subject, 'to equal', 'foo');
217+
});
218+
```

0 commit comments

Comments
 (0)