github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/interact/pollster_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package interact 5 6 import ( 7 "bytes" 8 "io" 9 "os" 10 "strings" 11 12 "github.com/juju/errors" 13 "github.com/juju/jsonschema" 14 "github.com/juju/testing" 15 jc "github.com/juju/testing/checkers" 16 gc "gopkg.in/check.v1" 17 ) 18 19 type PollsterSuite struct { 20 testing.IsolationSuite 21 } 22 23 var _ = gc.Suite(PollsterSuite{}) 24 25 func (p PollsterSuite) TearDownTest(c *gc.C) { 26 p.IsolationSuite.TearDownTest(c) 27 os.Unsetenv("SCHEMA_VAR") 28 os.Unsetenv("SCHEMA_VAR_TWO") 29 } 30 31 func (PollsterSuite) TestSelect(c *gc.C) { 32 r := strings.NewReader("macintosh") 33 w := &bytes.Buffer{} 34 p := New(r, w, w) 35 s, err := p.Select(List{ 36 Singular: "apple", 37 Plural: "apples", 38 Options: []string{"macintosh", "granny smith"}, 39 }) 40 c.Assert(err, jc.ErrorIsNil) 41 c.Assert(s, gc.Equals, "macintosh") 42 43 // Note: please only check the full output here, so that we don't have to 44 // edit a million tests if we make minor tweaks to the output. 45 c.Assert(w.String(), gc.Equals, ` 46 Apples 47 macintosh 48 granny smith 49 50 Select apple: 51 `[1:]) 52 } 53 54 func (PollsterSuite) TestSelectDefault(c *gc.C) { 55 r := strings.NewReader("\n") 56 w := &bytes.Buffer{} 57 p := New(r, w, w) 58 s, err := p.Select(List{ 59 Singular: "apple", 60 Plural: "apples", 61 Options: []string{"macintosh", "granny smith"}, 62 Default: "macintosh", 63 }) 64 c.Assert(err, jc.ErrorIsNil) 65 c.Assert(s, gc.Equals, "macintosh") 66 c.Assert(w.String(), jc.Contains, `Select apple [macintosh]: `) 67 } 68 69 func (PollsterSuite) TestSelectDefaultIfOnlyOption(c *gc.C) { 70 r := strings.NewReader("\n") 71 w := &bytes.Buffer{} 72 p := New(r, w, w) 73 s, err := p.Select(List{ 74 Singular: "apple", 75 Plural: "apples", 76 Options: []string{"macintosh"}, 77 Default: "macintosh", 78 }) 79 c.Assert(err, jc.ErrorIsNil) 80 c.Assert(s, gc.Equals, "macintosh") 81 c.Assert(w.String(), jc.Contains, `Select apple [macintosh]: `) 82 } 83 84 func (PollsterSuite) TestSelectIncorrect(c *gc.C) { 85 r := strings.NewReader("mac\nmacintosh") 86 w := &bytes.Buffer{} 87 p := New(r, w, w) 88 s, err := p.Select(List{ 89 Singular: "apple", 90 Plural: "apples", 91 Options: []string{"macintosh", "granny smith"}, 92 }) 93 c.Assert(err, jc.ErrorIsNil) 94 c.Assert(s, gc.Equals, "macintosh") 95 96 c.Assert(squash(w.String()), jc.Contains, `Invalid apple: "mac"Select apple:`) 97 } 98 99 // squash removes all newlines from the given string so our tests can be more 100 // resilient in the face of minor tweaks to spacing. 101 func squash(s string) string { 102 return strings.Replace(s, "\n", "", -1) 103 } 104 105 func (PollsterSuite) TestSelectNoMultiple(c *gc.C) { 106 r := strings.NewReader("macintosh,granny smith\ngranny smith") 107 w := &bytes.Buffer{} 108 p := New(r, w, w) 109 s, err := p.Select(List{ 110 Singular: "apple", 111 Plural: "apples", 112 Options: []string{"macintosh", "granny smith"}, 113 }) 114 c.Assert(err, jc.ErrorIsNil) 115 c.Assert(s, gc.Equals, "granny smith") 116 c.Assert(w.String(), jc.Contains, `Invalid apple: "macintosh,granny smith"`) 117 } 118 119 func (PollsterSuite) TestMultiSelectSingle(c *gc.C) { 120 r := strings.NewReader("macintosh") 121 w := &bytes.Buffer{} 122 p := New(r, w, w) 123 vals, err := p.MultiSelect(MultiList{ 124 Singular: "apple", 125 Plural: "apples", 126 Options: []string{"macintosh", "granny smith", "gala"}, 127 }) 128 c.Assert(err, jc.ErrorIsNil) 129 c.Assert(vals, jc.SameContents, []string{"macintosh"}) 130 } 131 132 func (PollsterSuite) TestMultiSelectMany(c *gc.C) { 133 // note there's a couple spaces in the middle here that we're stripping out. 134 r := strings.NewReader("macintosh, granny smith") 135 w := &bytes.Buffer{} 136 p := New(r, w, w) 137 vals, err := p.MultiSelect(MultiList{ 138 Singular: "apple", 139 Plural: "apples", 140 Options: []string{"macintosh", "granny smith", "gala"}, 141 }) 142 c.Assert(err, jc.ErrorIsNil) 143 c.Assert(vals, jc.SameContents, []string{"macintosh", "granny smith"}) 144 } 145 146 func (PollsterSuite) TestMultiSelectDefault(c *gc.C) { 147 r := strings.NewReader("\n") 148 w := &bytes.Buffer{} 149 p := New(r, w, w) 150 vals, err := p.MultiSelect(MultiList{ 151 Singular: "apple", 152 Plural: "apples", 153 Options: []string{"macintosh", "granny smith", "gala"}, 154 Default: []string{"gala", "granny smith"}, 155 }) 156 c.Assert(err, jc.ErrorIsNil) 157 c.Assert(vals, jc.SameContents, []string{"gala", "granny smith"}) 158 } 159 160 func (PollsterSuite) TestMultiSelectDefaultIfOnlyOne(c *gc.C) { 161 r := strings.NewReader("\n") 162 w := &bytes.Buffer{} 163 p := New(r, w, w) 164 vals, err := p.MultiSelect(MultiList{ 165 Singular: "apple", 166 Plural: "apples", 167 Options: []string{"macintosh"}, 168 Default: []string{"macintosh"}, 169 }) 170 c.Assert(err, jc.ErrorIsNil) 171 c.Assert(vals, jc.SameContents, []string{"macintosh"}) 172 c.Assert(w.String(), gc.Equals, "Apples\n macintosh\n\n") 173 } 174 175 func (PollsterSuite) TestMultiSelectWithMultipleDefaults(c *gc.C) { 176 r := strings.NewReader("\n") 177 w := &bytes.Buffer{} 178 p := New(r, w, w) 179 vals, err := p.MultiSelect(MultiList{ 180 Singular: "apple", 181 Plural: "apples", 182 Options: []string{"macintosh", "gala"}, 183 Default: []string{"macintosh", "gala"}, 184 }) 185 c.Assert(err, jc.ErrorIsNil) 186 c.Assert(vals, jc.SameContents, []string{"macintosh", "gala"}) 187 c.Assert(w.String(), jc.Contains, "Select one or more apples separated by commas [macintosh, gala]: \n") 188 } 189 190 func (PollsterSuite) TestMultiSelectOneError(c *gc.C) { 191 r := strings.NewReader("mac\nmacintosh") 192 w := &bytes.Buffer{} 193 p := New(r, w, w) 194 vals, err := p.MultiSelect(MultiList{ 195 Singular: "apple", 196 Plural: "apples", 197 Options: []string{"macintosh", "granny smith", "gala"}, 198 }) 199 c.Assert(err, jc.ErrorIsNil) 200 c.Assert(vals, jc.SameContents, []string{"macintosh"}) 201 c.Assert(w.String(), jc.Contains, `Invalid apple: "mac"`) 202 } 203 204 func (PollsterSuite) TestMultiSelectManyErrors(c *gc.C) { 205 r := strings.NewReader("mac, smith\nmacintosh") 206 w := &bytes.Buffer{} 207 p := New(r, w, w) 208 vals, err := p.MultiSelect(MultiList{ 209 Singular: "apple", 210 Plural: "apples", 211 Options: []string{"macintosh", "granny smith", "gala"}, 212 }) 213 c.Assert(err, jc.ErrorIsNil) 214 c.Assert(vals, jc.SameContents, []string{"macintosh"}) 215 c.Assert(w.String(), jc.Contains, `Invalid apples: "mac", "smith"`) 216 } 217 218 func (PollsterSuite) TestEnter(c *gc.C) { 219 r := strings.NewReader("Bill Smith") 220 w := &bytes.Buffer{} 221 p := New(r, w, w) 222 a, err := p.Enter("your name") 223 c.Assert(err, jc.ErrorIsNil) 224 c.Assert(a, gc.Equals, "Bill Smith") 225 c.Assert(w.String(), gc.Equals, "Enter your name: \n") 226 } 227 228 func (PollsterSuite) TestEnterEmpty(c *gc.C) { 229 r := strings.NewReader("\nBill") 230 w := &bytes.Buffer{} 231 p := New(r, w, w) 232 a, err := p.Enter("your name") 233 c.Assert(err, jc.ErrorIsNil) 234 c.Assert(a, gc.Equals, "Bill") 235 // We should re-query without any error on empty input. 236 c.Assert(squash(w.String()), jc.Contains, "Enter your name: Enter your name: ") 237 } 238 239 func (PollsterSuite) TestEnterVerify(c *gc.C) { 240 r := strings.NewReader("Bill Smith") 241 w := &bytes.Buffer{} 242 p := New(r, w, w) 243 verify := func(s string) (ok bool, errmsg string, err error) { 244 if s == "Bill Smith" { 245 return true, "", nil 246 } 247 return false, "not bill!", nil 248 } 249 a, err := p.EnterVerify("your name", verify) 250 c.Assert(err, jc.ErrorIsNil) 251 c.Assert(a, gc.Equals, "Bill Smith") 252 c.Assert(w.String(), gc.Equals, "Enter your name: \n") 253 } 254 255 func (PollsterSuite) TestEnterVerifyBad(c *gc.C) { 256 r := strings.NewReader("Will Smithy\nBill Smith") 257 w := &bytes.Buffer{} 258 p := New(r, w, w) 259 verify := func(s string) (ok bool, errmsg string, err error) { 260 if s == "Bill Smith" { 261 return true, "", nil 262 } 263 return false, "not bill!", nil 264 } 265 a, err := p.EnterVerify("your name", verify) 266 c.Assert(err, jc.ErrorIsNil) 267 c.Assert(a, gc.Equals, "Bill Smith") 268 c.Assert(squash(w.String()), gc.Equals, "Enter your name: not bill!Enter your name: ") 269 } 270 271 func (PollsterSuite) TestEnterDefaultNonEmpty(c *gc.C) { 272 r := strings.NewReader("Bill Smith") 273 w := &bytes.Buffer{} 274 p := New(r, w, w) 275 a, err := p.EnterDefault("your name", "John") 276 c.Assert(err, jc.ErrorIsNil) 277 c.Assert(a, gc.Equals, "Bill Smith") 278 c.Assert(w.String(), gc.Equals, "Enter your name [John]: \n") 279 } 280 281 func (PollsterSuite) TestEnterDefaultEmpty(c *gc.C) { 282 r := strings.NewReader("\n") 283 w := &bytes.Buffer{} 284 p := New(r, w, w) 285 a, err := p.EnterDefault("your name", "John") 286 c.Assert(err, jc.ErrorIsNil) 287 c.Assert(a, gc.Equals, "John") 288 // We should re-query without any error on empty input. 289 c.Assert(squash(w.String()), jc.Contains, "Enter your name [John]: ") 290 } 291 292 func (PollsterSuite) TestEnterVerifyDefaultEmpty(c *gc.C) { 293 r := strings.NewReader("\n") 294 w := &bytes.Buffer{} 295 p := New(r, w, w) 296 // note that the verification does not accept empty string, but the default 297 // should still work 298 verify := func(s string) (ok bool, errmsg string, err error) { 299 if s == "Bill Smith" { 300 return true, "", nil 301 } 302 return false, "not bill!", nil 303 } 304 a, err := p.EnterVerifyDefault("your name", verify, "John") 305 c.Assert(err, jc.ErrorIsNil) 306 c.Assert(a, gc.Equals, "John") 307 // We should re-query without any error on empty input. 308 c.Assert(squash(w.String()), jc.Contains, "Enter your name [John]: ") 309 } 310 311 func (PollsterSuite) TestYNDefaultFalse(c *gc.C) { 312 r := strings.NewReader("Y") 313 w := &bytes.Buffer{} 314 p := New(r, w, w) 315 a, err := p.YN("Should this test pass", false) 316 c.Assert(err, jc.ErrorIsNil) 317 c.Assert(a, jc.IsTrue) 318 c.Assert(w.String(), gc.Equals, "Should this test pass? (y/N): \n") 319 } 320 321 func (PollsterSuite) TestYNDefaultTrue(c *gc.C) { 322 r := strings.NewReader("Y") 323 w := &bytes.Buffer{} 324 p := New(r, w, w) 325 a, err := p.YN("Should this test pass", true) 326 c.Assert(err, jc.ErrorIsNil) 327 c.Assert(a, jc.IsTrue) 328 c.Assert(w.String(), gc.Equals, "Should this test pass? (Y/n): \n") 329 } 330 331 func (PollsterSuite) TestYNTable(c *gc.C) { 332 tests := []struct { 333 In string 334 Def, Res bool 335 }{ 336 0: {In: "Y", Def: false, Res: true}, 337 1: {In: "y", Def: false, Res: true}, 338 2: {In: "yes", Def: false, Res: true}, 339 3: {In: "YES", Def: false, Res: true}, 340 4: {In: "N", Def: true, Res: false}, 341 5: {In: "n", Def: true, Res: false}, 342 6: {In: "no", Def: true, Res: false}, 343 7: {In: "NO", Def: true, Res: false}, 344 8: {In: "Y", Def: true, Res: true}, 345 9: {In: "y", Def: true, Res: true}, 346 10: {In: "yes", Def: true, Res: true}, 347 11: {In: "YES", Def: true, Res: true}, 348 12: {In: "N", Def: false, Res: false}, 349 13: {In: "n", Def: false, Res: false}, 350 14: {In: "no", Def: false, Res: false}, 351 15: {In: "NO", Def: false, Res: false}, 352 } 353 for i, test := range tests { 354 c.Logf("test %d", i) 355 r := strings.NewReader(test.In) 356 w := &bytes.Buffer{} 357 p := New(r, w, w) 358 a, err := p.YN("doesn't matter", test.Def) 359 c.Assert(err, jc.ErrorIsNil) 360 c.Assert(a, gc.Equals, test.Res) 361 } 362 } 363 364 func (PollsterSuite) TestYNInvalid(c *gc.C) { 365 r := strings.NewReader("wat\nY") 366 w := &bytes.Buffer{} 367 p := New(r, w, w) 368 a, err := p.YN("Should this test pass", false) 369 c.Assert(err, jc.ErrorIsNil) 370 c.Assert(a, jc.IsTrue) 371 c.Assert(w.String(), jc.Contains, `Invalid entry: "wat", please choose y or n`) 372 } 373 374 func (PollsterSuite) TestQueryStringSchema(c *gc.C) { 375 schema := &jsonschema.Schema{ 376 Singular: "region", 377 Type: []jsonschema.Type{jsonschema.StringType}, 378 } 379 r := strings.NewReader("wat") 380 w := &bytes.Buffer{} 381 p := New(r, w, w) 382 v, err := p.QuerySchema(schema) 383 c.Assert(err, jc.ErrorIsNil) 384 s, ok := v.(string) 385 c.Check(ok, jc.IsTrue) 386 c.Check(s, gc.Equals, "wat") 387 c.Assert(w.String(), jc.Contains, "Enter region:") 388 } 389 390 func (PollsterSuite) TestQueryStringSchemaWithDefault(c *gc.C) { 391 schema := &jsonschema.Schema{ 392 Singular: "region", 393 Type: []jsonschema.Type{jsonschema.StringType}, 394 Default: "foo", 395 } 396 r := strings.NewReader("\n") 397 w := &bytes.Buffer{} 398 p := New(r, w, w) 399 v, err := p.QuerySchema(schema) 400 c.Assert(err, jc.ErrorIsNil) 401 s, ok := v.(string) 402 c.Check(ok, jc.IsTrue) 403 c.Check(s, gc.Equals, "foo") 404 c.Assert(w.String(), jc.Contains, "Enter region [foo]:") 405 } 406 407 func (PollsterSuite) TestQueryStringSchemaWithUnusedDefault(c *gc.C) { 408 schema := &jsonschema.Schema{ 409 Singular: "region", 410 Type: []jsonschema.Type{jsonschema.StringType}, 411 Default: "foo", 412 } 413 r := strings.NewReader("bar\n") 414 w := &bytes.Buffer{} 415 p := New(r, w, w) 416 v, err := p.QuerySchema(schema) 417 c.Assert(err, jc.ErrorIsNil) 418 s, ok := v.(string) 419 c.Check(ok, jc.IsTrue) 420 c.Check(s, gc.Equals, "bar") 421 c.Assert(w.String(), jc.Contains, "Enter region [foo]:") 422 } 423 424 func (PollsterSuite) TestQueryStringSchemaWithPromptDefault(c *gc.C) { 425 schema := &jsonschema.Schema{ 426 Singular: "region", 427 Type: []jsonschema.Type{jsonschema.StringType}, 428 Default: "foo", 429 PromptDefault: "not foo", 430 } 431 r := strings.NewReader("\n") 432 w := &bytes.Buffer{} 433 p := New(r, w, w) 434 v, err := p.QuerySchema(schema) 435 c.Assert(err, jc.ErrorIsNil) 436 s, ok := v.(string) 437 c.Check(ok, jc.IsTrue) 438 c.Check(s, gc.Equals, "foo") 439 c.Check(w.String(), jc.Contains, "Enter region [not foo]:") 440 } 441 442 func (PollsterSuite) TestQueryStringSchemaWithDefaultEnvVar(c *gc.C) { 443 schema := &jsonschema.Schema{ 444 Singular: "region", 445 Type: []jsonschema.Type{jsonschema.StringType}, 446 Default: "", 447 EnvVars: []string{"SCHEMA_VAR"}, 448 } 449 os.Setenv("SCHEMA_VAR", "value from env var") 450 r := strings.NewReader("\n") 451 w := &bytes.Buffer{} 452 p := New(r, w, w) 453 v, err := p.QuerySchema(schema) 454 c.Assert(err, jc.ErrorIsNil) 455 s, ok := v.(string) 456 c.Check(ok, jc.IsTrue) 457 c.Check(s, gc.Equals, "value from env var") 458 c.Assert(w.String(), jc.Contains, "Enter region [value from env var]:") 459 } 460 461 func (PollsterSuite) TestQueryStringSchemaWithDefaultEnvVarOverride(c *gc.C) { 462 schema := &jsonschema.Schema{ 463 Singular: "region", 464 Type: []jsonschema.Type{jsonschema.StringType}, 465 Default: "", 466 EnvVars: []string{"SCHEMA_VAR"}, 467 } 468 os.Setenv("SCHEMA_VAR", "value from env var") 469 r := strings.NewReader("use me\n") 470 w := &bytes.Buffer{} 471 p := New(r, w, w) 472 v, err := p.QuerySchema(schema) 473 c.Assert(err, jc.ErrorIsNil) 474 s, ok := v.(string) 475 c.Check(ok, jc.IsTrue) 476 c.Check(s, gc.Equals, "use me") 477 c.Assert(w.String(), jc.Contains, "Enter region [value from env var]:") 478 } 479 480 func (PollsterSuite) TestQueryStringSchemaWithDefaultTwoEnvVar(c *gc.C) { 481 schema := &jsonschema.Schema{ 482 Singular: "region", 483 Type: []jsonschema.Type{jsonschema.StringType}, 484 Default: "", 485 EnvVars: []string{"SCHEMA_VAR", "SCHEMA_VAR_TWO"}, 486 } 487 os.Setenv("SCHEMA_VAR_TWO", "value from second") 488 r := strings.NewReader("\n") 489 w := &bytes.Buffer{} 490 p := New(r, w, w) 491 v, err := p.QuerySchema(schema) 492 c.Assert(err, jc.ErrorIsNil) 493 s, ok := v.(string) 494 c.Check(ok, jc.IsTrue) 495 c.Check(s, gc.Equals, "value from second") 496 c.Assert(w.String(), jc.Contains, "Enter region [value from second]:") 497 } 498 499 func (PollsterSuite) TestQueryURISchema(c *gc.C) { 500 schema := &jsonschema.Schema{ 501 Singular: "region", 502 Type: []jsonschema.Type{jsonschema.StringType}, 503 Format: jsonschema.FormatURI, 504 } 505 // invalid escape sequence 506 r := strings.NewReader("https://&%5abc") 507 w := &bytes.Buffer{} 508 p := New(r, w, w) 509 _, err := p.QuerySchema(schema) 510 c.Check(errors.Cause(err), gc.Equals, io.EOF) 511 c.Assert(w.String(), gc.Equals, ` 512 Enter region: Invalid URI: "https://&%5abc" 513 514 Enter region: 515 `[1:]) 516 } 517 518 func (PollsterSuite) TestQueryArraySchema(c *gc.C) { 519 schema := &jsonschema.Schema{ 520 Singular: "number", 521 Plural: "numbers", 522 Type: []jsonschema.Type{jsonschema.ArrayType}, 523 Items: &jsonschema.ItemSpec{ 524 Schemas: []*jsonschema.Schema{{ 525 Type: []jsonschema.Type{jsonschema.StringType}, 526 Enum: []interface{}{ 527 "one", 528 "two", 529 "three", 530 }, 531 }}, 532 }, 533 } 534 r := strings.NewReader("one, three") 535 w := &bytes.Buffer{} 536 p := New(r, w, w) 537 v, err := p.QuerySchema(schema) 538 c.Assert(err, jc.ErrorIsNil) 539 c.Check(w.String(), gc.Equals, ` 540 Numbers 541 one 542 two 543 three 544 545 Select one or more numbers separated by commas: 546 `[1:]) 547 s, ok := v.([]string) 548 c.Check(ok, jc.IsTrue) 549 c.Check(s, jc.SameContents, []string{"one", "three"}) 550 } 551 552 func (PollsterSuite) TestQueryArraySchemaDefault(c *gc.C) { 553 schema := &jsonschema.Schema{ 554 Singular: "number", 555 Plural: "numbers", 556 Type: []jsonschema.Type{jsonschema.ArrayType}, 557 Default: "two", 558 Items: &jsonschema.ItemSpec{ 559 Schemas: []*jsonschema.Schema{{ 560 Type: []jsonschema.Type{jsonschema.StringType}, 561 Enum: []interface{}{ 562 "one", 563 "two", 564 "three", 565 }, 566 }}, 567 }, 568 } 569 r := strings.NewReader("\n") 570 w := &bytes.Buffer{} 571 p := New(r, w, w) 572 v, err := p.QuerySchema(schema) 573 c.Assert(err, jc.ErrorIsNil) 574 c.Check(w.String(), gc.Equals, ` 575 Numbers 576 one 577 two 578 three 579 580 Select one or more numbers separated by commas [two]: 581 `[1:]) 582 s, ok := v.([]string) 583 c.Check(ok, jc.IsTrue) 584 c.Check(s, jc.SameContents, []string{"two"}) 585 } 586 587 func (PollsterSuite) TestQueryArraySchemaNotDefault(c *gc.C) { 588 schema := &jsonschema.Schema{ 589 Singular: "number", 590 Plural: "numbers", 591 Type: []jsonschema.Type{jsonschema.ArrayType}, 592 Default: "two", 593 Items: &jsonschema.ItemSpec{ 594 Schemas: []*jsonschema.Schema{{ 595 Type: []jsonschema.Type{jsonschema.StringType}, 596 Enum: []interface{}{ 597 "one", 598 "two", 599 "three", 600 }, 601 }}, 602 }, 603 } 604 r := strings.NewReader("three") 605 w := &bytes.Buffer{} 606 p := New(r, w, w) 607 v, err := p.QuerySchema(schema) 608 c.Assert(err, jc.ErrorIsNil) 609 c.Check(w.String(), gc.Equals, ` 610 Numbers 611 one 612 two 613 three 614 615 Select one or more numbers separated by commas [two]: 616 `[1:]) 617 s, ok := v.([]string) 618 c.Check(ok, jc.IsTrue) 619 c.Check(s, jc.SameContents, []string{"three"}) 620 } 621 622 func (PollsterSuite) TestQueryEnum(c *gc.C) { 623 schema := &jsonschema.Schema{ 624 Singular: "number", 625 Plural: "numbers", 626 Type: []jsonschema.Type{jsonschema.IntegerType}, 627 Enum: []interface{}{ 628 1, 629 2, 630 3, 631 }, 632 } 633 r := strings.NewReader("2") 634 w := &bytes.Buffer{} 635 p := New(r, w, w) 636 v, err := p.QuerySchema(schema) 637 c.Assert(err, jc.ErrorIsNil) 638 c.Check(w.String(), gc.Equals, ` 639 Numbers 640 1 641 2 642 3 643 644 Select number: 645 `[1:]) 646 i, ok := v.(int) 647 c.Check(ok, jc.IsTrue) 648 c.Check(i, gc.Equals, 2) 649 } 650 651 func (PollsterSuite) TestQueryObjectSchema(c *gc.C) { 652 schema := &jsonschema.Schema{ 653 Type: []jsonschema.Type{jsonschema.ObjectType}, 654 Properties: map[string]*jsonschema.Schema{ 655 "numbers": { 656 Singular: "number", 657 Plural: "numbers", 658 Type: []jsonschema.Type{jsonschema.ArrayType}, 659 Items: &jsonschema.ItemSpec{ 660 Schemas: []*jsonschema.Schema{{ 661 Type: []jsonschema.Type{jsonschema.StringType}, 662 Enum: []interface{}{ 663 "one", 664 "two", 665 "three", 666 }, 667 }}, 668 }, 669 }, 670 "name": { 671 Type: []jsonschema.Type{jsonschema.StringType}, 672 Singular: "the name", 673 }, 674 }, 675 } 676 // queries should be alphabetical without an order specified, so name then 677 // number. 678 r := strings.NewReader("Bill\ntwo, three") 679 w := &bytes.Buffer{} 680 p := New(r, w, w) 681 v, err := p.QuerySchema(schema) 682 c.Assert(err, jc.ErrorIsNil) 683 c.Check(v, jc.DeepEquals, map[string]interface{}{ 684 "name": "Bill", 685 "numbers": []string{"two", "three"}, 686 }) 687 } 688 689 func (PollsterSuite) TestQueryObjectSchemaOrder(c *gc.C) { 690 schema := &jsonschema.Schema{ 691 Type: []jsonschema.Type{jsonschema.ObjectType}, 692 // Order should match up with order of input in strings.NewReader below. 693 Order: []string{"numbers", "name"}, 694 Properties: map[string]*jsonschema.Schema{ 695 "numbers": { 696 Singular: "number", 697 Plural: "numbers", 698 Type: []jsonschema.Type{jsonschema.ArrayType}, 699 Items: &jsonschema.ItemSpec{ 700 Schemas: []*jsonschema.Schema{{ 701 Type: []jsonschema.Type{jsonschema.StringType}, 702 Enum: []interface{}{ 703 "one", 704 "two", 705 "three", 706 }, 707 }}, 708 }, 709 }, 710 "name": { 711 Type: []jsonschema.Type{jsonschema.StringType}, 712 Singular: "the name", 713 }, 714 }, 715 } 716 // queries should be ordered by order, so number then name. 717 r := strings.NewReader("two, three\nBill") 718 w := &bytes.Buffer{} 719 p := New(r, w, w) 720 v, err := p.QuerySchema(schema) 721 c.Assert(err, jc.ErrorIsNil) 722 c.Check(v, jc.DeepEquals, map[string]interface{}{ 723 "name": "Bill", 724 "numbers": []string{"two", "three"}, 725 }) 726 } 727 728 func (PollsterSuite) TestQueryObjectSchemaAdditional(c *gc.C) { 729 schema := &jsonschema.Schema{ 730 Type: []jsonschema.Type{jsonschema.ObjectType}, 731 Singular: "region", 732 Plural: "regions", 733 AdditionalProperties: &jsonschema.Schema{ 734 Type: []jsonschema.Type{jsonschema.ObjectType}, 735 Properties: map[string]*jsonschema.Schema{ 736 "loc": { 737 Singular: "location", 738 Type: []jsonschema.Type{jsonschema.StringType}, 739 }, 740 }, 741 }, 742 } 743 r := strings.NewReader(` 744 one 745 east 746 y 747 two 748 west 749 n 750 `[1:]) 751 w := &bytes.Buffer{} 752 p := New(r, w, w) 753 v, err := p.QuerySchema(schema) 754 c.Assert(err, jc.ErrorIsNil) 755 c.Check(v, jc.DeepEquals, map[string]interface{}{ 756 "one": map[string]interface{}{"loc": "east"}, 757 "two": map[string]interface{}{"loc": "west"}, 758 }) 759 c.Check(w.String(), gc.Equals, ` 760 Enter region name: 761 Enter location: 762 Enter another region? (y/N): 763 Enter region name: 764 Enter location: 765 Enter another region? (y/N): 766 `[1:]) 767 } 768 769 func (PollsterSuite) TestQueryObjectSchemaAdditionalEmpty(c *gc.C) { 770 schema := &jsonschema.Schema{ 771 Type: []jsonschema.Type{jsonschema.ObjectType}, 772 Singular: "region", 773 Plural: "regions", 774 AdditionalProperties: &jsonschema.Schema{ 775 Type: []jsonschema.Type{jsonschema.ObjectType}, 776 }, 777 } 778 r := strings.NewReader(` 779 one 780 y 781 two 782 n 783 `[1:]) 784 w := &bytes.Buffer{} 785 p := New(r, w, w) 786 v, err := p.QuerySchema(schema) 787 c.Assert(err, jc.ErrorIsNil) 788 c.Check(v, jc.DeepEquals, map[string]interface{}{ 789 "one": map[string]interface{}{}, 790 "two": map[string]interface{}{}, 791 }) 792 c.Check(w.String(), gc.Equals, ` 793 Enter region name: 794 Enter another region? (y/N): 795 Enter region name: 796 Enter another region? (y/N): 797 `[1:]) 798 } 799 800 func (PollsterSuite) TestQueryObjectSchemaWithOutDefault(c *gc.C) { 801 schema := &jsonschema.Schema{ 802 Type: []jsonschema.Type{jsonschema.ObjectType}, 803 Order: []string{"name", "nested", "bar"}, 804 Properties: map[string]*jsonschema.Schema{ 805 "nested": { 806 Singular: "nested", 807 Type: []jsonschema.Type{jsonschema.ObjectType}, 808 AdditionalProperties: &jsonschema.Schema{ 809 Type: []jsonschema.Type{jsonschema.ObjectType}, 810 Required: []string{"name"}, 811 MaxProperties: jsonschema.Int(1), 812 Properties: map[string]*jsonschema.Schema{ 813 "name": { 814 Singular: "the name", 815 Type: []jsonschema.Type{jsonschema.StringType}, 816 Default: "", 817 PromptDefault: "use name", 818 }, 819 }, 820 }, 821 }, 822 "bar": { 823 Singular: "nested", 824 Type: []jsonschema.Type{jsonschema.ObjectType}, 825 Default: "", 826 AdditionalProperties: &jsonschema.Schema{ 827 Type: []jsonschema.Type{jsonschema.ObjectType}, 828 Required: []string{"name"}, 829 MaxProperties: jsonschema.Int(1), 830 Properties: map[string]*jsonschema.Schema{ 831 "name": { 832 Singular: "the name", 833 Type: []jsonschema.Type{jsonschema.StringType}, 834 Default: "", 835 PromptDefault: "use name", 836 }, 837 }, 838 }, 839 }, 840 "name": { 841 Type: []jsonschema.Type{jsonschema.StringType}, 842 Singular: "the name", 843 }, 844 }, 845 } 846 // queries should be alphabetical without an order specified, so name then 847 // number. 848 r := strings.NewReader("Bill\n\nnamespace\n\n\nfoo\nbaz\n\n\n") 849 w := &bytes.Buffer{} 850 p := New(r, w, w) 851 v, err := p.QuerySchema(schema) 852 c.Assert(err, jc.ErrorIsNil) 853 c.Check(v, jc.DeepEquals, map[string]interface{}{ 854 "name": "Bill", 855 "nested": map[string]interface{}{ 856 "namespace": map[string]interface{}{ 857 "name": "", 858 }, 859 }, 860 "bar": map[string]interface{}{ 861 "foo": map[string]interface{}{ 862 "name": "baz", 863 }, 864 }, 865 }) 866 } 867 868 func (PollsterSuite) TestQueryObjectSchemaWithDefault(c *gc.C) { 869 schema := &jsonschema.Schema{ 870 Type: []jsonschema.Type{jsonschema.ObjectType}, 871 Order: []string{"name", "nested"}, 872 Properties: map[string]*jsonschema.Schema{ 873 "nested": { 874 Singular: "nested", 875 Default: "default", 876 Type: []jsonschema.Type{jsonschema.ObjectType}, 877 AdditionalProperties: &jsonschema.Schema{ 878 Type: []jsonschema.Type{jsonschema.ObjectType}, 879 Required: []string{"name"}, 880 MaxProperties: jsonschema.Int(1), 881 Properties: map[string]*jsonschema.Schema{ 882 "name": { 883 Singular: "the name", 884 Type: []jsonschema.Type{jsonschema.StringType}, 885 Default: "", 886 PromptDefault: "use name", 887 }, 888 }, 889 }, 890 }, 891 "name": { 892 Type: []jsonschema.Type{jsonschema.StringType}, 893 Singular: "the name", 894 }, 895 }, 896 } 897 // queries should be alphabetical without an order specified, so name then 898 // number. 899 r := strings.NewReader("Bill\n\n\n\n") 900 w := &bytes.Buffer{} 901 p := New(r, w, w) 902 v, err := p.QuerySchema(schema) 903 c.Assert(err, jc.ErrorIsNil) 904 c.Check(v, jc.DeepEquals, map[string]interface{}{ 905 "name": "Bill", 906 "nested": map[string]interface{}{ 907 "default": map[string]interface{}{ 908 "name": "", 909 }, 910 }, 911 }) 912 } 913 914 func (PollsterSuite) TestQueryObjectSchemaWithDefaultEnvVars(c *gc.C) { 915 schema := &jsonschema.Schema{ 916 Type: []jsonschema.Type{jsonschema.ObjectType}, 917 Order: []string{"name", "nested"}, 918 Properties: map[string]*jsonschema.Schema{ 919 "nested": { 920 Singular: "nested", 921 Default: "default", 922 PromptDefault: "use default value", 923 EnvVars: []string{"TEST_ENV_VAR_NESTED"}, 924 Type: []jsonschema.Type{jsonschema.ObjectType}, 925 AdditionalProperties: &jsonschema.Schema{ 926 Type: []jsonschema.Type{jsonschema.ObjectType}, 927 Required: []string{"name"}, 928 MaxProperties: jsonschema.Int(1), 929 Properties: map[string]*jsonschema.Schema{ 930 "name": { 931 Singular: "the name", 932 Type: []jsonschema.Type{jsonschema.StringType}, 933 Default: "", 934 PromptDefault: "use name", 935 }, 936 }, 937 }, 938 }, 939 "name": { 940 Type: []jsonschema.Type{jsonschema.StringType}, 941 Singular: "the name", 942 }, 943 }, 944 } 945 // queries should be alphabetical without an order specified, so name then 946 // number. 947 os.Setenv("TEST_ENV_VAR_NESTED", "baz") 948 defer os.Unsetenv("TEST_ENV_VAR_NESTED") 949 950 r := strings.NewReader("Bill\n\n\n\n") 951 w := &bytes.Buffer{} 952 p := New(r, w, w) 953 v, err := p.QuerySchema(schema) 954 c.Assert(err, jc.ErrorIsNil) 955 c.Check(v, jc.DeepEquals, map[string]interface{}{ 956 "name": "Bill", 957 "nested": map[string]interface{}{ 958 "baz": map[string]interface{}{ 959 "name": "", 960 }, 961 }, 962 }) 963 } 964 965 func (PollsterSuite) TestQueryObjectSchemaEnvVarsWithOutDefault(c *gc.C) { 966 schema := &jsonschema.Schema{ 967 Type: []jsonschema.Type{jsonschema.ObjectType}, 968 Order: []string{"name", "nested"}, 969 Properties: map[string]*jsonschema.Schema{ 970 "nested": { 971 Singular: "nested", 972 EnvVars: []string{"TEST_ENV_VAR_NESTED"}, 973 Type: []jsonschema.Type{jsonschema.ObjectType}, 974 AdditionalProperties: &jsonschema.Schema{ 975 Type: []jsonschema.Type{jsonschema.ObjectType}, 976 Required: []string{"name"}, 977 MaxProperties: jsonschema.Int(1), 978 Properties: map[string]*jsonschema.Schema{ 979 "name": { 980 Singular: "the name", 981 Type: []jsonschema.Type{jsonschema.StringType}, 982 Default: "", 983 PromptDefault: "use name", 984 }, 985 }, 986 }, 987 }, 988 "name": { 989 Type: []jsonschema.Type{jsonschema.StringType}, 990 Singular: "the name", 991 }, 992 }, 993 } 994 // queries should be alphabetical without an order specified, so name then 995 // number. 996 os.Setenv("TEST_ENV_VAR_NESTED", "baz") 997 defer os.Unsetenv("TEST_ENV_VAR_NESTED") 998 999 r := strings.NewReader("Bill\nbaz\n\n\n") 1000 w := &bytes.Buffer{} 1001 p := New(r, w, w) 1002 v, err := p.QuerySchema(schema) 1003 c.Assert(err, jc.ErrorIsNil) 1004 c.Check(v, jc.DeepEquals, map[string]interface{}{ 1005 "name": "Bill", 1006 "nested": map[string]interface{}{ 1007 "baz": map[string]interface{}{ 1008 "name": "", 1009 }, 1010 }, 1011 }) 1012 }