improve: OAuth2 UI and test suite (via #5066)

* create `features` folder

* add base oauth2 server

* continue implementing OAuth tests

* WIP

* add password flow tests

* modify Password flow credential types

* remove query string credential type

* add test case for Authorization flow

* add specific Authorization value for Password flow test

* WIP

* fix linter issues
This commit is contained in:
kyle
2018-12-07 20:54:29 +01:00
committed by GitHub
parent 91b1becc65
commit a5568f9e16
14 changed files with 504 additions and 55 deletions

View File

@@ -0,0 +1,213 @@
describe("Deep linking feature", () => {
describe("in Swagger 2", () => {
const swagger2BaseUrl = "/?deepLinking=true&url=/documents/features/deep-linking.swagger.yaml"
describe("regular Operation", () => {
BaseDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet: ".opblock-get",
correctElementId: "operations-myTag-myOperation",
correctFragment: "#/myTag/myOperation",
correctHref: "#/myTag/myOperation"
})
})
describe("Operation with whitespace in tag+id", () => {
const elementToGet = ".opblock-post"
const correctFragment = "#/my%20Tag/my%20Operation"
BaseDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet,
correctElementId: "operations-my_Tag-my_Operation",
correctFragment,
correctHref: "#/my%20Tag/my%20Operation"
})
const legacyFragment = "#/my_Tag/my_Operation"
it("should expand the operation when reloaded and provided the legacy fragment", () => {
cy.visit(`${swagger2BaseUrl}${legacyFragment}`)
.reload()
.get(`${elementToGet}.is-open`)
.should("exist")
})
it.skip("should rewrite to the correct fragment when provided the legacy fragment", () => {
cy.visit(`${swagger2BaseUrl}${legacyFragment}`)
.reload()
.window()
.should("have.deep.property", "location.hash", correctFragment)
})
})
describe("Operation with underscores in tag+id", () => {
BaseDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet: ".opblock-patch",
correctElementId: "operations-underscore_Tag-underscore_Operation",
correctFragment: "#/underscore_Tag/underscore_Operation",
correctHref: "#/underscore_Tag/underscore_Operation"
})
})
describe("Operation with UTF-16 characters", () => {
BaseDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet: ".opblock-head",
correctElementId: "operations-шеллы-пошел",
correctFragment: "#/%D1%88%D0%B5%D0%BB%D0%BB%D1%8B/%D0%BF%D0%BE%D1%88%D0%B5%D0%BB",
correctHref: "#/шеллы/пошел"
})
})
describe("Operation with no operationId", () => {
BaseDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet: ".opblock-put",
correctElementId: "operations-tagTwo-put_noOperationId",
correctFragment: "#/tagTwo/put_noOperationId",
correctHref: "#/tagTwo/put_noOperationId"
})
})
describe("regular Operation with `docExpansion: none` enabled", function() {
it("should expand a tag", () => {
cy.visit(`${swagger2BaseUrl}&docExpansion=none#/myTag`)
.get(`.opblock-tag-section.is-open`)
.should("have.length", 1)
})
it("should expand an operation", () => {
cy.visit(`${swagger2BaseUrl}&docExpansion=none#/myTag/myOperation`)
.get(`.opblock.is-open`)
.should("have.length", 1)
})
})
})
describe("in OpenAPI 3", () => {
const openAPI3BaseUrl = "/?deepLinking=true&url=/documents/features/deep-linking.openapi.yaml"
describe("regular Operation", () => {
BaseDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-get",
correctElementId: "operations-myTag-myOperation",
correctFragment: "#/myTag/myOperation",
correctHref: "#/myTag/myOperation"
})
})
describe("Operation with whitespace in tag+id", () => {
const elementToGet = ".opblock-post"
const correctFragment = "#/my%20Tag/my%20Operation"
BaseDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-post",
correctElementId: "operations-my_Tag-my_Operation",
correctFragment,
correctHref: "#/my%20Tag/my%20Operation"
})
const legacyFragment = "#/my_Tag/my_Operation"
it("should expand the operation when reloaded and provided the legacy fragment", () => {
cy.visit(`${openAPI3BaseUrl}${legacyFragment}`)
.reload()
.get(`${elementToGet}.is-open`)
.should("exist")
})
it.skip("should rewrite to the correct fragment when provided the legacy fragment", () => {
cy.visit(`${openAPI3BaseUrl}${legacyFragment}`)
.reload()
.window()
.should("have.deep.property", "location.hash", correctFragment)
})
})
describe("Operation with underscores in tag+id", () => {
BaseDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-patch",
correctElementId: "operations-underscore_Tag-underscore_Operation",
correctFragment: "#/underscore_Tag/underscore_Operation",
correctHref: "#/underscore_Tag/underscore_Operation"
})
})
describe("Operation with UTF-16 characters", () => {
BaseDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-head",
correctElementId: "operations-шеллы-пошел",
correctFragment: "#/%D1%88%D0%B5%D0%BB%D0%BB%D1%8B/%D0%BF%D0%BE%D1%88%D0%B5%D0%BB",
correctHref: "#/шеллы/пошел"
})
})
describe("Operation with no operationId", () => {
BaseDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-put",
correctElementId: "operations-tagTwo-put_noOperationId",
correctFragment: "#/tagTwo/put_noOperationId",
correctHref: "#/tagTwo/put_noOperationId"
})
})
describe("regular Operation with `docExpansion: none` enabled", function () {
it("should expand a tag", () => {
cy.visit(`${openAPI3BaseUrl}&docExpansion=none#/myTag`)
.get(`.opblock-tag-section.is-open`)
.should("have.length", 1)
})
it("should expand an operation", () => {
cy.visit(`${openAPI3BaseUrl}&docExpansion=none#/myTag/myOperation`)
.get(`.opblock.is-open`)
.should("have.length", 1)
})
})
})
})
function BaseDeeplinkTestFactory({ baseUrl, elementToGet, correctElementId, correctFragment, correctHref }) {
it("should generate a correct element ID", () => {
cy.visit(baseUrl)
.get(elementToGet)
.should("have.id", correctElementId)
})
it("should add the correct element fragment to the URL when expanded", () => {
cy.visit(baseUrl)
.get(elementToGet)
.click()
.window()
.should("have.deep.property", "location.hash", correctFragment)
})
it("should provide an anchor link that has the correct fragment as href", () => {
cy.visit(baseUrl)
.get(elementToGet)
.find("a")
.should("have.attr", "href", correctHref)
.click()
.window()
.should("have.deep.property", "location.hash", correctFragment)
})
it("should expand the operation when reloaded", () => {
cy.visit(`${baseUrl}${correctFragment}`)
.get(`${elementToGet}.is-open`)
.should("exist")
})
it("should retain the correct fragment when reloaded", () => {
cy.visit(`${baseUrl}${correctFragment}`)
.reload()
.should("exist")
.window()
.should("have.deep.property", "location.hash", correctFragment)
})
}

