nushell/crates/nu-command/tests/commands/url/parse.rs
Bahex 3182adb6a0
Url split query (#14211)
Addresses the following points from #14162

> - There is no built-in counterpart to url build-query for splitting a
query string

There is `from url`, which, due to naming, is a little hard to discover
and suffers from the following point

> - url parse can create records with duplicate keys
> - url parse's params should either:
>   - ~group the same keys into a list.~
> - instead of a record, be a key-value table. (table<key: string,
value: string>)

# Description

## `url split-query`

Counterpart to `url build-query`, splits a url encoded query string to
key value pairs, represented as `table<key: string, value: string>`

```
> "a=one&a=two&b=three" | url split-query
╭───┬─────┬───────╮
│ # │ key │ value │
├───┼─────┼───────┤
│ 0 │ a   │ one   │
│ 1 │ a   │ two   │
│ 2 │ b   │ three │
╰───┴─────┴───────╯
```

## `url parse`

The output's `param` field is now a table as well, mirroring the new
`url split-query`

```
> 'http://localhost?a=one&a=two&b=three' | url parse
╭──────────┬─────────────────────╮
│ scheme   │ http                │
│ username │                     │
│ password │                     │
│ host     │ localhost           │
│ port     │                     │
│ path     │ /                   │
│ query    │ a=one&a=two&b=three │
│ fragment │                     │
│          │ ╭───┬─────┬───────╮ │
│ params   │ │ # │ key │ value │ │
│          │ ├───┼─────┼───────┤ │
│          │ │ 0 │ a   │ one   │ │
│          │ │ 1 │ a   │ two   │ │
│          │ │ 2 │ b   │ three │ │
│          │ ╰───┴─────┴───────╯ │
╰──────────┴─────────────────────╯
```

# User-Facing Changes

- `url parse`'s output has the mentioned change, which is backwards
incompatible.
2024-11-06 07:35:37 -06:00

171 lines
4.6 KiB
Rust

use nu_test_support::{nu, pipeline};
#[test]
fn url_parse_simple() {
let actual = nu!(pipeline(
r#"
("https://www.abc.com"
| url parse)
== {
scheme: 'https',
username: '',
password: '',
host: 'www.abc.com',
port: '',
path: '/',
query: '',
fragment: '',
params: []
}
"#
));
assert_eq!(actual.out, "true");
}
#[test]
fn url_parse_with_port() {
let actual = nu!(pipeline(
r#"
("https://www.abc.com:8011"
| url parse)
== {
scheme: 'https',
username: '',
password: '',
host: 'www.abc.com',
port: '8011',
path: '/',
query: '',
fragment: '',
params: []
}
"#
));
assert_eq!(actual.out, "true");
}
#[test]
fn url_parse_with_path() {
let actual = nu!(pipeline(
r#"
("http://www.abc.com:8811/def/ghj"
| url parse)
== {
scheme: 'http',
username: '',
password: '',
host: 'www.abc.com',
port: '8811',
path: '/def/ghj',
query: '',
fragment: '',
params: []
}
"#
));
assert_eq!(actual.out, "true");
}
#[test]
fn url_parse_with_params() {
let actual = nu!(pipeline(
r#"
("http://www.abc.com:8811/def/ghj?param1=11&param2="
| url parse)
== {
scheme: 'http',
username: '',
password: '',
host: 'www.abc.com',
port: '8811',
path: '/def/ghj',
query: 'param1=11&param2=',
fragment: '',
params: [[key, value]; ["param1", "11"], ["param2", ""]]
}
"#
));
assert_eq!(actual.out, "true");
}
#[test]
fn url_parse_with_duplicate_params() {
let actual = nu!(pipeline(
r#"
("http://www.abc.com:8811/def/ghj?param1=11&param2=&param1=22"
| url parse)
== {
scheme: 'http',
username: '',
password: '',
host: 'www.abc.com',
port: '8811',
path: '/def/ghj',
query: 'param1=11&param2=&param1=22',
fragment: '',
params: [[key, value]; ["param1", "11"], ["param2", ""], ["param1", "22"]]
}
"#
));
assert_eq!(actual.out, "true");
}
#[test]
fn url_parse_with_fragment() {
let actual = nu!(pipeline(
r#"
("http://www.abc.com:8811/def/ghj?param1=11&param2=#hello-fragment"
| url parse)
== {
scheme: 'http',
username: '',
password: '',
host: 'www.abc.com',
port: '8811',
path: '/def/ghj',
query: 'param1=11&param2=',
fragment: 'hello-fragment',
params: [[key, value]; ["param1", "11"], ["param2", ""]]
}
"#
));
assert_eq!(actual.out, "true");
}
#[test]
fn url_parse_with_username_and_password() {
let actual = nu!(pipeline(
r#"
("http://user123:password567@www.abc.com:8811/def/ghj?param1=11&param2=#hello-fragment"
| url parse)
== {
scheme: 'http',
username: 'user123',
password: 'password567',
host: 'www.abc.com',
port: '8811',
path: '/def/ghj',
query: 'param1=11&param2=',
fragment: 'hello-fragment',
params: [[key, value]; ["param1", "11"], ["param2", ""]]
}
"#
));
assert_eq!(actual.out, "true");
}
#[test]
fn url_parse_error_empty_url() {
let actual = nu!(r#""" | url parse"#);
assert!(actual.err.contains(
"Incomplete or incorrect URL. Expected a full URL, e.g., https://www.example.com"
));
}