View File

@@ -0,0 +1,55 @@
describe("OAuth2 Application flow", function() {
beforeEach(() => {
cy.server()
cy.route({
url: "**/oauth/*",
method: "POST"
}).as("tokenRequest")
})
it("should make an application flow Authorization header request", () => {
cy
.visit("/?url=http://localhost:3231/swagger.yaml")
.get(".btn.authorize")
.click()
.get("div.modal-ux-content > div:nth-child(2)").within(() => {
cy.get("#client_id")
.clear()
.type("confidentialApplication")
.get("#client_secret")
.clear()
.type("topSecret")
.get("button.btn.modal-btn.auth.authorize.button")
.click()
})
cy.get("button.close-modal")
.click()
.get("#operations-default-get_application")
.click()
.get(".btn.try-out__btn")
.click()
.get(".btn.execute")
.click()
cy.get("@tokenRequest")
.its("request")
.its("body")
.should("equal", "grant_type=client_credentials")
cy.get("@tokenRequest")
.its("request")
.its("headers")
.its("authorization")
.should("equal", "Basic Y29uZmlkZW50aWFsQXBwbGljYXRpb246dG9wU2VjcmV0")
.get(".live-responses-table .response-col_status")
.contains("200")
})
})

View File

@@ -0,0 +1,122 @@
describe("OAuth2 Password flow", function() {
beforeEach(() => {
cy.server()
cy.route({
url: "**/oauth/*",
method: "POST"
}).as("tokenRequest")
})
it("should make a password flow Authorization header request", () => {
cy
.visit("/?url=http://localhost:3231/swagger.yaml")
.get(".btn.authorize")
.click()
.get("#oauth_username")
.type("swagger")
.get("#oauth_password")
.type("password")
.get("#password_type")
.select("basic")
.get("#client_id")
.clear()
.type("application")
.get("#client_secret")
.clear()
.type("secret")
.get("div.modal-ux-content > div:nth-child(1) > div > div:nth-child(2) > div > div.auth-btn-wrapper > button.btn.modal-btn.auth.authorize.button")
.click()
.get("button.close-modal")
.click()
.get("#operations-default-get_password")
.click()
.get(".btn.try-out__btn")
.click()
.get(".btn.execute")
.click()
cy.get("@tokenRequest")
.its("request")
.its("body")
.should("include", "grant_type=password")
.should("include", "username=swagger")
.should("include", "password=password")
.should("not.include", "client_id")
.should("not.include", "client_secret")
cy.get("@tokenRequest")
.its("request")
.its("headers")
.its("authorization")
.should("equal", "Basic YXBwbGljYXRpb246c2VjcmV0")
.get(".live-responses-table .response-col_status")
.contains("200")
})
it("should make a Password flow request-body request", () => {
cy
.visit("/?url=http://localhost:3231/swagger.yaml")
.get(".btn.authorize")
.click()
.get("#oauth_username")
.type("swagger")
.get("#oauth_password")
.type("password")
.get("#password_type")
.select("request-body")
.get("#client_id")
.clear()
.type("application")
.get("#client_secret")
.clear()
.type("secret")
.get("div.modal-ux-content > div:nth-child(1) > div > div:nth-child(2) > div > div.auth-btn-wrapper > button.btn.modal-btn.auth.authorize.button")
.click()
.get("button.close-modal")
.click()
.get("#operations-default-get_password")
.click()
.get(".btn.try-out__btn")
.click()
.get(".btn.execute")
.click()
cy.get("@tokenRequest")
.its("request")
.its("body")
.should("include", "grant_type=password")
.should("include", "username=swagger")
.should("include", "password=password")
.should("include", "client_id=application")
.should("include", "client_secret=secret")
cy.get("@tokenRequest")
.its("request")
.its("headers")
.should("not.have.property", "authorization")
.get(".live-responses-table .response-col_status")
.contains("200")
})
})